Add new accessibilty events & fixed prevent issues
[apps/livebox/data-provider-master.git] / src / script_handler.c
1 /*
2  * Copyright 2013  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 <errno.h>
19 #include <stdlib.h> /* free */
20 #include <ctype.h>
21 #include <dlfcn.h>
22 #include <sys/types.h>
23 #include <dirent.h>
24 #include <string.h>
25
26 #include <Ecore_Evas.h>
27 #include <Ecore.h>
28 #include <Evas.h>
29
30 #include <dlog.h>
31 #include <packet.h>
32 #include <livebox-errno.h>
33
34 #include "slave_life.h"
35 #include "slave_rpc.h"
36 #include "client_life.h"
37 #include "package.h"
38 #include "instance.h"
39 #include "buffer_handler.h"
40 #include "script_handler.h"
41 #include "fb.h"
42 #include "debug.h"
43 #include "conf.h"
44 #include "util.h"
45
46 #define TYPE_COLOR "color"
47 #define TYPE_TEXT "text"
48 #define TYPE_IMAGE "image"
49 #define TYPE_EDJE "script"
50 #define TYPE_SIGNAL "signal"
51 #define TYPE_INFO "info"
52 #define TYPE_DRAG "drag"
53 #define TYPE_ACCESS "access"
54
55 #define INFO_SIZE "size"
56 #define INFO_CATEGORY "category"
57 #define ADDEND 256
58
59 int errno;
60
61 static struct info {
62         Eina_List *script_port_list;
63         enum buffer_type env_buf_type;
64 } s_info = {
65         .script_port_list = NULL,
66         .env_buf_type = BUFFER_TYPE_FILE,
67 };
68
69 struct script_port {
70         void *handle;
71
72         const char *(*magic_id)(void);
73         int (*update_color)(void *handle, Evas *e, const char *id, const char *part, const char *rgba);
74         int (*update_text)(void *handle, Evas *e, const char *id, const char *part, const char *text);
75         int (*update_image)(void *handle, Evas *e, const char *id, const char *part, const char *path, const char *option);
76         int (*update_access)(void *handle, Evas *e, const char *id, const char *part, const char *text, const char *option);
77         int (*update_script)(void *handle, Evas *e, const char *src_id, const char *target_id, const char *part, const char *path, const char *option);
78         int (*update_signal)(void *handle, Evas *e, const char *id, const char *part, const char *signal);
79         int (*update_drag)(void *handle, Evas *e, const char *id, const char *part, double x, double y);
80         int (*update_size)(void *handle, Evas *e, const char *id, int w, int h);
81         int (*update_category)(void *handle, Evas *e, const char *id, const char *category);
82         int (*feed_event)(void *handle, Evas *e, int event_type, int x, int y, double timestamp);
83
84         void *(*create)(const char *file, const char *option);
85         int (*destroy)(void *handle);
86
87         int (*load)(void *handle, Evas *e, int w, int h);
88         int (*unload)(void *handle, Evas *e);
89
90         int (*init)(void);
91         int (*fini)(void);
92 };
93
94 struct block {
95         char *type;
96         int type_len;
97
98         char *part;
99         int part_len;
100
101         char *data;
102         int data_len;
103
104         char *file;
105         int file_len;
106
107         char *option;
108         int option_len;
109
110         char *id;
111         int id_len;
112
113         char *target_id;
114         int target_len;
115 };
116
117 struct script_info {
118         Ecore_Evas *ee;
119         struct fb_info *fb;
120         struct inst_info *inst;
121         int loaded;
122
123         int w;
124         int h;
125
126         int x;
127         int y;
128         int down;
129
130         struct script_port *port;
131         void *port_data;
132 };
133
134 static inline struct script_port *find_port(const char *magic_id)
135 {
136         Eina_List *l;
137         struct script_port *item;
138
139         EINA_LIST_FOREACH(s_info.script_port_list, l, item) {
140                 if (!strcmp(item->magic_id(), magic_id))
141                         return item;
142         }
143
144         return NULL;
145 }
146
147 static void render_pre_cb(void *data, Evas *e, void *event_info)
148 {
149         struct inst_info *inst = data;
150         struct script_info *info;
151
152         if (instance_state(inst) != INST_ACTIVATED) {
153                 DbgPrint("Render pre invoked but instance is not activated\n");
154                 return;
155         }
156
157         info = instance_lb_script(inst);
158         if (info && script_handler_evas(info) == e) {
159                 return;
160         }
161
162         info = instance_pd_script(inst);
163         if (info && script_handler_evas(info) == e) {
164                 return;
165         }
166
167         ErrPrint("Failed to do sync\n");
168         return;
169 }
170
171 static void render_post_cb(void *data, Evas *e, void *event_info)
172 {
173         struct inst_info *inst;
174         struct script_info *info;
175
176         inst = data;
177
178         if (instance_state(inst) != INST_ACTIVATED) {
179                 DbgPrint("Render post invoked but instance is not activated\n");
180                 return;
181         }
182
183         info = instance_lb_script(inst);
184         if (info && script_handler_evas(info) == e) {
185                 fb_sync(script_handler_fb(info));
186                 instance_lb_updated_by_instance(inst);
187                 return;
188         }
189
190         info = instance_pd_script(inst);
191         if (info && script_handler_evas(info) == e) {
192                 fb_sync(script_handler_fb(info));
193                 instance_pd_updated_by_instance(inst, NULL);
194                 return;
195         }
196
197         ErrPrint("Failed to sync\n");
198         return;
199 }
200
201 /*!
202  * \NOTE
203  * Exported API
204  */
205 int script_signal_emit(Evas *e, const char *part, const char *signal, double sx, double sy, double ex, double ey)
206 {
207         Ecore_Evas *ee;
208         struct script_info *info;
209         int ret;
210
211         ee = ecore_evas_ecore_evas_get(e);
212         if (!ee) {
213                 ErrPrint("Evas has no Ecore_Evas\n");
214                 return LB_STATUS_ERROR_INVALID;
215         }
216
217         info = ecore_evas_data_get(ee, "script,info");
218         if (!info) {
219                 ErrPrint("ecore_evas doesn't carry info data\n");
220                 return LB_STATUS_ERROR_INVALID;
221         }
222
223         if (!signal || strlen(signal) == 0)
224                 signal = "";
225
226         if (!part || strlen(part) == 0)
227                 part = "";
228
229         ret = instance_signal_emit(info->inst, signal, part, sx, sy, ex, ey, (double)info->x / (double)info->w, (double)info->y / (double)info->h, info->down);
230         return ret;
231 }
232
233 HAPI int script_handler_load(struct script_info *info, int is_pd)
234 {
235         int ret;
236         Evas *e;
237
238         if (!info || !info->port) {
239                 ErrPrint("Script handler is not created\n");
240                 return LB_STATUS_ERROR_INVALID;
241         }
242
243         if (info->loaded > 0) {
244                 info->loaded++;
245                 return LB_STATUS_SUCCESS;
246         }
247
248         ret = fb_create_buffer(info->fb);
249         if (ret < 0)
250                 return ret;
251
252         info->ee = fb_canvas(info->fb);
253         if (!info->ee) {
254                 ErrPrint("Failed to get canvas\n");
255                 fb_destroy_buffer(info->fb);
256                 return LB_STATUS_ERROR_FAULT;
257         }
258
259         ecore_evas_data_set(info->ee, "script,info", info);
260
261         e = script_handler_evas(info);
262         if (e) {
263                 evas_event_callback_add(e, EVAS_CALLBACK_RENDER_PRE, render_pre_cb, info->inst);
264                 evas_event_callback_add(e, EVAS_CALLBACK_RENDER_POST, render_post_cb, info->inst);
265                 if (info->port->load(info->port_data, e, info->w, info->h) < 0) {
266                         ErrPrint("Failed to add new script object\n");
267                         evas_event_callback_del(e, EVAS_CALLBACK_RENDER_POST, render_post_cb);
268                         evas_event_callback_del(e, EVAS_CALLBACK_RENDER_PRE, render_pre_cb);
269                         fb_destroy_buffer(info->fb);
270                         return LB_STATUS_ERROR_FAULT;
271                 }
272                 info->loaded = 1;
273                 script_signal_emit(e, util_uri_to_path(instance_id(info->inst)),
274                                 is_pd ? "pd,show" : "lb,show", 0.0f, 0.0f, 0.0f, 0.0f);
275         } else {
276                 ErrPrint("Evas: (nil) %dx%d\n", info->w, info->h);
277         }
278
279         ecore_evas_manual_render_set(info->ee, EINA_FALSE);
280         ecore_evas_resize(info->ee, info->w, info->h);
281         ecore_evas_show(info->ee);
282         ecore_evas_activate(info->ee);
283         fb_sync(info->fb);
284
285         return LB_STATUS_SUCCESS;
286 }
287
288 HAPI int script_handler_unload(struct script_info *info, int is_pd)
289 {
290         Ecore_Evas *ee;
291         Evas *e;
292
293         if (!info || !info->port)
294                 return LB_STATUS_ERROR_INVALID;
295
296         info->loaded--;
297         if (info->loaded > 0)
298                 return LB_STATUS_SUCCESS;
299
300         if (info->loaded < 0) {
301                 info->loaded = 0;
302                 return LB_STATUS_SUCCESS;
303         }
304
305         e = script_handler_evas(info);
306         if (e) {
307                 script_signal_emit(e, util_uri_to_path(instance_id(info->inst)),
308                                 is_pd ? "pd,hide" : "lb,hide", 0.0f, 0.0f, 0.0f, 0.0f);
309                 if (info->port->unload(info->port_data, e) < 0)
310                         ErrPrint("Failed to unload script object. but go ahead\n");
311                 evas_event_callback_del(e, EVAS_CALLBACK_RENDER_POST, render_post_cb);
312                 evas_event_callback_del(e, EVAS_CALLBACK_RENDER_PRE, render_pre_cb);
313         } else {
314                 ErrPrint("Evas(nil): Unload script\n");
315         }
316
317         ee = fb_canvas(info->fb);
318         if (ee)
319                 ecore_evas_data_set(ee, "script,info", NULL);
320
321         fb_destroy_buffer(info->fb);
322         return LB_STATUS_SUCCESS;
323 }
324
325 HAPI struct script_info *script_handler_create(struct inst_info *inst, const char *file, const char *option, int w, int h)
326 {
327         struct script_info *info;
328
329         DbgPrint("Create script: %s (%s)\n", file, option);
330
331         if (!file)
332                 return NULL;
333
334         info = calloc(1, sizeof(*info));
335         if (!info) {
336                 ErrPrint("Heap: %s\n", strerror(errno));
337                 return NULL;
338         }
339
340         info->fb = fb_create(inst, w, h, s_info.env_buf_type);
341         if (!info->fb) {
342                 ErrPrint("Failed to create a FB (%dx%d)\n", w, h);
343                 DbgFree(info);
344                 return NULL;
345         }
346
347         info->inst = inst;
348         info->port = find_port(package_script(instance_package(inst)));
349         if (!info->port) {
350                 ErrPrint("Failed to find a proper port for [%s]%s\n",
351                                         instance_package(inst), package_script(instance_package(inst)));
352                 fb_destroy(info->fb);
353                 DbgFree(info);
354                 return NULL;
355         }
356
357         DbgPrint("Update info [%dx%d]\n", w, h);
358         info->w = w;
359         info->h = h;
360
361         info->port_data = info->port->create(file, option);
362         if (!info->port_data) {
363                 ErrPrint("Failed to create a port (%s - %s)\n", file, option);
364                 fb_destroy(info->fb);
365                 DbgFree(info);
366                 return NULL;
367         }
368
369         return info;
370 }
371
372 HAPI int script_handler_destroy(struct script_info *info)
373 {
374         if (!info || !info->port) {
375                 ErrPrint("port is not valid\n");
376                 return LB_STATUS_ERROR_INVALID;
377         }
378
379         if (info->loaded != 0) {
380                 ErrPrint("Script handler is not unloaded\n");
381                 return LB_STATUS_ERROR_INVALID;
382         }
383
384         if (info->port->destroy(info->port_data) < 0)
385                 ErrPrint("Failed to destroy port, but go ahead\n");
386
387         fb_destroy(info->fb);
388         DbgFree(info);
389         return LB_STATUS_SUCCESS;
390 }
391
392 HAPI int script_handler_is_loaded(struct script_info *info)
393 {
394         return info ? info->loaded > 0 : 0;
395 }
396
397 HAPI struct fb_info *script_handler_fb(struct script_info *info)
398 {
399         return info ? info->fb : NULL;
400 }
401
402 HAPI void *script_handler_evas(struct script_info *info)
403 {
404         if (!info)
405                 return NULL;
406
407         if (!info->ee)
408                 return NULL;
409
410         return ecore_evas_get(info->ee);
411 }
412
413 static int update_script_color(struct inst_info *inst, struct block *block, int is_pd)
414 {
415         struct script_info *info;
416         Evas *e;
417
418         if (!block || !block->part || !block->data) {
419                 ErrPrint("Block or part or data is not valid\n");
420                 return LB_STATUS_ERROR_INVALID;
421         }
422
423         info = is_pd ? instance_pd_script(inst) : instance_lb_script(inst);
424         if (!info) {
425                 ErrPrint("info is NIL (%d, %s)\n", is_pd, instance_id(inst));
426                 return LB_STATUS_ERROR_FAULT;
427         }
428
429         if (!info->port) {
430                 ErrPrint("info->port is NIL (%d, %s)\n", is_pd, instance_id(inst));
431                 return LB_STATUS_ERROR_INVALID;
432         }
433
434         e = script_handler_evas(info);
435         if (e)
436                 info->port->update_color(info->port_data, e, block->id, block->part, block->data);
437         else
438                 ErrPrint("Evas(nil) id[%s] part[%s] data[%s]\n", block->id, block->part, block->data);
439
440         return LB_STATUS_SUCCESS;
441 }
442
443 static int update_script_text(struct inst_info *inst, struct block *block, int is_pd)
444 {
445         struct script_info *info;
446         Evas *e;
447
448         if (!block || !block->part || !block->data) {
449                 ErrPrint("Block or part or data is not valid\n");
450                 return LB_STATUS_ERROR_INVALID;
451         }
452
453         info = is_pd ? instance_pd_script(inst) : instance_lb_script(inst);
454         if (!info) {
455                 ErrPrint("info is NIL (%d, %s)\n", is_pd, instance_id(inst));
456                 return LB_STATUS_ERROR_FAULT;
457         }
458
459         if (!info->port) {
460                 ErrPrint("info->port is NIL\n");
461                 return LB_STATUS_ERROR_INVALID;
462         }
463
464         e = script_handler_evas(info);
465         if (e)
466                 info->port->update_text(info->port_data, e, block->id, block->part, block->data);
467         else
468                 ErrPrint("Evas(nil) id[%s] part[%s] data[%s]\n", block->id, block->part, block->data);
469         return LB_STATUS_SUCCESS;
470 }
471
472 static int update_script_image(struct inst_info *inst, struct block *block, int is_pd)
473 {
474         struct script_info *info;
475         Evas *e;
476
477         if (!block || !block->part) {
478                 ErrPrint("Block or part is not valid\n");
479                 return LB_STATUS_ERROR_INVALID;
480         }
481
482         info = is_pd ? instance_pd_script(inst) : instance_lb_script(inst);
483         if (!info) {
484                 ErrPrint("info is NIL (%d, %s)\n", is_pd, instance_id(inst));
485                 return LB_STATUS_ERROR_FAULT;
486         }
487
488         if (!info->port) {
489                 ErrPrint("info->port is NIL\n");
490                 return LB_STATUS_ERROR_INVALID;
491         }
492
493         e = script_handler_evas(info);
494         if (e)
495                 info->port->update_image(info->port_data, e, block->id, block->part, block->data, block->option);
496         else
497                 ErrPrint("Evas: (nil) id[%s] part[%s] data[%s]\n", block->id, block->part, block->data);
498         return LB_STATUS_SUCCESS;
499 }
500
501 static int update_access(struct inst_info *inst, struct block *block, int is_pd)
502 {
503         struct script_info *info;
504         Evas *e;
505
506         if (!block || !block->part) {
507                 ErrPrint("Block or block->part is NIL\n");
508                 return LB_STATUS_ERROR_INVALID;
509         }
510
511         info = is_pd ? instance_pd_script(inst) : instance_lb_script(inst);
512         if (!info) {
513                 ErrPrint("info is NIL (%d, %s)\n", is_pd, instance_id(inst));
514                 return LB_STATUS_ERROR_FAULT;
515         }
516
517         if (!info->port) {
518                 ErrPrint("info->port is NIL\n");
519                 return LB_STATUS_ERROR_INVALID;
520         }
521
522         e = script_handler_evas(info);
523         if (e)
524                 info->port->update_access(info->port_data, e, block->id, block->part, block->data, block->option);
525         else
526                 ErrPrint("Evas: (nil) id[%s] part[%s] data[%s]\n", block->id, block->part, block->data);
527         return LB_STATUS_SUCCESS;
528 }
529
530 static int update_script_script(struct inst_info *inst, struct block *block, int is_pd)
531 {
532         struct script_info *info;
533         Evas *e;
534
535         if (!block || !block->part) {
536                 ErrPrint("Block or part is NIL\n");
537                 return LB_STATUS_ERROR_INVALID;
538         }
539
540         info = is_pd ? instance_pd_script(inst) : instance_lb_script(inst);
541         if (!info) {
542                 ErrPrint("info is NIL (%d, %s)\n", is_pd, instance_id(inst));
543                 return LB_STATUS_ERROR_FAULT;
544         }
545
546         if (!info->port) {
547                 ErrPrint("info->port is NIL\n");
548                 return LB_STATUS_ERROR_INVALID;
549         }
550
551         e = script_handler_evas(info);
552         if (e)
553                 info->port->update_script(info->port_data, e, block->id, block->target_id, block->part, block->data, block->option);
554         else
555                 ErrPrint("Evas: (nil) id[%s] part[%s] data[%s] option[%s]\n",
556                                                 block->id, block->part, block->data, block->option);
557         return LB_STATUS_SUCCESS;
558 }
559
560 static int update_script_signal(struct inst_info *inst, struct block *block, int is_pd)
561 {
562         struct script_info *info;
563         Evas *e;
564
565         if (!block) {
566                 ErrPrint("block is NIL\n");
567                 return LB_STATUS_ERROR_INVALID;
568         }
569
570         info = is_pd ? instance_pd_script(inst) : instance_lb_script(inst);
571         if (!info) {
572                 ErrPrint("info is NIL (%d, %s)\n", is_pd, instance_id(inst));
573                 return LB_STATUS_ERROR_FAULT;
574         }
575
576         if (!info->port) {
577                 ErrPrint("info->port is NIL\n");
578                 return LB_STATUS_ERROR_INVALID;
579         }
580
581         e = script_handler_evas(info);
582         if (e)
583                 info->port->update_signal(info->port_data, e, block->id, block->part, block->data);
584         else
585                 ErrPrint("Evas(nil) id[%s] part[%s] data[%s]\n", block->id, block->part, block->data);
586         return LB_STATUS_SUCCESS;
587 }
588
589 static int update_script_drag(struct inst_info *inst, struct block *block, int is_pd)
590 {
591         struct script_info *info;
592         double dx, dy;
593         Evas *e;
594
595         if (!block || !block->data || !block->part) {
596                 ErrPrint("block or block->data or block->part is NIL\n");
597                 return LB_STATUS_ERROR_INVALID;
598         }
599
600         info = is_pd ? instance_pd_script(inst) : instance_lb_script(inst);
601         if (!info) {
602                 ErrPrint("info is NIL (%d, %s)\n", is_pd, instance_id(inst));
603                 return LB_STATUS_ERROR_FAULT;
604         }
605
606         if (sscanf(block->data, "%lfx%lf", &dx, &dy) != 2) {
607                 ErrPrint("Invalid format of data (DRAG data [%s])\n", block->data);
608                 return LB_STATUS_ERROR_INVALID;
609         }
610
611         if (!info->port) {
612                 ErrPrint("info->port is NIL\n");
613                 return LB_STATUS_ERROR_INVALID;
614         }
615
616         e = script_handler_evas(info);
617         if (e)
618                 info->port->update_drag(info->port_data, e, block->id, block->part, dx, dy);
619         else
620                 ErrPrint("Evas(nil) id[%s] part[%s] %lfx%lf\n", block->id, block->part, dx, dy);
621         return LB_STATUS_SUCCESS;
622 }
623
624 HAPI int script_handler_resize(struct script_info *info, int w, int h)
625 {
626         if (!info) {
627         //|| (info->w == w && info->h == h)) {
628                 ErrPrint("info[%p] resize is ignored\n", info);
629                 return LB_STATUS_SUCCESS;
630         }
631
632         fb_resize(script_handler_fb(info), w, h);
633
634         if (info->port->update_size) {
635                 Evas *e;
636                 e = script_handler_evas(info);
637                 if (e)
638                         info->port->update_size(info->port_data, e, NULL , w, h);
639                 else
640                         ErrPrint("Evas(nil) resize to %dx%d\n", w, h);
641         }
642
643         if (info->w != w || info->h != h) {
644                 if (instance_lb_script(info->inst) == info) {
645                         instance_set_lb_info(info->inst, w, h, PRIORITY_NO_CHANGE, CONTENT_NO_CHANGE, TITLE_NO_CHANGE);
646                 } else if (instance_pd_script(info->inst) == info) {
647                         instance_set_pd_info(info->inst, w, h);
648                 } else {
649                         ErrPrint("Script is not known\n");
650                 }
651         }
652
653         info->w = w;
654         info->h = h;
655
656         return LB_STATUS_SUCCESS;
657 }
658
659 static int update_info(struct inst_info *inst, struct block *block, int is_pd)
660 {
661         struct script_info *info;
662
663         if (!block || !block->part || !block->data) {
664                 ErrPrint("block or block->part or block->data is NIL\n");
665                 return LB_STATUS_ERROR_INVALID;
666         }
667
668         info = is_pd ? instance_pd_script(inst) : instance_lb_script(inst);
669         if (!info) {
670                 ErrPrint("info is NIL (%d, %s)\n", is_pd, instance_id(inst));
671                 return LB_STATUS_ERROR_FAULT;
672         }
673
674         if (!info->port) {
675                 ErrPrint("info->port is NIL\n");
676                 return LB_STATUS_ERROR_INVALID;
677         }
678
679         if (!strcasecmp(block->part, INFO_SIZE)) {
680                 Evas_Coord w, h;
681
682                 if (sscanf(block->data, "%dx%d", &w, &h) != 2) {
683                         ErrPrint("Invalid format for SIZE(%s)\n", block->data);
684                         return LB_STATUS_ERROR_INVALID;
685                 }
686
687                 if (!block->id) {
688                         script_handler_resize(info, w, h);
689                 } else {
690                         Evas *e;
691                         e = script_handler_evas(info);
692                         if (e)
693                                 info->port->update_size(info->port_data, e, block->id, w, h);
694                         else
695                                 ErrPrint("Evas(nil): id[%s] %dx%d\n", block->id, w, h);
696                 }
697         } else if (!strcasecmp(block->part, INFO_CATEGORY)) {
698                 Evas *e;
699                 e = script_handler_evas(info);
700                 if (e)
701                         info->port->update_category(info->port_data, e, block->id, block->data);
702                 else
703                         ErrPrint("Evas(nil): id[%s] data[%s]\n", block->id, block->data);
704         }
705
706         return LB_STATUS_SUCCESS;
707 }
708
709 HAPI int script_handler_parse_desc(const char *pkgname, const char *id, const char *descfile, int is_pd)
710 {
711         struct inst_info *inst;
712         FILE *fp;
713         int ch;
714         int lineno;
715         enum state {
716                 UNKNOWN = 0x10,
717                 BLOCK_OPEN = 0x11,
718                 FIELD = 0x12,
719                 VALUE = 0x13,
720                 BLOCK_CLOSE = 0x14,
721
722                 VALUE_TYPE = 0x00,
723                 VALUE_PART = 0x01,
724                 VALUE_DATA = 0x02,
725                 VALUE_FILE = 0x03,
726                 VALUE_OPTION = 0x04,
727                 VALUE_ID = 0x05,
728                 VALUE_TARGET = 0x06,
729         };
730         const char *field_name[] = {
731                 "type",
732                 "part",
733                 "data",
734                 "file",
735                 "option",
736                 "id",
737                 "target",
738                 NULL
739         };
740         enum state state;
741         register int field_idx;
742         register int idx = 0;
743         register int i;
744         struct block *block;
745         struct {
746                 const char *type;
747                 int (*handler)(struct inst_info *inst, struct block *block, int is_pd);
748         } handlers[] = {
749                 {
750                         .type = TYPE_COLOR,
751                         .handler = update_script_color,
752                 },
753                 {
754                         .type = TYPE_TEXT,
755                         .handler = update_script_text,
756                 },
757                 {
758                         .type = TYPE_IMAGE,
759                         .handler = update_script_image,
760                 },
761                 {
762                         .type = TYPE_EDJE,
763                         .handler = update_script_script,
764                 },
765                 {
766                         .type = TYPE_SIGNAL,
767                         .handler = update_script_signal,
768                 },
769                 {
770                         .type = TYPE_DRAG,
771                         .handler = update_script_drag,
772                 },
773                 {
774                         .type = TYPE_INFO,
775                         .handler = update_info,
776                 },
777                 {
778                         .type = TYPE_ACCESS,
779                         .handler = update_access,
780                 },
781                 {
782                         .type = NULL,
783                         .handler = NULL,
784                 },
785         };
786
787         block = NULL;
788         inst = package_find_instance_by_id(pkgname, id);
789         if (!inst) {
790                 ErrPrint("Instance is not exists\n");
791                 return LB_STATUS_ERROR_NOT_EXIST;
792         }
793
794         fp = fopen(descfile, "rt");
795         if (!fp) {
796                 ErrPrint("Error: %s [%s]\n", descfile, strerror(errno));
797                 return LB_STATUS_ERROR_IO;
798         }
799
800         state = UNKNOWN;
801         field_idx = 0;
802         lineno = 1;
803
804         block = NULL;
805         while (!feof(fp)) {
806                 ch = getc(fp);
807                 if (ch == '\n')
808                         lineno++;
809
810                 switch (state) {
811                 case UNKNOWN:
812                         if (ch == '{') {
813                                 state = BLOCK_OPEN;
814                                 break;
815                         }
816
817                         if (!isspace(ch) && ch != EOF) {
818                                 ErrPrint("%d: Syntax error: Desc is not started with '{' or space - (%c = 0x%x)\n", lineno, ch, ch);
819                                 fclose(fp);
820                                 return LB_STATUS_ERROR_INVALID;
821                         }
822                         break;
823
824                 case BLOCK_OPEN:
825                         if (isblank(ch))
826                                 break;
827
828                         if (ch != '\n') {
829                                 ErrPrint("%d: Syntax error: New line must has to be started right after '{'\n", lineno);
830                                 goto errout;
831                         }
832
833                         block = calloc(1, sizeof(*block));
834                         if (!block) {
835                                 ErrPrint("Heap: %s\n", strerror(errno));
836                                 fclose(fp);
837                                 return LB_STATUS_ERROR_MEMORY;
838                         }
839
840                         state = FIELD;
841                         idx = 0;
842                         field_idx = 0;
843                         break;
844
845                 case FIELD:
846                         if (isspace(ch))
847                                 break;
848
849                         if (ch == '}') {
850                                 state = BLOCK_CLOSE;
851                                 break;
852                         }
853
854                         if (ch == '=') {
855                                 if (field_name[field_idx][idx] != '\0') {
856                                         ErrPrint("%d: Syntax error: Unrecognized field\n", lineno);
857                                         goto errout;
858                                 }
859
860                                 switch (field_idx) {
861                                 case 0:
862                                         state = VALUE_TYPE;
863                                         if (block->type) {
864                                                 DbgFree(block->type);
865                                                 block->type = NULL;
866                                                 block->type_len = 0;
867                                         }
868                                         idx = 0;
869                                         break;
870                                 case 1:
871                                         state = VALUE_PART;
872                                         if (block->part) {
873                                                 DbgFree(block->part);
874                                                 block->part = NULL;
875                                                 block->part_len = 0;
876                                         }
877                                         idx = 0;
878                                         break;
879                                 case 2:
880                                         state = VALUE_DATA;
881                                         if (block->data) {
882                                                 DbgFree(block->data);
883                                                 block->data = NULL;
884                                                 block->data_len = 0;
885                                         }
886                                         idx = 0;
887                                         break;
888                                 case 3:
889                                         state = VALUE_FILE;
890                                         if (block->file) {
891                                                 DbgFree(block->file);
892                                                 block->file = NULL;
893                                                 block->file_len = 0;
894                                         }
895                                         idx = 0;
896                                         break;
897                                 case 4:
898                                         state = VALUE_OPTION;
899                                         if (block->option) {
900                                                 DbgFree(block->option);
901                                                 block->option = NULL;
902                                                 block->option_len = 0;
903                                         }
904                                         idx = 0;
905                                         break;
906                                 case 5:
907                                         state = VALUE_ID;
908                                         if (block->id) {
909                                                 DbgFree(block->id);
910                                                 block->id = NULL;
911                                                 block->id_len = 0;
912                                         }
913                                         idx = 0;
914                                         break;
915                                 case 6:
916                                         state = VALUE_TARGET;
917                                         if (block->target_id) {
918                                                 DbgFree(block->target_id);
919                                                 block->target_id = NULL;
920                                                 block->target_len = 0;
921                                         }
922                                         idx = 0;
923                                         break;
924                                 default:
925                                         ErrPrint("%d: Syntax error: Unrecognized field\n", lineno);
926                                         goto errout;
927                                 }
928
929                                 break;
930                         }
931
932                         if (ch == '\n')
933                                 goto errout;
934
935                         if (field_name[field_idx][idx] != ch) {
936                                 ungetc(ch, fp);
937                                 if (ch == '\n')
938                                         lineno--;
939
940                                 while (--idx >= 0)
941                                         ungetc(field_name[field_idx][idx], fp);
942
943                                 field_idx++;
944                                 if (field_name[field_idx] == NULL) {
945                                         ErrPrint("%d: Syntax error: Unrecognized field\n", lineno);
946                                         goto errout;
947                                 }
948
949                                 idx = 0;
950                                 break;
951                         }
952
953                         idx++;
954                         break;
955
956                 case VALUE_TYPE:
957                         if (idx == block->type_len) {
958                                 char *tmp;
959                                 block->type_len += ADDEND;
960                                 tmp = realloc(block->type, block->type_len);
961                                 if (!tmp) {
962                                         ErrPrint("Heap: %s\n", strerror(errno));
963                                         goto errout;
964                                 }
965                                 block->type = tmp;
966                         }
967
968                         if (ch == '\n') {
969                                 block->type[idx] = '\0';
970                                 state = FIELD;
971                                 idx = 0;
972                                 field_idx = 0;
973                                 break;
974                         }
975
976                         block->type[idx] = ch;
977                         idx++;
978                         break;
979
980                 case VALUE_PART:
981                         if (idx == block->part_len) {
982                                 char *tmp;
983                                 block->part_len += ADDEND;
984                                 tmp = realloc(block->part, block->part_len);
985                                 if (!tmp) {
986                                         ErrPrint("Heap: %s\n", strerror(errno));
987                                         goto errout;
988                                 }
989                                 block->part = tmp;
990                         }
991
992                         if (ch == '\n') {
993                                 block->part[idx] = '\0';
994                                 state = FIELD;
995                                 idx = 0;
996                                 field_idx = 0;
997                                 break;
998                         }
999
1000                         block->part[idx] = ch;
1001                         idx++;
1002                         break;
1003
1004                 case VALUE_DATA:
1005                         if (idx == block->data_len) {
1006                                 char *tmp;
1007                                 block->data_len += ADDEND;
1008                                 tmp = realloc(block->data, block->data_len);
1009                                 if (!tmp) {
1010                                         ErrPrint("Heap: %s\n", strerror(errno));
1011                                         goto errout;
1012                                 }
1013                                 block->data = tmp;
1014                         }
1015
1016                         if (ch == '\n') {
1017                                 block->data[idx] = '\0';
1018                                 state = FIELD;
1019                                 idx = 0;
1020                                 field_idx = 0;
1021                                 break;
1022                         }
1023
1024                         block->data[idx] = ch;
1025                         idx++;
1026                         break;
1027
1028                 case VALUE_FILE:
1029                         if (idx == block->file_len) {
1030                                 char *tmp;
1031                                 block->file_len += ADDEND;
1032                                 tmp = realloc(block->file, block->file_len);
1033                                 if (!tmp) {
1034                                         ErrPrint("Heap: %s\n", strerror(errno));
1035                                         goto errout;
1036                                 }
1037                                 block->file = tmp;
1038                         }
1039
1040                         if (ch == '\n') {
1041                                 block->file[idx] = '\0';
1042                                 state = FIELD;
1043                                 idx = 0;
1044                                 field_idx = 0;
1045                                 break;
1046                         }
1047
1048                         block->file[idx] = ch;
1049                         idx++;
1050                         break;
1051
1052                 case VALUE_OPTION:
1053                         if (idx == block->option_len) {
1054                                 char *tmp;
1055                                 block->option_len += ADDEND;
1056                                 tmp = realloc(block->option, block->option_len);
1057                                 if (!tmp) {
1058                                         ErrPrint("Heap: %s\n", strerror(errno));
1059                                         goto errout;
1060                                 }
1061                                 block->option = tmp;
1062                         }
1063
1064                         if (ch == '\n') {
1065                                 block->option[idx] = '\0';
1066                                 state = FIELD;
1067                                 idx = 0;
1068                                 field_idx = 0;
1069                                 break;
1070                         }
1071
1072                         block->option[idx] = ch;
1073                         idx++;
1074                         break;
1075                 case VALUE_ID:
1076                         if (idx == block->id_len) {
1077                                 char *tmp;
1078                                 block->id_len += ADDEND;
1079                                 tmp = realloc(block->id, block->id_len);
1080                                 if (!tmp) {
1081                                         ErrPrint("Heap: %s\n", strerror(errno));
1082                                         goto errout;
1083                                 }
1084                                 block->id = tmp;
1085                         }
1086
1087                         if (ch == '\n') {
1088                                 block->id[idx] = '\0';
1089                                 state = FIELD;
1090                                 idx = 0;
1091                                 field_idx = 0;
1092                                 break;
1093                         }
1094
1095                         block->id[idx] = ch;
1096                         idx++;
1097                         break;
1098                 case VALUE_TARGET:
1099                         if (idx == block->target_len) {
1100                                 char *tmp;
1101                                 block->target_len += ADDEND;
1102                                 tmp = realloc(block->target_id, block->target_len);
1103                                 if (!tmp) {
1104                                         ErrPrint("Heap: %s\n", strerror(errno));
1105                                         goto errout;
1106                                 }
1107                                 block->target_id = tmp;
1108                         }
1109
1110                         if (ch == '\n') {
1111                                 block->target_id[idx] = '\0';
1112                                 state = FIELD;
1113                                 idx = 0;
1114                                 field_idx = 0;
1115                                 break;
1116                         }
1117
1118                         block->target_id[idx] = ch;
1119                         idx++;
1120                         break;
1121                 case BLOCK_CLOSE:
1122                         if (!block->file) {
1123                                 block->file = strdup(util_uri_to_path(id));
1124                                 if (!block->file) {
1125                                         ErrPrint("Heap: %s\n", strerror(errno));
1126                                         goto errout;
1127                                 }
1128                         }
1129
1130                         i = 0;
1131                         while (handlers[i].type) {
1132                                 if (!strcasecmp(handlers[i].type, block->type)) {
1133                                         handlers[i].handler(inst, block, is_pd);
1134                                         break;
1135                                 }
1136                                 i++;
1137                         }
1138
1139                         if (!handlers[i].type)
1140                                 ErrPrint("%d: Unknown block type: %s\n", lineno, block->type);
1141
1142                         DbgFree(block->file);
1143                         DbgFree(block->type);
1144                         DbgFree(block->part);
1145                         DbgFree(block->data);
1146                         DbgFree(block->option);
1147                         DbgFree(block->id);
1148                         DbgFree(block->target_id);
1149                         DbgFree(block);
1150                         block = NULL;
1151
1152                         state = UNKNOWN;
1153                         break;
1154
1155                 default:
1156                         break;
1157                 } /* switch */
1158         } /* while */
1159
1160         if (state != UNKNOWN) {
1161                 ErrPrint("%d: Unknown state\n", lineno);
1162                 goto errout;
1163         }
1164
1165         fclose(fp);
1166         return LB_STATUS_SUCCESS;
1167
1168 errout:
1169         ErrPrint("Parse error at %d file %s\n", lineno, util_basename(descfile));
1170         if (block) {
1171                 DbgFree(block->file);
1172                 DbgFree(block->type);
1173                 DbgFree(block->part);
1174                 DbgFree(block->data);
1175                 DbgFree(block->option);
1176                 DbgFree(block->id);
1177                 DbgFree(block->target_id);
1178                 DbgFree(block);
1179         }
1180         fclose(fp);
1181         return LB_STATUS_ERROR_INVALID;
1182 }
1183
1184 HAPI int script_init(void)
1185 {
1186         struct script_port *item;
1187         struct dirent *ent;
1188         DIR *dir;
1189         char *path;
1190         int pathlen;
1191
1192         if (!strcasecmp(PROVIDER_METHOD, "shm"))
1193                 s_info.env_buf_type = BUFFER_TYPE_SHM;
1194         else if (!strcasecmp(PROVIDER_METHOD, "pixmap"))
1195                 s_info.env_buf_type = BUFFER_TYPE_PIXMAP;
1196
1197         dir = opendir(SCRIPT_PORT_PATH);
1198         if (!dir) {
1199                 ErrPrint("Error: %s\n", strerror(errno));
1200                 return LB_STATUS_ERROR_IO;
1201         }
1202
1203         while ((ent = readdir(dir))) {
1204                 if (ent->d_name[0] == '.')
1205                         continue;
1206
1207                 pathlen = strlen(ent->d_name) + strlen(SCRIPT_PORT_PATH) + 1;
1208                 path = malloc(pathlen);
1209                 if (!path) {
1210                         ErrPrint("Heap: %s %d\n", strerror(errno), pathlen);
1211                         closedir(dir);
1212                         return LB_STATUS_ERROR_MEMORY;
1213                 }
1214
1215                 snprintf(path, pathlen, "%s%s", SCRIPT_PORT_PATH, ent->d_name);
1216
1217                 item = malloc(sizeof(*item));
1218                 if (!item) {
1219                         ErrPrint("Heap: %s\n", strerror(errno));
1220                         DbgFree(path);
1221                         closedir(dir);
1222                         return LB_STATUS_ERROR_MEMORY;
1223                 }
1224
1225                 DbgPrint("Open SCRIPT PORT: %s\n", path);
1226                 item->handle = dlopen(path, RTLD_GLOBAL | RTLD_NOW | RTLD_DEEPBIND);
1227                 DbgFree(path);
1228                 if (!item->handle) {
1229                         ErrPrint("Error: %s\n", dlerror());
1230                         DbgFree(item);
1231                         closedir(dir);
1232                         return LB_STATUS_ERROR_FAULT;
1233                 }
1234
1235                 item->magic_id = dlsym(item->handle, "script_magic_id");
1236                 if (!item->magic_id)
1237                         goto errout;
1238
1239                 DbgPrint("SCRIPT PORT magic id: %s\n", item->magic_id());
1240
1241                 item->update_color = dlsym(item->handle, "script_update_color");
1242                 if (!item->update_color)
1243                         goto errout;
1244
1245                 item->update_text = dlsym(item->handle, "script_update_text");
1246                 if (!item->update_text)
1247                         goto errout;
1248
1249                 item->update_image = dlsym(item->handle, "script_update_image");
1250                 if (!item->update_image)
1251                         goto errout;
1252
1253                 item->update_access = dlsym(item->handle, "script_update_access");
1254                 if (!item->update_access)
1255                         goto errout;
1256
1257                 item->update_script = dlsym(item->handle, "script_update_script");
1258                 if (!item->update_script)
1259                         goto errout;
1260
1261                 item->update_signal = dlsym(item->handle, "script_update_signal");
1262                 if (!item->update_signal)
1263                         goto errout;
1264
1265                 item->update_drag = dlsym(item->handle, "script_update_drag");
1266                 if (!item->update_drag)
1267                         goto errout;
1268
1269                 item->update_size = dlsym(item->handle, "script_update_size");
1270                 if (!item->update_size)
1271                         goto errout;
1272
1273                 item->update_category = dlsym(item->handle, "script_update_category");
1274                 if (!item->update_category)
1275                         goto errout;
1276
1277                 item->create = dlsym(item->handle, "script_create");
1278                 if (!item->create)
1279                         goto errout;
1280
1281                 item->destroy = dlsym(item->handle, "script_destroy");
1282                 if (!item->destroy)
1283                         goto errout;
1284
1285                 item->load = dlsym(item->handle, "script_load");
1286                 if (!item->load)
1287                         goto errout;
1288
1289                 item->unload = dlsym(item->handle, "script_unload");
1290                 if (!item->unload)
1291                         goto errout;
1292
1293                 item->init = dlsym(item->handle, "script_init");
1294                 if (!item->init)
1295                         goto errout;
1296
1297                 item->fini = dlsym(item->handle, "script_fini");
1298                 if (!item->fini)
1299                         goto errout;
1300
1301                 item->feed_event = dlsym(item->handle, "script_feed_event");
1302                 if (!item->feed_event)
1303                         goto errout;
1304
1305                 if (item->init() < 0) {
1306                         ErrPrint("Failed to initialize script engine\n");
1307                         goto errout;
1308                 }
1309
1310                 s_info.script_port_list = eina_list_append(s_info.script_port_list, item);
1311         }
1312
1313         closedir(dir);
1314         return LB_STATUS_SUCCESS;
1315
1316 errout:
1317         ErrPrint("Error: %s\n", dlerror());
1318         dlclose(item->handle);
1319         DbgFree(item);
1320         closedir(dir);
1321         return LB_STATUS_ERROR_FAULT;
1322 }
1323
1324 HAPI int script_fini(void)
1325 {
1326         struct script_port *item;
1327         /*!
1328          * \TODO: Release all handles
1329          */
1330         EINA_LIST_FREE(s_info.script_port_list, item) {
1331                 item->fini();
1332                 dlclose(item->handle);
1333                 DbgFree(item);
1334         }
1335
1336         return 0;
1337 }
1338
1339 HAPI int script_handler_update_pointer(struct script_info *info, int x, int y, int down)
1340 {
1341         if (!info)
1342                 return LB_STATUS_SUCCESS;
1343
1344         info->x = x;
1345         info->y = y;
1346
1347         if (down == 0)
1348                 info->down = 0;
1349         else if (down == 1)
1350                 info->down = 1;
1351
1352         return LB_STATUS_SUCCESS;
1353 }
1354
1355 HAPI int script_handler_feed_event(struct script_info *info, int event, double timestamp)
1356 {
1357         Evas *e;
1358
1359         if (!info->port) {
1360                 ErrPrint("info->port is NIL\n");
1361                 return LB_STATUS_ERROR_INVALID;
1362         }
1363
1364         e = script_handler_evas(info);
1365         if (!e) {
1366                 ErrPrint("Evas is not exists\n");
1367                 return LB_STATUS_ERROR_FAULT;
1368         }
1369
1370         return info->port->feed_event(info->port_data, e, event, info->x, info->y, timestamp);
1371 }
1372
1373 /* End of a file */