Merge branch 'master' into tizen_2.1
[platform/framework/web/livebox-edje.git] / src / script_port.c
1 /*
2  * Copyright 2012  Samsung Electronics Co., Ltd
3  *
4  * Licensed under the Flora License, Version 1.0 (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://www.tizenopensource.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 <Evas.h>
24 #include <Edje.h>
25 #include <Eina.h>
26 #include <Ecore.h>
27 #include <Ecore_Evas.h>
28 #include <Eet.h>
29 #include <Ecore_X.h>
30
31 #include <dlog.h>
32 #include <debug.h>
33 #include <vconf.h>
34
35 #include "script_port.h"
36
37 #define TEXT_CLASS      "tizen"
38 #define BASE_WIDTH      720.0f
39
40 #define PUBLIC __attribute__((visibility("default")))
41
42 extern void evas_common_font_flush(void);
43 extern int evas_common_font_cache_get(void);
44 extern void evas_common_font_cache_set(int size);
45
46 struct image_option {
47         int orient;
48         int aspect;
49         enum {
50                 FILL_DISABLE,
51                 FILL_IN_SIZE,
52                 FILL_OVER_SIZE,
53         } fill;
54
55         int width;
56         int height;
57 };
58
59 struct info {
60         char *file;
61         char *group;
62         char *category;
63         int w;
64         int h;
65
66         Evas *e;
67
68         Eina_List *obj_list;
69 };
70
71 struct child {
72         Evas_Object *obj;
73         char *part;
74 };
75
76 struct obj_info {
77         char *id;
78         Eina_List *children;
79 };
80
81 static struct {
82         Ecore_Event_Handler *property_handler;
83         char *font;
84         int size;
85 } s_info = {
86         .property_handler = NULL,
87         .font = NULL,
88         .size = -100,
89 };
90
91 static inline double scale_get(void)
92 {
93         int width;
94         int height;
95         ecore_x_window_size_get(0, &width, &height);
96         return (double)width / BASE_WIDTH;
97 }
98
99 /*!
100  * \NOTE
101  * Reservce this for future use
102 static inline void common_cache_flush(void *evas)
103 {
104         int file_cache;
105         int collection_cache;
106         int image_cache;
107         int font_cache;
108
109         file_cache = edje_file_cache_get();
110         collection_cache = edje_collection_cache_get();
111         image_cache = evas_image_cache_get(evas);
112         font_cache = evas_font_cache_get(evas);
113
114         edje_file_cache_set(file_cache);
115         edje_collection_cache_set(collection_cache);
116         evas_image_cache_set(evas, 0);
117         evas_font_cache_set(evas, 0);
118
119         evas_image_cache_flush(evas);
120         evas_render_idle_flush(evas);
121         evas_font_cache_flush(evas);
122
123         edje_file_cache_flush();
124         edje_collection_cache_flush();
125
126         edje_file_cache_set(file_cache);
127         edje_collection_cache_set(collection_cache);
128         evas_image_cache_set(evas, image_cache);
129         evas_font_cache_set(evas, font_cache);
130
131         eet_clearcache();
132 }
133  */
134
135 static inline Evas_Object *find_edje(struct info *handle, const char *id)
136 {
137         Eina_List *l;
138         Evas_Object *edje;
139         struct obj_info *obj_info;
140
141         EINA_LIST_FOREACH(handle->obj_list, l, edje) {
142                 obj_info = evas_object_data_get(edje, "obj_info");
143                 if (!obj_info) {
144                         ErrPrint("Object info is not valid\n");
145                         continue;
146                 }
147
148                 if (!id) {
149                         if (!obj_info->id)
150                                 return edje;
151
152                         continue;
153                 } else if (!obj_info->id) {
154                         continue;
155                 }
156
157                 if (!strcmp(obj_info->id, id))
158                         return edje;
159         }
160
161         DbgPrint("EDJE[%s] is not found\n", id);
162         return NULL;
163 }
164
165 PUBLIC const char *script_magic_id(void)
166 {
167         return "edje";
168 }
169
170 PUBLIC int script_update_color(void *h, Evas *e, const char *id, const char *part, const char *rgba)
171 {
172         struct info *handle = h;
173         Evas_Object *edje;
174         int r[3], g[3], b[3], a[3];
175         int ret;
176
177         edje = find_edje(handle, id);
178         if (!edje)
179                 return -ENOENT;
180
181         ret = sscanf(rgba, "%d %d %d %d %d %d %d %d %d %d %d %d",
182                                         r, g, b, a,                     /* OBJECT */
183                                         r + 1, g + 1, b + 1, a + 1,     /* OUTLINE */
184                                         r + 2, g + 2, b + 2, a + 2);    /* SHADOW */
185         if (ret != 12) {
186                 DbgPrint("id[%s] part[%s] rgba[%s]\n", id, part, rgba);
187                 return -EINVAL;
188         }
189
190         ret = edje_object_color_class_set(edje, part,
191                                 r[0], g[0], b[0], a[0], /* OBJECT */
192                                 r[1], g[1], b[1], a[1], /* OUTLINE */
193                                 r[2], g[2], b[2], a[2]); /* SHADOW */
194
195         DbgPrint("EDJE[%s] color class is %s changed", id, ret == EINA_TRUE ? "successfully" : "not");
196         return 0;
197 }
198
199 PUBLIC int script_update_text(void *h, Evas *e, const char *id, const char *part, const char *text)
200 {
201         struct info *handle = h;
202         Evas_Object *edje;
203
204         edje = find_edje(handle, id);
205         if (!edje)
206                 return -ENOENT;
207
208         edje_object_part_text_set(edje, part, text);
209         return 0;
210 }
211
212 static void parse_aspect(struct image_option *img_opt, const char *value, int len)
213 {
214         while (len > 0 && *value == ' ') {
215                 value++;
216                 len--;
217         }
218
219         if (len < 4)
220                 return;
221
222         img_opt->aspect = !strncasecmp(value, "true", 4);
223         DbgPrint("Parsed ASPECT: %d (%s)\n", img_opt->aspect, value);
224 }
225
226 static void parse_orient(struct image_option *img_opt, const char *value, int len)
227 {
228         while (len > 0 && *value == ' ') {
229                 value++;
230                 len--;
231         }
232
233         if (len < 4)
234                 return;
235
236         img_opt->orient = !strncasecmp(value, "true", 4);
237         DbgPrint("Parsed ORIENT: %d (%s)\n", img_opt->aspect, value);
238 }
239
240 static void parse_size(struct image_option *img_opt, const char *value, int len)
241 {
242         int width;
243         int height;
244         char *buf;
245
246         while (len > 0 && *value == ' ') {
247                 value++;
248                 len--;
249         }
250
251         buf = strndup(value, len);
252         if (!buf) {
253                 ErrPrint("Heap: %s\n", strerror(errno));
254                 return;
255         }
256
257         if (sscanf(buf, "%dx%d", &width, &height) == 2) {
258                 img_opt->width = width;
259                 img_opt->height = height;
260                 DbgPrint("Parsed size : %dx%d (%s)\n", width, height, buf);
261         } else {
262                 DbgPrint("Invalid size tag[%s]\n", buf);
263         }
264
265         free(buf);
266 }
267
268 static void parse_fill(struct image_option *img_opt, const char *value, int len)
269 {
270         while (len > 0 && *value == ' ') {
271                 value++;
272                 len--;
273         }
274
275         if (!strncasecmp(value, "in-size", len))
276                 img_opt->fill = FILL_IN_SIZE;
277         else if (!strncasecmp(value, "over-size", len))
278                 img_opt->fill = FILL_OVER_SIZE;
279         else
280                 img_opt->fill = FILL_DISABLE;
281
282         DbgPrint("Parsed FILL: %d (%s)\n", img_opt->fill, value);
283 }
284
285 static inline void parse_image_option(const char *option, struct image_option *img_opt)
286 {
287         const char *ptr;
288         const char *cmd;
289         const char *value;
290         struct {
291                 const char *cmd;
292                 void (*handler)(struct image_option *img_opt, const char *value, int len);
293         } cmd_list[] = {
294                 {
295                         .cmd = "aspect", /* Keep the aspect ratio */
296                         .handler = parse_aspect,
297                 },
298                 {
299                         .cmd = "orient", /* Keep the orientation value: for the rotated images */
300                         .handler = parse_orient,
301                 },
302                 {
303                         .cmd = "fill", /* Fill the image to its container */
304                         .handler = parse_fill, /* Value: in-size, over-size, disable(default) */
305                 },
306                 {
307                         .cmd = "size",
308                         .handler = parse_size,
309                 },
310         };
311         enum {
312                 STATE_START,
313                 STATE_TOKEN,
314                 STATE_DATA,
315                 STATE_IGNORE,
316                 STATE_ERROR,
317                 STATE_END,
318         } state;
319         int idx;
320         int tag;
321
322         if (!option || !*option)
323                 return;
324
325         state = STATE_START;
326         /*!
327          * \note
328          * GCC 4.7 warnings uninitialized idx and tag value.
329          * But it will be initialized by the state machine. :(
330          * Anyway, I just reset idx and tag for reducing the GCC4.7 complains.
331          */
332         idx = 0;
333         tag = 0;
334         cmd = NULL;
335         value = NULL;
336
337         for (ptr = option; state != STATE_END; ptr++) {
338                 switch (state) {
339                 case STATE_START:
340                         if (*ptr == '\0') {
341                                 state = STATE_END;
342                                 continue;
343                         }
344
345                         if (isalpha(*ptr)) {
346                                 state = STATE_TOKEN;
347                                 ptr--;
348                         }
349                         tag = 0;
350                         idx = 0;
351
352                         cmd = cmd_list[tag].cmd;
353                         break;
354                 case STATE_IGNORE:
355                         if (*ptr == '=') {
356                                 state = STATE_DATA;
357                                 value = ptr;
358                         } else if (*ptr == '\0') {
359                                 state = STATE_END;
360                         }
361                         break;
362                 case STATE_TOKEN:
363                         if (cmd[idx] == '\0' && (*ptr == ' ' || *ptr == '\t' || *ptr == '=')) {
364                                 if (*ptr == '=') {
365                                         value = ptr;
366                                         state = STATE_DATA;
367                                 } else {
368                                         state = STATE_IGNORE;
369                                 }
370                                 idx = 0;
371                         } else if (*ptr == '\0') {
372                                 state = STATE_END;
373                         } else if (cmd[idx] == *ptr) {
374                                 idx++;
375                         } else {
376                                 ptr -= (idx + 1);
377
378                                 tag++;
379                                 if (tag == sizeof(cmd_list) / sizeof(cmd_list[0])) {
380                                         tag = 0;
381                                         state = STATE_ERROR;
382                                 } else {
383                                         cmd = cmd_list[tag].cmd;
384                                 }
385                                 idx = 0;
386                         }
387                         break;
388                 case STATE_DATA:
389                         if (*ptr == ';' || *ptr == '\0') {
390                                 cmd_list[tag].handler(img_opt, value + 1, idx);
391                                 state = *ptr ? STATE_START : STATE_END;
392                         } else {
393                                 idx++;
394                         }
395                         break;
396                 case STATE_ERROR:
397                         if (*ptr == ';')
398                                 state = STATE_START;
399                         else if (*ptr == '\0')
400                                 state = STATE_END;
401                         break;
402                 default:
403                         break;
404                 }
405         }
406 }
407
408 PUBLIC int script_update_image(void *_h, Evas *e, const char *id, const char *part, const char *path, const char *option)
409 {
410         struct info *handle = _h;
411         Evas_Load_Error err;
412         Evas_Object *edje;
413         Evas_Object *img;
414         Evas_Coord w, h;
415         struct obj_info *obj_info;
416         struct child *child;
417         struct image_option img_opt = {
418                 .aspect = 0,
419                 .orient = 0,
420                 .fill = FILL_DISABLE,
421                 .width = -1,
422                 .height = -1,
423         };
424
425         edje = find_edje(handle, id);
426         if (!edje) {
427                 ErrPrint("No such object: %s\n", id);
428                 return -ENOENT;
429         }
430
431         obj_info = evas_object_data_get(edje, "obj_info");
432         if (!obj_info) {
433                 ErrPrint("Object info is not available\n");
434                 return -EFAULT;
435         }
436
437         img = edje_object_part_swallow_get(edje, part);
438         if (img) {
439                 Eina_List *l;
440                 Eina_List *n;
441
442                 edje_object_part_unswallow(edje, img);
443
444                 EINA_LIST_FOREACH_SAFE(obj_info->children, l, n, child) {
445                         if (child->obj != img)
446                                 continue;
447
448                         obj_info->children = eina_list_remove(obj_info->children, child);
449                         free(child->part);
450                         free(child);
451                         break;
452                 }
453
454                 DbgPrint("delete object %s %p\n", part, img);
455                 evas_object_del(img);
456         }
457
458         if (!path || !strlen(path) || access(path, R_OK) != 0) {
459                 DbgPrint("SKIP - Path: [%s]\n", path);
460                 return 0;
461         }
462
463         child = malloc(sizeof(*child));
464         if (!child) {
465                 ErrPrint("Heap: %s\n", strerror(errno));
466                 return -ENOMEM;
467         }
468
469         child->part = strdup(part);
470         if (!child->part) {
471                 ErrPrint("Heap: %s\n", strerror(errno));
472                 free(child);
473                 return -ENOMEM;
474         }
475
476         img = evas_object_image_add(e);
477         if (!img) {
478                 ErrPrint("Failed to add an image object\n");
479                 free(child->part);
480                 free(child);
481                 return -EFAULT;
482         }
483
484         evas_object_image_preload(img, EINA_FALSE);
485         parse_image_option(option, &img_opt);
486         evas_object_image_load_orientation_set(img, img_opt.orient);
487
488         evas_object_image_file_set(img, path, NULL);
489         err = evas_object_image_load_error_get(img);
490         if (err != EVAS_LOAD_ERROR_NONE) {
491                 ErrPrint("Load error: %s\n", evas_load_error_str(err));
492                 evas_object_del(img);
493                 free(child->part);
494                 free(child);
495                 return -EIO;
496         }
497
498         evas_object_image_size_get(img, &w, &h);
499         if (img_opt.aspect) {
500                 if (img_opt.fill == FILL_OVER_SIZE) {
501                         Evas_Coord part_w;
502                         Evas_Coord part_h;
503
504                         if (img_opt.width >= 0 && img_opt.height >= 0) {
505                                 part_w = img_opt.width * scale_get();
506                                 part_h = img_opt.height * scale_get();
507                         } else {
508                                 part_w = 0;
509                                 part_h = 0;
510                                 edje_object_part_geometry_get(edje, part, NULL, NULL, &part_w, &part_h);
511                         }
512                         DbgPrint("Original %dx%d (part: %dx%d)\n", w, h, part_w, part_h);
513
514                         if (part_w > w || part_h > h) {
515                                 double fw;
516                                 double fh;
517
518                                 fw = (double)part_w / (double)w;
519                                 fh = (double)part_h / (double)h;
520
521                                 if (fw > fh) {
522                                         w = part_w;
523                                         h = (double)h * fw;
524                                 } else {
525                                         h = part_h;
526                                         w = (double)w * fh;
527                                 }
528                         }
529                         DbgPrint("Size: %dx%d\n", w, h);
530
531                         evas_object_image_load_size_set(img, w, h);
532                         evas_object_image_load_region_set(img, (w - part_w) / 2, (h - part_h) / 2, part_w, part_h);
533                         evas_object_image_fill_set(img, 0, 0, part_w, part_h);
534                         evas_object_image_reload(img);
535                 } else {
536                         evas_object_image_fill_set(img, 0, 0, w, h);
537                         evas_object_size_hint_fill_set(img, EVAS_HINT_FILL, EVAS_HINT_FILL);
538                         evas_object_size_hint_aspect_set(img, EVAS_ASPECT_CONTROL_BOTH, w, h);
539                 }
540         } else {
541                 if (img_opt.width >= 0 && img_opt.height >= 0) {
542                         w = img_opt.width;
543                         h = img_opt.height;
544                         DbgPrint("Using given image size: %dx%d\n", w, h);
545                 }
546
547                 evas_object_image_fill_set(img, 0, 0, w, h);
548                 evas_object_size_hint_fill_set(img, EVAS_HINT_FILL, EVAS_HINT_FILL);
549                 evas_object_size_hint_weight_set(img, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
550         }
551
552         /*!
553          * \note
554          * object will be shown by below statement automatically
555          */
556         DbgPrint("%s part swallow image %p (%dx%d)\n", part, img, w, h);
557         child->obj = img;
558         edje_object_part_swallow(edje, part, img);
559         obj_info->children = eina_list_append(obj_info->children, child);
560
561         return 0;
562 }
563
564 static void script_signal_cb(void *data, Evas_Object *obj, const char *emission, const char *source)
565 {
566         struct info *handle = data;
567         Evas_Coord w;
568         Evas_Coord h;
569         Evas_Coord px = 0;
570         Evas_Coord py = 0;
571         Evas_Coord pw = 0;
572         Evas_Coord ph = 0;
573         double sx;
574         double sy;
575         double ex;
576         double ey;
577
578         evas_object_geometry_get(obj, NULL, NULL, &w, &h);
579         edje_object_part_geometry_get(obj, source, &px, &py, &pw, &ph);
580
581         sx = ex = 0.0f;
582         if (w) {
583                 sx = (double)px / (double)w;
584                 ex = (double)(px + pw) / (double)w;
585         }
586
587         sy = ey = 0.0f;
588         if (h) {
589                 sy = (double)py / (double)h;
590                 ey = (double)(py + ph) / (double)h;
591         }
592
593         DbgPrint("Signal emit: source[%s], emission[%s]\n", source, emission);
594         script_signal_emit(handle->e, source, emission, sx, sy, ex, ey);
595 }
596
597 static void edje_del_cb(void *_info, Evas *e, Evas_Object *obj, void *event_info)
598 {
599         struct info *handle = _info;
600         struct obj_info *obj_info;
601         struct child *child;
602
603         handle->obj_list = eina_list_remove(handle->obj_list, obj);
604
605         obj_info = evas_object_data_del(obj, "obj_info");
606         if (!obj_info) {
607                 ErrPrint("Object info is not valid\n");
608                 return;
609         }
610
611         DbgPrint("delete object %s %p\n", obj_info->id, obj);
612
613         edje_object_signal_callback_del_full(obj, "*", "*", script_signal_cb, handle);
614
615         EINA_LIST_FREE(obj_info->children, child) {
616                 DbgPrint("delete object %s %p\n", child->part, child->obj);
617                 if (child->obj)
618                         evas_object_del(child->obj);
619                 free(child->part);
620                 free(child);
621         }
622
623         free(obj_info->id);
624         free(obj_info);
625 }
626
627 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)
628 {
629         struct info *handle = h;
630         Evas_Object *edje;
631         Evas_Object *obj;
632         struct obj_info *obj_info;
633         struct child *child;
634
635         DbgPrint("src_id[%s] target_id[%s] part[%s] path[%s] group[%s]\n", src_id, target_id, part, path, group);
636
637         edje = find_edje(handle, src_id);
638         if (!edje) {
639                 ErrPrint("Edje is not exists\n");
640                 return -ENOENT;
641         }
642
643         obj_info = evas_object_data_get(edje, "obj_info");
644         if (!obj_info) {
645                 ErrPrint("Object info is not valid\n");
646                 return -EINVAL;
647         }
648
649         obj = edje_object_part_swallow_get(edje, part);
650         if (obj) {
651                 Eina_List *l;
652                 Eina_List *n;
653
654                 edje_object_part_unswallow(edje, obj);
655
656                 EINA_LIST_FOREACH_SAFE(obj_info->children, l, n, child) {
657                         if (child->obj != obj)
658                                 continue;
659
660                         obj_info->children = eina_list_remove(obj_info->children, child);
661                         free(child->part);
662                         free(child);
663                         break;
664                 }
665
666                 DbgPrint("delete object %s %p\n", part, obj);
667                 evas_object_del(obj);
668         }
669
670         if (!path || !strlen(path) || access(path, R_OK) != 0) {
671                 DbgPrint("SKIP - Path: [%s]\n", path);
672                 return 0;
673         }
674
675         obj = edje_object_add(e);
676         if (!obj) {
677                 ErrPrint("Failed to add a new edje object\n");
678                 return -EFAULT;
679         }
680
681         if (!edje_object_file_set(obj, path, group)) {
682                 int err;
683                 const char *errmsg;
684
685                 err = edje_object_load_error_get(obj);
686                 errmsg = edje_load_error_str(err);
687                 ErrPrint("Could not load %s from %s: %s\n", group, path, errmsg);
688                 evas_object_del(obj);
689                 return -EIO;
690         }
691
692         evas_object_show(obj);
693
694         obj_info = calloc(1, sizeof(*obj_info));
695         if (!obj_info) {
696                 ErrPrint("Failed to add a obj_info\n");
697                 evas_object_del(obj);
698                 return -ENOMEM;
699         }
700
701         obj_info->id = strdup(target_id);
702         if (!obj_info->id) {
703                 ErrPrint("Failed to add a obj_info\n");
704                 free(obj_info);
705                 evas_object_del(obj);
706                 return -ENOMEM;
707         }
708
709         child = malloc(sizeof(*child));
710         if (!child) {
711                 ErrPrint("Error: %s\n", strerror(errno));
712                 free(obj_info->id);
713                 free(obj_info);
714                 evas_object_del(obj);
715                 return -ENOMEM;
716         }
717
718         child->part = strdup(part);
719         if (!child->part) {
720                 ErrPrint("Error: %s\n", strerror(errno));
721                 free(child);
722                 free(obj_info->id);
723                 free(obj_info);
724                 evas_object_del(obj);
725                 return -ENOMEM;
726         }
727
728         child->obj = obj;
729
730         evas_object_data_set(obj, "obj_info", obj_info);
731         evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, edje_del_cb, handle);
732         edje_object_signal_callback_add(obj, "*", "*", script_signal_cb, handle);
733         handle->obj_list = eina_list_append(handle->obj_list, obj);
734
735         DbgPrint("%s part swallow edje %p\n", part, obj);
736         edje_object_part_swallow(edje, part, obj);
737         obj_info = evas_object_data_get(edje, "obj_info");
738         obj_info->children = eina_list_append(obj_info->children, child);
739         return 0;
740 }
741
742 PUBLIC int script_update_signal(void *h, Evas *e, const char *id, const char *part, const char *signal)
743 {
744         struct info *handle = h;
745         Evas_Object *edje;
746
747         DbgPrint("id[%s], part[%s], signal[%s]\n", id, part, signal);
748
749         edje = find_edje(handle, id);
750         if (!edje)
751                 return -ENOENT;
752
753         edje_object_signal_emit(edje, signal, part);
754         return 0;
755 }
756
757 PUBLIC int script_update_drag(void *h, Evas *e, const char *id, const char *part, double x, double y)
758 {
759         struct info *handle = h;
760         Evas_Object *edje;
761
762         DbgPrint("id[%s], part[%s], %lfx%lf\n", id, part, x, y);
763
764         edje = find_edje(handle, id);
765         if (!edje)
766                 return -ENOENT;
767
768         edje_object_part_drag_value_set(edje, part, x, y);
769         return 0;
770 }
771
772 PUBLIC int script_update_size(void *han, Evas *e, const char *id, int w, int h)
773 {
774         struct info *handle = han;
775         Evas_Object *edje;
776
777         edje = find_edje(handle, id);
778         if (!edje)
779                 return -ENOENT;
780
781         if (!id) {
782                 handle->w = w;
783                 handle->h = h;
784         }
785
786         DbgPrint("Resize object to %dx%d\n", w, h);
787         evas_object_resize(edje, w, h);
788         return 0;
789 }
790
791 PUBLIC int script_update_category(void *h, Evas *e, const char *id, const char *category)
792 {
793         struct info *handle = h;
794
795         DbgPrint("id[%s], category[%s]\n", id, category);
796
797         if (handle->category) {
798                 free(handle->category);
799                 handle->category = NULL;
800         }
801
802         if (!category)
803                 return 0;
804
805         handle->category = strdup(category);
806         if (!handle->category) {
807                 ErrPrint("Error: %s\n", strerror(errno));
808                 return -ENOMEM;
809         }
810
811         return 0;
812 }
813
814 PUBLIC void *script_create(const char *file, const char *group)
815 {
816         struct info *handle;
817
818         DbgPrint("file[%s], group[%s]\n", file, group);
819
820         handle = calloc(1, sizeof(*handle));
821         if (!handle) {
822                 ErrPrint("Error: %s\n", strerror(errno));
823                 return NULL;
824         }
825
826         handle->file = strdup(file);
827         if (!handle->file) {
828                 ErrPrint("Error: %s\n", strerror(errno));
829                 free(handle);
830                 return NULL;
831         }
832
833         handle->group = strdup(group);
834         if (!handle->group) {
835                 ErrPrint("Error: %s\n", strerror(errno));
836                 free(handle->file);
837                 free(handle);
838                 return NULL;
839         }
840
841         return handle;
842 }
843
844 PUBLIC int script_destroy(void *_handle)
845 {
846         struct info *handle;
847         Evas_Object *edje;
848
849         handle = _handle;
850
851         edje = eina_list_nth(handle->obj_list, 0);
852         if (edje)
853                 evas_object_del(edje);
854
855         free(handle->category);
856         free(handle->file);
857         free(handle->group);
858         free(handle);
859         return 0;
860 }
861
862 PUBLIC int script_load(void *_handle, Evas *e, int w, int h)
863 {
864         struct info *handle;
865         Evas_Object *edje;
866         struct obj_info *obj_info;
867
868         handle = _handle;
869
870         obj_info = calloc(1, sizeof(*obj_info));
871         if (!obj_info) {
872                 ErrPrint("Heap: %s\n", strerror(errno));
873                 return -ENOMEM;
874         }
875
876         edje = edje_object_add(e);
877         if (!edje) {
878                 ErrPrint("Failed to create an edje object\n");
879                 free(obj_info);
880                 return -EFAULT;
881         }
882
883         DbgPrint("Load edje: %s - %s\n", handle->file, handle->group);
884         if (!edje_object_file_set(edje, handle->file, handle->group)) {
885                 int err;
886                 const char *errmsg;
887
888                 err = edje_object_load_error_get(edje);
889                 errmsg = edje_load_error_str(err);
890                 ErrPrint("Could not load %s from %s: %s\n", handle->group, handle->file, errmsg);
891                 evas_object_del(edje);
892                 free(obj_info);
893                 return -EIO;
894         }
895
896         handle->e = e;
897         handle->w = w;
898         handle->h = h;
899
900         edje_object_signal_callback_add(edje, "*", "*", script_signal_cb, handle);
901         evas_object_event_callback_add(edje, EVAS_CALLBACK_DEL, edje_del_cb, handle);
902         evas_object_size_hint_weight_set(edje, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
903         evas_object_size_hint_fill_set(edje, EVAS_HINT_FILL, EVAS_HINT_FILL);
904         evas_object_resize(edje, handle->w, handle->h);
905         evas_object_show(edje);
906         evas_object_data_set(edje, "obj_info", obj_info);
907
908         handle->obj_list = eina_list_append(handle->obj_list, edje);
909         return 0;
910 }
911
912 PUBLIC int script_unload(void *_handle, Evas *e)
913 {
914         struct info *handle;
915         Evas_Object *edje;
916
917         handle = _handle;
918
919         DbgPrint("Unload edje: %s - %s\n", handle->file, handle->group);
920         edje = eina_list_nth(handle->obj_list, 0);
921         if (edje)
922                 evas_object_del(edje);
923         handle->e = NULL;
924         return 0;
925 }
926
927 static inline int update_font(const char *font)
928 {
929         Eina_List *list;
930         char *text;
931         int cache;
932
933         cache = evas_common_font_cache_get();
934         evas_common_font_cache_set(0);
935         evas_common_font_flush();
936
937         list = edje_text_class_list();
938         EINA_LIST_FREE(list, text) {
939                 if (!strncasecmp(text, TEXT_CLASS, strlen(TEXT_CLASS))) {
940                         edje_text_class_del(text);
941                         edje_text_class_set(text, s_info.font, s_info.size);
942                         DbgPrint("Update text class %s (%s, %d)\n", text, s_info.font, s_info.size);
943                 } else {
944                         DbgPrint("Skip text class %s\n", text);
945                 }
946         }
947         DbgPrint("Font for text_class is updated\n");
948
949         evas_common_font_cache_set(cache);
950         return 0;
951 }
952
953 static Eina_Bool property_cb(void *data, int type, void *event)
954 {
955         Ecore_X_Event_Window_Property *info = (Ecore_X_Event_Window_Property *)event;
956
957         if (info->atom == ecore_x_atom_get("FONT_TYPE_change") || info->atom == ecore_x_atom_get("BADA_FONT_change")) {
958                 char *font;
959
960                 font = vconf_get_str("db/setting/accessibility/font_name");
961                 if (!font)
962                         return ECORE_CALLBACK_PASS_ON;
963
964                 if (s_info.font && !strcmp(s_info.font, font)) {
965                         DbgPrint("Font is not changed (%s)\n", font);
966                         free(font);
967                         return ECORE_CALLBACK_PASS_ON;
968                 }
969
970                 if (s_info.font)
971                         free(s_info.font);
972
973                 s_info.font = font;
974
975                 update_font(font);
976         }
977
978         return ECORE_CALLBACK_PASS_ON;
979 }
980
981 static void font_name_cb(keynode_t *node, void *user_data)
982 {
983         const char *font;
984
985         if (!node)
986                 return;
987
988         font = vconf_keynode_get_str(node);
989         if (!font)
990                 return;
991
992         if (s_info.font && !strcmp(s_info.font, font)) {
993                 DbgPrint("Font is not changed\n");
994                 return;
995         }
996
997         DbgPrint("Font changed to %s\n", font);
998
999         if (s_info.font)
1000                 free(s_info.font);
1001
1002         s_info.font = strdup(font);
1003         if (!s_info.font)
1004                 ErrPrint("Heap: %s\n", strerror(errno));
1005
1006         update_font(font);
1007 }
1008
1009 static void font_size_cb(keynode_t *node, void *user_data)
1010 {
1011         if (!node)
1012                 return;
1013         /*!
1014          * \TODO
1015          * Implementing me.
1016          */
1017         DbgPrint("Size type: %d\n", vconf_keynode_get_int(node));
1018 }
1019
1020 PUBLIC int script_init(void)
1021 {
1022         int ret;
1023         /* ecore is already initialized */
1024         edje_init();
1025         edje_scale_set(scale_get());
1026
1027         s_info.property_handler = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_PROPERTY, property_cb, NULL);
1028         if (!s_info.property_handler)
1029                 ErrPrint("Failed to add a property change event handler\n");
1030
1031         ret = vconf_notify_key_changed(VCONFKEY_SETAPPL_ACCESSIBILITY_FONT_SIZE, font_size_cb, NULL);
1032         if (ret < 0)
1033                 ErrPrint("Failed to add vconf for font size change\n");
1034
1035         ret = vconf_notify_key_changed("db/setting/accessibility/font_name", font_name_cb, NULL);
1036         if (ret < 0)
1037                 ErrPrint("Failed to add vconf for font name change\n");
1038
1039         return 0;
1040 }
1041
1042 PUBLIC int script_fini(void)
1043 {
1044         vconf_ignore_key_changed("db/setting/accessibility/font_name", font_name_cb);
1045         vconf_ignore_key_changed(VCONFKEY_SETAPPL_ACCESSIBILITY_FONT_SIZE, font_size_cb);
1046         ecore_event_handler_del(s_info.property_handler);
1047         s_info.property_handler = NULL;
1048         edje_shutdown();
1049         return 0;
1050 }
1051
1052 /* End of a file */