From aac41d6ff049111995f8185313d7da4c9190ac29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Briano?= Date: Thu, 2 Dec 2010 18:20:34 +0000 Subject: [PATCH] Edje_Edit has been taught the basics of Embryo scripting. It is possible now to call a recompile of the script, which if it doesn't fail, will also update the running Embryo VM. Saving the object, when opened from a file compiled with a sufficiently new edje_cc (early this week, I think), will generate the source including the scripts in their right place. It's still missing a proper report of errors during the script build, but that will come later. SVN revision: 55160 --- legacy/edje/src/lib/Edje_Edit.h | 67 ++- legacy/edje/src/lib/edje_edit.c | 838 ++++++++++++++++++++++++++++++-- 2 files changed, 853 insertions(+), 52 deletions(-) diff --git a/legacy/edje/src/lib/Edje_Edit.h b/legacy/edje/src/lib/Edje_Edit.h index 1ee7b4f74d..f1451631e7 100644 --- a/legacy/edje/src/lib/Edje_Edit.h +++ b/legacy/edje/src/lib/Edje_Edit.h @@ -3381,13 +3381,74 @@ EAPI Eina_Bool edje_edit_program_filter_part_set(Evas_Object *obj, const char *p */ //@{ /** - * Get the script for the given object, + * Get the Embryo script for the group of the given object. + * + * Get the shared script for the group under edition. Shared script means + * the script {} block for the group, not counting what's in each program. + * It returns a malloc'd duplicate of the code, so users are free to modify + * the contents directly and they should remember to free() it when done. + * NULL will be returned if there's no script or an error occurred. * * @param obj Object being edited. * - * @return The script name. + * @return The shared script code for this group. */ -EAPI const char * edje_edit_script_get(Evas_Object *obj); +EAPI char *edje_edit_script_get(Evas_Object *obj); + +/** + * Set the code for the group script. + * + * Set the Embryo source code for the shared script of the edited group. + * Note that changing the code itself will not update the running VM, you + * need to call edje_edit_script_compile for it to get updated. + * + * @param obj The object being edited + * @param code The Embryo source + */ +EAPI void edje_edit_script_set(Evas_Object *obj, const char *code); + +/** + * Get the Embryo script for the given program. + * + * Get the script code for the given program. Like the group script, this + * function returns a duplicate of the code that the user can modify at will + * and must free when done using it. + * NULL will be returned if the program doesn't exist, doesn't have any + * script or is not of type script. + * + * @param obj Object being edited + * @param prog Program name + * + * @return The program script code + */ +EAPI char *edje_edit_script_program_get(Evas_Object *obj, const char *prog); + +/** + * Set the Embryo script for the given program. + * + * Set the Embryo source code for the program @p prog. It must be an + * existing program of type EDJE_ACTION_TYPE_SCRIPT, or the function + * will fail and do nothing. + * Note that changing the code itself will not update the running VM, you + * need to call edje_edit_script_compile for it to get updated. + * + * @param obj The object being edited + * @param prog The program name. + * @param code The Embryo source + */ +EAPI void edje_edit_script_program_set(Evas_Object *obj, const char *prog, const char *code); + +/** + * Compile the Embryo script for the given object + * + * If required, this function will process all script code for the group and + * build the bytecode, updating the running Embryo VM Program if the build + * is succesful. + * + * @param obj The object being edited + * + */ +EAPI Eina_Bool edje_edit_script_compile(Evas_Object *obj); //@} diff --git a/legacy/edje/src/lib/edje_edit.c b/legacy/edje/src/lib/edje_edit.c index dfb22fda23..16bfc681a2 100644 --- a/legacy/edje/src/lib/edje_edit.c +++ b/legacy/edje/src/lib/edje_edit.c @@ -90,6 +90,28 @@ typedef struct _Edje_Edit Edje_Edit; struct _Edje_Edit { Edje base; + + void *bytecode; + int bytecode_size; + + char *embryo_source; + char *embryo_processed; + Eina_Hash *program_scripts; + + Eina_Bool bytecode_dirty:1; + Eina_Bool embryo_source_dirty:1; + Eina_Bool all_dirty:1; + Eina_Bool script_need_recompile:1; +}; + +typedef struct _Program_Script Program_Script; +struct _Program_Script +{ + int id; + char *code; + char *processed; + Eina_Bool dirty:1; + Eina_Bool delete_me:1; }; static void _edje_edit_smart_add(Evas_Object *obj); @@ -133,23 +155,61 @@ _edje_edit_smart_add(Evas_Object *obj) _edje_edit_parent_sc->base.add(obj); } +static void +_edje_edit_data_clean(Edje_Edit *eed) +{ + free(eed->bytecode); + free(eed->embryo_source); + free(eed->embryo_processed); + + if (eed->program_scripts) + eina_hash_free(eed->program_scripts); + + eed->bytecode = NULL; + eed->embryo_source = NULL; + eed->embryo_processed = NULL; + eed->program_scripts = NULL; + eed->bytecode_size = 0; + eed->bytecode_dirty = EINA_FALSE; + eed->embryo_source_dirty = EINA_FALSE; + eed->all_dirty = EINA_FALSE; + eed->script_need_recompile = EINA_FALSE; +} + static void _edje_edit_smart_del(Evas_Object *obj) { -// Edje_Edit *eed; + Edje_Edit *eed; + + eed = evas_object_smart_data_get(obj); + + _edje_edit_data_clean(eed); -// eed = evas_object_smart_data_get(obj); _edje_edit_parent_sc->base.del(obj); } +static void +_edje_edit_program_script_free(Program_Script *ps) +{ + free(ps->code); + free(ps->processed); + free(ps); +} + static Eina_Bool _edje_edit_smart_file_set(Evas_Object *obj, const char *file, const char *group) { -// Edje_Edit *eed; + Edje_Edit *eed; + Eet_File *ef; + char **keys, buf[64]; + int count, i; + int len = strlen("edje/scripts/embryo/source/"); -// eed = evas_object_smart_data_get(obj); - /* Nothing custom here yet, so we just call the parent function. - * TODO and maybes: + eed = evas_object_smart_data_get(obj); + + _edje_edit_data_clean(eed); + + /* TODO and maybes: * * The whole point of this thing is keep track of stuff such as * strings to free and who knows what, so we need to take care * of those if the file/group changes. @@ -162,7 +222,33 @@ _edje_edit_smart_file_set(Evas_Object *obj, const char *file, const char *group) * (GROUP parts or BOX/TABLE items pointing to non-existent/renamed * groups). */ - return _edje_edit_parent_sc->file_set(obj, file, group); + if (!_edje_edit_parent_sc->file_set(obj, file, group)) + return EINA_FALSE; + + eed->program_scripts = eina_hash_int32_new((Eina_Free_Cb)_edje_edit_program_script_free); + + ef = eet_open(file, EET_FILE_MODE_READ); + + snprintf(buf, sizeof(buf), "edje/scripts/embryo/source/%i", + eed->base.collection->id); + eed->embryo_source = eet_read(ef, buf, &count); + + snprintf(buf, sizeof(buf), "edje/scripts/embryo/source/%i/*", + eed->base.collection->id); + keys = eet_list(ef, buf, &count); + for (i = 0; i < count; i++) + { + Program_Script *ps; + int size; + + ps = calloc(1, sizeof(Program_Script)); + + sscanf(keys[i] + len, "%*i/%i", &ps->id); + ps->code = eet_read(ef, keys[i], &size); + eina_hash_add(eed->program_scripts, &ps->id, ps); + } + + return EINA_TRUE; } static void @@ -205,39 +291,36 @@ _edje_part_description_find_byname(Edje_Edit *eed, const char *part, const char } static int -_edje_image_id_find(Evas_Object *obj, const char *image_name) +_edje_image_id_find(Edje_Edit *eed, const char *image_name) { unsigned int i; - GET_ED_OR_RETURN(-1); - - if (!ed->file) return -1; - if (!ed->file->image_dir) return -1; + if (!eed->base.file) return -1; + if (!eed->base.file->image_dir) return -1; //printf("SEARCH IMAGE %s\n", image_name); - for (i = 0; i < ed->file->image_dir->entries_count; ++i) - if (ed->file->image_dir->entries[i].entry - && !strcmp(image_name, ed->file->image_dir->entries[i].entry)) + for (i = 0; i < eed->base.file->image_dir->entries_count; ++i) + if (eed->base.file->image_dir->entries[i].entry + && !strcmp(image_name, eed->base.file->image_dir->entries[i].entry)) return i; return -1; } static const char * -_edje_image_name_find(Evas_Object *obj, int image_id) +_edje_image_name_find(Edje_Edit *eed, int image_id) { - GET_ED_OR_RETURN(NULL); - - if (!ed->file) return NULL; - if (!ed->file->image_dir) return NULL; + if (!eed->base.file) return NULL; + if (!eed->base.file->image_dir) return NULL; /* Special case for external image */ if (image_id < 0) image_id = -image_id - 1; //printf("SEARCH IMAGE ID %d\n", image_id); - if ((unsigned int) image_id >= ed->file->image_dir->entries_count) return NULL; - return ed->file->image_dir->entries[image_id].entry; + if ((unsigned int) image_id >= eed->base.file->image_dir->entries_count) + return NULL; + return eed->base.file->image_dir->entries[image_id].entry; } static void @@ -819,6 +902,14 @@ _edje_edit_group_references_update(Evas_Object *obj, const char *old_group_name, evas_object_del(part_obj); } +static void +_edje_edit_flag_script_dirty(Edje_Edit *eed, Eina_Bool all) +{ + eed->script_need_recompile = EINA_TRUE; + if (all) + eed->all_dirty = EINA_TRUE; +} + /*****************/ /* GENERAL API */ /*****************/ @@ -990,7 +1081,8 @@ edje_edit_group_del(Evas_Object *obj, const char *group_name) Edje_Part_Collection *g; Eina_List *l; Eet_File *eetf; - char buf[32]; + char buf[64], **keys; + int count; eina_error_set(0); @@ -1043,8 +1135,19 @@ edje_edit_group_del(Evas_Object *obj, const char *group_name) "for writing output", ed->file->path); return EINA_FALSE; } - snprintf(buf, sizeof(buf), "collections/%d", e->id); + snprintf(buf, sizeof(buf), "edje/collections/%d", e->id); eet_delete(eetf, buf); + snprintf(buf, sizeof(buf), "edje/scripts/embryo/compiled/%d", e->id); + eet_delete(eetf, buf); + snprintf(buf, sizeof(buf), "edje/scripts/embryo/source/%d", e->id); + eet_delete(eetf, buf); + snprintf(buf, sizeof(buf), "edje/scripts/embryo/source/%d/*", e->id); + keys = eet_list(eetf, buf, &count); + if (keys) + do { + count--; + eet_delete(eetf, keys[count]); + } while(count); eet_close(eetf); /* Free Group */ @@ -1922,6 +2025,8 @@ edje_edit_part_name_set(Evas_Object *obj, const char* part, const char* new_name _edje_if_string_free(ed, rp->part->name); rp->part->name = (char *)eina_stringshare_add(new_name); + _edje_edit_flag_script_dirty(eed, EINA_TRUE); + return EINA_TRUE; } @@ -2224,6 +2329,8 @@ edje_edit_part_del(Evas_Object *obj, const char* part) ce->count.part--; + _edje_edit_flag_script_dirty(eed, EINA_TRUE); + return EINA_TRUE; } @@ -2297,6 +2404,8 @@ edje_edit_part_restack_below(Evas_Object *obj, const char* part) if (rp->swallowed_object) evas_object_stack_above(rp->swallowed_object, rp->object); + _edje_edit_flag_script_dirty(eed, EINA_TRUE); + return EINA_TRUE; } @@ -2331,6 +2440,8 @@ edje_edit_part_restack_above(Evas_Object *obj, const char* part) if (rp->swallowed_object) evas_object_stack_above(rp->swallowed_object, rp->object); + _edje_edit_flag_script_dirty(eed, EINA_TRUE); + return EINA_TRUE; } @@ -4574,6 +4685,8 @@ edje_edit_image_del(Evas_Object *obj, const char* name) _edje_if_string_free(ed, de->entry); de->entry = NULL; + _edje_edit_flag_script_dirty(eed, EINA_TRUE); + return EINA_TRUE; invalid_image: @@ -4618,7 +4731,9 @@ edje_edit_image_id_get(Evas_Object *obj, const char *image_name) { eina_error_set(0); - return _edje_image_id_find(obj, image_name); + GET_ED_OR_RETURN(-1); + + return _edje_image_id_find(eed, image_name); } EAPI Edje_Edit_Image_Comp @@ -4693,7 +4808,7 @@ EAPI const char * edje_edit_state_image_get(Evas_Object *obj, const char *part, const char *state, double value) { Edje_Part_Description_Image *img; - char *image; + const char *image; eina_error_set(0); @@ -4704,7 +4819,7 @@ edje_edit_state_image_get(Evas_Object *obj, const char *part, const char *state, img = (Edje_Part_Description_Image *) pd; - image = (char *)_edje_image_name_find(obj, img->image.id); + image = _edje_image_name_find(eed, img->image.id); if (!image) return NULL; //printf("GET IMAGE for %s [%s]\n", state, image); @@ -4726,7 +4841,7 @@ edje_edit_state_image_set(Evas_Object *obj, const char *part, const char *state, if (rp->part->type != EDJE_PART_TYPE_IMAGE) return; - id = _edje_image_id_find(obj, image); + id = _edje_image_id_find(eed, image); //printf("SET IMAGE for %s [%s]\n", state, image); img = (Edje_Part_Description_Image *) pd; @@ -4755,7 +4870,7 @@ edje_edit_state_tweens_list_get(Evas_Object *obj, const char *part, const char * for (i = 0; i < img->image.tweens_count; ++i) { - name = _edje_image_name_find(obj, img->image.tweens[i]->id); + name = _edje_image_name_find(eed, img->image.tweens[i]->id); //printf(" t: %s\n", name); tweens = eina_list_append(tweens, eina_stringshare_add(name)); } @@ -4778,7 +4893,7 @@ edje_edit_state_tween_add(Evas_Object *obj, const char *part, const char *state, if (rp->part->type != EDJE_PART_TYPE_IMAGE) return EINA_FALSE; - id = _edje_image_id_find(obj, tween); + id = _edje_image_id_find(eed, tween); if (id < EINA_FALSE) return 0; /* alloc Edje_Part_Image_Id */ @@ -4821,7 +4936,7 @@ edje_edit_state_tween_del(Evas_Object *obj, const char *part, const char *state, if (!img->image.tweens_count) return EINA_FALSE; - search = _edje_image_id_find(obj, tween); + search = _edje_image_id_find(eed, tween); if (search < 0) return EINA_FALSE; for (i = 0; i < img->image.tweens_count; ++i) @@ -4935,6 +5050,21 @@ edje_edit_state_image_border_fill_set(Evas_Object *obj, const char *part, const /******************/ /* PROGRAMS API */ /******************/ +static int +_edje_program_id_find(Edje_Edit *eed, const char *program) +{ + Edje_Program *epr; + int i; + + for (i = 0; i < eed->base.table_programs_size; i++) + { + epr = eed->base.table_programs[i]; + if (epr->name && !strcmp(epr->name, program)) + return epr->id; + } + return -1; +} + static Edje_Program * _edje_program_get_byname(Evas_Object *obj, const char *prog_name) { @@ -5049,6 +5179,7 @@ edje_edit_program_del(Evas_Object *obj, const char *prog) Edje_Program_After *pa; Edje_Part_Collection *pc; Edje_Program *p; + Program_Script *ps, *old_ps; int id, i; int old_id = -1; @@ -5073,6 +5204,37 @@ edje_edit_program_del(Evas_Object *obj, const char *prog) ed->table_programs[epr->id]->id = epr->id; } + ps = eina_hash_find(eed->program_scripts, &id); + old_ps = eina_hash_find(eed->program_scripts, &old_id); + if (old_ps) + { + if (!ps) + { + ps = _alloc(sizeof(Program_Script)); + ps->id = id; + eina_hash_add(eed->program_scripts, &id, ps); + } + else + { + free(ps->code); + free(ps->processed); + ps->processed = NULL; + ps->delete_me = EINA_FALSE; + } + ps->code = old_ps->code; + old_ps->code = NULL; + free(old_ps->processed); + old_ps->processed = NULL; + ps->dirty = EINA_TRUE; + old_ps->dirty = EINA_FALSE; + old_ps->delete_me = EINA_TRUE; + } + else if (ps) + { + ps->dirty = EINA_FALSE; + ps->delete_me = EINA_TRUE; + } + //Free Edje_Program _edje_if_string_free(ed, epr->name); _edje_if_string_free(ed, epr->signal); @@ -5105,7 +5267,10 @@ edje_edit_program_del(Evas_Object *obj, const char *prog) if (pa->id == old_id) pa->id = id; else if (pa->id == id) - p->after = eina_list_remove_list(p->after, l); + { + p->after = eina_list_remove_list(p->after, l); + free(pa); + } } /* check in targets */ if (p->action == EDJE_ACTION_TYPE_ACTION_STOP) @@ -5117,11 +5282,16 @@ edje_edit_program_del(Evas_Object *obj, const char *prog) if (pt->id == old_id) pt->id = id; else if (pt->id == id) - p->targets = eina_list_remove_list(p->targets, l); + { + p->targets = eina_list_remove_list(p->targets, l); + free(pt); + } } } } + _edje_edit_flag_script_dirty(eed, EINA_TRUE); + return EINA_TRUE; } @@ -5164,6 +5334,8 @@ edje_edit_program_name_set(Evas_Object *obj, const char *prog, const char* new_n _edje_if_string_free(ed, epr->name); epr->name = eina_stringshare_add(new_name); + _edje_edit_flag_script_dirty(eed, EINA_TRUE); + return EINA_TRUE; } @@ -5503,13 +5675,49 @@ edje_edit_program_action_get(Evas_Object *obj, const char *prog) EAPI Eina_Bool edje_edit_program_action_set(Evas_Object *obj, const char *prog, Edje_Action_Type action) { + Program_Script *ps; + eina_error_set(0); + GET_ED_OR_RETURN(EINA_FALSE); GET_EPR_OR_RETURN(EINA_FALSE); //printf("SET ACTION for program: %s [%d]\n", prog, action); if (action >= EDJE_ACTION_TYPE_LAST) return EINA_FALSE; + if ((Edje_Action_Type)epr->action == action) + return EINA_TRUE; + + if (action == EDJE_ACTION_TYPE_SCRIPT) + { + ps = eina_hash_find(eed->program_scripts, &epr->id); + if (!ps) + { + ps = _alloc(sizeof(Program_Script)); + if (!ps) + return EINA_FALSE; + } + ps->id = epr->id; + ps->code = strdup(""); + ps->dirty = EINA_TRUE; + ps->delete_me = EINA_FALSE; + eina_hash_set(eed->program_scripts, &ps->id, ps); + _edje_edit_flag_script_dirty(eed, EINA_FALSE); + } + if (epr->action == EDJE_ACTION_TYPE_SCRIPT) + { + ps = eina_hash_find(eed->program_scripts, &epr->id); + if (ps) + { + free(ps->code); + free(ps->processed); + ps->code = ps->processed = NULL; + ps->dirty = EINA_FALSE; + ps->delete_me = EINA_TRUE; + _edje_edit_flag_script_dirty(eed, EINA_FALSE); + } + } + epr->action = action; return EINA_TRUE; } @@ -5797,25 +6005,471 @@ edje_edit_program_api_description_set(Evas_Object *obj, const char *prog, const /*************************/ /* EMBRYO SCRIPTS API */ /*************************/ -EAPI const char * +EAPI char * edje_edit_script_get(Evas_Object *obj) { - Embryo_Program *script = NULL; - eina_error_set(0); GET_ED_OR_RETURN(NULL); if (!ed->collection) return NULL; - if (!ed->collection->script) return NULL; + if (!eed->embryo_source) return NULL; - script = ed->collection->script; - - printf("Get Script [%p] %d\n", script, embryo_program_recursion_get(script)); - - return "Not yet complete..."; + return strdup(eed->embryo_source); } +EAPI void +edje_edit_script_set(Evas_Object *obj, const char *code) +{ + eina_error_set(0); + + GET_ED_OR_RETURN(); + + free(eed->embryo_source); + free(eed->embryo_processed); + + if (code) + eed->embryo_source = strdup(code); + else + eed->embryo_source = NULL; + eed->embryo_processed = NULL; + + eed->embryo_source_dirty = EINA_TRUE; + + _edje_edit_flag_script_dirty(eed, EINA_FALSE); +} + +EAPI char * +edje_edit_script_program_get(Evas_Object *obj, const char *prog) +{ + Program_Script *ps; + + eina_error_set(0); + + GET_ED_OR_RETURN(NULL); + GET_EPR_OR_RETURN(NULL); + + if (epr->action != EDJE_ACTION_TYPE_SCRIPT) + return NULL; + + ps = eina_hash_find(eed->program_scripts, prog); + if (!ps) /* mmm? it should be there, even if empty */ + return NULL; + + return ps->code ? strdup(ps->code) : NULL; +} + +EAPI void +edje_edit_script_program_set(Evas_Object *obj, const char *prog, const char *code) +{ + Program_Script *ps; + + eina_error_set(0); + + GET_ED_OR_RETURN(); + GET_EPR_OR_RETURN(); + + if (epr->action != EDJE_ACTION_TYPE_SCRIPT) + return; + + ps = eina_hash_find(eed->program_scripts, prog); + if (!ps) /* ???? how so? */ + return; + + free(ps->code); + free(ps->processed); + + if (code) + ps->code = strdup(code); + else + ps->code = NULL; + ps->processed = NULL; + ps->dirty = EINA_TRUE; + + _edje_edit_flag_script_dirty(eed, EINA_FALSE); +} + +static int +__part_replace(Edje_Edit *eed, char *pcode, char *name) +{ + int id; + + id = _edje_part_id_find((Edje *)eed, name); + if (id < 0) + return 0; + return eina_convert_itoa(id, pcode); +} + +static int +__program_replace(Edje_Edit *eed, char *pcode, char *name) +{ + int id; + + id = _edje_program_id_find(eed, name); + if (id < 0) + return 0; + return eina_convert_itoa(id, pcode); +} + +static int +__group_replace(Edje_Edit *eed __UNUSED__, char *pcode, char *name) +{ + strcpy(pcode, name); + return strlen(name) + 1; +} + +static int +__image_replace(Edje_Edit *eed, char *pcode, char *name) +{ + int id; + + id = _edje_image_id_find(eed, name); + if (id < 0) + return 0; + return eina_convert_itoa(id, pcode); +} + +static char * +_edje_edit_script_process(Edje_Edit *eed, char *code) +{ + char *pcode, *psrc, *pdst; + int codesize, pcodesize; + int quoted = 0, escaped = 0; + Eina_Bool success = EINA_TRUE; + + codesize = strlen(code); + pcode = malloc(codesize + 1); + if (!pcode) + return NULL; + + pcodesize = 0; + psrc = code; + pdst = pcode; + while (*psrc) + { + if (!quoted) + { + char *ptr = NULL; + int (*func)(Edje_Edit *, char *, char *); + + if (*psrc == 'P') + { + if (!strncmp(psrc, "PART:\"", 6)) + { + psrc += 6; + ptr = psrc; + func = __part_replace; + } + else if (!strncmp(psrc, "PROGRAM:\"", 9)) + { + psrc += 9; + ptr = psrc; + func = __program_replace; + } + } + else if (*psrc == 'G') + { + if (!strncmp(psrc, "GROUP:\"", 7)) + { + psrc += 7; + ptr = psrc; + func = __group_replace; + } + } + else if (*psrc == 'I') + { + if (!strncmp(psrc, "IMAGE:\"", 7)) + { + psrc += 7; + ptr = psrc; + func = __image_replace; + } + } + else if (*psrc == '#') + { + while (*psrc) + if (*psrc == '\n') + break; + continue; + } + else if (*psrc == '\"') + quoted = 1; + + if (ptr) + { + int i = 0, inesc = 0; + char *name; + while (*psrc) + { + if (!inesc) + { + if (*psrc == '\\') + inesc = 1; + else if (*psrc == '\"') + { + /* string concatenation as in "foo""bar" */ + if (*(psrc + 1) != '\"') + { + psrc++; + break; + } + else + psrc++; + } + } + else + inesc = 0; + psrc++; + } + name = alloca(psrc - ptr); + inesc = 0; + while (*ptr) + { + if (!inesc) + { + if (*ptr == '\\') + inesc = 1; + else if (*ptr == '\"') + { + if (*(ptr + 1) == '\"') + ptr++; + else + { + name[i] = 0; + break; + } + } + else + { + name[i] = *ptr; + name[i + 1] = 0; + i++; + } + } + else + inesc = 0; + ptr++; + } + i = func(eed, pdst, name); + if (!i) + { + /* something was not found, report it, keep track of + * it to inform of non-existant referenced things + * and continue processing to find all of those errors + */ + success = EINA_FALSE; + } + else + { + pcodesize += i; + pdst += i; + } + /* replaced reference for the right value, now go + * to the next iteration */ + continue; + } + } + else + { + if (!escaped) + { + if (*psrc == '\"') + quoted = 0; + else if (*psrc == '\\') + escaped = 1; + } + else if (escaped) + escaped = 0; + } + *pdst = *psrc; + pdst++; + psrc++; + pcodesize++; + } + + if (!success) + { + free(pcode); + return NULL; + } + + if (pcodesize < codesize) + pcode = realloc(pcode, pcodesize + 1); + pcode[pcodesize] = 0; + + return pcode; +} + +static Eina_Bool +_edje_edit_embryo_rebuild(Edje_Edit *eed) +{ + FILE *f; + int fd, size, ret; + const char *tmp_dir; + char tmp_in[PATH_MAX]; + char tmp_out[PATH_MAX]; + char buf[4096]; + Eina_Iterator *it; + Program_Script *ps; + Edje_Part_Collection *edc; + Eina_Bool success = EINA_TRUE; /* we are optimists! */ + +#ifdef HAVE_EVIL + tmp_dir = evil_tmpdir_get(); +#else + tmp_dir = "/tmp"; +#endif + + snprintf(tmp_in, sizeof(tmp_in), "%s/edje_edit.sma-tmp-XXXXXX", tmp_dir); + snprintf(tmp_out, sizeof(tmp_out), "%s/edje_edit.amx-tmp-XXXXXX", tmp_dir); + + fd = mkstemp(tmp_in); + if (fd < 0) + return EINA_FALSE; /* FIXME: report something */ + + f = fdopen(fd, "w"); + if (!f) + { + close(fd); + unlink(tmp_in); + return EINA_FALSE; + } + + fprintf(f, "#include \n"); + if (eed->embryo_source) + { + if (eed->all_dirty) + { + free(eed->embryo_processed); + eed->embryo_processed = NULL; + } + if (!eed->embryo_processed) + eed->embryo_processed = _edje_edit_script_process(eed, + eed->embryo_source); + if (!eed->embryo_processed) + { + /* oops.. an error finding references parts or something. + * we could flag it and do some lighter processing of the + * rest of the scripts, in order to find all the errors of + * this kind and report them at once, but knowing already + * that the script will not compile we can avoid some work + */ + success = EINA_FALSE; + } + else + fprintf(f, eed->embryo_processed); + } + + it = eina_hash_iterator_data_new(eed->program_scripts); + EINA_ITERATOR_FOREACH(it, ps) + { + if (ps->delete_me) + continue; + if (eed->all_dirty) + { + free(ps->processed); + ps->processed = NULL; + } + if (!ps->processed) + ps->processed = _edje_edit_script_process(eed, ps->code); + if (!ps->processed) + { + /* oops.. an error finding references parts or something. + * we could flag it and do some lighter processing of the + * rest of the scripts, in order to find all the errors of + * this kind and report them at once, but knowing already + * that the script will not compile we can avoid some work + */ + success = EINA_FALSE; + continue; + } + fprintf(f, "public _p%i(sig[], src[]) {\n", ps->id); + fprintf(f, ps->processed); + fprintf(f, "}\n"); + } + eina_iterator_free(it); + + fclose(f); + + fd = mkstemp(tmp_out); + if (fd < 0) + { + success = EINA_FALSE; + goto almost_out; + } + + snprintf(buf, sizeof(buf), "embryo_cc -i %s/include -o %s %s", + PACKAGE_DATA_DIR, tmp_out, tmp_in); + ret = system(buf); + + if ((ret < 0) || (ret > 1)) + { + success = EINA_FALSE; + close(fd); + goto the_way_out; + } + + f = fdopen(fd, "rb"); + if (!f) + { + success = EINA_FALSE; + close(fd); + goto the_way_out; + } + + fseek(f, 0, SEEK_END); + size = ftell(f); + rewind(f); + + free(eed->bytecode); + if (size > 0) + { + eed->bytecode = malloc(size); + if (!eed->bytecode) + { + success = EINA_FALSE; + goto the_way_out; + } + if (fread(eed->bytecode, size, 1, f) != 1) + { + success = EINA_FALSE; + goto the_way_out; + } + } + else + eed->bytecode = NULL; /* correctness mostly, I don't see why we + would get a 0 sized program */ + + eed->bytecode_size = size; + eed->bytecode_dirty = EINA_TRUE; + eed->script_need_recompile = EINA_FALSE; + eed->all_dirty = EINA_FALSE; + + edc = eed->base.collection; + embryo_program_free(edc->script); + edc->script = embryo_program_new(eed->bytecode, eed->bytecode_size); + _edje_embryo_script_init(edc); + _edje_var_init((Edje *)eed); + +the_way_out: + fclose(f); + unlink(tmp_out); +almost_out: + unlink(tmp_in); + + return success; +} + +EAPI Eina_Bool +edje_edit_script_compile(Evas_Object *obj) +{ + GET_ED_OR_RETURN(EINA_FALSE); + + if (!eed->script_need_recompile) + return EINA_TRUE; + + return _edje_edit_embryo_rebuild(eed); +} /***************************/ /* EDC SOURCE GENERATION */ @@ -5893,9 +6547,12 @@ _edje_generate_source_of_program(Evas_Object *obj, const char *program, Eina_Str char *data; Eina_Bool ret = EINA_TRUE; const char *api_name, *api_description; + Edje_Program *epr; GET_ED_OR_RETURN(EINA_FALSE); + epr = _edje_program_get_byname(obj, program); + BUF_APPENDF(I3"program { name: \"%s\";\n", program); /* Signal */ @@ -5936,6 +6593,19 @@ _edje_generate_source_of_program(Evas_Object *obj, const char *program, Eina_Str edje_edit_string_free(s2); } break; + case EDJE_ACTION_TYPE_SCRIPT: + { + Program_Script *ps; + + ps = eina_hash_find(eed->program_scripts, &epr->id); + if (ps && !ps->delete_me) + { + BUF_APPEND(I4"script {\n"); + BUF_APPEND(ps->code); + BUF_APPEND(I4"}\n"); + } + } + break; //TODO Support Drag //~ case EDJE_ACTION_TYPE_DRAG_VAL_SET: //~ eina_strbuf_append(buf, I4"action: DRAG_VAL_SET TODO;\n"); @@ -6134,7 +6804,7 @@ _edje_generate_source_of_state(Evas_Object *obj, const char *part, const char *s BUF_APPEND(I5"image {\n"); - image_name = _edje_image_name_find(obj, img->image.id); + image_name = _edje_image_name_find(eed, img->image.id); if (image_name) BUF_APPENDF(I6"normal: \"%s\";\n", image_name); @@ -6375,17 +7045,30 @@ _edje_generate_source_of_part(Evas_Object *obj, Edje_Part *ep, Eina_Strbuf *buf) static Eina_Bool _edje_generate_source_of_group(Edje *ed, Edje_Part_Collection_Directory_Entry *pce, Eina_Strbuf *buf) { + Edje_Edit *eed; + Eet_File *ef; Evas_Object *obj; Eina_List *l, *ll; unsigned int i; int w, h; char *data; const char *group = pce->entry; + Edje_Part_Collection *pc; Eina_Bool ret = EINA_TRUE; obj = edje_edit_object_add(ed->evas); if (!edje_object_file_set(obj, ed->file->path, group)) return EINA_FALSE; + ef = eet_open(ed->file->path, EET_FILE_MODE_READ); + if (!ef) + { + evas_object_del(obj); + return EINA_FALSE; + } + + eed = evas_object_smart_data_get(obj); + pc = eed->base.collection; + BUF_APPENDF(I1"group { name: \"%s\";\n", group); //TODO Support alias: w = edje_edit_group_min_w_get(obj); @@ -6398,13 +7081,13 @@ _edje_generate_source_of_group(Edje *ed, Edje_Part_Collection_Directory_Entry *p BUF_APPENDF(I2"max: %d %d;\n", w, h); /* Data */ - if (pce->ref->data) + if (pc->data) { Eina_Iterator *it; Eina_Hash_Tuple *tuple; BUF_APPEND(I2"data {\n"); - it = eina_hash_iterator_tuple_new(pce->ref->data); + it = eina_hash_iterator_tuple_new(pc->data); if (!it) { @@ -6420,14 +7103,19 @@ _edje_generate_source_of_group(Edje *ed, Edje_Part_Collection_Directory_Entry *p BUF_APPEND(I2"}\n"); } - //TODO Support script + if (eed->embryo_source) + { + BUF_APPEND(I2"script {\n"); + BUF_APPEND(eed->embryo_source); + BUF_APPEND(I2"}\n"); + } /* Parts */ BUF_APPEND(I2"parts {\n"); - for (i = 0; i < pce->ref->parts_count; i++) + for (i = 0; i < pc->parts_count; i++) { Edje_Part *ep; - ep = pce->ref->parts[i]; + ep = pc->parts[i]; ret &= _edje_generate_source_of_part(obj, ep, buf); } BUF_APPEND(I2"}\n");//parts @@ -6447,7 +7135,7 @@ _edje_generate_source_of_group(Edje *ed, Edje_Part_Collection_Directory_Entry *p BUF_APPEND(I2 "}\n"); edje_edit_string_list_free(ll); } - BUF_APPEND(" }\n");//group + BUF_APPEND(I1"}\n");//group if (!ret) { @@ -6456,6 +7144,7 @@ _edje_generate_source_of_group(Edje *ed, Edje_Part_Collection_Directory_Entry *p return EINA_FALSE; } + eet_close(ef); evas_object_del(obj); return ret; } @@ -6867,6 +7556,57 @@ _edje_edit_internal_save(Evas_Object *obj, int current_only) } } + if (eed->bytecode_dirty || eed->script_need_recompile) + { + char buf[64]; + Eina_Iterator *it; + Program_Script *ps; + Eina_List *deathnote = NULL; + + if (eed->bytecode_dirty) + { + snprintf(buf, sizeof(buf), "edje/scripts/embryo/compiled/%i", + ed->collection->id); + eet_write(eetf, buf, eed->bytecode, eed->bytecode_size, 1); + free(eed->bytecode); + eed->bytecode = NULL; + eed->bytecode_size = 0; + eed->bytecode_dirty = EINA_FALSE; + } + + if (eed->embryo_source_dirty) + { + snprintf(buf, sizeof(buf), "edje/scripts/embryo/source/%i", + ed->collection->id); + eet_write(eetf, buf, eed->embryo_source, + strlen(eed->embryo_source) +1, 1); + eed->embryo_source_dirty = EINA_FALSE; + } + + it = eina_hash_iterator_data_new(eed->program_scripts); + EINA_ITERATOR_FOREACH(it, ps) + { + if (ps->dirty) + { + snprintf(buf, sizeof(buf), "edje/scripts/embryo/source/%i/%i", + ed->collection->id, ps->id); + eet_write(eetf, buf, ps->code, strlen(ps->code) + 1, 1); + ps->dirty = EINA_FALSE; + } + else if (ps->delete_me) + { + snprintf(buf, sizeof(buf), "edje/scripts/embryo/source/%i/%i", + ed->collection->id, ps->id); + eet_delete(eetf, buf); + deathnote = eina_list_append(deathnote, ps); + } + } + eina_iterator_free(it); + + EINA_LIST_FREE(deathnote, ps) + eina_hash_del(eed->program_scripts, &ps->id, ps); + } + if (!_edje_edit_source_save(eetf, obj)) { eet_close(eetf);