move around - flatter.
authorraster <raster@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Sun, 17 Aug 2008 07:44:18 +0000 (07:44 +0000)
committerraster <raster@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Sun, 17 Aug 2008 07:44:18 +0000 (07:44 +0000)
git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/edje@35497 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

99 files changed:
.cvsignore [new file with mode: 0644]
AUTHORS [new file with mode: 0644]
COPYING [new file with mode: 0644]
COPYING-PLAIN [new file with mode: 0644]
ChangeLog [new file with mode: 0644]
Doxyfile [new file with mode: 0644]
INSTALL [new file with mode: 0644]
Makefile.am [new file with mode: 0644]
NEWS [new file with mode: 0644]
README [new file with mode: 0644]
autogen.sh [new file with mode: 0755]
configure.in [new file with mode: 0644]
data/.cvsignore [new file with mode: 0644]
data/Makefile.am [new file with mode: 0644]
data/edc.vim [new file with mode: 0644]
data/edje-mode.el [new file with mode: 0644]
data/include/.cvsignore [new file with mode: 0644]
data/include/Makefile.am [new file with mode: 0644]
data/include/edje.inc [new file with mode: 0644]
debian/.cvsignore [new file with mode: 0644]
debian/changelog.in [new file with mode: 0644]
debian/compat [new file with mode: 0644]
debian/control [new file with mode: 0644]
debian/copyright [new file with mode: 0644]
debian/edje_cc.1 [new file with mode: 0644]
debian/edje_decc.1 [new file with mode: 0644]
debian/edje_recc.1 [new file with mode: 0644]
debian/libedje-bin.install [new file with mode: 0644]
debian/libedje-bin.manpages [new file with mode: 0644]
debian/libedje-dev.install [new file with mode: 0644]
debian/libedje-doc.dirs [new file with mode: 0644]
debian/libedje-doc.doc-base [new file with mode: 0644]
debian/libedje0.install [new file with mode: 0644]
debian/rules [new file with mode: 0644]
doc/.cvsignore [new file with mode: 0644]
doc/e.css [new file with mode: 0644]
doc/edje.css [new file with mode: 0644]
doc/foot.html [new file with mode: 0644]
doc/head.html [new file with mode: 0644]
doc/img/_.gif [new file with mode: 0644]
doc/img/b.png [new file with mode: 0644]
doc/img/edje.png [new file with mode: 0644]
doc/img/edje_big.png [new file with mode: 0644]
doc/img/edje_mini.png [new file with mode: 0644]
doc/img/edje_small.png [new file with mode: 0644]
doc/img/hilite.png [new file with mode: 0644]
doc/img/n.gif [new file with mode: 0644]
doc/img/n.png [new file with mode: 0644]
doc/img/t.gif [new file with mode: 0644]
doc/img/t.png [new file with mode: 0644]
doc/img/tl.gif [new file with mode: 0644]
doc/img/tl.png [new file with mode: 0644]
edje.c.in [new file with mode: 0644]
edje.pc.in [new file with mode: 0644]
edje.spec.in [new file with mode: 0644]
edje.supp [new file with mode: 0644]
gendoc [new file with mode: 0755]
src/.cvsignore [new file with mode: 0644]
src/Makefile.am [new file with mode: 0644]
src/bin/.cvsignore [new file with mode: 0644]
src/bin/Makefile.am [new file with mode: 0644]
src/bin/edje_cc.c [new file with mode: 0644]
src/bin/edje_cc.h [new file with mode: 0644]
src/bin/edje_cc_handlers.c [new file with mode: 0644]
src/bin/edje_cc_mem.c [new file with mode: 0644]
src/bin/edje_cc_out.c [new file with mode: 0644]
src/bin/edje_cc_parse.c [new file with mode: 0644]
src/bin/edje_cc_sources.c [new file with mode: 0644]
src/bin/edje_decc.c [new file with mode: 0644]
src/bin/edje_decc.h [new file with mode: 0644]
src/bin/edje_main.h [new file with mode: 0644]
src/bin/edje_prefix.c [new file with mode: 0644]
src/bin/edje_prefix.h [new file with mode: 0644]
src/bin/edje_recc [new file with mode: 0644]
src/lib/.cvsignore [new file with mode: 0644]
src/lib/Edje.h [new file with mode: 0644]
src/lib/Edje_Edit.h [new file with mode: 0644]
src/lib/Makefile.am [new file with mode: 0644]
src/lib/edje_cache.c [new file with mode: 0644]
src/lib/edje_calc.c [new file with mode: 0644]
src/lib/edje_callbacks.c [new file with mode: 0644]
src/lib/edje_container.c [new file with mode: 0644]
src/lib/edje_container.h [new file with mode: 0644]
src/lib/edje_data.c [new file with mode: 0644]
src/lib/edje_edit.c [new file with mode: 0644]
src/lib/edje_embryo.c [new file with mode: 0644]
src/lib/edje_load.c [new file with mode: 0644]
src/lib/edje_main.c [new file with mode: 0644]
src/lib/edje_match.c [new file with mode: 0644]
src/lib/edje_message_queue.c [new file with mode: 0644]
src/lib/edje_misc.c [new file with mode: 0644]
src/lib/edje_private.h [new file with mode: 0644]
src/lib/edje_program.c [new file with mode: 0644]
src/lib/edje_script_only.c [new file with mode: 0644]
src/lib/edje_smart.c [new file with mode: 0644]
src/lib/edje_text.c [new file with mode: 0644]
src/lib/edje_textblock_styles.c [new file with mode: 0644]
src/lib/edje_util.c [new file with mode: 0644]
src/lib/edje_var.c [new file with mode: 0644]

diff --git a/.cvsignore b/.cvsignore
new file mode 100644 (file)
index 0000000..efbdd47
--- /dev/null
@@ -0,0 +1,26 @@
+Makefile
+Makefile.in
+aclocal.m4
+autom4te.cache
+config.guess
+config.h
+config.h.in
+config.log
+config.status
+config.sub
+configure
+edje-config
+edje.c
+edje_docs.tar.gz
+libtool
+ltmain.sh
+stamp-h1
+compile
+depcomp
+edje.pc
+install-sh
+missing
+doc
+*.tar.gz
+mkinstalldirs
+edje.spec
diff --git a/AUTHORS b/AUTHORS
new file mode 100644 (file)
index 0000000..63cdede
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,5 @@
+The Rasterman (Carsten Haitzler) <raster@rasterman.com>
+Tilman Sauerbeck (tilman at code-monkey de)
+ZigsMcKenzie <zigsmckenzie@gmail.com>
+Cedric BAIL <cedric.bail@free.fr>
+Brian Mattern <rephorm@rephorm.com>
diff --git a/COPYING b/COPYING
new file mode 100644 (file)
index 0000000..474fcc5
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,28 @@
+Copyright (C) 2000 Carsten Haitzler and various contributors (see AUTHORS)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to
+deal in the Software without restriction, including without limitation the
+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies of the Software and its Copyright notices. In addition publicly
+documented acknowledgment must be given that this software has been used if no
+source code of this software is made available publicly. This includes
+acknowledgments in either Copyright notices, Manuals, Publicity and Marketing
+documents or any documentation provided with any product containing this
+software. This License does not apply to any software that links to the
+libraries provided by this software (statically or dynamically), but only to
+the software provided.
+
+Please see the COPYING.PLAIN for a plain-english explanation of this notice
+and it's intent.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/COPYING-PLAIN b/COPYING-PLAIN
new file mode 100644 (file)
index 0000000..376875e
--- /dev/null
@@ -0,0 +1,33 @@
+Plain English Copyright Notice
+
+This file is not intended to be the actual License. The reason this file
+exists is that we here are programmers and engineers. We aren't lawyers. We
+provide licenses that we THINK say the right things, but we have our own
+intentions at heart. This is a plain-english explanation of what those
+intentions are, and if you follow them you will be within the "spirit" of
+the license.
+
+The intent is for us to enjoy writing software that is useful to us (the
+AUTHORS) and allow others to use it freely and also benefit from the work we
+put into making it. We don't want to restrict others using it. They should
+not *HAVE* to make the source code of the applications they write that
+simply link to these libraries (be that statically or dynamically), or for
+them to be limited as to what license they choose to use (be it open, closed
+or anything else). But we would like to know you are using these libraries.
+We simply would like to know that it has been useful to someone. This is why
+we ask for acknowledgement of some sort.
+
+You can do what you want with the source of this software - it doesn't
+matter. We still have it here for ourselves and it is open and free to use
+and download and play with. It can't be taken away. We don't really mind what
+you do with the source to your software. We would simply like to know that
+you are using it - especially if it makes it to a commerical product. If you
+simply e-mail all the AUTHORS (see COPYING and AUTHORS files) telling us, and
+then make sure you include a paragraph or page in the manual for the product
+with the copyright notice and state that you used this software, we will be
+very happy. If you want to contribute back modifications and fixes you may have
+made we will welcome those too with open arms (generally). If you want help
+with changes needed, ports needed or features to be added, arrangements can
+be easily made with some dialogue.
+
+Carsten Haitzler <raster@rasterman.com>
diff --git a/ChangeLog b/ChangeLog
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/Doxyfile b/Doxyfile
new file mode 100644 (file)
index 0000000..accec4e
--- /dev/null
+++ b/Doxyfile
@@ -0,0 +1,146 @@
+PROJECT_NAME           = Edje
+PROJECT_NUMBER         =
+OUTPUT_DIRECTORY       = doc
+INPUT                  = edje.c ./src/bin/edje_cc_handlers.c ./src/lib/Edje_Edit.h
+IMAGE_PATH             = doc/img
+OUTPUT_LANGUAGE        = English
+GENERATE_HTML          = YES
+HTML_OUTPUT            = html
+HTML_FILE_EXTENSION    = .html
+HTML_HEADER            = doc/head.html
+HTML_FOOTER            = doc/foot.html
+HTML_STYLESHEET        = doc/e.css
+HTML_ALIGN_MEMBERS     = YES
+ENUM_VALUES_PER_LINE   = 1
+GENERATE_HTMLHELP      = NO
+CHM_FILE               = 
+HHC_LOCATION           = 
+GENERATE_CHI           = NO
+BINARY_TOC             = NO
+TOC_EXPAND             = NO
+DISABLE_INDEX          = YES
+EXTRACT_ALL            = NO
+EXTRACT_PRIVATE        = NO
+EXTRACT_STATIC         = NO
+EXTRACT_LOCAL_CLASSES  = NO
+HIDE_UNDOC_MEMBERS     = YES
+HIDE_UNDOC_CLASSES     = YES
+HIDE_FRIEND_COMPOUNDS  = YES
+BRIEF_MEMBER_DESC      = YES
+REPEAT_BRIEF           = YES
+ALWAYS_DETAILED_SEC    = NO
+INLINE_INHERITED_MEMB  = NO
+FULL_PATH_NAMES        = NO
+STRIP_FROM_PATH        = 
+INTERNAL_DOCS          = NO
+STRIP_CODE_COMMENTS    = YES
+CASE_SENSE_NAMES       = YES
+SHORT_NAMES            = NO
+HIDE_SCOPE_NAMES       = NO
+VERBATIM_HEADERS       = NO
+SHOW_INCLUDE_FILES     = NO
+JAVADOC_AUTOBRIEF      = YES
+MULTILINE_CPP_IS_BRIEF = NO
+DETAILS_AT_TOP         = YES
+INHERIT_DOCS           = YES
+INLINE_INFO            = YES
+SORT_MEMBER_DOCS       = YES
+DISTRIBUTE_GROUP_DOC   = NO
+TAB_SIZE               = 2
+GENERATE_TODOLIST      = YES
+GENERATE_TESTLIST      = YES
+GENERATE_BUGLIST       = YES
+GENERATE_DEPRECATEDLIST= YES
+ALIASES                = block="<tr><td class=\"block\"><b>"
+ALIASES               += context="</b></td><td class=\"context\" colspan=2>\code"
+ALIASES               += description="\endcode</td></tr><tr><td>&nbsp;</td><td class=\"description\" colspan=2>"
+ALIASES               += endblock="</td></tr>"
+ALIASES               += property="<tr><td>&nbsp;</td><td><table class=\"edcref\" border=\"0\"><tr><td class=\"property\"><tt>"
+ALIASES               += parameters="</tt></td><td class=\"parameters\"><tt>"
+ALIASES               += effect="</tt></td></tr><tr><td>&nbsp;</td><td class=\"effect\">"
+ALIASES               += endproperty="</td></tr></table></td></tr>"
+ENABLED_SECTIONS       = 
+MAX_INITIALIZER_LINES  = 30
+OPTIMIZE_OUTPUT_FOR_C  = YES
+OPTIMIZE_OUTPUT_JAVA   = NO
+SHOW_USED_FILES        = NO
+QUIET                  = NO
+WARNINGS               = YES
+WARN_IF_UNDOCUMENTED   = YES
+WARN_FORMAT            = "$file:$line: $text"
+WARN_LOGFILE           = 
+FILE_PATTERNS          =
+RECURSIVE              = NO
+EXCLUDE                = 
+EXCLUDE_SYMLINKS       = NO
+EXCLUDE_PATTERNS       = 
+EXAMPLE_PATH           = 
+EXAMPLE_PATTERNS       = 
+EXAMPLE_RECURSIVE      = NO
+INPUT_FILTER           = 
+FILTER_SOURCE_FILES    = NO
+SOURCE_BROWSER         = NO
+INLINE_SOURCES         = NO
+REFERENCED_BY_RELATION = YES
+REFERENCES_RELATION    = YES
+ALPHABETICAL_INDEX     = YES
+COLS_IN_ALPHA_INDEX    = 2
+IGNORE_PREFIX          = 
+GENERATE_TREEVIEW      = NO
+TREEVIEW_WIDTH         = 250
+GENERATE_LATEX         = YES
+LATEX_OUTPUT           = latex
+LATEX_CMD_NAME         = latex
+MAKEINDEX_CMD_NAME     = makeindex
+COMPACT_LATEX          = NO
+PAPER_TYPE             = a4wide
+EXTRA_PACKAGES         = 
+LATEX_HEADER           = 
+PDF_HYPERLINKS         = YES
+USE_PDFLATEX           = NO
+LATEX_BATCHMODE        = NO
+GENERATE_RTF           = NO
+RTF_OUTPUT             = rtf
+COMPACT_RTF            = NO
+RTF_HYPERLINKS         = NO
+RTF_STYLESHEET_FILE    = 
+RTF_EXTENSIONS_FILE    = 
+GENERATE_MAN           = YES
+MAN_OUTPUT             = man
+MAN_EXTENSION          = .3
+MAN_LINKS              = YES
+GENERATE_XML           = NO
+XML_SCHEMA             = 
+XML_DTD                = 
+GENERATE_AUTOGEN_DEF   = NO
+ENABLE_PREPROCESSING   = YES
+MACRO_EXPANSION        = NO
+EXPAND_ONLY_PREDEF     = NO
+SEARCH_INCLUDES        = NO
+INCLUDE_PATH           =
+INCLUDE_FILE_PATTERNS  = 
+PREDEFINED             = 
+EXPAND_AS_DEFINED      = 
+SKIP_FUNCTION_MACROS   = YES
+TAGFILES               = 
+GENERATE_TAGFILE       = 
+ALLEXTERNALS           = NO
+EXTERNAL_GROUPS        = YES
+PERL_PATH              = /usr/bin/perl
+CLASS_DIAGRAMS         = NO
+HIDE_UNDOC_RELATIONS   = YES
+HAVE_DOT               = NO
+CLASS_GRAPH            = NO
+COLLABORATION_GRAPH    = NO
+TEMPLATE_RELATIONS     = NO
+INCLUDE_GRAPH          = NO
+INCLUDED_BY_GRAPH      = NO
+GRAPHICAL_HIERARCHY    = NO
+DOT_IMAGE_FORMAT       = png
+DOT_PATH               = 
+DOTFILE_DIRS           = 
+MAX_DOT_GRAPH_WIDTH    = 512
+MAX_DOT_GRAPH_HEIGHT   = 512
+GENERATE_LEGEND        = YES
+DOT_CLEANUP            = YES
+SEARCHENGINE           = NO
diff --git a/INSTALL b/INSTALL
new file mode 100644 (file)
index 0000000..c7bf98a
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,14 @@
+COMPILING and INSTALLING:
+
+If you got a official release tar archive do:
+    ./configure
+    
+( otherwise if you got this from enlightenment cvs do: ./autogen.sh )
+    
+Then to compile:
+    make
+
+To install (run this as root, or the user who handles installs):
+    make install
+
+NOTE: You MUST make install Edje for it to run properly.
diff --git a/Makefile.am b/Makefile.am
new file mode 100644 (file)
index 0000000..51b69f7
--- /dev/null
@@ -0,0 +1,24 @@
+SUBDIRS = data src
+
+MAINTAINERCLEANFILES = Makefile.in aclocal.m4 config.guess \
+                       config.h.in config.sub configure install-sh \
+                      ltconfig ltmain.sh missing mkinstalldirs \
+                      stamp-h.in edje_docs.tar edje_docs.tar.gz edje.c \
+                      edje.spec depcomp compile edje.pc
+
+### this is all fine and great - but edje should not be going and installing
+### data in another software's data dir - it's just wrong. not to mention this
+### also breaks make distcheck...
+#      if test "x${vimdir}" != "x"; then \
+#        $(mkinstalldirs) $(DESTDIR)$(vimdir)/syntax; \
+#        cp -p $(srcdir)/data/edc.vim $(DESTDIR)$(vimdir)/syntax/; \
+#      fi
+
+bin_SCRIPTS = 
+
+EXTRA_DIST = README AUTHORS COPYING COPYING-PLAIN autogen.sh edje.spec \
+       edje.spec.in edje.pc.in edje.c.in Doxyfile \
+       doc gendoc
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = edje.pc
diff --git a/NEWS b/NEWS
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..839bbcb
--- /dev/null
+++ b/README
@@ -0,0 +1,82 @@
+Edje 0.5.0
+
+Requirements:
+-------------
+
+Must:
+  libc libm eet ecore ecore-evas ecore-job ecore-file embryo evas
+
+A graphical layout and animation library for animated resizable, compressed and
+scalable themes.
+
+It's current under development and isn't complete. See src/lib/edje_private.h
+for a list of FIXME's to do. Hopefully it will be complete in a few weeks.
+
+Quick start-up guide:
+
+1. You need eet from the HEAD cvs branch (must be up-to-date)
+
+  cvs co e17/libs/eet
+  cd e17/libs/eet
+  ./autogen.sh
+  make
+  sudo make install
+  cd
+
+2. You need evas from the HEAD branch built with eet loader support.
+
+  cvs co e17/libs/evas
+  cd e17/libs/evas
+  ./autogen.sh
+  make
+  sudo make install
+  cd
+  
+3. You need ecore from the HEAD cvs branch
+
+  cvs co e17/libs/ecore
+  cd e17/libs/ecore
+  ./autogen.sh
+  make
+  sudo make install
+  cd
+
+4. You need embryo from the HEAD cvs branch
+
+  cvs co e17/libs/embryo
+  cd e17/libs/embryo
+  ./autogen.sh
+  make
+  sudo make install
+  cd
+
+5. You already have Edje. now build it:
+
+   ./autogen.sh
+   make
+   sudo make install
+
+You now want to go test it out. first you'll need to make an Edje EET file.
+   
+   cd data
+   ./e_logo.sh
+   
+Now you can view the Edje you just built:
+   
+   edje ./e_logo.edj
+   
+You can view multiple files at once with the Edje test program:
+   
+   edje ./e_logo.edj ./e_logo.edj ./e_logo.edj
+   
+to view the same one 3 times.
+   
+You can read the source file that builds the Edje EET file by looking at:
+
+   data/src/e_logo.edc
+
+Another test file is also there:
+
+   data/src/test.edc
+   
+The test file doesn't build anything useful at the moment.
diff --git a/autogen.sh b/autogen.sh
new file mode 100755 (executable)
index 0000000..0846992
--- /dev/null
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+rm -rf autom4te.cache
+rm -f aclocal.m4 ltmain.sh
+
+touch README
+
+echo "Running aclocal..." ; aclocal $ACLOCAL_FLAGS || exit 1
+echo "Running autoheader..." ; autoheader || exit 1
+echo "Running autoconf..." ; autoconf || exit 1
+echo "Running libtoolize..." ; (libtoolize --copy --automake || glibtoolize --automake) || exit 1
+echo "Running automake..." ; automake --add-missing --copy --gnu || exit 1
+
+if [ -z "$NOCONFIGURE" ]; then
+       ./configure "$@"
+fi
diff --git a/configure.in b/configure.in
new file mode 100644 (file)
index 0000000..40118c6
--- /dev/null
@@ -0,0 +1,171 @@
+dnl Process this file with autoconf to produce a configure script.
+
+# get rid of that stupid cache mechanism
+rm -f config.cache
+
+AC_INIT(edje, 0.9.9.043, enlightenment-devel@lists.sourceforge.net)
+AC_PREREQ(2.52)
+AC_CONFIG_SRCDIR(configure.in)
+AC_CANONICAL_BUILD
+AC_CANONICAL_HOST
+AC_ISC_POSIX
+
+AM_INIT_AUTOMAKE(1.6 dist-bzip2)
+AM_CONFIG_HEADER(config.h)
+
+AC_PROG_CC
+AM_PROG_CC_STDC
+AM_PROG_CC_C_O
+AC_HEADER_STDC
+AC_C_CONST
+
+AC_LIBTOOL_WIN32_DLL
+define([AC_LIBTOOL_LANG_CXX_CONFIG], [:])dnl
+define([AC_LIBTOOL_LANG_F77_CONFIG], [:])dnl
+AC_PROG_LIBTOOL
+
+VMAJ=`echo $PACKAGE_VERSION | awk -F. '{printf("%s", $1);}'`
+VMIN=`echo $PACKAGE_VERSION | awk -F. '{printf("%s", $2);}'`
+VMIC=`echo $PACKAGE_VERSION | awk -F. '{printf("%s", $3);}'`
+SNAP=`echo $PACKAGE_VERSION | awk -F. '{printf("%s", $4);}'`
+version_info=`expr $VMAJ + $VMIN`":$VMIC:$VMIN"
+AC_SUBST(version_info)
+
+PKG_PROG_PKG_CONFIG
+
+AC_FUNC_ALLOCA
+
+WIN32_CFLAGS=""
+lt_no_undefined=""
+lt_enable_auto_import=""
+case "$host_os" in
+       mingw*|cegcc)
+               PKG_CHECK_MODULES([EVIL], [evil])
+               AC_DEFINE(HAVE_EVIL, 1, [Set to 1 if evil package is installed])
+               AC_DEFINE(HAVE_REALPATH, 1, [Define to 1 if you have the `realpath' function.])
+               dnl needed for correct definition of EAPI
+               AC_DEFINE(EFL_EDJE_BUILD, 1, [Define to mention that embryo is built])
+               if test "x$host_os" = "xcegcc" ; then
+                       WIN32_CFLAGS="-mwin32"
+                       lt_enable_auto_import="-Wl,--enable-auto-import"
+               fi
+               lt_no_undefined="-no-undefined"
+               ;;
+       *)
+               AC_CHECK_FUNCS(realpath)
+               ;;
+esac
+AC_SUBST(WIN32_CFLAGS)
+AC_SUBST(lt_no_undefined)
+AC_SUBST(lt_enable_auto_import)
+
+AC_MSG_CHECKING(whether to build edje_cc)
+have_edje_cc="yes"
+AC_ARG_ENABLE(edje-cc, [  --disable-edje-cc       disable building of edje_cc ], [
+     if test x"$enableval" = x"yes" ; then
+       AC_MSG_RESULT(yes)
+       have_edje_cc="yes"
+     else
+       AC_MSG_RESULT(no)
+       have_edje_cc="no"
+     fi
+   ], [
+      AC_MSG_RESULT($have_edje_cc)
+   ]
+)
+
+PKG_CHECK_MODULES(EDJE, [
+  evas >= 0.9.9
+  ecore >= 0.9.9
+  ecore-job >= 0.9.9
+  eet >= 1.0.1
+  embryo >= 0.9.1
+])
+
+PKG_CHECK_MODULES(ECORE_FILE, [
+  ecore-file >= 0.9.9
+])
+
+PKG_CHECK_MODULES(ECORE_EVAS, [
+  ecore-evas >= 0.9.9
+])
+
+AC_MSG_CHECKING([for location of Vim data files])
+install_vim="yes";
+AC_ARG_WITH(vim,
+    [  --with-vim=DIR          Location of Vim data files [[autodetect]]],
+    [if test -d "${withval}"; then
+       vimdir="${withval}"
+    fi])
+
+if test "x${vimdir}" = "x" ; then
+   if test -d "${prefix}/share/vim"; then
+      vimdir="${prefix}/share/vim"
+   elif test -d "/usr/share/vim"; then
+      vimdir="/usr/share/vim"
+   elif test -d "/usr/local/share/vim"; then
+      vimdir="/usr/local/share/vim"
+   elif test -d "/opt/share/vim"; then
+      vimdir="/opt/share/vim"
+   else
+      install_vim="no"
+   fi
+fi
+
+if test "${install_vim}" = "yes"; then
+   AC_MSG_RESULT([$vimdir])
+else
+   AC_MSG_RESULT([Not found, EDC syntax file will not be installed])
+fi
+
+AC_SUBST(vimdir)
+
+EDJE_CC_PRG=""
+EDJE_DECC_PRG=""
+EDJE_RECC_PRG=""
+if test "x$have_edje_cc" = "xyes"; then
+  AM_CONDITIONAL(BUILD_EDJE_CC, true)
+  AM_CONDITIONAL(BUILD_EDJE_DECC, true)
+  EDJE_CC_PRG="edje_cc"
+  EDJE_DECC_PRG="edje_decc"
+  EDJE_RECC_PRG="edje_recc"
+else
+  AM_CONDITIONAL(BUILD_EDJE_CC, false)
+  AM_CONDITIONAL(BUILD_EDJE_DECC, false)
+fi
+AC_SUBST(EDJE_CC_PRG)
+AC_SUBST(EDJE_DECC_PRG)
+AC_SUBST(EDJE_RECC_PRG)
+
+AC_OUTPUT([
+edje.pc
+edje.spec
+Makefile
+data/Makefile
+data/include/Makefile
+src/Makefile
+src/lib/Makefile
+src/bin/Makefile
+])
+
+
+#####################################################################
+## Info
+
+echo
+echo
+echo
+echo "------------------------------------------------------------------------"
+echo "$PACKAGE $VERSION"
+echo "------------------------------------------------------------------------"
+echo
+echo "Configuration Options Summary:"
+echo
+echo "  Build binaries.......: $have_edje_cc"
+echo
+echo "  Compilation..........: make"
+echo
+echo "  Installation.........: make install"
+echo
+echo "    prefix.............: $prefix"
+echo
diff --git a/data/.cvsignore b/data/.cvsignore
new file mode 100644 (file)
index 0000000..282522d
--- /dev/null
@@ -0,0 +1,2 @@
+Makefile
+Makefile.in
diff --git a/data/Makefile.am b/data/Makefile.am
new file mode 100644 (file)
index 0000000..eac54ce
--- /dev/null
@@ -0,0 +1,7 @@
+
+MAINTAINERCLEANFILES = Makefile.in
+
+SUBDIRS = include
+
+EXTRA_DIST = edc.vim edje-mode.el
+
diff --git a/data/edc.vim b/data/edc.vim
new file mode 100644 (file)
index 0000000..7e470b4
--- /dev/null
@@ -0,0 +1,326 @@
+" Vim syntax file
+" Language:    EDC
+" Maintainer:  no one?
+" Last Change: 2005
+
+" For version 5.x: Clear all syntax items
+" For version 6.x: Quit when a syntax file was already loaded
+if version < 600
+  syntax clear
+elseif exists("b:current_syntax")
+  finish
+endif
+
+" A bunch of useful C keywords
+syn keyword    cStructure      images data fonts collections group
+syn keyword    cStructure      part parts dragable description rel1 rel2
+syn keyword    cStatement      text image font fill origin size tag
+syn keyword    cStructure      programs program script styles style base
+syn keyword    cStructure      spectra spectrum
+syn match      cType           "+ + +;" contained 
+
+syn keyword    cLabel          item name min max type effect
+syn keyword    cLabel          mouse_events repeat_events clip_to
+syn keyword    cLabel          color_class text_class x y confine
+syn keyword    cLabel          state visible align step aspect aspect_preference fixed
+syn keyword    cLabel          relative offset to to_x to_y normal tween
+syn keyword    cLabel          border color color2 color3 font size fit align
+syn keyword    cLabel          signal source action transition in target after
+syn keyword    cLabel          text smooth inherit
+
+syn keyword    cConditional    if else switch
+syn keyword    cRepeat         while for do
+syn keyword    cConstant       COMP RAW LOSSY 
+syn keyword    cConstant       TEXT IMAGE RECT SWALLOW
+syn keyword    cConstant       NONE PLAIN OUTLINE SOFT_OUTLINE SHADOW
+syn keyword    cConstant       SOFT_SHADOW OUTLINE_SHADOW OUTLINE_SOFT_SHADOW
+syn keyword    cConstant       STATE_SET ACTION_STOP SIGNAL_EMIT
+syn keyword    cConstant       DRAG_VAL_SET DRAG_VAL_STEP DRAG_VAL_PAGE
+syn keyword    cConstant       LINEAR SINUSOIDAL ACCELERATE DECELERATE
+syn keyword    cConstant       "default"
+
+syn keyword    cTodo           contained TODO FIXME XXX
+
+" cCommentGroup allows adding matches for special things in comments
+syn cluster    cCommentGroup   contains=cTodo
+
+" String and Character constants
+" Highlight special characters (those which have a backslash) differently
+syn match      cSpecial        display contained "\\\(x\x\+\|\o\{1,3}\|.\|$\)"
+if !exists("c_no_utf")
+  syn match    cSpecial        display contained "\\\(u\x\{4}\|U\x\{8}\)"
+endif
+if exists("c_no_cformat")
+  syn region   cString         start=+L\="+ skip=+\\\\\|\\"+ end=+"+ contains=cSpecial
+  " cCppString: same as cString, but ends at end of line
+  syn region   cCppString      start=+L\="+ skip=+\\\\\|\\"\|\\$+ excludenl end=+"+ end='$' contains=cSpecial
+else
+  syn match    cFormat         display "%\(\d\+\$\)\=[-+' #0*]*\(\d*\|\*\|\*\d\+\$\)\(\.\(\d*\|\*\|\*\d\+\$\)\)\=\([hlL]\|ll\)\=\([diuoxXfeEgGcCsSpn]\|\[\^\=.[^]]*\]\)" contained
+  syn match    cFormat         display "%%" contained
+  syn region   cString         start=+L\="+ skip=+\\\\\|\\"+ end=+"+ contains=cSpecial,cFormat
+  " cCppString: same as cString, but ends at end of line
+  syn region   cCppString      start=+L\="+ skip=+\\\\\|\\"\|\\$+ excludenl end=+"+ end='$' contains=cSpecial,cFormat
+endif
+
+syn match      cCharacter      "L\='[^\\]'"
+syn match      cCharacter      "L'[^']*'" contains=cSpecial
+if exists("c_gnu")
+  syn match    cSpecialError   "L\='\\[^'\"?\\abefnrtv]'"
+  syn match    cSpecialCharacter "L\='\\['\"?\\abefnrtv]'"
+else
+  syn match    cSpecialError   "L\='\\[^'\"?\\abfnrtv]'"
+  syn match    cSpecialCharacter "L\='\\['\"?\\abfnrtv]'"
+endif
+syn match      cSpecialCharacter display "L\='\\\o\{1,3}'"
+syn match      cSpecialCharacter display "'\\x\x\{1,2}'"
+syn match      cSpecialCharacter display "L'\\x\x\+'"
+
+"when wanted, highlight trailing white space
+if exists("c_space_errors")
+  if !exists("c_no_trail_space_error")
+    syn match  cSpaceError     display excludenl "\s\+$"
+  endif
+  if !exists("c_no_tab_space_error")
+    syn match  cSpaceError     display " \+\t"me=e-1
+  endif
+endif
+
+"catch errors caused by wrong parenthesis and brackets
+syn cluster    cParenGroup     contains=cParenError,cIncluded,cSpecial,cCommentSkip,cCommentString,cComment2String,@cCommentGroup,cCommentStartError,cUserCont,cUserLabel,cBitField,cCommentSkip,cOctalZero,cCppOut,cCppOut2,cCppSkip,cFormat,cNumber,cFloat,cOctal,cOctalError,cNumbersCom
+if exists("c_no_bracket_error")
+  syn region   cParen          transparent start='(' end=')' contains=ALLBUT,@cParenGroup,cCppParen,cCppString
+  " cCppParen: same as cParen but ends at end-of-line; used in cDefine
+  syn region   cCppParen       transparent start='(' skip='\\$' excludenl end=')' end='$' contained contains=ALLBUT,@cParenGroup,cParen,cString
+  syn match    cParenError     display ")"
+  syn match    cErrInParen     display contained "[{}]"
+else
+  syn region   cParen          transparent start='(' end=')' contains=ALLBUT,@cParenGroup,cCppParen,cErrInBracket,cCppBracket,cCppString
+  " cCppParen: same as cParen but ends at end-of-line; used in cDefine
+  syn region   cCppParen       transparent start='(' skip='\\$' excludenl end=')' end='$' contained contains=ALLBUT,@cParenGroup,cErrInBracket,cParen,cBracket,cString
+  syn match    cParenError     display "[\])]"
+  syn match    cErrInParen     display contained "[\]{}]"
+  syn region   cBracket        transparent start='\[' end=']' contains=ALLBUT,@cParenGroup,cErrInParen,cCppParen,cCppBracket,cCppString
+  " cCppBracket: same as cParen but ends at end-of-line; used in cDefine
+  syn region   cCppBracket     transparent start='\[' skip='\\$' excludenl end=']' end='$' contained contains=ALLBUT,@cParenGroup,cErrInParen,cParen,cBracket,cString
+  syn match    cErrInBracket   display contained "[);{}]"
+endif
+
+"integer number, or floating point number without a dot and with "f".
+syn case ignore
+syn match      cNumbers        display transparent "\<\d\|\.\d" contains=cNumber,cFloat,cOctalError,cOctal
+" Same, but without octal error (for comments)
+syn match      cNumbersCom     display contained transparent "\<\d\|\.\d" contains=cNumber,cFloat,cOctal
+syn match      cNumber         display contained "\d\+\(u\=l\{0,2}\|ll\=u\)\>"
+"hex number
+syn match      cNumber         display contained "0x\x\+\(u\=l\{0,2}\|ll\=u\)\>"
+" Flag the first zero of an octal number as something special
+syn match      cOctal          display contained "0\o\+\(u\=l\{0,2}\|ll\=u\)\>" contains=cOctalZero
+syn match      cOctalZero      display contained "\<0"
+syn match      cFloat          display contained "\d\+f"
+"floating point number, with dot, optional exponent
+syn match      cFloat          display contained "\d\+\.\d*\(e[-+]\=\d\+\)\=[fl]\="
+"floating point number, starting with a dot, optional exponent
+syn match      cFloat          display contained "\.\d\+\(e[-+]\=\d\+\)\=[fl]\=\>"
+"floating point number, without dot, with exponent
+syn match      cFloat          display contained "\d\+e[-+]\=\d\+[fl]\=\>"
+" flag an octal number with wrong digits
+syn match      cOctalError     display contained "0\o*[89]\d*"
+syn case match
+
+if exists("c_comment_strings")
+  " A comment can contain cString, cCharacter and cNumber.
+  " But a "*/" inside a cString in a cComment DOES end the comment!  So we
+  " need to use a special type of cString: cCommentString, which also ends on
+  " "*/", and sees a "*" at the start of the line as comment again.
+  " Unfortunately this doesn't very well work for // type of comments :-(
+  syntax match cCommentSkip    contained "^\s*\*\($\|\s\+\)"
+  syntax region cCommentString contained start=+L\=\\\@<!"+ skip=+\\\\\|\\"+ end=+"+ end=+\*/+me=s-1 contains=cSpecial,cCommentSkip
+  syntax region cComment2String        contained start=+L\=\\\@<!"+ skip=+\\\\\|\\"+ end=+"+ end="$" contains=cSpecial
+  syntax region  cCommentL     start="//" skip="\\$" end="$" keepend contains=@cCommentGroup,cComment2String,cCharacter,cNumbersCom,cSpaceError
+  syntax region cComment       matchgroup=cCommentStart start="/\*" matchgroup=NONE end="\*/" contains=@cCommentGroup,cCommentStartError,cCommentString,cCharacter,cNumbersCom,cSpaceError
+else
+  syn region   cCommentL       start="//" skip="\\$" end="$" keepend contains=@cCommentGroup,cSpaceError
+  syn region   cComment        matchgroup=cCommentStart start="/\*" matchgroup=NONE end="\*/" contains=@cCommentGroup,cCommentStartError,cSpaceError
+endif
+" keep a // comment separately, it terminates a preproc. conditional
+syntax match   cCommentError   display "\*/"
+syntax match   cCommentStartError display "/\*"me=e-1 contained
+
+syn keyword    cOperator       sizeof
+if exists("c_gnu")
+  syn keyword  cStatement      __asm__
+  syn keyword  cOperator       typeof __real__ __imag__
+endif
+syn keyword    cType           int long short char void
+syn keyword    cType           signed unsigned float double
+if !exists("c_no_ansi") || exists("c_ansi_typedefs")
+  syn keyword   cType          size_t wchar_t ptrdiff_t sig_atomic_t fpos_t
+  syn keyword   cType          clock_t time_t va_list jmp_buf FILE DIR div_t ldiv_t
+  syn keyword   cType          mbstate_t wctrans_t wint_t wctype_t
+endif
+if !exists("c_no_c99") " ISO C99
+  syn keyword  cType           bool complex
+  syn keyword  cType           int8_t int16_t int32_t int64_t
+  syn keyword  cType           uint8_t uint16_t uint32_t uint64_t
+  syn keyword  cType           int_least8_t int_least16_t int_least32_t int_least64_t
+  syn keyword  cType           uint_least8_t uint_least16_t uint_least32_t uint_least64_t
+  syn keyword  cType           int_fast8_t int_fast16_t int_fast32_t int_fast64_t
+  syn keyword  cType           uint_fast8_t uint_fast16_t uint_fast32_t uint_fast64_t
+  syn keyword  cType           intptr_t uintptr_t
+  syn keyword  cType           intmax_t uintmax_t
+endif
+if exists("c_gnu")
+  syn keyword  cType           __label__ __complex__ __volatile__
+endif
+
+syn keyword    cStructure      struct union enum typedef
+syn keyword    cStorageClass   static register auto volatile extern const
+if exists("c_gnu")
+  syn keyword  cStorageClass   inline __attribute__
+endif
+
+if !exists("c_no_ansi") || exists("c_ansi_constants") || exists("c_gnu")
+  if exists("c_gnu")
+    syn keyword cConstant __GNUC__ __FUNCTION__ __PRETTY_FUNCTION__
+  endif
+  syn keyword cConstant __LINE__ __FILE__ __DATE__ __TIME__ __STDC__
+  syn keyword cConstant __STDC_VERSION__
+  syn keyword cConstant CHAR_BIT MB_LEN_MAX MB_CUR_MAX
+  syn keyword cConstant UCHAR_MAX UINT_MAX ULONG_MAX USHRT_MAX
+  syn keyword cConstant CHAR_MIN INT_MIN LONG_MIN SHRT_MIN
+  syn keyword cConstant CHAR_MAX INT_MAX LONG_MAX SHRT_MAX
+  syn keyword cConstant SCHAR_MIN SINT_MIN SLONG_MIN SSHRT_MIN
+  syn keyword cConstant SCHAR_MAX SINT_MAX SLONG_MAX SSHRT_MAX
+  syn keyword cConstant FLT_RADIX FLT_ROUNDS
+  syn keyword cConstant FLT_DIG FLT_MANT_DIG FLT_EPSILON
+  syn keyword cConstant DBL_DIG DBL_MANT_DIG DBL_EPSILON
+  syn keyword cConstant LDBL_DIG LDBL_MANT_DIG LDBL_EPSILON
+  syn keyword cConstant FLT_MIN FLT_MAX FLT_MIN_EXP FLT_MAX_EXP
+  syn keyword cConstant FLT_MIN_10_EXP FLT_MAX_10_EXP
+  syn keyword cConstant DBL_MIN DBL_MAX DBL_MIN_EXP DBL_MAX_EXP
+  syn keyword cConstant DBL_MIN_10_EXP DBL_MAX_10_EXP
+  syn keyword cConstant LDBL_MIN LDBL_MAX LDBL_MIN_EXP LDBL_MAX_EXP
+  syn keyword cConstant LDBL_MIN_10_EXP LDBL_MAX_10_EXP
+  syn keyword cConstant HUGE_VAL CLOCKS_PER_SEC NULL
+  syn keyword cConstant LC_ALL LC_COLLATE LC_CTYPE LC_MONETARY
+  syn keyword cConstant LC_NUMERIC LC_TIME
+  syn keyword cConstant SIG_DFL SIG_ERR SIG_IGN
+  syn keyword cConstant SIGABRT SIGFPE SIGILL SIGHUP SIGINT SIGSEGV SIGTERM
+  " Add POSIX signals as well...
+  syn keyword cConstant SIGABRT SIGALRM SIGCHLD SIGCONT SIGFPE SIGHUP
+  syn keyword cConstant SIGILL SIGINT SIGKILL SIGPIPE SIGQUIT SIGSEGV
+  syn keyword cConstant SIGSTOP SIGTERM SIGTRAP SIGTSTP SIGTTIN SIGTTOU
+  syn keyword cConstant SIGUSR1 SIGUSR2
+  syn keyword cConstant _IOFBF _IOLBF _IONBF BUFSIZ EOF
+  syn keyword cConstant FOPEN_MAX FILENAME_MAX L_tmpnam
+  syn keyword cConstant SEEK_CUR SEEK_END SEEK_SET
+  syn keyword cConstant TMP_MAX stderr stdin stdout
+  syn keyword cConstant EXIT_FAILURE EXIT_SUCCESS RAND_MAX
+  " Add POSIX errors as well
+  syn keyword cConstant E2BIG EACCES EAGAIN EBADF EBADMSG EBUSY
+  syn keyword cConstant ECANCELED ECHILD EDEADLK EDOM EEXIST EFAULT
+  syn keyword cConstant EFBIG EILSEQ EINPROGRESS EINTR EINVAL EIO EISDIR
+  syn keyword cConstant EMFILE EMLINK EMSGSIZE ENAMETOOLONG ENFILE ENODEV
+  syn keyword cConstant ENOENT ENOEXEC ENOLCK ENOMEM ENOSPC ENOSYS
+  syn keyword cConstant ENOTDIR ENOTEMPTY ENOTSUP ENOTTY ENXIO EPERM
+  syn keyword cConstant EPIPE ERANGE EROFS ESPIPE ESRCH ETIMEDOUT EXDEV
+  " math.h
+  syn keyword cConstant M_E M_LOG2E M_LOG10E M_LN2 M_LN10 M_PI M_PI_2 M_PI_4
+  syn keyword cConstant M_1_PI M_2_PI M_2_SQRTPI M_SQRT2 M_SQRT1_2
+endif
+if !exists("c_no_c99") " ISO C99
+  syn keyword cConstant true false
+endif
+
+syn region     cPreCondit      start="^\s*#\s*\(if\|ifdef\|ifndef\|elif\)\>" skip="\\$" end="$" end="//"me=s-1 contains=cComment,cCppString,cCharacter,cCppParen,cParenError,cNumbers,cCommentError,cSpaceError
+syn match      cPreCondit      display "^\s*#\s*\(else\|endif\)\>"
+if !exists("c_no_if0")
+  syn region   cCppOut         start="^\s*#\s*if\s\+0\+\>" end=".\|$" contains=cCppOut2
+  syn region   cCppOut2        contained start="0" end="^\s*#\s*\(endif\>\|else\>\|elif\>\)" contains=cSpaceError,cCppSkip
+  syn region   cCppSkip        contained start="^\s*#\s*\(if\>\|ifdef\>\|ifndef\>\)" skip="\\$" end="^\s*#\s*endif\>" contains=cSpaceError,cCppSkip
+endif
+syn region     cIncluded       display contained start=+"+ skip=+\\\\\|\\"+ end=+"+
+syn match      cIncluded       display contained "<[^>]*>"
+syn match      cInclude        display "^\s*#\s*include\>\s*["<]" contains=cIncluded
+"syn match cLineSkip   "\\$"
+syn cluster    cPreProcGroup   contains=cPreCondit,cIncluded,cInclude,cDefine,cErrInParen,cErrInBracket,cUserLabel,cSpecial,cOctalZero,cCppOut,cCppOut2,cCppSkip,cFormat,cNumber,cFloat,cOctal,cOctalError,cNumbersCom,cString,cCommentSkip,cCommentString,cComment2String,@cCommentGroup,cCommentStartError,cParen,cBracket,cMulti
+syn region     cDefine         start="^\s*#\s*\(define\|undef\)\>" skip="\\$" end="$" end="//"me=s-1 contains=ALLBUT,@cPreProcGroup
+syn region     cPreProc        start="^\s*#\s*\(pragma\>\|line\>\|warning\>\|warn\>\|error\>\)" skip="\\$" end="$" keepend contains=ALLBUT,@cPreProcGroup
+
+syn match      cUserLabel      display "\I\i*" contained
+
+
+
+if exists("c_minlines")
+  let b:c_minlines = c_minlines
+else
+  if !exists("c_no_if0")
+    let b:c_minlines = 50      " #if 0 constructs can be long
+  else
+    let b:c_minlines = 15      " mostly for () constructs
+  endif
+endif
+exec "syn sync ccomment cComment minlines=" . b:c_minlines
+
+" Define the default highlighting.
+" For version 5.7 and earlier: only when not done already
+" For version 5.8 and later: only when an item doesn't have highlighting yet
+if version >= 508 || !exists("did_c_syn_inits")
+  if version < 508
+    let did_c_syn_inits = 1
+    command -nargs=+ HiLink hi link <args>
+  else
+    command -nargs=+ HiLink hi def link <args>
+  endif
+
+  HiLink cFormat               cSpecial
+  HiLink cCppString            cString
+  HiLink cCommentL             cComment
+  HiLink cCommentStart         cComment
+  HiLink cLabel                        Label
+  HiLink cUserLabel            Label
+  HiLink cConditional          Conditional
+  HiLink cRepeat               Repeat
+  HiLink cCharacter            Character
+  HiLink cSpecialCharacter     cSpecial
+  HiLink cNumber               Number
+  HiLink cOctal                        Number
+  HiLink cOctalZero            PreProc  " link this to Error if you want
+  HiLink cFloat                        Float
+  HiLink cOctalError           cError
+  HiLink cParenError           cError
+  HiLink cErrInParen           cError
+  HiLink cErrInBracket         cError
+  HiLink cCommentError         cError
+  HiLink cCommentStartError    cError
+  HiLink cSpaceError           cError
+  HiLink cSpecialError         cError
+  HiLink cOperator             Operator
+  HiLink cStructure            Structure
+  HiLink cStorageClass         StorageClass
+  HiLink cInclude              Include
+  HiLink cPreProc              PreProc
+  HiLink cDefine               Macro
+  HiLink cIncluded             cString
+  HiLink cError                        Error
+  HiLink cStatement            Statement
+  HiLink cPreCondit            PreCondit
+  HiLink cType                 Type
+  HiLink cConstant             Constant
+  HiLink cCommentString                cString
+  HiLink cComment2String       cString
+  HiLink cCommentSkip          cComment
+  HiLink cString               String
+  HiLink cComment              Comment
+  HiLink cSpecial              SpecialChar
+  HiLink cTodo                 Todo
+  HiLink cCppSkip              cCppOut
+  HiLink cCppOut2              cCppOut
+  HiLink cCppOut               Comment
+
+  delcommand HiLink
+endif
+
+let b:current_syntax = "edc"
+
+" vim: ts=8
diff --git a/data/edje-mode.el b/data/edje-mode.el
new file mode 100644 (file)
index 0000000..33c6fe6
--- /dev/null
@@ -0,0 +1,512 @@
+;;; edje-mode-el -- Major mode for editing Edje files
+
+;; Author: Gustavo Sverzut Barbieri <barbieri@gmail.com>
+;; Created: 2007-07-23
+;; Keywords: Edje major-mode
+;; Url: http://barbieri-playground.googlecode.com/svn/dot-files/edje-mode.el
+;;      (if you find this file have problems, check that Url and request update)
+
+;; Copyright (C) 2007 Gustavo Sverzut Barbieri <barbieri@gmail.com>
+
+;; This program is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation; either version 2 of
+;; the License, or (at your option) any later version.
+
+;; This program is distributed in the hope that it will be
+;; useful, but WITHOUT ANY WARRANTY; without even the implied
+;; warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+;; PURPOSE.  See the GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public
+;; License along with this program; if not, write to the Free
+;; Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+;; MA 02111-1307 USA
+
+;;; Commentary:
+;;
+;; This mode is based on tutorial from Scott Andrew Borton:
+;; http://two-wugs.net/emacs/mode-tutorial.html
+
+
+(defvar edje-mode-hook nil)
+
+(defun number-or-nil-to-string (v &optional default)
+  (cond ((numberp v) (number-to-string v))
+        ((stringp v) (if (string= v "") (number-to-string default) v))
+        (t           (number-to-string default))))
+
+(defun non-empty-string (s)
+  (and (not (eq 'nil s))
+       (not (string= "" s))))
+
+(defun edje-new-program-action-signal-emit (source emission)
+  "Insert new program SIGNAL_EMIT"
+  (interactive "ssource: \nsemission: ")
+  (insert
+   (concat
+    "               action: SIGNAL_EMIT \"" source "\" \"" emission "\";\n"
+    )))
+
+(defun edje-new-program-action-state-set (state value target)
+  "Insert new program STATE_SET"
+  (interactive "sstate: \nsvalue (0.0): \nstarget: ")
+  (insert
+   (concat
+    "               action: STATE_SET \"" state "\" "
+       (number-or-nil-to-string value 0.0) ";\n"
+    "               target: \"" target "\";\n"
+    )))
+
+(defun edje-new-program-action (action)
+  "Insert new program action"
+  (interactive "saction: ")
+  (setq action (upcase action))
+  (cond ((string= action "STATE_SET")
+         (edje-new-program-action-state-set "" 0.0 ""))
+        ((string= action "SIGNAL_EMIT")
+         (edje-new-program-action-signal-emit "" ""))
+        ))
+
+(defun edje-new-program (name signal source action)
+  "Insert new program block"
+  (interactive "sname: \nssignal: \nssource: \nsaction: ")
+  (insert
+   (concat
+    "\n"
+    "            program {\n"
+    "               name: \"" name "\";\n"
+
+    (if (non-empty-string signal)
+        (concat "               signal: \"" signal "\";\n"))
+
+    (if (non-empty-string source)
+        (concat "               source: \"" source "\";\n"))
+    ))
+
+  (edje-new-program-action action)
+
+  (insert
+   (concat
+    "            }\n"
+    "\n"
+    )))
+
+(defun edje-new-desc-relative (x y &optional defx defy)
+  "Insert new part description 'relative' line"
+  (interactive "sx: \nsy: ")
+  (insert
+   (concat
+    "                  relative: "
+    (number-or-nil-to-string x defx) " "
+    (number-or-nil-to-string y defy) ";\n"
+    )))
+
+(defun edje-new-desc-offset (x y &optional defx defy)
+  "Insert new part description 'offset' line"
+  (interactive "sx: \nsy: ")
+  (insert
+   (concat
+    "                  offset: "
+    (number-or-nil-to-string x defx) " "
+    (number-or-nil-to-string y defy) ";\n"
+    )))
+
+(defun edje-new-desc-inherit (name val)
+  "Insert new part description 'inherit' line"
+  (interactive "sname: \nsvalue: ")
+  (insert
+   (concat
+    "               inherit: \"" name "\" "
+    (number-or-nil-to-string val 0.0) ";\n"
+    )))
+
+(defun edje-new-desc-text (font size text)
+  "Insert new part description 'text' block"
+  (interactive "sfont: \nssize: \nstext: ")
+  (insert
+   (concat
+    "               text {\n"
+    "                  font: \"" font "\";\n"
+    "                  size: " (number-or-nil-to-string size) ";\n"
+    "                  text: \"" text "\";\n"
+    "               }\n"
+    )))
+
+(defun edje-new-desc-image (name)
+  "Insert new part description 'image' block"
+  (interactive "sname: ")
+  (insert
+   (concat
+    "               image {\n"
+    "                  normal: \"" name "\";\n"
+    "               }\n"
+    )))
+
+(defun edje-new-desc-color (r g b a &optional defr defg defb defa)
+  "Insert new part description 'color' line"
+  (interactive "sred: \nsgreen: \nsblue: \nsalpha: ")
+  (insert
+   (concat
+    "               color: "
+    (number-or-nil-to-string r defr) " "
+    (number-or-nil-to-string g defg) " "
+    (number-or-nil-to-string b defb) " "
+    (number-or-nil-to-string a defa) ";\n"
+    )))
+
+(defun edje-new-desc (name val &optional
+                           r1_rx r1_ry
+                           r2_rx r2_ry
+                           r1_ox r1_oy
+                           r2_ox r2_oy
+                           part_type)
+  "Insert new part description block"
+  (interactive "sName: \nsValue: ")
+  (insert
+   (concat
+    "            description {\n"
+    "               state: \"" name "\" " (number-or-nil-to-string val 0.0) ";\n"))
+  (if (string= part_type "RECT") (edje-new-desc-color 255 255 255 255))
+  (insert "               rel1 {\n")
+  (edje-new-desc-relative r1_rx r1_ry 0.0 0.0)
+  (edje-new-desc-offset r1_ox r1_oy 0 0)
+  (insert
+   (concat
+    "               }\n"
+    "               rel2 {\n"
+    ))
+  (edje-new-desc-relative r2_rx r2_ry 1.0 1.0)
+  (edje-new-desc-offset r2_ox r2_oy -1 -1)
+  (insert "               }\n")
+  (cond ((string= part_type "IMAGE") (edje-new-desc-image ""))
+        ((string= part_type "TEXT") (edje-new-desc-text "" 10 "contents"))
+        )
+  (insert "            }\n")
+  )
+
+(defun edje-new-part (name type &optional
+                           r1_rx r1_ry
+                           r2_rx r2_ry
+                           r1_ox r1_oy
+                           r2_ox r2_oy)
+  "Insert new part"
+  (interactive "sName: \nsType: ")
+  (setq type (upcase type))
+  (insert
+   (concat
+    "\n"
+    "         part {\n"
+    "            name: \"" name "\";\n"
+    "            type: " type ";\n"
+    "            mouse_events: 0;\n"
+    ))
+  (edje-new-desc "default" 0.0 r1_rx r1_ry r2_rx r2_ry r1_ox r1_oy r2_ox r2_oy type)
+  (insert
+   (concat
+    "         }\n"
+    )))
+
+(defun edje-setup-compile ()
+  (set (make-local-variable 'compile-command)
+       (concat "edje_cc " (buffer-file-name))
+  ))
+
+(defun edje-cc ()
+  "Runs edje_cc with current buffer."
+  (interactive)
+  (compile (edje-setup-compile)))
+
+(defvar edje-mode-map
+  (let ((edje-mode-map (make-sparse-keymap)))
+    (define-key edje-mode-map "\C-j" 'newline-and-indent)
+    (define-key edje-mode-map "\C-cp" 'edje-new-part)
+    (define-key edje-mode-map "\C-cd" 'edje-new-desc)
+    (define-key edje-mode-map "\C-cr" 'edje-new-desc-relative)
+    (define-key edje-mode-map "\C-co" 'edje-new-desc-offset)
+    (define-key edje-mode-map "\C-ch" 'edje-new-desc-inherit)
+    (define-key edje-mode-map "\C-cc" 'edje-new-desc-color)
+    (define-key edje-mode-map "\C-ci" 'edje-new-desc-image)
+    (define-key edje-mode-map "\C-ct" 'edje-new-desc-text)
+    (define-key edje-mode-map "\C-cg" 'edje-new-program)
+    (define-key edje-mode-map "\C-ca" 'edje-new-program-action)
+    (define-key edje-mode-map "\C-cs" 'edje-new-program-action-state-set)
+    (define-key edje-mode-map "\C-ce" 'edje-new-program-action-signal-emit)
+    edje-mode-map)
+  "Keymap for Edje major mode")
+
+(add-hook 'c-mode-hook 'edje-setup-compile)
+(add-to-list 'auto-mode-alist '("\\.edc$" . edje-mode))
+
+(defconst edje-font-lock-keywords-1
+  (eval-when-compile
+    (list
+     (list (concat "[ \t]*\\<"
+                   (regexp-opt
+                    '(
+                      "collections"
+                      "data"
+                      "description"
+                      "dragable"
+                      "fill"
+                      "fonts"
+                      "group"
+                      "image"
+                      "images"
+                      "origin"
+                      "part"
+                      "parts"
+                      "program"
+                      "programs"
+                      "rel1"
+                      "rel2"
+                      "script"
+                      "spectra"
+                      "style"
+                      "styles"
+                      "text"
+                      ) t) "\\>\\([ \t]*{\\|\\.\\)")
+           '(1 font-lock-function-name-face))
+
+     ))
+  "Major keywords")
+
+(defconst edje-font-lock-keywords-2
+  (eval-when-compile
+    (append edje-font-lock-keywords-1
+            (list
+             (list
+              (concat "^\\([ \t]*\\|[ \t]*[a-z]+\\.\\|\\)\\<"
+                      (regexp-opt
+                       '("action"
+                         "after"
+                         "alias"
+                         "align"
+                         "angle"
+                         "aspect"
+                         "aspect_preference"
+                         "base"
+                         "border"
+                         "clip_to"
+                         "collections"
+                         "color"
+                         "color2"
+                         "color3"
+                         "color_class"
+                         "color_classes"
+                         "confine"
+                         "data"
+                         "description"
+                         "dragable"
+                         "effect"
+                         "elipsis"
+                         "events"
+                         "fill"
+                         "fit"
+                         "fixed"
+                         "font"
+                         "fonts"
+                         "gradient"
+                         "group"
+                         "ignore_flags"
+                         "image"
+                         "images"
+                         "in"
+                         "inherit"
+                         "item"
+                         "max"
+                         "middle"
+                         "min"
+                         "mouse_events"
+                         "name"
+                         "normal"
+                         "offset"
+                         "origin"
+                         "part"
+                         "parts"
+                         "pointer_mode"
+                         "precise_is_inside"
+                         "program"
+                         "programs"
+                         "rel1"
+                         "rel2"
+                         "relative"
+                         "repeat_events"
+                         "signal"
+                         "size"
+                         "smooth"
+                         "source"
+                         "spectra"
+                         "spectrum"
+                         "spread"
+                         "state"
+                         "step"
+                         "style"
+                         "styles"
+                         "tag"
+                         "target"
+                         "text"
+                         "text_class"
+                         "text_source"
+                         "to"
+                         "to_x"
+                         "to_y"
+                         "transition"
+                         "tween"
+                         "type"
+                         "use_alternate_font_metrics"
+                         "visible"
+                         "x"
+                         "y"
+                         ) t) "\\>[ \t]*[:,]")
+              '(2 font-lock-keyword-face))
+             )))
+  "Minor keywords")
+
+(defconst edje-font-lock-keywords-3
+  (eval-when-compile
+    (append edje-font-lock-keywords-2
+            (list
+             (list
+              (concat "\\<"
+                      (regexp-opt
+                       '(; image options (st_images_image)
+                         "RAW"
+                         "COMP"
+                         "LOSSY"
+                         "USER"
+                         ; part types (st_collections_group_parts_part_type)
+                         "NONE"
+                         "RECT"
+                         "TEXT"
+                         "IMAGE"
+                         "SWALLOW"
+                         "TEXTBLOCK"
+                         "GRADIENT"
+                         "GROUP"
+                         ; ignore flags (st_collections_group_parts_part_ignore_flags)
+                         ;"NONE"
+                         "ON_HOLD"
+                         ; pointer mode (st_collections_group_parts_part_pointer_mode)
+                         "AUTOGRAB"
+                         "NOGRAB"
+                         ; aspect (st_collections_group_parts_part_description_aspect_preference)
+                         "NONE"
+                         "VERTICAL"
+                         "HORIZONTAL"
+                         "BOTH"
+                         ; text effect (st_collections_group_parts_part_effect)
+                         "NONE"
+                         "PLAIN"
+                         "OUTLINE"
+                         "SOFT_OUTLINE"
+                         "SHADOW"
+                         "SOFT_SHADOW"
+                         "OUTLINE_SHADOW"
+                         "OUTLINE_SOFT_SHADOW"
+                         "FAR_SHADOW"
+                         "FAR_SOFT_SHADOW"
+                         "GLOW"
+                         ; image fill (st_collections_group_parts_part_description_fill_type)
+                         "SCALE"
+                         "TILE"
+                         ; program action (st_collections_group_programs_program_action)
+                         "STATE_SET"
+                         "ACTION_STOP"
+                         "SIGNAL_EMIT"
+                         "DRAG_VAL_SET"
+                         "DRAG_VAL_STEP"
+                         "DRAG_VAL_PAGE"
+                         "SCRIPT"
+                         ; program transition (st_collections_group_programs_program_transition)
+                         "LINEAR"
+                         "SINUSOIDAL"
+                         "ACCELERATE"
+                         "DECELERATE"
+                         ) t) "\\>")
+              '(1 font-lock-builtin-face))
+             )))
+  "Enumerate values")
+
+(defconst edje-font-lock-keywords-4
+  (eval-when-compile
+    (append edje-font-lock-keywords-3
+            (list
+             (list
+              (concat "[ \t]*#"
+                      (regexp-opt
+                       '("if"
+                         "ifdef"
+                         "ifndef"
+                         "define"
+                         "else"
+                         "endif"
+                         "include"
+                         "undef") t) "[ \t]*")
+              '(1 font-lock-builtin-face))
+             )))
+  "CPP directives")
+
+(defconst edje-font-lock-keywords-5
+  (eval-when-compile
+    (append edje-font-lock-keywords-4
+            (list
+             (list "[ \t]*#undef[ \t]+\\([a-zA-Z_][a-zA-Z0-9_]*\\)"
+                   '(1 font-lock-variable-name-face))
+             (list "[ \t]*#define[ \t]+\\([a-zA-Z_][a-zA-Z0-9_]*\\)("
+                   '(1 font-lock-function-name-face))
+             (list "[ \t]*#define[ \t]+\\([a-zA-Z_][a-zA-Z0-9_]*\\)"
+                   '(1 font-lock-variable-name-face))
+             )))
+  "CPP directives that define constants")
+
+
+(defvar edje-font-lock-keywords edje-font-lock-keywords-5)
+
+(defvar edje-mode-syntax-table
+  (let ((edje-mode-syntax-table (make-syntax-table)))
+    ; This is added so entity names with underscores can be more easily parsed
+    (modify-syntax-entry ?_ "w" edje-mode-syntax-table)
+    (modify-syntax-entry ?/ ". 124b" edje-mode-syntax-table)
+    (modify-syntax-entry ?* ". 23" edje-mode-syntax-table)
+    (modify-syntax-entry ?\n "> b" edje-mode-syntax-table)
+
+    edje-mode-syntax-table)
+  "Syntax table for edje-mode")
+
+(c-add-style
+ "edje"
+ '("gnu"
+   (indent-tabs-mode . nil)
+   (tab-width . 8)
+   (c-basic-offset . 3)
+   (c-backslash-column . 72)
+   (c-hanging-braces-alist  .
+                            ((block-open after)
+                             (brace-list-open after)
+                             (substatement-open after))
+                            )
+   (c-offsets-alist         .
+                            ((statement-block-intro . +)
+                             (defun-open            . 0)
+                             (substatement-open     . 0)
+                             (defun-block-intro     . +)
+                             (block-open            . 0)
+                             (label                 . +)
+                             ))))
+
+
+(define-derived-mode edje-mode c-mode "Edje"
+  "Major mode for editing Edje files"
+  (interactive)
+  (use-local-map edje-mode-map)
+  (set-syntax-table edje-mode-syntax-table)
+  (set (make-local-variable 'font-lock-defaults) '(edje-font-lock-keywords))
+  (set (make-local-variable 'require-final-newline) t)
+  (c-set-style "edje")
+  (run-hooks 'edje-mode-hook)
+  )
+
+(provide 'edje-mode)
+
+;;; edje-mode.el ends here
diff --git a/data/include/.cvsignore b/data/include/.cvsignore
new file mode 100644 (file)
index 0000000..282522d
--- /dev/null
@@ -0,0 +1,2 @@
+Makefile
+Makefile.in
diff --git a/data/include/Makefile.am b/data/include/Makefile.am
new file mode 100644 (file)
index 0000000..478813c
--- /dev/null
@@ -0,0 +1,10 @@
+
+MAINTAINERCLEANFILES = Makefile.in
+
+FILES = edje.inc
+
+incdir = $(pkgdatadir)/include
+inc_DATA = $(FILES)
+
+EXTRA_DIST = $(FILES)
+
diff --git a/data/include/edje.inc b/data/include/edje.inc
new file mode 100644 (file)
index 0000000..7179c1c
--- /dev/null
@@ -0,0 +1,228 @@
+/* ************************** */
+/* This is for script-only objects */
+/* ************************** */
+
+native e_obj_del(obj);
+
+native e_obj_rect_add();
+
+native e_obj_show(obj);
+native e_obj_hide(obj);
+native e_obj_move(obj, x, y);
+native e_obj_resize(obj, w, h);
+native e_obj_geometry_set(obj, x, y, w, h);
+native e_obj_geometry_get(obj, &x, &y, &w, &h);
+native e_obj_color_set(obj, r, g, b, a);
+native e_obj_color_get(obj, &r, &g, &b, &a);
+
+/* threw this in for debug... but need it */
+native e_signal_emit(sig[], src[]);
+
+
+
+
+
+
+
+
+
+
+
+
+
+/* ************************** */
+/* The below is for non-script-only objects. these calls will not work for */
+/* script-only objects. above are for script-only. perhaps this will be */
+/* deprecated sometime? or merged to the above partly? */
+/* ************************** */
+
+/* Edje exported calls */
+
+/************************************************/
+/* Basic data storage/retrieval (it's explicit) */
+/************************************************/
+/* Example:
+ * 
+ * In the "global" script section of a group:
+ * 
+ * script {
+ *   public global_value1;
+ *   public global_value2;
+ *   public global_value3;
+ * }
+ * 
+ * In the program script sections, OR in any global functions/routines:
+ * ( several examples of setting/getting values)
+ * 
+ * set_int(global_value1, 7);
+ * set_float(global_value2, 42.0);
+ * set_str(global_value3, "I am a smelly fish!");
+ * new value1 = get_int(global_value1);
+ * new Float:value2 = get_float(global_value2);
+ * new value3[100]; get_str(global_value3, value3, 100);
+ * set_int(global_value1, value1);
+ * set_float(global_value2, value2);
+ * set_str(global_value3, value3);
+ */
+native       get_int   (id);
+native       set_int   (id, val);
+native Float:get_float (id);
+native       set_float (id, Float:val);
+native       get_strlen(id);
+native       get_str   (id, dst[], maxlen);
+native       set_str   (id, str[]);
+
+/********************/
+/* Edje list calls */
+/********************/
+native       count      (id);
+native       remove     (id, n);
+native       append_int (id, v);
+native       prepend_int(id, v);
+native       insert_int (id, pos, v);
+native       replace_int (id, pos, v);
+native       fetch_int  (id, pos);
+native       append_str (id, str[]);
+native       prepend_str(id, str[]);
+native       insert_str (id, pos, str[]);
+native       replace_str(id, pos, str[]);
+native       fetch_str  (id, pos, dst[], maxlen);
+native       append_float (id, Float:v);
+native       prepend_float(id, Float:v);
+native       insert_float (id, pos, Float:v);
+native       replace_float(id, pos, Float:v);
+native Float:fetch_float  (id, pos);
+
+/********************/
+/* Edje timer calls */
+/********************/
+native       timer       (Float:in, fname[], val);
+native       cancel_timer(id);
+
+/*******************/
+/* Edje anim calls */
+/*******************/
+native       anim       (Float:len, fname[], val);
+native       cancel_anim(id);
+
+/***********************************************************/
+/* Edje utility calls for dealing with edjes/programs etc. */
+/***********************************************************/
+/* Example:
+ * 
+ * emit("this_thing", "clicked");
+ * emit("state", "playing");
+ * 
+ * set_state(PART:"logo", "glowing", 0.0);
+ * set_state(PART:"button", "default", 0.0);
+ * 
+ * set_tween_state(PART:"button", 0.5, "default", 0.0, "clicked", 0.0);
+ * 
+ * run_program(PROGRAM:"program_name");
+ */
+native       emit             (sig[], src[]);
+native       set_state        (part_id, state[], Float:state_val);
+native       get_state        (part_id, dst[], maxlen, &Float:val);
+native       set_tween_state  (part_id, Float:tween, state1[], Float:state1_val, state2[], Float:state2_val);
+native       run_program      (program_id);
+native       get_drag_dir     (part_id);
+native       get_drag         (part_id, &Float:dx, &Float:dy);
+native       set_drag         (part_id, Float:dx, Float:dy);
+native       get_drag_size    (part_id, &Float:dx, &Float:dy);
+native       set_drag_size    (part_id, Float:dx, Float:dy);
+native       get_drag_step    (part_id, &Float:dx, &Float:dy);
+native       set_drag_step    (part_id, Float:dx, Float:dy);
+native       get_drag_page    (part_id, &Float:dx, &Float:dy);
+native       set_drag_page    (part_id, Float:dx, Float:dy);
+native       set_text         (part_id, str[]);
+native       get_text         (part_id, dst[], maxlen);
+native       get_min_size     (&w, &h);
+native       get_max_size     (&w, &h);
+native       get_color_class  (class[], &r, &g, &b, &a);
+native       set_color_class  (class[], r, g, b, a);
+native       set_text_class   (class[], font[], Float:size);
+native       get_text_class   (class[], font[], &Float:size);
+native       get_geometry     (part_id, &x, &y, &w, &h);
+native       get_mouse        (&x, &y);
+native       get_mouse_buttons();
+native       stop_program     (program_id);
+native       stop_programs_on (part_id);
+native       set_min_size     (Float:w, Float:h);
+native       set_max_size     (Float:w, Float:h);
+native       part_swallow     (part_id, GROUP:str[]);
+
+enum Msg_Type
+{
+   MSG_NONE = 0,
+     MSG_STRING = 2,
+     MSG_INT = 3,
+     MSG_FLOAT = 4,
+     MSG_STRING_SET = 5,
+     MSG_INT_SET = 6,
+     MSG_FLOAT_SET = 7,
+     MSG_STRING_INT = 8,
+     MSG_STRING_FLOAT = 9,
+     MSG_STRING_INT_SET = 10,
+     MSG_STRING_FLOAT_SET = 11
+};
+
+native send_message(Msg_Type:type, id, ...);
+
+/**********************/
+/* Custom state calls */
+/**********************/
+
+/* Example:
+ *
+ * Create the custom state for "my_part", based on the
+ * default description of the same part:
+ *
+ * custom_state(PART:"my_part", "default", 0.0);
+ *
+ * Later, use set_state_val() to change the properties of the custom
+ * state:
+ *
+ * set_state_val(PART:"my_part", STATE_ALIGNMENT, 0.5, 0.5);
+ *
+ * get_state_val() works the same way.
+ */
+
+native custom_state(part_id, state[], Float:state_val = 0.0);
+
+enum State_Param
+{
+       STATE_ALIGNMENT = 1,
+       STATE_MIN = 2,
+       STATE_MAX = 3,
+       STATE_STEP = 4,
+       STATE_ASPECT = 5,
+       STATE_ASPECT_PREF = 6,
+       STATE_COLOR = 7,
+       STATE_COLOR2 = 8,
+       STATE_COLOR3 = 9,
+       STATE_COLOR_CLASS = 10,
+       STATE_REL1 = 11,
+       STATE_REL1_TO = 12,
+       STATE_REL1_OFFSET = 13,
+       STATE_REL2 = 14,
+       STATE_REL2_TO = 15,
+       STATE_REL2_OFFSET = 16,
+       STATE_IMAGE = 17,
+       STATE_BORDER = 18,
+       STATE_FILL_SMOOTH = 19,
+       STATE_FILL_POS = 20,
+       STATE_FILL_SIZE = 21,
+       STATE_TEXT = 22,
+       STATE_TEXT_CLASS = 23,
+       STATE_TEXT_FONT = 24,
+       STATE_TEXT_STYLE = 25,
+       STATE_TEXT_SIZE = 26,
+       STATE_TEXT_FIT = 27,
+       STATE_TEXT_MIN = 28,
+       STATE_TEXT_MAX = 29,
+       STATE_TEXT_ALIGN = 30,
+       STATE_VISIBLE = 31
+};
+
+native set_state_val(part_id, State_Param:p, ...);
+native get_state_val(part_id, State_Param:p, ...);
diff --git a/debian/.cvsignore b/debian/.cvsignore
new file mode 100644 (file)
index 0000000..6d10dce
--- /dev/null
@@ -0,0 +1 @@
+changelog
diff --git a/debian/changelog.in b/debian/changelog.in
new file mode 100644 (file)
index 0000000..aab92de
--- /dev/null
@@ -0,0 +1,6 @@
+edje (@VERSION@-1) unstable; urgency=low
+
+  * a CVS snapshot release.
+
+ -- Falko Schmidt <falko@alphagemini.org>  Mon, 28 Apr 2008 15:54:13 +0000
+
diff --git a/debian/compat b/debian/compat
new file mode 100644 (file)
index 0000000..1e8b314
--- /dev/null
@@ -0,0 +1 @@
+6
diff --git a/debian/control b/debian/control
new file mode 100644 (file)
index 0000000..841d05e
--- /dev/null
@@ -0,0 +1,73 @@
+Source: edje
+Section: libs
+Priority: optional
+Maintainer: Falko Schmidt <falko@alphagemini.org>
+Build-Depends: debhelper (>= 6), cdbs, libeet-dev, libevas-dev, libecore-dev,
+ libembryo-dev, doxygen
+Standards-Version: 3.7.3
+Homepage: http://www.enlightenment.org
+
+Package: libedje-bin
+Architecture: any
+Section: devel
+Depends: ${shlibs:Depends}, libembryo-bin, libevas-engines 
+Provides: libedje0-bin
+Description: Various binaries for use with libedje
+ Edje is a graphical layout and animation library for animated resizable,
+ compressed and scalable themes. It is the theming engine behind
+ Enlightenment DR 0.17.
+ .
+ This package contains the following binaries:
+  - edje_cc: Compiles EDC files.
+  - edje_decc: Used to decompile compiled edje files.
+  - edje_recc: A convenience script to recompile EDC files.
+
+Package: libedje0
+Architecture: any
+Depends: ${shlibs:Depends}
+Provides: libedje
+Suggests: libedje-bin (= ${binary:Version})
+Description: Graphical layout and animation library
+ Edje is a graphical layout and animation library for animated resizable,
+ compressed and scalable themes. It is the theming engine behind
+ Enlightenment DR 0.17.
+
+Package: libedje-doc
+Architecture: all
+Section: doc
+Enhances: libedje-dev
+Provides: libedje0-doc
+Description: libedje0 development documentation
+ Edje is a graphical layout and animation library for animated resizable,
+ compressed and scalable themes. It is the theming engine behind
+ Enlightenment DR 0.17.
+ .
+ This package provides development documentation for Edje.
+Package: libedje-dev
+Architecture: any
+Section: libdevel
+Depends: libedje0 (= ${binary:Version}), libeet-dev, libecore-dev, libevas-dev, libembryo-dev, pkg-config
+Provides: libedje0-dev
+Description: libedje headers and static libraries
+ Edje is a graphical layout and animation library for animated resizable,
+ compressed and scalable themes. It is the theming engine behind
+ Enlightenment DR 0.17.
+ .
+ This package provides headers and shared libraries for Edje.
+
+Package: libedje-dbg
+Architecture: any
+Section: libdevel
+Priority: extra
+Depends: libedje0 (= ${binary:Version})
+Provides: libedje0-dbg
+Description: Graphical layout and animation library
+ Edje is a graphical layout and animation library for animated resizable,
+ compressed and scalable themes. It is the theming engine behind
+ Enlightenment DR 0.17.
+ .
+ This package contains unstripped shared libraries. It is provided primarily
+ to provide a backtrace with names in a debugger, this makes it somewhat
+ easier to interpret core dumps. The libraries are installed in
+ /usr/lib/debug and are automatically used by gdb.
diff --git a/debian/copyright b/debian/copyright
new file mode 100644 (file)
index 0000000..600a6e5
--- /dev/null
@@ -0,0 +1,42 @@
+This package was debianized by Falko Schmidt <falko@alphagemini.org> on
+Sat, 20 Apr 2008 22:50:45 +0000.
+
+The source code is from the e17/libs/edje module of the enlightenment CVS
+tree. For more information, see:
+
+ http://www.enlightenment.org
+Upstream Authors:
+       
+       Carsten Haitzler <raster@rasterman.com>
+
+Copyright:
+
+       Copyright (C) 2000 Carsten Haitzler and various contributors (see AUTHORS)
+License:
+
+  Permission is hereby granted, free of charge, to any person obtaining a copy
+  of this software and associated documentation files (the "Software"), to
+  deal in the Software without restriction, including without limitation the
+  rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+  sell copies of the Software, and to permit persons to whom the Software is
+  furnished to do so, subject to the following conditions:
+    
+  The above copyright notice and this permission notice shall be included in
+  all copies of the Software, its documentation and marketing & publicity 
+  materials, and acknowledgment shall be given in the documentation, materials
+  and software packages that this Software was used.
+     
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+  THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 
+  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+On Debian systems, the complete text of the BSD License can be found
+in `/usr/share/common-licenses/BSD'.
+
+The Debian packaging is:
+  (C) 2006 2007,Debian Pkg-e Team <pkg-e-devel@lists.alioth.debian.org>
+  and is licensed under the GPL, see `/usr/share/common-licenses/GPL'.
diff --git a/debian/edje_cc.1 b/debian/edje_cc.1
new file mode 100644 (file)
index 0000000..62f8685
--- /dev/null
@@ -0,0 +1,47 @@
+.TH EDJE_CC 1 "Jan 29, 2007" "0.5.0.042" "The edje compiler"
+.SH NAME
+edje_cc - an edje compiler
+.SH SYNOPSIS
+.B edje_cc
+.RI [\| OPTIONS \|]
+.B input_file.edc
+.RI [\| output_file.edj \|]
+.SH DESCRIPTION
+edje_cc is a compiler for edje files
+.SH EXAMPLES
+edje_cc -v file.edc
+.SH OPTIONS
+.BI \-id " \|image/directory
+Add a directory to look in for relative path images
+.P
+.BI \-fd " \|font/directory
+Add a directory to look in for relative path fonts
+.P
+.B \-v
+Verbose output
+.P
+.B \-no\-lossy
+Do NOT allow images to be lossy
+.P
+.B \-no\-comp
+Do NOT allow images to be stored with lossless compression
+.P
+.B \-no\-raw
+Do NOT allow images to be stored with zero compression (raw)
+.P
+.BI \-min\-quality " \|VAL
+Do NOT allow lossy images with quality < VAL (0-100)
+.P
+.BI \-max\-quality " \|VAL
+Do NOT allow lossy images with quality > VAL (0-100)
+.P
+.BI \-Ddefine_val= " \|to
+CPP style define to define input macro definitions to the .edc source
+.SH SEE ALSO
+edje_decc(1)
+.BR
+edje_recc(1)
+.SH BUGS
+Please reports bugs to the Pkg-E Team <pkg-e-devel@lists.alioth.debian.org>
+.SH AUTHOR
+This man page was written by Ronald Claveau for the Debian GNU/Linux system (but may  be  used by others).
diff --git a/debian/edje_decc.1 b/debian/edje_decc.1
new file mode 100644 (file)
index 0000000..d79785a
--- /dev/null
@@ -0,0 +1,16 @@
+.TH EDJE_DECC 1 "Jan 30, 2007" "0.5.0.042" "The edje decompiler"
+.SH NAME
+edje_decc \- an edje decompiler
+.SH SYNOPSIS
+.B edje_decc
+.B input_file.edj
+.SH DESCRIPTION
+edje_decc is a decompiler for edje files.
+.SH SEE ALSO
+edje_cc(1)
+.BR
+edje_recc(1)
+.SH BUGS
+Please reports bugs to the Pkg-E Team <pkg-e-devel@lists.alioth.debian.org>
+.SH AUTHOR
+This man page was written by Ronald Claveau for the Debian GNU/Linux system (but may  be  used by others).
diff --git a/debian/edje_recc.1 b/debian/edje_recc.1
new file mode 100644 (file)
index 0000000..985118d
--- /dev/null
@@ -0,0 +1,37 @@
+.TH EDJE_RECC 1 "Jan 30, 2007" "0.5.0.042" "The edje recompiler"
+.SH NAME
+edje_recc \- an edje recompiler
+.SH SYNOPSIS
+.B edje_recc
+.RI [\| OPTIONS \|]
+.B input_file.edj
+.SH DESCRIPTION
+edje_recc is a recompiler for edje files.
+.SH EXAMPLES
+edje_recc -v file.edj
+.SH OPTIONS
+.B -v
+Verbose output
+.P
+.B -no-lossy
+Do NOT allow images to be lossy
+.P
+.B -no-comp
+Do NOT allow images to be stored with lossless compression
+.P
+.B -no-raw
+Do NOT allow images to be stored with zero compression (raw)
+.P
+.BI -min-quality " \|VAL
+Do NOT allow lossy images with quality < VAL (0-100)
+.P
+.BI -max-quality " \|VAL
+Do NOT allow lossy images with quality > VAL (0-100)
+.SH SEE ALSO
+edje_cc(1)
+.BR
+edje_decc(1)
+.SH BUGS
+Please reports bugs to the Pkg-E Team <pkg-e-devel@lists.alioth.debian.org>
+.SH AUTHOR
+This man page was written by Ronald Claveau for the Debian GNU/Linux system (but may  be  used by others).
diff --git a/debian/libedje-bin.install b/debian/libedje-bin.install
new file mode 100644 (file)
index 0000000..8f5682f
--- /dev/null
@@ -0,0 +1,4 @@
+debian/tmp/usr/bin/edje_cc
+debian/tmp/usr/bin/edje_decc
+debian/tmp/usr/bin/edje_recc
+debian/tmp/usr/share/edje/include/edje.inc
diff --git a/debian/libedje-bin.manpages b/debian/libedje-bin.manpages
new file mode 100644 (file)
index 0000000..e2b8466
--- /dev/null
@@ -0,0 +1 @@
+debian/edje_*.1
diff --git a/debian/libedje-dev.install b/debian/libedje-dev.install
new file mode 100644 (file)
index 0000000..0794b58
--- /dev/null
@@ -0,0 +1,4 @@
+debian/tmp/usr/include/*
+debian/tmp/usr/lib/*.a
+debian/tmp/usr/lib/*.so
+debian/tmp/usr/lib/pkgconfig/*
diff --git a/debian/libedje-doc.dirs b/debian/libedje-doc.dirs
new file mode 100644 (file)
index 0000000..419b09b
--- /dev/null
@@ -0,0 +1 @@
+usr/share/doc/libedje-doc
diff --git a/debian/libedje-doc.doc-base b/debian/libedje-doc.doc-base
new file mode 100644 (file)
index 0000000..5e51436
--- /dev/null
@@ -0,0 +1,10 @@
+Document: edje
+Title: Edje Guide
+Author: Carsten Haitzler
+Abstract: This document describes Edje API
+ and provides sample C code.
+Section: Programming/C
+
+Format: HTML
+Index: /usr/share/doc/libedje-doc/html/index.html
+Files: /usr/share/doc/libedje-doc/html/*.html
diff --git a/debian/libedje0.install b/debian/libedje0.install
new file mode 100644 (file)
index 0000000..c45ebcf
--- /dev/null
@@ -0,0 +1 @@
+debian/tmp/usr/lib/lib*.so.*
diff --git a/debian/rules b/debian/rules
new file mode 100644 (file)
index 0000000..dda320f
--- /dev/null
@@ -0,0 +1,21 @@
+#!/usr/bin/make -f
+
+include /usr/share/cdbs/1/rules/debhelper.mk
+include /usr/share/cdbs/1/class/autotools.mk
+
+#DEB_INSTALL_MANPAGES_libedje-doc := $(DEB_SRCDIR)/doc/man/man3/*.3
+DEB_DH_STRIP_ARGS := --dbg-package=libedje-dbg
+DEB_CONFIGURE_EXTRA_FLAGS := --disable-rpath
+
+build/libedje-doc::
+       cd $(DEB_SRCDIR) && doxygen
+
+install/libedje-doc::
+       cp -R $(DEB_SRCDIR)/doc/html debian/libedje-doc/usr/share/doc/libedje-doc/
+
+clean::
+       rm -rf $(DEB_SRCDIR)/doc/html $(DEB_SRCDIR)/doc/latex $(DEB_SRCDIR)/doc/man
+       mkdir -p $(DEB_SRCDIR)/doc/html
+       cp $(DEB_SRCDIR)/doc/img/*.png $(DEB_SRCDIR)/doc/html/
+       cp $(DEB_SRCDIR)/doc/img/*.gif $(DEB_SRCDIR)/doc/html/
+       ./autogen.sh --prefix=/usr $(DEB_CONFIGURE_EXTRA_FLAGS)
diff --git a/doc/.cvsignore b/doc/.cvsignore
new file mode 100644 (file)
index 0000000..cc370ed
--- /dev/null
@@ -0,0 +1,3 @@
+html
+latex
+man
diff --git a/doc/e.css b/doc/e.css
new file mode 100644 (file)
index 0000000..604ee7f
--- /dev/null
+++ b/doc/e.css
@@ -0,0 +1,161 @@
+body {
+    background: url("b.png");
+    background-repeat: repeat-x;
+    background-position: top left;
+    background-color: #f4f4f4;
+    text-align: center;
+    font-family: sans-serif;
+    padding: 0;
+    margin: 0;
+}
+
+div.main {
+    margin: 1em auto;
+    vertical-align: top;
+    font-family: "Bitstream Vera", "Vera", "Trebuchet MS", Trebuchet, Tahoma, sans-serif;
+    color: #444444;
+    font-size: 0.8em;
+    text-align: justify;
+    width: 80%;
+}
+
+td.t { background-image:url("t.gif"); }
+td.t[class] { background-image:url("t.png"); }
+td.tl { background-image:url("tl.gif"); }
+td.tl[class] { background-image:url("tl.png"); }
+
+td.nav, td.lnav,  td.rnav {
+   align: middle;
+   text-align: center;
+   vertical-align: middle;
+   width: 100px;
+   height: 25px;
+   font-family: "Bitstream Vera", "Vera", "Trebuchet MS", Trebuchet, Tahoma, sans-serif;
+   color: #000000;
+   font-size: 9px;
+   font-weight: bold;
+   white-space: no-wrap;
+}  
+
+td.lnav[class] { background-image:url("n.png"); }
+td.lnav[class] { background-image:url("n.png"); }
+td.rnav { background-image:url("n.gif"); }
+td.rnav[class] { background-image:url("n.png"); }
+
+hr {
+    width: 200px;
+    height: 1px;
+    background: #dddddd;
+    border: 0;
+}
+
+p { color: #444444 ;}
+p.tiny, small {
+    color: #888888;
+    font-size: 0.5em;
+}
+
+h1 { 
+    text-align: center;
+    font-size: 1.3em; 
+}
+
+h2 { font-size: 1.1em; }
+h3 { font-size: 0.9em; }
+
+span.keyword { color: #008000; }
+span.keywordtype { color: #604020; }
+span.keywordflow { color: #e08000; }
+span.comment { color: #800000; }
+span.preprocessor { color: #806020; }
+span.stringliteral { color: #002080; }
+span.charliteral { color: #008080; }
+
+a:link {
+    color: #445566;
+    text-decoration: underline;
+}  
+   
+a:visited {
+    color: #667788;
+    text-decoration: underline;
+}  
+
+a:active {                
+    color: #88cccc;
+    text-decoration: none;
+}
+
+a:hover {
+    color: #112266;
+    text-decoration: underline;
+}  
+
+a.nav {
+    text-decoration: none;
+    display: block;
+}
+a.nav:link, a.nav:visited { color: #888888; }
+a.nav:active { color: #000000; }
+a.nav:hover { color: #444444; }
+a.code:link, a.code:visited { text-decoration: none; }
+
+div.fragment {
+    font-size: 1em;
+    border: 1px dotted #cccccc;
+    background-color: #ffffff;
+    text-align: left;
+    vertical-align: middle;
+    padding: 2px;
+    margin-left: 25px;
+    margin-right: 25px;
+    overflow: auto;
+}
+
+td.indexkey {
+    font-weight: bold;
+    padding-left: 10px;
+    padding-right: 0;
+    padding-top: 2px;
+    padding-bottom: 0px;
+    margin: 0;
+    margin-top: 2px;
+    margin-bottom: 2px;
+    border: 1px dotted #cccccc;
+    border-right: 0px dotted #cccccc;
+}
+
+td.indexvalue {
+    font-style: italic;
+    padding-right: 10px;
+    padding-left: 0;
+    padding-top: 2px;
+    padding-bottom: 2px;
+    margin: 0;
+    margin-top: 2px;
+    margin-bottom: 2px;
+    border: 1px dotted #cccccc;
+    border-left: 0px dotted #cccccc;
+}
+
+.mdescRight { font-style: italic; }
+.memitem {
+    padding-left: 2px;
+    padding-right: 2px;
+    border: 1px dotted #cccccc;
+    background-color: #ffffff;
+}
+.memname {
+    white-space: nowrap;
+    font-weight: bold;
+}
+.paramname { font-weight: normal; }
+
+div.ah {
+    border: thin solid #888888;
+    font-weight: bold;
+    margin-bottom: 3px;
+    margin-top: 3px;
+}
+
diff --git a/doc/edje.css b/doc/edje.css
new file mode 100644 (file)
index 0000000..7f2887a
--- /dev/null
@@ -0,0 +1,189 @@
+td.md { 
+ background-color: #ffffff;
+ font-family: monospace;
+ text-align: left;
+ vertical-align: center;
+ font-size: 10;
+ padding-right  : 1px; 
+ padding-top    : 1px; 
+ padding-left   : 1px; 
+ padding-bottom : 1px; 
+ margin-left    : 1px; 
+ margin-right   : 1px; 
+ margin-top     : 1px; 
+ margin-bottom  : 1px  
+}
+td.mdname { 
+ font-family: monospace;
+ text-align: left;
+ vertical-align: center;
+ font-size: 10;
+ padding-right  : 1px; 
+ padding-top    : 1px; 
+ padding-left   : 1px; 
+ padding-bottom : 1px; 
+ margin-left    : 1px; 
+ margin-right   : 1px; 
+ margin-top     : 1px; 
+ margin-bottom  : 1px  
+}
+h1
+{
+ text-align: center;
+ color: #333333
+}
+h2
+{
+ text-align: left;
+ color: #333333
+}
+h3
+{
+ text-align: left;
+ color: #333333
+}
+a:link
+{
+ text-decoration: none;
+ color: #444444;
+ font-weight: bold;
+}
+a:visited
+{
+ text-decoration: none;
+ color: #666666;
+ font-weight: bold;
+}
+a:hover
+{
+ text-decoration: none;
+ color: #000000;
+ font-weight: bold;
+}
+a.nav:link
+{
+ text-decoration: none;
+ color: #444444;
+ font-weight: normal;
+}
+a.nav:visited
+{
+ text-decoration: none;
+ color: #666666;
+ font-weight: normal;
+}
+a.nav:hover
+{
+ text-decoration: none;
+ color: #000000;
+ font-weight: normal;
+}
+a.qindex:link
+{
+ text-decoration: none;
+ color: #444444;
+ font-weight: normal;
+}
+a.qindex:visited
+{
+ text-decoration: none;
+ color: #666666;
+ font-weight: normal;
+}
+a.qindex:hover
+{
+ text-decoration: none;
+ color: #000000;
+ font-weight: normal;
+}
+p
+{
+ color: #000000;
+ font-family: sans-serif;
+ font-size: 10;
+}
+body { 
+ background-image: url("hilite.png");
+ background-repeat: no-repeat;
+ background-position: left top;
+ background-color: #dddddd;
+ color: #000000;
+ font-family: sans-serif;
+ padding: 8px;
+ margin: 0;
+}
+div.fragment
+{
+ background-image: url("hilite.png");
+ background-repeat: no-repeat;
+ background-position: left top;
+ border: thin solid #888888;
+ background-color: #eeeeee;
+ padding: 4px;
+ text-align: left;
+ vertical-align: center;
+ font-size: 12;
+}
+hr
+{
+ border: 0;
+ background-color: #000000;
+ width: 80%;
+ height: 1;
+}
+dl
+{
+ background-image: url("hilite.png");
+ background-repeat: no-repeat;
+ background-position: left top;
+ border: thin solid #aaaaaa;
+ background-color: #eeeeee;
+ padding: 4px;
+ text-align: left;
+ vertical-align: center;
+ font-size: 12;
+}
+em
+{
+  color: #334466;
+  font-family: courier;
+  font-size: 10;
+  font-style: normal;
+}
+
+div.nav
+{
+ border: thin solid #000000;
+ background-color: #ffffff;
+ padding: 1px;
+ text-align: center;
+ vertical-align: center;
+ font-size: 12;
+}
+div.body
+{
+ border: thin solid #000000;
+ background-color: #ffffff;
+ padding: 4px;
+ text-align: left;
+ font-size: 10; 
+}
+div.diag
+{
+ border: thin solid #888888;
+ background-color: #eeeeee;
+ padding: 4px;
+ text-align: center;
+ font-size: 8; 
+}
+table.edcref {
+ border-collapse: collapse;
+}
+table.edcref td {
+ border-style: hidden;
+ vertical-align:top;
+ padding: 0.5em;
+}
+td.property {
+    width: 5em;
+}
diff --git a/doc/foot.html b/doc/foot.html
new file mode 100644 (file)
index 0000000..0d3303d
--- /dev/null
@@ -0,0 +1,6 @@
+  </div>
+  <hr />
+  <p class="tiny">Copyright &copy; Enlightenment.org</p>
+  <p class="tiny">$projectname Documentation Generated: $datetime</p>
+ </body>
+</html>
diff --git a/doc/head.html b/doc/head.html
new file mode 100644 (file)
index 0000000..63d814a
--- /dev/null
@@ -0,0 +1,45 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+            "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html>
+ <head>
+  <title>$title</title>
+  <link href="e.css" rel="stylesheet" type="text/css" />
+ </head>
+
+<body>
+ <table width="100%" border="0" cellpadding="0" cellspacing="0">
+  <tr>
+   <td class="t" width="50%" valign="top" align="left">
+     <table width="100px" height="100px" border="0" cellpadding="0" cellspacing="0">
+     <tr><td class="lnav"><a class="nav" href="http://web.enlightenment.org/p.php?p=index">Home</a></td></tr>
+     <tr><td class="lnav"><a class="nav" href="http://web.enlightenment.org/p.php?p=news">News</a></td></tr>
+     <tr><td class="lnav"><a class="nav" href="http://web.enlightenment.org/p.php?p=about">About</a></td></tr>
+     <tr><td class="rnav"><a class="nav" href="http://web.enlightenment.org/p.php?p=download">Download</a></td></tr>
+    </table>
+   </td>
+   <td class="tl" width="612" height="250" valign="bottom" align="center">
+    <img src="_.gif" width="612" height="1" />
+    <table border="0" cellpadding="0" cellspacing="4px">
+     <tr>
+      <td class='nav'><a class='nav' href="index.html">Main Page</a></td>
+      <td class="nav"><a class="nav" href="edje_8c.html">Edje API</a></td>
+      <td class="nav"><a class="nav" href="edcref.html">EDC Reference</a></td>
+      <td class="nav"><a class="nav" href="Edje__Edit_8h.html">Edje Edit API</a></td>
+      <td class="nav"><a class="nav" href="todo.html">Todo</a></td>
+     </tr>
+    </table>
+    <hr />
+   </td>
+   <td class="t" width="50%" valign="top" align="right">
+    <table width="100px" height="100px" border="0" cellpadding="0" cellspacing="0">
+     <tr><td class="rnav"><a class="nav" href="http://web.enlightenment.org/p.php?p=support">Support</a></td></tr>
+     <tr><td class="lnav"><a class="nav" href="http://web.enlightenment.org/p.php?p=contribute">Contribute</a></td></tr>
+     <tr><td class="lnav"><a class="nav" href="http://web.enlightenment.org/p.php?p=contact">Contact</a></td></tr>
+     <tr><td class="lnav"><a class="nav" href="http://trac.enlightenment.org/e">Tracker</a></td></tr>
+    </table>
+   </td>
+  </tr>
+ </table>
+
+ <div class="main">
diff --git a/doc/img/_.gif b/doc/img/_.gif
new file mode 100644 (file)
index 0000000..60fa7a1
Binary files /dev/null and b/doc/img/_.gif differ
diff --git a/doc/img/b.png b/doc/img/b.png
new file mode 100644 (file)
index 0000000..04e5ac8
Binary files /dev/null and b/doc/img/b.png differ
diff --git a/doc/img/edje.png b/doc/img/edje.png
new file mode 100644 (file)
index 0000000..47597a8
Binary files /dev/null and b/doc/img/edje.png differ
diff --git a/doc/img/edje_big.png b/doc/img/edje_big.png
new file mode 100644 (file)
index 0000000..cd818f7
Binary files /dev/null and b/doc/img/edje_big.png differ
diff --git a/doc/img/edje_mini.png b/doc/img/edje_mini.png
new file mode 100644 (file)
index 0000000..f4f99f0
Binary files /dev/null and b/doc/img/edje_mini.png differ
diff --git a/doc/img/edje_small.png b/doc/img/edje_small.png
new file mode 100644 (file)
index 0000000..8bea367
Binary files /dev/null and b/doc/img/edje_small.png differ
diff --git a/doc/img/hilite.png b/doc/img/hilite.png
new file mode 100644 (file)
index 0000000..88a4381
Binary files /dev/null and b/doc/img/hilite.png differ
diff --git a/doc/img/n.gif b/doc/img/n.gif
new file mode 100644 (file)
index 0000000..28608c4
Binary files /dev/null and b/doc/img/n.gif differ
diff --git a/doc/img/n.png b/doc/img/n.png
new file mode 100644 (file)
index 0000000..2bb256f
Binary files /dev/null and b/doc/img/n.png differ
diff --git a/doc/img/t.gif b/doc/img/t.gif
new file mode 100644 (file)
index 0000000..cff3068
Binary files /dev/null and b/doc/img/t.gif differ
diff --git a/doc/img/t.png b/doc/img/t.png
new file mode 100644 (file)
index 0000000..06b6079
Binary files /dev/null and b/doc/img/t.png differ
diff --git a/doc/img/tl.gif b/doc/img/tl.gif
new file mode 100644 (file)
index 0000000..4455dbc
Binary files /dev/null and b/doc/img/tl.gif differ
diff --git a/doc/img/tl.png b/doc/img/tl.png
new file mode 100644 (file)
index 0000000..95ae5b6
Binary files /dev/null and b/doc/img/tl.png differ
diff --git a/edje.c.in b/edje.c.in
new file mode 100644 (file)
index 0000000..45a8182
--- /dev/null
+++ b/edje.c.in
@@ -0,0 +1,210 @@
+/** 
+@file
+@brief Edje Graphical Design Library
+These routines are used for Edje.
+*/
+
+/**
+
+@mainpage Edje Library Documentation
+@image html  edje.png
+@version 0.5.0
+@author Carsten Haitzler <raster\@rasterman.com>
+@date 2003-2004
+
+
+
+
+
+
+
+
+
+
+@section intro What is Edje?
+
+Edje is a complex graphical design & layout library.
+
+It's purpose is to be a sequel to "Ebits" which to date has serviced the
+needs of Enlightenment development for version 0.17. The original design
+parameters under which Ebits came about were a lot more restricted than
+the resulting use of them, thus Edje was born.
+
+Edje is a more complex layout engine compared to Ebits. It doesn't pretend to
+do containing and regular layout like a widget set. It still inherits the
+more simplistic layout ideas behind Ebits, but it now does them a lot more
+cleanly, allowing for easy expansion, and the ability to cover much more
+ground than Ebits ever could. For the purposes of Enlightenment 0.17, Edje
+should serve all the purposes of creating visual elements (borders of
+windows, scrollbars, etc.) and allow the designer the ability to animate,
+layout and control the look and feel of any program using Edje as its basic
+GUI constructor. This library allows for multiple collections of Layouts in
+one file, sharing the same image database and thus allowing a whole theme to
+be conveniently packaged into 1 file and shipped around.
+
+Edje, unlike Ebits, separates the layout and behavior logic. Edje files ship
+with an image database, used by all the parts in all the collections to
+source graphical data. It has a directory of logical part names pointing to
+the part collection entry ID in the file (thus allowing for multiple logical
+names to point to the same part collection, allowing for the sharing of data
+between display elements). Each part collection consists of a list of visual
+parts, as well as a list of programs. A program is a conditionally run
+program that if a particular event occurs (a button is pressed, a mouse enters
+or leaves a part) will trigger an action that may affect other parts. In this
+way a part collection can be "programmed" via its file as to hilight buttons
+when the mouse passes over them or show hidden parts when a button is clicked
+somewhere etc. The actions performed in changing from one state to another are
+also allowed to transition over a period of time, allowing animation.
+
+This separation and simplistic event driven style of programming can produce
+almost any look and feel one could want for basic visual elements. Anything
+more complex is likely the domain of an application or widget set that may
+use Edje as a convenient way of being able to configure parts of the display.
+
+
+
+
+
+
+
+
+
+
+@section requirements What does Edje require?
+
+Edje requires fairly little on your system. to use the Edje runtime library
+you need:
+
+  - Evas (library)
+  - Ecore (library)
+  - Eet (library)
+
+Evas needs to be build with the PNG and EET image loaders enabled at a
+minimum. Edje uses X for the test program, so you will need the SOFTWARE_X11
+engine built into Evas as well. A suggested configure list is below in the
+"cheat sheet" for Evas.
+
+Ecore needs the ECORE, ECORE_EVAS and ECORE_X modules built at a minimum.
+It's suggested to build all the Ecore modules, but the ECORE_FB modules is
+definitely optional.
+
+Eet has no options so just build and install it.
+
+It is suggested right now that you get the latest CVS versions of the
+required libraries. You also need to build them in the right order and make
+sure the right options are enabled in the required libraries. Here is a
+quick "cheat sheet" on how to get started.
+
+@verbatim
+1. You need Eet from the HEAD cvs branch (must be up-to-date)
+
+  cvs co e17/libs/eet
+  cd e17/libs/eet
+  ./autogen.sh
+  ./configure
+  make
+  sudo make install
+  cd
+
+2. You need Evas from the HEAD branch built with eet loader support.
+
+  cvs co e17/libs/evas
+  cd e17/libs/evas
+  ./autogen.sh
+  ./configure
+  make
+  sudo make install
+  cd
+  
+3. You need Ecore from the HEAD cvs branch
+
+  cvs co e17/libs/ecore
+  cd e17/libs/ecore
+  ./autogen.sh
+  ./configure
+  make
+  sudo make install
+  cd
+
+4. You need embryo from the HEAD cvs branch
+
+  cvs co e17/libs/embryo
+  cd e17/libs/embryo
+  ./autogen.sh
+  ./configure
+  make
+  sudo make install
+  cd
+
+@endverbatim
+
+
+
+
+
+
+
+
+
+@section compiling How to compile and test Edje
+
+Now you need to compile and install Edje.
+
+@verbatim
+  ./configure
+  make
+  sudo make install
+@endverbatim
+
+You now have it installed and ready to go, but you are missing data files. In
+data/ there are data sets for you to look at as examples. To try one out do:
+
+@verbatim
+   cd data
+   ./e_logo.sh
+   
+   edje ./e_logo.eet
+@endverbatim
+
+The Edje test program/viewer is able to view multiple Edje data sets. The
+following will view 3 of them at once in the one window (which you can resize
+to give you more space to move and resize the Edje data sets around):
+
+@verbatim
+  edje ./e_logo.eet ./e_logo.eet ./e_logo.eet
+@endverbatim
+
+
+
+
+
+
+
+
+
+
+
+@section details So how does this all work?
+
+Edje internally holds a geometry state machine and state graph of what is
+visible, not, where, at what size, with what colors etc. This is described
+to Edje from an Edje .eet file containing this information. These files can
+be produced by using edje_cc to take a text file (a .edc file) and "compile"
+an output .eet file that contains this information, images and any other
+data needed.
+
+
+
+
+
+
+
+
+
+
+@todo See src/lib/edje_private.h for a list of FIXME's
+@todo Complete documentation of API
+@todo Bytecode language for extending programs... but what/how?
+
+*/
diff --git a/edje.pc.in b/edje.pc.in
new file mode 100644 (file)
index 0000000..f4a3650
--- /dev/null
@@ -0,0 +1,14 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+datarootdir=@datarootdir@
+datadir=@datadir@/edje
+
+Name: edje
+Description: Enlightened graphical design and layout engine. 
+Requires: evas
+Version: @VERSION@
+Libs: -L${libdir} -ledje
+Libs.private: @EDJE_LIBS@
+Cflags: -I${includedir}
diff --git a/edje.spec.in b/edje.spec.in
new file mode 100644 (file)
index 0000000..b212286
--- /dev/null
@@ -0,0 +1,96 @@
+%define _missing_doc_files_terminate_build 0
+
+Summary: Complex Graphical Design/Layout Engine
+Name: @PACKAGE@
+Version: @VERSION@
+Release: 0.%(date '+%Y%m%d')
+License: BSD
+Group: System Environment/Libraries
+URL: http://www.enlightenment.org/
+Source: ftp://ftp.enlightenment.org/pub/evoak/%{name}-%{version}.tar.gz
+Packager: %{?_packager:%{_packager}}%{!?_packager:Michael Jennings <mej@eterm.org>}
+Vendor: %{?_vendorinfo:%{_vendorinfo}}%{!?_vendorinfo:The Enlightenment Project (http://www.enlightenment.org/)}
+Distribution: %{?_distribution:%{_distribution}}%{!?_distribution:%{_vendor}}
+#BuildSuggests: xorg-x11-devel, vim-enhanced
+BuildRequires: eet-devel, embryo-devel, evas-devel, ecore-devel
+Requires:  evas-module_loader_eet
+BuildRoot: %{_tmppath}/%{name}-%{version}-root
+
+%description
+Edje is a complex graphical design and layout engine. It provides a
+mechanism for allowing configuration data to define visual elements in
+terms of layout, behavior, and appearance.  Edje allows for multiple
+collections of layouts in one file, allowing a complete set of images,
+animations, and controls to exist as a unified whole.
+
+Edje separates the arrangement, appearance, and behavior logic into
+distinct independent entities.  This allows visual objects to share
+image data and configuration information without requiring them to do
+so.  This separation and simplistic event driven style of programming
+can produce almost any look and feel one could want for basic visual
+elements. Anything more complex is likely the domain of an application
+or widget set that may use Edje as a conveneient way of being able to
+configure parts of the display.
+
+%package devel
+Summary: Edje headers, static libraries, documentation and test programs
+Group: System Environment/Libraries
+Requires: %{name} = %{version}, %{name}-bin = %{version}
+Requires: eet-devel embryo-devel evas-devel ecore-devel
+
+%description devel
+Headers, static libraries, test programs and documentation for Edje
+
+%package bin
+Summary: Edje file compiler/decompiler suite
+Group: System Environment/Libraries
+Requires: %{name} = %{version}
+Requires: embryo-bin
+Requires: evas-module_saver_eet, evas-module_loader_png, evas-module_saver_png
+Requires: evas-module_loader_jpeg, evas-module_saver_jpeg, evas-module_engine_buffer
+
+%description bin
+Edje file compiler/decompiler suite
+
+%prep
+%setup -q
+
+%build
+%{configure} --prefix=%{_prefix}
+%{__make} %{?_smp_mflags} %{?mflags}
+
+%install
+%{__make} %{?mflags_install} DESTDIR=$RPM_BUILD_ROOT install
+test -x `which doxygen` && sh gendoc || :
+
+%post
+/sbin/ldconfig || :
+
+%postun
+/sbin/ldconfig || :
+
+%clean
+test "x$RPM_BUILD_ROOT" != "x/" && rm -rf $RPM_BUILD_ROOT
+
+%files
+%defattr(-, root, root)
+%doc AUTHORS COPYING README
+%{_libdir}/libedje.so.*
+
+%files devel
+%defattr(-, root, root)
+%doc doc/html
+%{_libdir}/*.so
+%{_libdir}/*.la
+%{_libdir}/*.a
+%{_libdir}/pkgconfig/*
+%{_includedir}/*.h
+
+%files bin
+%defattr(-, root, root)
+%{_bindir}/edje_cc
+%{_bindir}/edje_decc
+%{_bindir}/edje_recc
+%{_datadir}/edje/include/edje.inc
+
+%changelog
diff --git a/edje.supp b/edje.supp
new file mode 100644 (file)
index 0000000..cbe3c3e
--- /dev/null
+++ b/edje.supp
@@ -0,0 +1,8 @@
+# $Id$
+# valgrind suppression file for Edje.
+#
+{
+   BogusWarning
+   Memcheck:Cond
+   fun:_edje_part_recalc
+}
diff --git a/gendoc b/gendoc
new file mode 100755 (executable)
index 0000000..1b20190
--- /dev/null
+++ b/gendoc
@@ -0,0 +1,17 @@
+#!/bin/sh
+cp ./edje.c.in ./edje.c
+cat ./src/lib/Edje.h >> ./edje.c
+for I in `find ./src/lib -name "*.c" -print | grep -v edje_edit.c`; do
+  cat $I >> ./edje.c
+done
+rm -rf ./doc/html ./doc/latex ./doc/man
+mkdir -p ./doc/html ./doc/latex ./doc/man
+doxygen
+cp doc/img/*.png doc/html/
+cp doc/img/*.gif doc/html/
+cp doc/img/*.jpg doc/html/
+cp doc/*.css doc/html/
+rm -f edje_docs.tar edje_docs.tar.gz
+tar -cvf edje_docs.tar doc/html doc/man doc/latex
+gzip -9 edje_docs.tar
+exit 0
diff --git a/src/.cvsignore b/src/.cvsignore
new file mode 100644 (file)
index 0000000..282522d
--- /dev/null
@@ -0,0 +1,2 @@
+Makefile
+Makefile.in
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644 (file)
index 0000000..7b45af6
--- /dev/null
@@ -0,0 +1,3 @@
+## Process this file with automake to produce Makefile.in
+
+SUBDIRS = lib bin
diff --git a/src/bin/.cvsignore b/src/bin/.cvsignore
new file mode 100644 (file)
index 0000000..93f5fa1
--- /dev/null
@@ -0,0 +1,10 @@
+.deps
+.libs
+Makefile
+Makefile.in
+edje
+edje_ls
+edje_cc
+edje_decc
+edje_test
+edje_thumb
diff --git a/src/bin/Makefile.am b/src/bin/Makefile.am
new file mode 100644 (file)
index 0000000..0ac94ee
--- /dev/null
@@ -0,0 +1,67 @@
+
+MAINTAINERCLEANFILES = Makefile.in
+
+AM_CPPFLAGS = \
+-I$(top_srcdir) \
+-I$(top_srcdir)/src/bin \
+-I$(top_srcdir)/src/lib \
+-DPACKAGE_BIN_DIR=\"$(bindir)\" \
+-DPACKAGE_LIB_DIR=\"$(libdir)\" \
+-DPACKAGE_DATA_DIR=\"$(datadir)/$(PACKAGE)\" \
+@EDJE_CFLAGS@ \
+@ECORE_EVAS_CFLAGS@ \
+@ECORE_FILE_CFLAGS@ \
+@EVIL_CFLAGS@
+
+if BUILD_EDJE_CC
+EDJE_CC = edje_cc
+else
+EDJE_CC =
+endif
+
+if BUILD_EDJE_DECC
+EDJE_DECC = edje_decc
+else
+EDJE_DECC =
+endif
+
+bin_SCRIPTS = \
+@EDJE_RECC_PRG@
+
+EXTRA_DIST = @EDJE_RECC_PRG@
+EXTRA_SCRIPTS = edje_recc
+
+bin_PROGRAMS = $(EDJE_CC) $(EDJE_DECC)
+
+EXTRA_PROGRAMS = \
+edje_cc \
+edje_decc
+
+edje_cc_SOURCES = \
+edje_cc.c \
+edje_cc.h \
+edje_cc_out.c \
+edje_cc_parse.c \
+edje_cc_mem.c \
+edje_cc_handlers.c \
+edje_cc_sources.c \
+edje_prefix.c \
+edje_prefix.h \
+edje_main.h
+
+edje_cc_CFLAGS = @WIN32_CFLAGS@
+edje_cc_LDADD = $(top_builddir)/src/lib/libedje.la $(EDJE_LIBS) $(ECORE_EVAS_LIBS) $(EVIL_LIBS)
+edje_cc_LDFLAGS = @lt_enable_auto_import@
+edje_cc_DEPENDENCIES = $(top_builddir)/src/lib/libedje.la
+
+
+edje_decc_SOURCES = \
+edje_decc.c \
+edje_decc.h \
+edje_cc_mem.c \
+edje_cc_sources.c
+
+edje_decc_CFLAGS = @WIN32_CFLAGS@
+edje_decc_LDADD = $(top_builddir)/src/lib/libedje.la $(EDJE_LIBS) $(ECORE_EVAS_LIBS) $(ECORE_FILE_LIBS) $(EVIL_LIBS)
+edje_decc_LDFLAGS = @lt_enable_auto_import@
+edje_decc_DEPENDENCIES = $(top_builddir)/src/lib/libedje.la
diff --git a/src/bin/edje_cc.c b/src/bin/edje_cc.c
new file mode 100644 (file)
index 0000000..450edc1
--- /dev/null
@@ -0,0 +1,192 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#include "edje_cc.h"
+
+static void main_help(void);
+
+Evas_List *img_dirs = NULL;
+Evas_List *fnt_dirs = NULL;
+Evas_List *defines = NULL;
+char      *file_in = NULL;
+char      *file_out = NULL;
+char      *progname = NULL;
+int        verbose = 0;
+
+int        no_lossy = 0;
+int        no_comp = 0;
+int        no_raw = 0;
+int        min_quality = 0;
+int        max_quality = 100;
+
+static void
+main_help(void)
+{
+   printf
+     ("Usage:\n"
+      "\t%s [OPTIONS] input_file.edc [output_file.edj]\n"
+      "\n"
+      "Where OPTIONS is one or more of:\n"
+      "\n"
+      "-id image/directory      Add a directory to look in for relative path images\n"
+      "-fd font/directory       Add a directory to look in for relative path fonts\n"
+      "-v                       Verbose output\n"
+      "-no-lossy                Do NOT allow images to be lossy\n"
+      "-no-comp                 Do NOT allow images to be stored with lossless compression\n"
+      "-no-raw                  Do NOT allow images to be stored with zero compression (raw)\n"
+      "-min-quality VAL         Do NOT allow lossy images with quality < VAL (0-100)\n"
+      "-max-quality VAL         Do NOT allow lossy images with quality > VAL (0-100)\n"
+      "-Ddefine_val=to          CPP style define to define input macro definitions to the .edc source\n"
+      ,progname);
+}
+
+int
+main(int argc, char **argv)
+{
+   int i;
+   struct stat st;
+   char rpath[PATH_MAX], rpath2[PATH_MAX];
+
+   setlocale(LC_NUMERIC, "C");
+
+   progname = argv[0];
+   for (i = 1; i < argc; i++)
+     {
+       if (!strcmp(argv[i], "-h"))
+         {
+            main_help();
+            exit(0);
+         }
+       else if (!strcmp(argv[i], "-v"))
+         {
+            verbose = 1;
+         }
+       else if (!strcmp(argv[i], "-no-lossy"))
+         {
+            no_lossy = 1;
+         }
+       else if (!strcmp(argv[i], "-no-comp"))
+         {
+            no_comp = 1;
+         }
+       else if (!strcmp(argv[i], "-no-raw"))
+         {
+            no_raw = 1;
+         }
+       else if ((!strcmp(argv[i], "-id") || !strcmp(argv[i], "--image_dir")) && (i < (argc - 1)))
+         {
+            i++;
+            img_dirs = evas_list_append(img_dirs, argv[i]);
+         }
+       else if ((!strcmp(argv[i], "-fd") || !strcmp(argv[i], "--font_dir")) && (i < (argc - 1)))
+         {
+            i++;
+            fnt_dirs = evas_list_append(fnt_dirs, argv[i]);
+         }
+       else if ((!strcmp(argv[i], "-min-quality")) && (i < (argc - 1)))
+         {
+            i++;
+            min_quality = atoi(argv[i]);
+            if (min_quality < 0) min_quality = 0;
+            if (min_quality > 100) min_quality = 100;
+         }
+       else if ((!strcmp(argv[i], "-max-quality")) && (i < (argc - 1)))
+         {
+            i++;
+            max_quality = atoi(argv[i]);
+            if (max_quality < 0) max_quality = 0;
+            if (max_quality > 100) max_quality = 100;
+         }
+       else if (!strncmp(argv[i], "-D", 2))
+         {
+            defines = evas_list_append(defines, mem_strdup(argv[i]));
+         }
+       else if ((!strcmp(argv[i], "-o")) && (i < (argc - 1)))
+         {
+            i++;
+            file_out = argv[i];
+         }
+       else if (!file_in)
+         file_in = argv[i];
+       else if (!file_out)
+         file_out = argv[i];
+     }
+   if (!file_in)
+     {
+       fprintf(stderr, "%s: Error: no input file specified.\n", progname);
+       main_help();
+       exit(-1);
+     }
+
+   e_prefix_determine(argv[0]);
+
+   /* check whether file_in exists */
+#ifdef HAVE_REALPATH
+   if (!realpath(file_in, rpath) || stat(rpath, &st) || !S_ISREG(st.st_mode))
+#else
+   if (stat(file_in, &st) || !S_ISREG(st.st_mode))
+#endif
+     {
+       fprintf(stderr, "%s: Error: file not found: %s.\n", progname, file_in);
+       main_help();
+       exit(-1);
+     }
+
+   if (!file_out)
+      {
+         char *suffix;
+
+         if ((suffix = strstr(file_in,".edc")) && (suffix[4] == 0))
+            {
+               file_out = strdup(file_in);
+               if (file_out)
+                  {
+                     suffix = strstr(file_out,".edc");
+                     strcpy(suffix,".edj");
+                  }
+            }
+      }
+   if (!file_out)
+     {
+       fprintf(stderr, "%s: Error: no output file specified.\n", progname);
+       main_help();
+       exit(-1);
+     }
+
+#ifdef HAVE_REALPATH
+   if (realpath(file_out, rpath2) && !strcmp (rpath, rpath2))
+#else
+   if (!strcmp (file_in, file_out))
+#endif
+     {
+       fprintf(stderr, "%s: Error: input file equals output file.\n", progname);
+       main_help();
+       exit(-1);
+     }
+
+   edje_init();
+
+   edje_file = mem_alloc(SZ(Edje_File));
+   edje_file->compiler = strdup("edje_cc");
+   edje_file->version = EDJE_FILE_VERSION;
+   edje_file->feature_ver = 1; /* increment this every time we add a field
+                               * or feature to the edje file format that
+                               * does not load nicely as a NULL or 0 value
+                               * and needs a special fallback initialization
+                               */
+
+   source_edd();
+   source_fetch();
+
+   data_setup();
+   compile();
+   data_process_scripts();
+   data_process_lookups();
+   data_process_script_lookups();
+   data_write();
+
+   edje_shutdown();
+
+   return 0;
+}
diff --git a/src/bin/edje_cc.h b/src/bin/edje_cc.h
new file mode 100644 (file)
index 0000000..2c9af76
--- /dev/null
@@ -0,0 +1,147 @@
+#ifndef EDJE_CC_H
+#define EDJE_CC_H
+
+#include "edje_main.h"
+
+/*
+ * On Windows, if the file is not opened in binary mode,
+ * read does not return the correct size, because of
+ * CR / LF translation.
+ */
+#ifndef O_BINARY
+# define O_BINARY 0
+#endif
+
+/* types */
+typedef struct _New_Object_Handler    New_Object_Handler;
+typedef struct _New_Statement_Handler New_Statement_Handler;
+typedef struct _Font_List             Font_List;
+typedef struct _Font                  Font;
+typedef struct _Code                  Code;
+typedef struct _Code_Program          Code_Program;
+typedef struct _SrcFile               SrcFile;
+typedef struct _SrcFile_List          SrcFile_List;
+
+struct _New_Object_Handler
+{
+   const char *type;
+   void (*func)(void);
+};
+
+struct _New_Statement_Handler
+{
+   const char *type;
+   void (*func)(void);
+};
+
+struct _Font_List
+{
+   Evas_List *list;
+};
+
+struct _Font
+{
+   char *file;
+   char *name;
+};
+
+struct _Code
+{
+   int       l1, l2;
+   char      *shared;
+   Evas_List *programs;
+};
+
+struct _Code_Program
+{
+   int        l1, l2;
+   int        id;
+   char      *script;
+};
+
+struct _SrcFile
+{
+   char *name;
+   char *file;
+};
+
+struct _SrcFile_List
+{
+   Evas_List *list;
+};
+
+/* global fn calls */
+void    data_setup(void);
+void    data_write(void);
+void    data_queue_part_lookup(Edje_Part_Collection *pc, char *name, int *dest);
+void    data_queue_program_lookup(Edje_Part_Collection *pc, char *name, int *dest);
+void    data_queue_image_lookup(char *name, int *dest);
+void    data_queue_part_slave_lookup(int *master, int *slave);
+void    data_queue_image_slave_lookup(int *master, int *slave);
+void    data_queue_spectrum_lookup(char *name, int *dest);
+void    data_queue_spectrum_slave_lookup(int *master, int *slave);
+void    data_process_lookups(void);
+void    data_process_scripts(void);
+void    data_process_script_lookups(void);
+
+
+int     is_verbatim(void);
+void    track_verbatim(int on);
+void    set_verbatim(char *s, int l1, int l2);
+char   *get_verbatim(void);
+int     get_verbatim_line1(void);
+int     get_verbatim_line2(void);
+void    compile(void);
+int     is_param(int n);
+int     is_num(int n);
+char   *parse_str(int n);
+int     parse_enum(int n, ...);
+int     parse_flags(int n, ...);
+int     parse_int(int n);
+int     parse_int_range(int n, int f, int t);
+int     parse_bool(int n);
+double  parse_float(int n);
+double  parse_float_range(int n, double f, double t);
+void    check_arg_count(int n);
+void    check_min_arg_count(int n);
+
+int     object_handler_num(void);
+int     statement_handler_num(void);
+
+void    source_edd(void);
+void    source_fetch(void);
+int     source_append(Eet_File *ef);
+SrcFile_List *source_load(Eet_File *ef);
+int     source_fontmap_save(Eet_File *ef, Evas_List *fonts);
+Font_List *source_fontmap_load(Eet_File *ef);
+
+void   *mem_alloc(size_t size);
+char   *mem_strdup(const char *s);
+#define SZ sizeof
+
+/* global vars */
+extern Evas_List             *img_dirs;
+extern Evas_List             *fnt_dirs;
+extern char                  *file_in;
+extern char                  *file_out;
+extern char                  *progname;
+extern int                    verbose;
+extern int                    no_lossy;
+extern int                    no_comp;
+extern int                    no_raw;
+extern int                    min_quality;
+extern int                    max_quality;
+extern int                    line;
+extern Evas_List             *stack;
+extern Evas_List             *params;
+extern Edje_File             *edje_file;
+extern Evas_List             *edje_collections;
+extern Evas_List             *fonts;
+extern Evas_List             *codes;
+extern Evas_List             *defines;
+extern Evas_List             *aliases;
+extern New_Object_Handler     object_handlers[];
+extern New_Statement_Handler  statement_handlers[];
+
+
+#endif
diff --git a/src/bin/edje_cc_handlers.c b/src/bin/edje_cc_handlers.c
new file mode 100644 (file)
index 0000000..8c6868b
--- /dev/null
@@ -0,0 +1,4419 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+/*
+    Concerning the EDC reference:
+
+    The formatting for blocks and properties has been implemented as a table
+    which is filled using ALIASES.
+    For maximum flexibility I implemented them in the \@code/\@encode style,
+    this means that missing one or changing the order most certainly cause
+    formatting errors.
+
+    \@block
+        block name
+    \@context
+        code sample of the block
+    \@description
+        the block's description
+    \@endblock
+
+    \@property
+        property name
+    \@parameters
+        property's parameter list
+    \@effect
+        the property description (lol)
+    \@endproperty
+*/
+
+/**
+ * @page edcref Edje Data Collection reference
+ * An Edje Data Collection, it's a plain text file (normally identified with the
+ * .edc extension),consisting of instructions for the Edje Compiler.
+ *
+ * The syntax for the edje data collection files follows a simple structure of
+ * "blocks { .. }" that can contain "properties: ..", more blocks, or both.
+ *
+ * @author Andres Blanc (dresb) andresblanc@gmail.com
+ *
+ * <table class="edcref" border="0">
+ */
+
+#include "edje_cc.h"
+
+static void st_images_image(void);
+
+static void st_fonts_font(void);
+
+static void st_data_item(void);
+static void st_data_file(void);
+
+static void ob_styles_style(void);
+static void st_styles_style_name(void);
+static void st_styles_style_base(void);
+static void st_styles_style_tag(void);
+
+static void ob_color_class(void);
+static void st_color_class_name(void);
+static void st_color_class_color(void);
+static void st_color_class_color2(void);
+static void st_color_class_color3(void);
+
+static void ob_spectrum(void);
+/*static void st_spectrum(void);*/
+static void st_spectrum_name(void);
+static void st_spectrum_color(void);
+
+static void ob_collections(void);
+
+static void ob_collections_group(void);
+static void st_collections_group_name(void);
+static void st_collections_group_script_only(void);
+static void st_collections_group_alias(void);
+static void st_collections_group_min(void);
+static void st_collections_group_max(void);
+static void st_collections_group_data_item(void);
+
+static void ob_collections_group_script(void);
+
+static void ob_collections_group_parts_part(void);
+static void st_collections_group_parts_part_name(void);
+static void st_collections_group_parts_part_type(void);
+static void st_collections_group_parts_part_effect(void);
+static void st_collections_group_parts_part_mouse_events(void);
+static void st_collections_group_parts_part_repeat_events(void);
+static void st_collections_group_parts_part_ignore_flags(void);
+static void st_collections_group_parts_part_pointer_mode(void);
+static void st_collections_group_parts_part_precise_is_inside(void);
+static void st_collections_group_parts_part_use_alternate_font_metrics(void);
+static void st_collections_group_parts_part_clip_to_id(void);
+static void st_collections_group_parts_part_source(void);
+static void st_collections_group_parts_part_dragable_x(void);
+static void st_collections_group_parts_part_dragable_y(void);
+static void st_collections_group_parts_part_dragable_confine(void);
+static void st_collections_group_parts_part_dragable_events(void);
+
+static void ob_collections_group_parts_part_description(void);
+static void st_collections_group_parts_part_description_inherit(void);
+static void st_collections_group_parts_part_description_state(void);
+static void st_collections_group_parts_part_description_visible(void);
+static void st_collections_group_parts_part_description_align(void);
+static void st_collections_group_parts_part_description_fixed(void);
+static void st_collections_group_parts_part_description_min(void);
+static void st_collections_group_parts_part_description_max(void);
+static void st_collections_group_parts_part_description_step(void);
+static void st_collections_group_parts_part_description_aspect(void);
+static void st_collections_group_parts_part_description_aspect_preference(void);
+static void st_collections_group_parts_part_description_rel1_relative(void);
+static void st_collections_group_parts_part_description_rel1_offset(void);
+static void st_collections_group_parts_part_description_rel1_to(void);
+static void st_collections_group_parts_part_description_rel1_to_x(void);
+static void st_collections_group_parts_part_description_rel1_to_y(void);
+static void st_collections_group_parts_part_description_rel2_relative(void);
+static void st_collections_group_parts_part_description_rel2_offset(void);
+static void st_collections_group_parts_part_description_rel2_to(void);
+static void st_collections_group_parts_part_description_rel2_to_x(void);
+static void st_collections_group_parts_part_description_rel2_to_y(void);
+static void st_collections_group_parts_part_description_image_normal(void);
+static void st_collections_group_parts_part_description_image_tween(void);
+static void st_collections_group_parts_part_description_image_border(void);
+static void st_collections_group_parts_part_description_image_middle(void);
+static void st_collections_group_parts_part_description_fill_smooth(void);
+static void st_collections_group_parts_part_description_fill_origin_relative(void);
+static void st_collections_group_parts_part_description_fill_origin_offset(void);
+static void st_collections_group_parts_part_description_fill_size_relative(void);
+static void st_collections_group_parts_part_description_fill_size_offset(void);
+static void st_collections_group_parts_part_description_fill_angle(void);
+static void st_collections_group_parts_part_description_fill_spread(void);
+static void st_collections_group_parts_part_description_fill_type(void);
+static void st_collections_group_parts_part_description_color_class(void);
+static void st_collections_group_parts_part_description_color(void);
+static void st_collections_group_parts_part_description_color2(void);
+static void st_collections_group_parts_part_description_color3(void);
+static void st_collections_group_parts_part_description_text_text(void);
+static void st_collections_group_parts_part_description_text_text_class(void);
+static void st_collections_group_parts_part_description_text_font(void);
+static void st_collections_group_parts_part_description_text_style(void);
+static void st_collections_group_parts_part_description_text_size(void);
+static void st_collections_group_parts_part_description_text_fit(void);
+static void st_collections_group_parts_part_description_text_min(void);
+static void st_collections_group_parts_part_description_text_max(void);
+static void st_collections_group_parts_part_description_text_align(void);
+static void st_collections_group_parts_part_description_text_source(void);
+static void st_collections_group_parts_part_description_text_text_source(void);
+static void st_collections_group_parts_part_description_text_elipsis(void);
+static void st_collections_group_parts_part_description_gradient_type(void);
+static void st_collections_group_parts_part_description_gradient_spectrum(void);
+static void st_collections_group_parts_part_description_gradient_rel1_relative(void);
+static void st_collections_group_parts_part_description_gradient_rel1_offset(void);
+static void st_collections_group_parts_part_description_gradient_rel2_relative(void);
+static void st_collections_group_parts_part_description_gradient_rel2_offset(void);
+
+static void ob_collections_group_programs_program(void);
+static void st_collections_group_programs_program_name(void);
+static void st_collections_group_programs_program_signal(void);
+static void st_collections_group_programs_program_source(void);
+static void st_collections_group_programs_program_in(void);
+static void st_collections_group_programs_program_action(void);
+static void st_collections_group_programs_program_transition(void);
+static void st_collections_group_programs_program_target(void);
+static void st_collections_group_programs_program_after(void);
+
+static void ob_collections_group_programs_program_script(void);
+
+/*****/
+
+New_Statement_Handler statement_handlers[] =
+{
+     {"images.image", st_images_image},
+     {"fonts.font", st_fonts_font},
+     {"data.item", st_data_item},
+     {"data.file", st_data_file},
+     {"styles.style.name", st_styles_style_name},
+     {"styles.style.base", st_styles_style_base},
+     {"styles.style.tag", st_styles_style_tag},
+     {"color_classes.color_class.name", st_color_class_name},
+     {"color_classes.color_class.color", st_color_class_color},
+     {"color_classes.color_class.color2", st_color_class_color2},
+     {"color_classes.color_class.color3", st_color_class_color3},
+     /*{"spectra.spectrum", st_spectrum},*/
+     {"spectra.spectrum.name", st_spectrum_name},
+     {"spectra.spectrum.color", st_spectrum_color},
+     {"collections.image", st_images_image}, /* dup */
+     {"collections.images.image", st_images_image}, /* dup */
+     {"collections.font", st_fonts_font}, /* dup */
+     {"collections.fonts.font", st_fonts_font}, /* dup */
+     {"collections.styles.style.name", st_styles_style_name}, /* dup */
+     {"collections.styles.style.base", st_styles_style_base}, /* dup */
+     {"collections.styles.style.tag", st_styles_style_tag}, /* dup */
+     {"collections.color_classes.color_class.name", st_color_class_name}, /* dup */
+     {"collections.color_classes.color_class.color", st_color_class_color}, /* dup */
+     {"collections.color_classes.color_class.color2", st_color_class_color2}, /* dup */
+     {"collections.color_classes.color_class.color3", st_color_class_color3}, /* dup */
+     {"collections.group.name", st_collections_group_name},
+     {"collections.group.script_only", st_collections_group_script_only},
+     {"collections.group.alias", st_collections_group_alias},
+     {"collections.group.min", st_collections_group_min},
+     {"collections.group.max", st_collections_group_max},
+     {"collections.group.data.item", st_collections_group_data_item},
+     {"collections.group.image", st_images_image}, /* dup */
+     {"collections.group.images.image", st_images_image}, /* dup */
+     {"collections.group.font", st_fonts_font}, /* dup */
+     {"collections.group.fonts.font", st_fonts_font}, /* dup */
+     {"collections.group.styles.style.name", st_styles_style_name}, /* dup */
+     {"collections.group.styles.style.base", st_styles_style_base}, /* dup */
+     {"collections.group.styles.style.tag", st_styles_style_tag}, /* dup */
+     {"collections.group.color_classes.color_class.name", st_color_class_name}, /* dup */
+     {"collections.group.color_classes.color_class.color", st_color_class_color}, /* dup */
+     {"collections.group.color_classes.color_class.color2", st_color_class_color2}, /* dup */
+     {"collections.group.color_classes.color_class.color3", st_color_class_color3}, /* dup */
+     {"collections.group.parts.image", st_images_image}, /* dup */
+     {"collections.group.parts.images.image", st_images_image}, /* dup */
+     {"collections.group.parts.font", st_fonts_font}, /* dup */
+     {"collections.group.parts.fonts.font", st_fonts_font}, /* dup */
+     {"collections.group.parts.styles.style.name", st_styles_style_name}, /* dup */
+     {"collections.group.parts.styles.style.base", st_styles_style_base}, /* dup */
+     {"collections.group.parts.styles.style.tag", st_styles_style_tag}, /* dup */
+     {"collections.group.parts.color_classes.color_class.name", st_color_class_name}, /* dup */
+     {"collections.group.parts.color_classes.color_class.color", st_color_class_color}, /* dup */
+     {"collections.group.parts.color_classes.color_class.color2", st_color_class_color2}, /* dup */
+     {"collections.group.parts.color_classes.color_class.color3", st_color_class_color3}, /* dup */
+     {"collections.group.parts.part.name", st_collections_group_parts_part_name},
+     {"collections.group.parts.part.type", st_collections_group_parts_part_type},
+     {"collections.group.parts.part.effect", st_collections_group_parts_part_effect},
+     {"collections.group.parts.part.mouse_events", st_collections_group_parts_part_mouse_events},
+     {"collections.group.parts.part.repeat_events", st_collections_group_parts_part_repeat_events},
+     {"collections.group.parts.part.ignore_flags", st_collections_group_parts_part_ignore_flags},
+     {"collections.group.parts.part.pointer_mode", st_collections_group_parts_part_pointer_mode},
+     {"collections.group.parts.part.precise_is_inside", st_collections_group_parts_part_precise_is_inside},
+     {"collections.group.parts.part.use_alternate_font_metrics", st_collections_group_parts_part_use_alternate_font_metrics},
+     {"collections.group.parts.part.clip_to", st_collections_group_parts_part_clip_to_id},
+     {"collections.group.parts.part.source", st_collections_group_parts_part_source},
+     {"collections.group.parts.part.dragable.x", st_collections_group_parts_part_dragable_x},
+     {"collections.group.parts.part.dragable.y", st_collections_group_parts_part_dragable_y},
+     {"collections.group.parts.part.dragable.confine", st_collections_group_parts_part_dragable_confine},
+     {"collections.group.parts.part.dragable.events", st_collections_group_parts_part_dragable_events},
+     {"collections.group.parts.part.image", st_images_image}, /* dup */
+     {"collections.group.parts.part.images.image", st_images_image}, /* dup */
+     {"collections.group.parts.part.font", st_fonts_font}, /* dup */
+     {"collections.group.parts.part.fonts.font", st_fonts_font}, /* dup */
+     {"collections.group.parts.part.styles.style.name", st_styles_style_name}, /* dup */
+     {"collections.group.parts.part.styles.style.base", st_styles_style_base}, /* dup */
+     {"collections.group.parts.part.styles.style.tag", st_styles_style_tag}, /* dup */
+     {"collections.group.parts.part.color_classes.color_class.name", st_color_class_name}, /* dup */
+     {"collections.group.parts.part.color_classes.color_class.color", st_color_class_color}, /* dup */
+     {"collections.group.parts.part.color_classes.color_class.color2", st_color_class_color2}, /* dup */
+     {"collections.group.parts.part.color_classes.color_class.color3", st_color_class_color3}, /* dup */
+     {"collections.group.parts.part.description.inherit", st_collections_group_parts_part_description_inherit},
+     {"collections.group.parts.part.description.state", st_collections_group_parts_part_description_state},
+     {"collections.group.parts.part.description.visible", st_collections_group_parts_part_description_visible},
+     {"collections.group.parts.part.description.align", st_collections_group_parts_part_description_align},
+     {"collections.group.parts.part.description.fixed", st_collections_group_parts_part_description_fixed},
+     {"collections.group.parts.part.description.min", st_collections_group_parts_part_description_min},
+     {"collections.group.parts.part.description.max", st_collections_group_parts_part_description_max},
+     {"collections.group.parts.part.description.step", st_collections_group_parts_part_description_step},
+     {"collections.group.parts.part.description.aspect", st_collections_group_parts_part_description_aspect},
+     {"collections.group.parts.part.description.aspect_preference", st_collections_group_parts_part_description_aspect_preference},
+     {"collections.group.parts.part.description.rel1.relative", st_collections_group_parts_part_description_rel1_relative},
+     {"collections.group.parts.part.description.rel1.offset", st_collections_group_parts_part_description_rel1_offset},
+     {"collections.group.parts.part.description.rel1.to", st_collections_group_parts_part_description_rel1_to},
+     {"collections.group.parts.part.description.rel1.to_x", st_collections_group_parts_part_description_rel1_to_x},
+     {"collections.group.parts.part.description.rel1.to_y", st_collections_group_parts_part_description_rel1_to_y},
+     {"collections.group.parts.part.description.rel2.relative", st_collections_group_parts_part_description_rel2_relative},
+     {"collections.group.parts.part.description.rel2.offset", st_collections_group_parts_part_description_rel2_offset},
+     {"collections.group.parts.part.description.rel2.to", st_collections_group_parts_part_description_rel2_to},
+     {"collections.group.parts.part.description.rel2.to_x", st_collections_group_parts_part_description_rel2_to_x},
+     {"collections.group.parts.part.description.rel2.to_y", st_collections_group_parts_part_description_rel2_to_y},
+     {"collections.group.parts.part.description.image.normal", st_collections_group_parts_part_description_image_normal},
+     {"collections.group.parts.part.description.image.tween", st_collections_group_parts_part_description_image_tween},
+     {"collections.group.parts.part.description.image.image", st_images_image}, /* dup */
+     {"collections.group.parts.part.description.image.images.image", st_images_image}, /* dup */
+     {"collections.group.parts.part.description.image.border", st_collections_group_parts_part_description_image_border},
+     {"collections.group.parts.part.description.image.middle", st_collections_group_parts_part_description_image_middle},
+     {"collections.group.parts.part.description.fill.smooth", st_collections_group_parts_part_description_fill_smooth},
+     {"collections.group.parts.part.description.fill.origin.relative", st_collections_group_parts_part_description_fill_origin_relative},
+     {"collections.group.parts.part.description.fill.origin.offset", st_collections_group_parts_part_description_fill_origin_offset},
+     {"collections.group.parts.part.description.fill.size.relative", st_collections_group_parts_part_description_fill_size_relative},
+     {"collections.group.parts.part.description.fill.size.offset", st_collections_group_parts_part_description_fill_size_offset},
+     {"collections.group.parts.part.description.fill.angle", st_collections_group_parts_part_description_fill_angle},
+     {"collections.group.parts.part.description.fill.spread", st_collections_group_parts_part_description_fill_spread},
+     {"collections.group.parts.part.description.fill.type", st_collections_group_parts_part_description_fill_type},
+     {"collections.group.parts.part.description.color_class", st_collections_group_parts_part_description_color_class},
+     {"collections.group.parts.part.description.color", st_collections_group_parts_part_description_color},
+     {"collections.group.parts.part.description.color2", st_collections_group_parts_part_description_color2},
+     {"collections.group.parts.part.description.color3", st_collections_group_parts_part_description_color3},
+     {"collections.group.parts.part.description.text.text", st_collections_group_parts_part_description_text_text},
+     {"collections.group.parts.part.description.text.text_class", st_collections_group_parts_part_description_text_text_class},
+     {"collections.group.parts.part.description.text.font", st_collections_group_parts_part_description_text_font},
+     {"collections.group.parts.part.description.text.style", st_collections_group_parts_part_description_text_style},
+     {"collections.group.parts.part.description.text.size", st_collections_group_parts_part_description_text_size},
+     {"collections.group.parts.part.description.text.fit", st_collections_group_parts_part_description_text_fit},
+     {"collections.group.parts.part.description.text.min", st_collections_group_parts_part_description_text_min},
+     {"collections.group.parts.part.description.text.max", st_collections_group_parts_part_description_text_max},
+     {"collections.group.parts.part.description.text.align", st_collections_group_parts_part_description_text_align},
+     {"collections.group.parts.part.description.text.source", st_collections_group_parts_part_description_text_source},
+     {"collections.group.parts.part.description.text.text_source", st_collections_group_parts_part_description_text_text_source},
+     {"collections.group.parts.part.description.text.font", st_fonts_font}, /* dup */
+     {"collections.group.parts.part.description.text.fonts.font", st_fonts_font}, /* dup */
+     {"collections.group.parts.part.description.text.elipsis", st_collections_group_parts_part_description_text_elipsis},
+     {"collections.group.parts.part.description.gradient.type", st_collections_group_parts_part_description_gradient_type},
+     {"collections.group.parts.part.description.gradient.rel1.relative", st_collections_group_parts_part_description_gradient_rel1_relative},
+     {"collections.group.parts.part.description.gradient.rel1.offset", st_collections_group_parts_part_description_gradient_rel1_offset},
+     {"collections.group.parts.part.description.gradient.rel2.relative", st_collections_group_parts_part_description_gradient_rel2_relative},
+     {"collections.group.parts.part.description.gradient.rel2.offset", st_collections_group_parts_part_description_gradient_rel2_offset},
+     {"collections.group.parts.part.description.gradient.spectrum", st_collections_group_parts_part_description_gradient_spectrum},
+     {"collections.group.parts.part.description.images.image", st_images_image}, /* dup */
+     {"collections.group.parts.part.description.font", st_fonts_font}, /* dup */
+     {"collections.group.parts.part.description.fonts.font", st_fonts_font}, /* dup */
+     {"collections.group.parts.part.description.styles.style.name", st_styles_style_name}, /* dup */
+     {"collections.group.parts.part.description.styles.style.base", st_styles_style_base}, /* dup */
+     {"collections.group.parts.part.description.styles.style.tag", st_styles_style_tag}, /* dup */
+     {"collections.group.parts.part.description.color_classes.color_class.name", st_color_class_name}, /* dup */
+     {"collections.group.parts.part.description.color_classes.color_class.color", st_color_class_color}, /* dup */
+     {"collections.group.parts.part.description.color_classes.color_class.color2", st_color_class_color2}, /* dup */
+     {"collections.group.parts.part.description.color_classes.color_class.color3", st_color_class_color3}, /* dup */
+     {"collections.group.parts.part.description.programs.image", st_images_image}, /* dup */
+     {"collections.group.parts.part.description.programs.images.image", st_images_image}, /* dup */
+     {"collections.group.parts.part.description.programs.font", st_fonts_font}, /* dup */
+     {"collections.group.parts.part.description.programs.fonts.font", st_fonts_font}, /* dup */
+     {"collections.group.parts.part.description.programs.program.name", st_collections_group_programs_program_name}, /* dup */
+     {"collections.group.parts.part.description.programs.program.signal", st_collections_group_programs_program_signal}, /* dup */
+     {"collections.group.parts.part.description.programs.program.source", st_collections_group_programs_program_source}, /* dup */
+     {"collections.group.parts.part.description.programs.program.in", st_collections_group_programs_program_in}, /* dup */
+     {"collections.group.parts.part.description.programs.program.action", st_collections_group_programs_program_action}, /* dup */
+     {"collections.group.parts.part.description.programs.program.transition", st_collections_group_programs_program_transition}, /* dup */
+     {"collections.group.parts.part.description.programs.program.target", st_collections_group_programs_program_target}, /* dup */
+     {"collections.group.parts.part.description.programs.program.after", st_collections_group_programs_program_after}, /* dup */
+     {"collections.group.parts.part.description.program.name", st_collections_group_programs_program_name}, /* dup */
+     {"collections.group.parts.part.description.program.signal", st_collections_group_programs_program_signal}, /* dup */
+     {"collections.group.parts.part.description.program.source", st_collections_group_programs_program_source}, /* dup */
+     {"collections.group.parts.part.description.program.in", st_collections_group_programs_program_in}, /* dup */
+     {"collections.group.parts.part.description.program.action", st_collections_group_programs_program_action}, /* dup */
+     {"collections.group.parts.part.description.program.transition", st_collections_group_programs_program_transition}, /* dup */
+     {"collections.group.parts.part.description.program.target", st_collections_group_programs_program_target}, /* dup */
+     {"collections.group.parts.part.description.program.after", st_collections_group_programs_program_after}, /* dup */
+     {"collections.group.parts.part.programs.image", st_images_image}, /* dup */
+     {"collections.group.parts.part.programs.images.image", st_images_image}, /* dup */
+     {"collections.group.parts.part.programs.font", st_fonts_font}, /* dup */
+     {"collections.group.parts.part.programs.fonts.font", st_fonts_font}, /* dup */
+     {"collections.group.parts.part.programs.program.name", st_collections_group_programs_program_name}, /* dup */
+     {"collections.group.parts.part.programs.program.signal", st_collections_group_programs_program_signal}, /* dup */
+     {"collections.group.parts.part.programs.program.source", st_collections_group_programs_program_source}, /* dup */
+     {"collections.group.parts.part.programs.program.in", st_collections_group_programs_program_in}, /* dup */
+     {"collections.group.parts.part.programs.program.action", st_collections_group_programs_program_action}, /* dup */
+     {"collections.group.parts.part.programs.program.transition", st_collections_group_programs_program_transition}, /* dup */
+     {"collections.group.parts.part.programs.program.target", st_collections_group_programs_program_target}, /* dup */
+     {"collections.group.parts.part.programs.program.after", st_collections_group_programs_program_after}, /* dup */
+     {"collections.group.parts.part.program.name", st_collections_group_programs_program_name}, /* dup */
+     {"collections.group.parts.part.program.signal", st_collections_group_programs_program_signal}, /* dup */
+     {"collections.group.parts.part.program.source", st_collections_group_programs_program_source}, /* dup */
+     {"collections.group.parts.part.program.in", st_collections_group_programs_program_in}, /* dup */
+     {"collections.group.parts.part.program.action", st_collections_group_programs_program_action}, /* dup */
+     {"collections.group.parts.part.program.transition", st_collections_group_programs_program_transition}, /* dup */
+     {"collections.group.parts.part.program.target", st_collections_group_programs_program_target}, /* dup */
+     {"collections.group.parts.part.program.after", st_collections_group_programs_program_after}, /* dup */
+     {"collections.group.parts.programs.image", st_images_image}, /* dup */
+     {"collections.group.parts.programs.images.image", st_images_image}, /* dup */
+     {"collections.group.parts.programs.font", st_fonts_font}, /* dup */
+     {"collections.group.parts.programs.fonts.font", st_fonts_font}, /* dup */
+     {"collections.group.parts.programs.program.name", st_collections_group_programs_program_name}, /* dup */
+     {"collections.group.parts.programs.program.signal", st_collections_group_programs_program_signal}, /* dup */
+     {"collections.group.parts.programs.program.source", st_collections_group_programs_program_source}, /* dup */
+     {"collections.group.parts.programs.program.in", st_collections_group_programs_program_in}, /* dup */
+     {"collections.group.parts.programs.program.action", st_collections_group_programs_program_action}, /* dup */
+     {"collections.group.parts.programs.program.transition", st_collections_group_programs_program_transition}, /* dup */
+     {"collections.group.parts.programs.program.target", st_collections_group_programs_program_target}, /* dup */
+     {"collections.group.parts.programs.program.after", st_collections_group_programs_program_after},
+     {"collections.group.parts.program.name", st_collections_group_programs_program_name}, /* dup */
+     {"collections.group.parts.program.signal", st_collections_group_programs_program_signal}, /* dup */
+     {"collections.group.parts.program.source", st_collections_group_programs_program_source}, /* dup */
+     {"collections.group.parts.program.in", st_collections_group_programs_program_in}, /* dup */
+     {"collections.group.parts.program.action", st_collections_group_programs_program_action}, /* dup */
+     {"collections.group.parts.program.transition", st_collections_group_programs_program_transition}, /* dup */
+     {"collections.group.parts.program.target", st_collections_group_programs_program_target}, /* dup */
+     {"collections.group.parts.program.after", st_collections_group_programs_program_after}, /* dup */
+     {"collections.group.program.name", st_collections_group_programs_program_name}, /* dup */
+     {"collections.group.program.signal", st_collections_group_programs_program_signal}, /* dup */
+     {"collections.group.program.source", st_collections_group_programs_program_source}, /* dup */
+     {"collections.group.program.in", st_collections_group_programs_program_in}, /* dup */
+     {"collections.group.program.action", st_collections_group_programs_program_action}, /* dup */
+     {"collections.group.program.transition", st_collections_group_programs_program_transition}, /* dup */
+     {"collections.group.program.target", st_collections_group_programs_program_target}, /* dup */
+     {"collections.group.program.after", st_collections_group_programs_program_after}, /* dup */
+     {"collections.group.programs.program.name", st_collections_group_programs_program_name},
+     {"collections.group.programs.program.signal", st_collections_group_programs_program_signal},
+     {"collections.group.programs.program.source", st_collections_group_programs_program_source},
+     {"collections.group.programs.program.in", st_collections_group_programs_program_in},
+     {"collections.group.programs.program.action", st_collections_group_programs_program_action},
+     {"collections.group.programs.program.transition", st_collections_group_programs_program_transition},
+     {"collections.group.programs.program.target", st_collections_group_programs_program_target},
+     {"collections.group.programs.program.after", st_collections_group_programs_program_after},
+     {"collections.group.programs.image", st_images_image}, /* dup */
+     {"collections.group.programs.images.image", st_images_image}, /* dup */
+     {"collections.group.programs.font", st_fonts_font}, /* dup */
+     {"collections.group.programs.fonts.font", st_fonts_font} /* dup */
+};
+
+New_Object_Handler object_handlers[] =
+{
+     {"images", NULL},
+     {"fonts", NULL},
+     {"data", NULL},
+     {"styles", NULL},
+     {"styles.style", ob_styles_style},
+     {"color_classes", NULL},
+     {"color_classes.color_class", ob_color_class},
+     {"spectra", NULL},
+     {"spectra.spectrum", ob_spectrum},
+     {"collections", ob_collections},
+     {"collections.images", NULL}, /* dup */
+     {"collections.fonts", NULL}, /* dup */
+     {"collections.styles", NULL}, /* dup */
+     {"collections.styles.style", ob_styles_style}, /* dup */
+     {"collections.color_classes", NULL}, /* dup */
+     {"collections.color_classes.color_class", ob_color_class}, /* dup */
+     {"collections.group", ob_collections_group},
+     {"collections.group.data", NULL},
+     {"collections.group.script", ob_collections_group_script},
+     {"collections.group.images", NULL}, /* dup */
+     {"collections.group.fonts", NULL}, /* dup */
+     {"collections.group.styles", NULL}, /* dup */
+     {"collections.group.styles.style", ob_styles_style}, /* dup */
+     {"collections.group.color_classes", NULL}, /* dup */
+     {"collections.group.color_classes.color_class", ob_color_class}, /* dup */
+     {"collections.group.parts", NULL},
+     {"collections.group.parts.images", NULL}, /* dup */
+     {"collections.group.parts.fonts", NULL}, /* dup */
+     {"collections.group.parts.styles", NULL}, /* dup */
+     {"collections.group.parts.styles.style", ob_styles_style}, /* dup */
+     {"collections.group.parts.color_classes", NULL}, /* dup */
+     {"collections.group.parts.color_classes.color_class", ob_color_class}, /* dup */
+     {"collections.group.parts.part", ob_collections_group_parts_part},
+     {"collections.group.parts.part.dragable", NULL},
+     {"collections.group.parts.part.images", NULL}, /* dup */
+     {"collections.group.parts.part.fonts", NULL}, /* dup */
+     {"collections.group.parts.part.styles", NULL}, /* dup */
+     {"collections.group.parts.part.styles.style", ob_styles_style}, /* dup */
+     {"collections.group.parts.part.color_classes", NULL}, /* dup */
+     {"collections.group.parts.part.color_classes.color_class", ob_color_class}, /* dup */
+     {"collections.group.parts.part.description", ob_collections_group_parts_part_description},
+     {"collections.group.parts.part.description.rel1", NULL},
+     {"collections.group.parts.part.description.rel2", NULL},
+     {"collections.group.parts.part.description.image", NULL}, /* dup */
+     {"collections.group.parts.part.description.image.images", NULL}, /* dup */
+     {"collections.group.parts.part.description.fill", NULL},
+     {"collections.group.parts.part.description.fill.origin", NULL},
+     {"collections.group.parts.part.description.fill.size", NULL},
+     {"collections.group.parts.part.description.text", NULL},
+     {"collections.group.parts.part.description.text.fonts", NULL}, /* dup */
+     {"collections.group.parts.part.description.images", NULL}, /* dup */
+     {"collections.group.parts.part.description.fonts", NULL}, /* dup */
+     {"collections.group.parts.part.description.styles", NULL}, /* dup */
+     {"collections.group.parts.part.description.styles.style", ob_styles_style}, /* dup */
+     {"collections.group.parts.part.description.gradient", NULL},
+     {"collections.group.parts.part.description.gradient.rel1", NULL},
+     {"collections.group.parts.part.description.gradient.rel2", NULL},
+     {"collections.group.parts.part.description.color_classes", NULL}, /* dup */
+     {"collections.group.parts.part.description.color_classes.color_class", ob_color_class}, /* dup */
+     {"collections.group.parts.part.description.program", ob_collections_group_programs_program}, /* dup */
+     {"collections.group.parts.part.description.program.script", ob_collections_group_programs_program_script}, /* dup */
+     {"collections.group.parts.part.description.programs", NULL}, /* dup */
+     {"collections.group.parts.part.description.programs.images", NULL}, /* dup */
+     {"collections.group.parts.part.description.programs.fonts", NULL}, /* dup */
+     {"collections.group.parts.part.description.programs.program", ob_collections_group_programs_program}, /* dup */
+     {"collections.group.parts.part.description.programs.program.script", ob_collections_group_programs_program_script}, /* dup */
+     {"collections.group.parts.part.description.script", ob_collections_group_script}, /* dup */
+     {"collections.group.parts.part.program", ob_collections_group_programs_program}, /* dup */
+     {"collections.group.parts.part.program.script", ob_collections_group_programs_program_script}, /* dup */
+     {"collections.group.parts.part.programs", NULL}, /* dup */
+     {"collections.group.parts.part.programs.images", NULL}, /* dup */
+     {"collections.group.parts.part.programs.fonts", NULL}, /* dup */
+     {"collections.group.parts.part.programs.program", ob_collections_group_programs_program}, /* dup */
+     {"collections.group.parts.part.programs.program.script", ob_collections_group_programs_program_script}, /* dup */
+     {"collections.group.parts.part.script", ob_collections_group_script}, /* dup */
+     {"collections.group.parts.program", ob_collections_group_programs_program}, /* dup */
+     {"collections.group.parts.program.script", ob_collections_group_programs_program_script}, /* dup */
+     {"collections.group.parts.programs", NULL}, /* dup */
+     {"collections.group.parts.programs.images", NULL}, /* dup */
+     {"collections.group.parts.programs.fonts", NULL}, /* dup */
+     {"collections.group.parts.programs.program", ob_collections_group_programs_program}, /* dup */
+     {"collections.group.parts.programs.program.script", ob_collections_group_programs_program_script}, /* dup */
+     {"collections.group.parts.script", ob_collections_group_script}, /* dup */
+     {"collections.group.program", ob_collections_group_programs_program}, /* dup */
+     {"collections.group.program.script", ob_collections_group_programs_program_script}, /* dup */
+     {"collections.group.programs", NULL},
+     {"collections.group.programs.images", NULL}, /* dup */
+     {"collections.group.programs.fonts", NULL}, /* dup */
+     {"collections.group.programs.program", ob_collections_group_programs_program},
+     {"collections.group.programs.program.script", ob_collections_group_programs_program_script},
+     {"collections.group.programs.script", ob_collections_group_script} /* dup */
+};
+
+/*****/
+
+int
+object_handler_num(void)
+{
+   return sizeof(object_handlers) / sizeof (New_Object_Handler);
+}
+
+int
+statement_handler_num(void)
+{
+   return sizeof(statement_handlers) / sizeof (New_Object_Handler);
+}
+
+/*****/
+
+/**
+    @page edcref
+
+    @block
+        images
+    @context
+        images {
+            image: "filename1.ext" COMP;
+            image: "filename2.ext" LOSSY 99;
+            ..
+        }
+    @description
+        The "images" block is used to list each image file that will be used in
+        the theme along with its compression method (if any).
+        Besides the domcument's root, additional "images" blocks can be
+        included inside other blocks, normally "collections", "group" and
+        "part", easing mantienance of the file list when the theme is split
+        among multiple files.
+    @endblock
+
+    @property
+        image
+    @parameters
+        [image file] [compression method] (compression level)
+    @effect
+        Used to include each image file. The full path to the directory holding
+        the images can be defined later with edje_cc's "-id" option.
+        Compression methods:
+        @li RAW: Uncompressed.
+        @li COMP: Lossless compression.
+        @li LOSSY [0-100]: Lossy comression with quality from 0 to 100.
+    @endproperty
+ */
+static void
+st_images_image(void)
+{
+   Edje_Image_Directory_Entry *img;
+   int v;
+
+   if (!edje_file->image_dir)
+     edje_file->image_dir = mem_alloc(SZ(Edje_Image_Directory));
+   img = mem_alloc(SZ(Edje_Image_Directory_Entry));
+   img->entry = parse_str(0);
+     {
+       Evas_List *l;
+
+       for (l = edje_file->image_dir->entries; l; l = l->next)
+         {
+            Edje_Image_Directory_Entry *limg;
+
+            limg = l->data;
+            if (!strcmp(limg->entry, img->entry))
+              {
+                 free(img->entry);
+                 free(img);
+                 return;
+              }
+         }
+     }
+   edje_file->image_dir->entries = evas_list_append(edje_file->image_dir->entries, img);
+   img->id = evas_list_count(edje_file->image_dir->entries) - 1;
+   v = parse_enum(1,
+                 "RAW", 0,
+                 "COMP", 1,
+                 "LOSSY", 2,
+                 "USER", 3,
+                 NULL);
+   if (v == 0)
+     {
+       img->source_type = EDJE_IMAGE_SOURCE_TYPE_INLINE_PERFECT;
+       img->source_param = 0;
+     }
+   else if (v == 1)
+     {
+       img->source_type = EDJE_IMAGE_SOURCE_TYPE_INLINE_PERFECT;
+       img->source_param = 1;
+     }
+   else if (v == 2)
+     {
+       img->source_type = EDJE_IMAGE_SOURCE_TYPE_INLINE_LOSSY;
+       img->source_param = 0;
+     }
+   else if (v == 3)
+     {
+       img->source_type = EDJE_IMAGE_SOURCE_TYPE_EXTERNAL;
+       img->source_param = 0;
+     }
+   if (img->source_type != EDJE_IMAGE_SOURCE_TYPE_INLINE_LOSSY)
+       check_arg_count(2);
+   else
+     {
+       img->source_param = parse_int_range(2, 0, 100);
+       check_arg_count(3);
+     }
+}
+
+/**
+    @page edcref
+
+    @block
+        fonts
+    @context
+        fonts {
+            font: "filename1.ext" "fontname";
+            font: "filename2.ext" "otherfontname";
+            ..
+        }
+    @description
+        The "fonts" block is used to list each font file with an alias used later
+        in the theme. As with the "images" block, additional "fonts" blocks can
+        be included inside other blocks.
+    @endblock
+
+    @property
+        font
+    @parameters
+        [font filename] [font alias]
+    @effect
+        Defines each font "file" and "alias", the full path to the directory
+        holding the font files can be defined with edje_cc's "-fd" option.
+    @endproperty
+ */
+static void
+st_fonts_font(void)
+{
+   Font *fn;
+   Edje_Font_Directory_Entry *fnt;
+
+   check_arg_count(2);
+
+   if (!edje_file->font_dir)
+     edje_file->font_dir = mem_alloc(SZ(Edje_Font_Directory));
+
+   fn = mem_alloc(SZ(Font));
+   fn->file = parse_str(0);
+   fn->name = parse_str(1);
+     {
+       Evas_List *l;
+
+       for (l = fonts; l; l = l->next)
+         {
+            Font *lfn;
+
+            lfn = l->data;
+            if (!strcmp(lfn->name, fn->name))
+              {
+                 free(fn->file);
+                 free(fn->name);
+                 free(fn);
+                 return;
+              }
+         }
+     }
+   fonts = evas_list_append(fonts, fn);
+
+   if (edje_file->font_dir)
+     {
+       fnt = mem_alloc(SZ(Edje_Font_Directory_Entry));
+       fnt->entry = mem_strdup(fn->name);
+       edje_file->font_dir->entries = evas_list_append(edje_file->font_dir->entries, fnt);
+     }
+}
+
+/**
+    @page edcref
+    @block
+        data
+    @context
+        data {
+            item: "arbitraryname" "arbitraryvalue";
+            item: "othername" "othervalue";
+            ..
+        }
+    @description
+        The "data" block is used to pass arbitrary parameters from the theme to
+        the application. Unlike the "images" and "fonts" blocks, additional
+        "data" blocks can only be included inside the "group" block.
+    @endblock
+
+    @property
+        item
+    @parameters
+        [parameter name] [parameter value]
+    @effect
+        Defines each additional parameter.
+    @endproperty
+ */
+static void
+st_data_item(void)
+{
+   Edje_Data *di;
+
+   check_arg_count(2);
+
+   di = mem_alloc(SZ(Edje_Data));
+   di->key = parse_str(0);
+   di->value = parse_str(1);
+   edje_file->data = evas_list_append(edje_file->data, di);
+}
+
+/**
+    @page edcref
+    @block
+        data
+    @context
+        data {
+            file: "arbitraryname" "filename";
+            file: "othername" "otherfilename";
+            ..
+        }
+    @description
+        The "data" block is used to pass arbitrary parameters from the theme to
+        the application. Unlike the "images" and "fonts" blocks, additional
+        "data" blocks can only be included inside the "group" block.
+    @endblock
+
+    @property
+        file
+    @parameters
+        [parameter name] [parameter filename]
+    @effect
+        Defines each additional parameter.
+    @endproperty
+ */
+static void
+st_data_file(void)
+{
+   const char *data;
+   const char *over;
+   Edje_Data *di;
+   char *filename;
+   char *value;
+   int fd;
+   int i;
+   struct stat buf;
+
+   check_arg_count(2);
+
+   di = mem_alloc(SZ(Edje_Data));
+   di->key = parse_str(0);
+   filename = parse_str(1);
+
+   fd = open(filename, O_RDONLY | O_BINARY);
+   if (fd < 0)
+     {
+        fprintf(stderr, "%s: Error. %s:%i when opening file \"%s\": \"%s\"\n",
+                progname, file_in, line, filename, strerror(errno));
+        exit(-1);
+     }
+
+   if (fstat(fd, &buf))
+     {
+        fprintf(stderr, "%s: Error. %s:%i when stating file \"%s\": \"%s\"\n",
+                progname, file_in, line, filename, strerror(errno));
+        exit(-1);
+     }
+
+   data = mmap(NULL, buf.st_size, PROT_READ, MAP_SHARED, fd, 0);
+   if (data == MAP_FAILED)
+     {
+        fprintf(stderr, "%s: Error. %s:%i when mapping file \"%s\": \"%s\"\n",
+                progname, file_in, line, filename, strerror(errno));
+        exit(-1);
+     }
+
+   over = data;
+   for (i = 0; i < buf.st_size; ++i, ++over)
+     if (*over == '\0')
+       {
+          fprintf(stderr, "%s: Error. %s:%i file \"%s\" is a binary file.\n",
+                  progname, file_in, line, filename);
+          exit(-1);
+       }
+
+   value = malloc(sizeof (char) * buf.st_size + 1);
+   snprintf(value, buf.st_size + 1, "%s", data);
+
+   munmap((void*)data, buf.st_size);
+   close(fd);
+
+   di->value = value;
+   edje_file->data = evas_list_append(edje_file->data, di);
+
+   free(filename);
+}
+
+/**
+    @page edcref
+    @block
+        color_classes
+    @context
+        color_classes {
+            color_class {
+                name:  "colorclassname";
+                color:  [0-255] [0-255] [0-255] [0-255];
+                color2: [0-255] [0-255] [0-255] [0-255];
+                color3: [0-255] [0-255] [0-255] [0-255]
+            }
+            ..
+        }
+    @description
+        The "color_classes" block contains a list of one or more "color_class"
+        blocks. Each "color_class" allows the designer to name an arbitrary
+        group of colors to be used in the theme, the application can use that
+        name to alter the color values at runtime.
+    @endblock
+*/
+static void
+ob_color_class(void)
+{
+   Edje_Color_Class *cc;
+
+   cc = mem_alloc(SZ(Edje_Color_Class));
+   edje_file->color_classes = evas_list_append(edje_file->color_classes, cc);
+
+   cc->r = 0;
+   cc->g = 0;
+   cc->b = 0;
+   cc->a = 0;
+   cc->r2 = 0;
+   cc->g2 = 0;
+   cc->b2 = 0;
+   cc->a2 = 0;
+   cc->r3 = 0;
+   cc->g3 = 0;
+   cc->b3 = 0;
+   cc->a3 = 0;
+}
+
+/**
+    @page edcref
+
+    @property
+        name
+    @parameters
+        [color class name]
+    @effect
+        Sets the name for the color class, used as reference by both the theme
+        and the application.
+    @endproperty
+*/
+static void
+st_color_class_name(void)
+{
+   Edje_Color_Class *cc, *tcc;
+   Evas_List *l;
+
+   cc = evas_list_data(evas_list_last(edje_file->color_classes));
+   cc->name = parse_str(0);
+   for (l = edje_file->color_classes; l; l = l->next)
+     {
+       tcc = l->data;
+       if ((cc != tcc) && (!strcmp(cc->name, tcc->name)))
+         {
+            fprintf(stderr, "%s: Error. parse error %s:%i. There is already a color class named \"%s\"\n",
+                    progname, file_in, line - 1, cc->name);
+            exit(-1);
+         }
+     }
+}
+
+/**
+    @page edcref
+    @property
+        color
+    @parameters
+        [red] [green] [blue] [alpha]
+    @effect
+        The main color.
+    @endproperty
+*/
+static void
+st_color_class_color(void)
+{
+   Edje_Color_Class *cc;
+
+   check_arg_count(4);
+
+   cc = evas_list_data(evas_list_last(edje_file->color_classes));
+   cc->r = parse_int_range(0, 0, 255);
+   cc->g = parse_int_range(1, 0, 255);
+   cc->b = parse_int_range(2, 0, 255);
+   cc->a = parse_int_range(3, 0, 255);
+}
+
+/**
+    @page edcref
+    @property
+        color2
+    @parameters
+        [red] [green] [blue] [alpha]
+    @effect
+        Used as shadow in text and textblock parts.
+    @endproperty
+*/
+static void
+st_color_class_color2(void)
+{
+   Edje_Color_Class *cc;
+
+   check_arg_count(4);
+
+   cc = evas_list_data(evas_list_last(edje_file->color_classes));
+   cc->r2 = parse_int_range(0, 0, 255);
+   cc->g2 = parse_int_range(1, 0, 255);
+   cc->b2 = parse_int_range(2, 0, 255);
+   cc->a2 = parse_int_range(3, 0, 255);
+}
+
+/**
+    @page edcref
+    @property
+        color3
+    @parameters
+        [red] [green] [blue] [alpha]
+    @effect
+        Used as outline in text and textblock parts.
+    @endproperty
+*/
+static void
+st_color_class_color3(void)
+{
+   Edje_Color_Class *cc;
+
+   check_arg_count(4);
+
+   cc = evas_list_data(evas_list_last(edje_file->color_classes));
+   cc->r3 = parse_int_range(0, 0, 255);
+   cc->g3 = parse_int_range(1, 0, 255);
+   cc->b3 = parse_int_range(2, 0, 255);
+   cc->a3 = parse_int_range(3, 0, 255);
+}
+
+/**
+    @page edcref
+    @block
+        spectra
+    @context
+        spectra {
+            spectrum {
+                name: "colorspectrumname";
+                color: [0-255] [0-255] [0-255] [0-255] [0-?]
+                color: [0-255] [0-255] [0-255] [0-255] [0-?]
+                ..
+            }
+            ..
+        }
+    @description
+        The "spectra" block contains a list of one or more "spectrum" blocks.
+        Each "spectrum" block defines a color range used to fill GRADIENT
+        parts. The colors are defined with the red, green, blue, alpha, delta
+        format.
+    @endblock
+*/
+static void
+ob_spectrum(void)
+{
+   Edje_Spectrum_Directory_Entry *se;
+
+   if (!edje_file->spectrum_dir)
+     edje_file->spectrum_dir = mem_alloc(SZ(Edje_Spectrum_Directory));
+   se = mem_alloc(SZ(Edje_Spectrum_Directory_Entry));
+   edje_file->spectrum_dir->entries = evas_list_append(edje_file->spectrum_dir->entries, se);
+   se->id = evas_list_count(edje_file->spectrum_dir->entries) - 1;
+   se->entry = NULL;
+   se->filename = NULL;
+   se->color_list = NULL;
+}
+
+/**
+    @page edcref
+    @property
+        name
+    @parameters
+        [spectrum name]
+    @effect
+        The name of the spectrum used as reference later in the theme.
+    @endproperty
+*/
+static void
+st_spectrum_name(void)
+{
+   Edje_Spectrum_Directory_Entry *se;
+
+   se = evas_list_data(evas_list_last(edje_file->spectrum_dir->entries));
+   se->entry = parse_str(0);
+}
+
+/**
+    @page edcref
+    @property
+        color
+    @parameters
+        [red] [green] [blue] [alpha] [delta]
+    @effect
+        Each color declaration represents a stop point in the color range. The
+        last parameter (delta) is used to set the proportion of a given stop
+        point higher or lower in contrast with the other color's delta value.
+    @endproperty
+*/
+static void
+st_spectrum_color(void)
+{
+   Edje_Spectrum_Directory_Entry *se;
+   Edje_Spectrum_Color *sc;
+
+   se = evas_list_data(evas_list_last(edje_file->spectrum_dir->entries));
+
+   sc = mem_alloc(SZ(Edje_Spectrum_Color));
+   se->color_list = evas_list_append(se->color_list, sc);
+   sc->r = parse_int_range(0, 0, 255);
+   sc->g = parse_int_range(1, 0, 255);
+   sc->b = parse_int_range(2, 0, 255);
+   sc->a = parse_int_range(3, 0, 255);
+   sc->d = parse_int(4);
+}
+
+/**
+    @page edcref
+    @block
+        styles
+    @context
+        styles {
+            style {
+                name: "stylename";
+                base: "..default style properties..";
+
+                tag:  "tagname" "..style properties..";
+                ..
+            }
+            ..
+        }
+    @description
+        The "styles" block contains a list of one or more "style" blocks. A
+        "style" block is used to create style \<tags\> for advanced TEXTBLOCK
+        formatting.
+    @endblock
+*/
+static void
+ob_styles_style(void)
+{
+   Edje_Style *stl;
+
+   stl = mem_alloc(SZ(Edje_Style));
+   edje_file->styles = evas_list_append(edje_file->styles, stl);
+}
+
+/**
+    @page edcref
+    @property
+        name
+    @parameters
+        [style name]
+    @effect
+        The name of  the style to be used as reference later in the theme.
+    @endproperty
+*/
+static void
+st_styles_style_name(void)
+{
+   Edje_Style *stl, *tstl;
+   Evas_List *l;
+
+   stl = evas_list_data(evas_list_last(edje_file->styles));
+   stl->name = parse_str(0);
+   for (l = edje_file->styles; l; l = l->next)
+     {
+       tstl = l->data;
+       if ((stl != tstl) && (!strcmp(stl->name, tstl->name)))
+         {
+            fprintf(stderr, "%s: Error. parse error %s:%i. There is already a style named \"%s\"\n",
+                    progname, file_in, line - 1, stl->name);
+            exit(-1);
+         }
+     }
+}
+
+/**
+    @page edcref
+    @property
+        base
+    @parameters
+        [style properties string]
+    @effect
+        The default style properties that will be applied to the complete
+        text.
+    @endproperty
+*/
+static void
+st_styles_style_base(void)
+{
+   Edje_Style *stl;
+   Edje_Style_Tag *tag;
+
+   stl = evas_list_data(evas_list_last(edje_file->styles));
+   if (stl->tags)
+     {
+       fprintf(stderr, "%s: Error. parse error %s:%i. There is already a basic format for the style\n",
+               progname, file_in, line - 1);
+       exit(-1);
+     }
+   tag = mem_alloc(SZ(Edje_Style_Tag));
+   tag->key = mem_strdup("DEFAULT");
+   tag->value = parse_str(0);
+   stl->tags = evas_list_append(stl->tags, tag);
+}
+
+/**
+    @page edcref
+    @property
+        tag
+    @parameters
+        [tag name] [style properties string]
+    @effect
+        Style to be applied only to text between style \<tags\>..\</tags\>.
+    @endproperty
+*/
+static void
+st_styles_style_tag(void)
+{
+   Edje_Style *stl;
+   Edje_Style_Tag *tag;
+
+   stl = evas_list_data(evas_list_last(edje_file->styles));
+   tag = mem_alloc(SZ(Edje_Style_Tag));
+   tag->key = parse_str(0);
+   tag->value = parse_str(1);
+   stl->tags = evas_list_append(stl->tags, tag);
+}
+
+/**
+    @page edcref
+    @block
+        collections
+    @context
+        collections {
+            ..
+            group { }
+            group { }
+            ..
+        }
+    @description
+        The "collections" block is used to list the groups that compose the
+        theme. Additional "collections" blocks do not prevent overriding group
+        names.
+    @endblock
+*/
+static void
+ob_collections(void)
+{
+   if (!edje_file->collection_dir)
+     edje_file->collection_dir = mem_alloc(SZ(Edje_Part_Collection_Directory));
+}
+
+/**
+    @page edcref
+    @block
+        group
+    @context
+        collections {
+            ..
+            group {
+                name: "nameusedbytheapplication";
+                alias: "anothername";
+                min: width height;
+                max: width height;
+
+                data { }
+                script { }
+                parts { }
+                programs { }
+            }
+            ..
+        }
+    @description
+        A "group" block contains the list of parts and programs that compose a
+        given Edje Object.
+    @endblock
+*/
+static void
+ob_collections_group(void)
+{
+   Edje_Part_Collection_Directory_Entry *de;
+   Edje_Part_Collection *pc;
+   Code *cd;
+
+   de = mem_alloc(SZ(Edje_Part_Collection_Directory_Entry));
+   edje_file->collection_dir->entries = evas_list_append(edje_file->collection_dir->entries, de);
+   de->id = evas_list_count(edje_file->collection_dir->entries) - 1;
+
+   pc = mem_alloc(SZ(Edje_Part_Collection));
+   edje_collections = evas_list_append(edje_collections, pc);
+   pc->id = evas_list_count(edje_collections) - 1;
+
+   cd = mem_alloc(SZ(Code));
+   codes = evas_list_append(codes, cd);
+}
+
+/**
+    @page edcref
+    @property
+        name
+    @parameters
+        [group name]
+    @effect
+        The name that will be used by the application to load the resulting
+        Edje object, must be unique within the theme.
+    @endproperty
+*/
+static void
+st_collections_group_name(void)
+{
+   Edje_Part_Collection_Directory_Entry *de;
+
+   check_arg_count(1);
+
+   de = evas_list_data(evas_list_last(edje_file->collection_dir->entries));
+   de->entry = parse_str(0);
+}
+
+/**
+    @page edcref
+    @property
+        script_only
+    @parameters
+        [on/off]
+    @effect
+        The flag (on/off) as to if this group is defined ONLY by script
+        callbacks such as init(), resize() and shutdown()
+    @endproperty
+*/
+static void
+st_collections_group_script_only(void)
+{
+   Edje_Part_Collection *pc;
+
+   check_arg_count(1);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   pc->script_only = parse_bool(0);
+}
+
+/**
+    @page edcref
+    @property
+        alias
+    @parameters
+        [aditional group name]
+    @effect
+        Additional name to serve as identifier. Defining multiple aliases is
+        supported.
+    @endproperty
+*/
+static void
+st_collections_group_alias(void)
+{
+   Edje_Part_Collection_Directory_Entry *de, *alias;
+
+   check_arg_count(1);
+   de = evas_list_data(evas_list_last(edje_file->collection_dir->entries));
+
+   alias = mem_alloc(SZ(Edje_Part_Collection_Directory_Entry));
+   alias->id = de->id;
+   alias->entry = parse_str(0);
+
+   aliases = evas_list_append(aliases, alias);
+}
+
+/**
+    @page edcref
+    @property
+        min
+    @parameters
+        [width] [height]
+    @effect
+        The minimum size for the container defined by the composition of the
+        parts.
+    @endproperty
+*/
+static void
+st_collections_group_min(void)
+{
+   Edje_Part_Collection *pc;
+
+   check_arg_count(2);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   pc->prop.min.w = parse_int_range(0, 0, 0x7fffffff);
+   pc->prop.min.h = parse_int_range(1, 0, 0x7fffffff);
+}
+
+/**
+    @page edcref
+    @property
+        max
+    @parameters
+        [width] [height]
+    @effect
+        The maximum size for the container defined by the totality of the
+        parts.
+    @endproperty
+*/
+static void
+st_collections_group_max(void)
+{
+   Edje_Part_Collection *pc;
+
+   check_arg_count(2);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   pc->prop.max.w = parse_int_range(0, 0, 0x7fffffff);
+   pc->prop.max.h = parse_int_range(1, 0, 0x7fffffff);
+}
+
+/**
+    @page edcref
+    @block
+        script
+    @context
+        ..
+        group {
+            script {
+                //embryo script
+            }
+            ..
+            program {
+                script {
+                    //embryo script
+                }
+            }
+            ..
+        }
+        ..
+    @description
+        This block is used to "inject" embryo scripts to a given Edje theme and
+        it functions in two modalities. When it's included inside a "program"
+        block, the script will be executed every time the program is run, on
+        the other hand, when included directly into a "group", "part" or
+        "description" block, it will be executed once at load time, in the
+        load order.
+    @endblock
+*/
+static void
+ob_collections_group_script(void)
+{
+   Edje_Part_Collection *pc;
+   Code *cd;
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   cd = evas_list_data(evas_list_last(codes));
+
+   if (!is_verbatim()) track_verbatim(1);
+   else
+     {
+       char *s;
+
+       s = get_verbatim();
+       if (s)
+         {
+            cd->l1 = get_verbatim_line1();
+            cd->l2 = get_verbatim_line2();
+            if (cd->shared)
+              {
+                 fprintf(stderr, "%s: Error. parse error %s:%i. There is already an existing script section for the group\n",
+                         progname, file_in, line - 1);
+                 exit(-1);
+              }
+            cd->shared = s;
+            set_verbatim(NULL, 0, 0);
+         }
+     }
+}
+
+static void
+st_collections_group_data_item(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Data *di;
+
+   check_arg_count(2);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   di = mem_alloc(SZ(Edje_Data));
+   di->key = parse_str(0);
+   di->value = parse_str(1);
+   pc->data = evas_list_append(pc->data, di);
+}
+
+/**
+    @page edcref
+    @block
+        part
+    @context
+        group {
+            parts {
+                ..
+                part {
+                    name: "partname";
+                    type: IMAGE;
+                    mouse_events:  1;
+                    repeat_events: 0;
+                    ignore_flags: NONE;
+                    clip_to: "anotherpart";
+                    source:  "groupname";
+                    pointer_mode: AUTOGRAB;
+                    use_alternate_font_metrics: 0;
+
+                    description { }
+                    dragable { }
+                }
+                ..
+            }
+        }
+    @description
+        Parts are used to represent the most basic design elements of the
+        theme, for example, a part can represent a line in a border or a label
+        on a button.
+    @endblock
+*/
+static void
+ob_collections_group_parts_part(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+
+   ep = mem_alloc(SZ(Edje_Part));
+   pc = evas_list_data(evas_list_last(edje_collections));
+   pc->parts = evas_list_append(pc->parts, ep);
+   ep->id = evas_list_count(pc->parts) - 1;
+   ep->type = EDJE_PART_TYPE_IMAGE;
+   ep->mouse_events = 1;
+   ep->repeat_events = 0;
+   ep->ignore_flags = EVAS_EVENT_FLAG_NONE;
+   ep->pointer_mode = EVAS_OBJECT_POINTER_MODE_AUTOGRAB;
+   ep->precise_is_inside = 0;
+   ep->use_alternate_font_metrics = 0;
+   ep->clip_to_id = -1;
+   ep->dragable.confine_id = -1;
+   ep->dragable.events_id = -1;
+}
+
+/**
+    @page edcref
+    @property
+        name
+    @parameters
+        [part name]
+    @effect
+        The part's name will be used as reference in the theme's relative
+        positioning system, by programs and in some cases by the application.
+        It must be unique within the group.
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_name(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+
+   check_arg_count(1);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+   ep->name = parse_str(0);
+
+   {
+       Evas_List *l;
+
+       for (l = pc->parts; l; l = l->next)
+         {
+            Edje_Part *lep;
+
+            lep = l->data;
+            if ((lep != ep) && (lep->name) && (!strcmp(lep->name, ep->name)))
+              {
+                 fprintf(stderr, "%s: Error. parse error %s:%i. There is already a part of the name %s\n",
+                         progname, file_in, line - 1, ep->name);
+                 exit(-1);
+              }
+         }
+   }
+}
+
+/**
+    @page edcref
+    @property
+        type
+    @parameters
+        [TYPE]
+    @effect
+        Set the type (all caps) from among the available types, it's set to
+        IMAGE by default. Valid types:
+            @li RECT
+            @li TEXT
+            @li IMAGE
+            @li SWALLOW
+            @li TEXTBLOCK
+            @li GRADIENT
+            @li GROUP
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_type(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+
+   check_arg_count(1);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+   ep->type = parse_enum(0,
+                        "NONE", EDJE_PART_TYPE_NONE,
+                        "RECT", EDJE_PART_TYPE_RECTANGLE,
+                        "TEXT", EDJE_PART_TYPE_TEXT,
+                        "IMAGE", EDJE_PART_TYPE_IMAGE,
+                        "SWALLOW", EDJE_PART_TYPE_SWALLOW,
+                        "TEXTBLOCK", EDJE_PART_TYPE_TEXTBLOCK,
+                        "GRADIENT", EDJE_PART_TYPE_GRADIENT,
+                        "GROUP", EDJE_PART_TYPE_GROUP,
+                        NULL);
+}
+
+/**
+    @page edcref
+    @property
+        mouse_events
+    @parameters
+        [1 or 0]
+    @effect
+        Specifies whether the part will emit signals, altought is named
+        "mouse_events", disabling it (0) will prevent the part from emitting
+        any type of signal at all. Its set to 1 by default.
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_mouse_events(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+
+   check_arg_count(1);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+   ep->mouse_events = parse_bool(0);
+}
+
+/**
+    @page edcref
+    @property
+        repeat_events
+    @parameters
+        [1 or 0]
+    @effect
+        Specifies whether a part echoes a mouse event to other parts below the
+        pointer (1), or not (0). Its set to 0 by default.
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_repeat_events(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+
+   check_arg_count(1);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+   ep->repeat_events = parse_bool(0);
+}
+
+/**
+    @page edcref
+    @property
+        ignore_flags
+    @parameters
+        [FLAG] ...
+    @effect
+        Specifies whether events with the given flags should be ignored,
+       i.e., will not have the signals emitted to the parts. Multiple flags
+       must be separated by spaces, the effect will be ignoring all events
+       with one of the flags specified. Possible flags:
+            @li NONE (default value, no event will be ignored)
+            @li ON_HOLD
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_ignore_flags(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+
+   check_min_arg_count(1);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+   ep->ignore_flags = parse_flags(0,
+                                 "NONE", EVAS_EVENT_FLAG_NONE,
+                                 "ON_HOLD", EVAS_EVENT_FLAG_ON_HOLD,
+                                 NULL);
+}
+
+/**
+    @page edcref
+    @property
+        pointer_mode
+    @parameters
+        [MODE]
+    @effect
+        Sets the mouse pointer behavior for a given part. The default value is
+        AUTOGRAB. Aviable modes:
+            @li AUTOGRAB, when the part is clicked and the button remains
+                pressed, the part will be the source of all future mouse
+                signals emitted, even outside the object, until the button is
+                released.
+            @li NOGRAB, the effect will be limited to the part's container.
+        container.
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_pointer_mode(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+
+   check_arg_count(1);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+   ep->pointer_mode = parse_enum(0,
+                                "AUTOGRAB", EVAS_OBJECT_POINTER_MODE_AUTOGRAB,
+                                "NOGRAB", EVAS_OBJECT_POINTER_MODE_NOGRAB,
+                                NULL);
+}
+
+/**
+    @page edcref
+    @property
+        precise_is_inside
+    @parameters
+        [1 or 0]
+    @effect
+        Enables precise point collision detection for the part, which is more
+        resource intensive. Disabled by default.
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_precise_is_inside(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+
+   check_arg_count(1);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+   ep->precise_is_inside = parse_bool(0);
+}
+
+/**
+    @page edcref
+    @property
+        use_alternate_font_metrics
+    @parameters
+        [1 or 0]
+    @effect
+        Only affects text and textblock parts, when enabled Edje will use
+        different size measurement functions. Disabled by default. (note from
+        the author: I don't know what this is exactlu useful for?)
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_use_alternate_font_metrics(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+
+   check_arg_count(1);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+   ep->use_alternate_font_metrics = parse_bool(0);
+}
+
+/**
+    @page edcref
+    @property
+        clip_to
+    @parameters
+        [another part's name]
+    @effect
+        Only renders the area of part that coincides with another part's
+        container. Overflowing content will not be displayed.
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_clip_to_id(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+
+   check_arg_count(1);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+     {
+       char *name;
+
+       name = parse_str(0);
+       data_queue_part_lookup(pc, name, &(ep->clip_to_id));
+       free(name);
+     }
+}
+
+/**
+    @page edcref
+    @property
+        source
+    @parameters
+        [another group's name]
+    @effect
+        Only available to GROUP parts. Swallows the specified group into the
+        part's container.
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_source(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+
+   check_arg_count(1);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+
+   if (ep->type != EDJE_PART_TYPE_GROUP)
+     {
+       fprintf(stderr, "%s: Error. parse error %s:%i. "
+               "source attribute in non-GROUP part.\n",
+               progname, file_in, line - 1);
+       exit(-1);
+     }
+
+   //XXX validate this somehow (need to decide on the format also)
+   ep->source = parse_str(0);
+}
+
+/**
+    @page edcref
+
+    @property
+        effect
+    @parameters
+        [EFFECT]
+    @effect
+        Causes Edje to draw the selected effect among:
+        @li PLAIN
+        @li OUTLINE
+        @li SOFT_OUTLINE
+        @li SHADOW
+        @li SOFT_SHADOW
+        @li OUTLINE_SHADOW
+        @li OUTLINE_SOFT_SHADOW
+        @li FAR_SHADOW
+        @li FAR_SOFT_SHADOW
+        @li GLOW
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_effect(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+
+   check_arg_count(1);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+   ep->effect = parse_enum(0,
+               "NONE", EDJE_TEXT_EFFECT_NONE,
+               "PLAIN", EDJE_TEXT_EFFECT_PLAIN,
+               "OUTLINE", EDJE_TEXT_EFFECT_OUTLINE,
+               "SOFT_OUTLINE", EDJE_TEXT_EFFECT_SOFT_OUTLINE,
+               "SHADOW", EDJE_TEXT_EFFECT_SHADOW,
+               "SOFT_SHADOW", EDJE_TEXT_EFFECT_SOFT_SHADOW,
+               "OUTLINE_SHADOW", EDJE_TEXT_EFFECT_OUTLINE_SHADOW,
+               "OUTLINE_SOFT_SHADOW", EDJE_TEXT_EFFECT_OUTLINE_SOFT_SHADOW,
+               "FAR_SHADOW", EDJE_TEXT_EFFECT_FAR_SHADOW,
+               "FAR_SOFT_SHADOW", EDJE_TEXT_EFFECT_FAR_SOFT_SHADOW,
+               "GLOW", EDJE_TEXT_EFFECT_GLOW,
+               NULL);
+}
+
+/**
+    @page edcref
+    @block
+        dragable
+    @context
+        part {
+            ..
+            dragable {
+                confine: "another part";
+                events:  "another dragable part";
+                x: 0 0 0;
+                y: 0 0 0;
+            }
+            ..
+        }
+    @description
+        When this block is used the resulting part can be dragged around the
+        interface, do not confuse with external drag & drop. By default Edje
+        (and most applications) will attempt to use the minimal size possible
+        for a dragable part. If the min property is not set in the description
+        the part will be (most likely) set to 0px width and 0px height, thus
+        invisible.
+    @endblock
+
+    @property
+        x
+    @parameters
+        [enable/disable] [step] [count]
+    @effect
+        Used to setup dragging events for the X axis. The first parameter is
+        used to enable (1 or -1) and disable (0) dragging along the axis. When
+        enabled, 1 will set the starting point at 0.0 and -1 at 1.0. The second
+        parameter takes any integer and will limit movement to values
+        divisibles by it, causing the part to jump from position to position.
+        The third parameter, (question from the author: What is count for?).
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_dragable_x(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+
+   check_arg_count(3);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+   ep->dragable.x = parse_int_range(0, -1, 1);
+   ep->dragable.step_x = parse_int_range(1, 0, 0x7fffffff);
+   ep->dragable.count_x = parse_int_range(2, 0, 0x7fffffff);
+}
+
+/**
+    @page edcref
+    @property
+        y
+    @parameters
+        [enable/disable] [step] [count]
+    @effect
+        Used to setup dragging events for the Y axis. The first parameter is
+        used to enable (1 or -1) and disable (0) dragging along the axis. When
+        enabled, 1 will set the starting point at 0.0 and -1 at 1.0. The second
+        parameter takes any integer and will limit movement to values
+        divisibles by it, causing the part to jump from position to position.
+        The third parameter, (question from the author: What is count for?).
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_dragable_y(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+
+   check_arg_count(3);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+   ep->dragable.y = parse_int_range(0, -1, 1);
+   ep->dragable.step_y = parse_int_range(1, 0, 0x7fffffff);
+   ep->dragable.count_y = parse_int_range(2, 0, 0x7fffffff);
+}
+
+/**
+    @page edcref
+    @property
+        confine
+    @parameters
+        [another part's name]
+    @effect
+        When set, limits the movement of the dragged part to another part's
+        container.
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_dragable_confine(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+
+   check_arg_count(1);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+     {
+       char *name;
+
+       name = parse_str(0);
+       data_queue_part_lookup(pc, name, &(ep->dragable.confine_id));
+       free(name);
+     }
+}
+
+/**
+    @page edcref
+    @property
+        events
+    @parameters
+        [another dragable part's name]
+    @effect
+        It causes the part to forward the drag events to another part, thus
+        ignoring them for itself.
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_dragable_events(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+
+   check_arg_count(1);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+     {
+       char *name;
+
+       name = parse_str(0);
+       data_queue_part_lookup(pc, name, &(ep->dragable.events_id));
+       free(name);
+     }
+}
+
+/**
+    @page edcref
+    @block
+        description
+    @context
+        description {
+            inherit: "another_description" INDEX;
+            state: "description_name" INDEX;
+            visible: 1;
+            min: 0 0;
+            max: -1 -1;
+            align: 0.5 0.5;
+            fixed: 0 0;
+            step: 0 0;
+            aspect: 1 1;
+
+            rel1 {
+                ..
+            }
+
+            rel2 {
+                ..
+            }
+        }
+    @description
+        Every part can have one or more description blocks. Each description is
+        used to define style and layout properties of a part in a given
+        "state".
+    @endblock
+*/
+static void
+ob_collections_group_parts_part_description(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+   Edje_Part_Description *ed;
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+   ed = mem_alloc(SZ(Edje_Part_Description));
+   if (!ep->default_desc)
+     ep->default_desc = ed;
+   else
+     ep->other_desc = evas_list_append(ep->other_desc, ed);
+   ed->visible = 1;
+   ed->align.x = 0.5;
+   ed->align.y = 0.5;
+   ed->min.w = 0;
+   ed->min.h = 0;
+   ed->fixed.w = 0;
+   ed->fixed.h = 0;
+   ed->max.w = -1;
+   ed->max.h = -1;
+   ed->rel1.relative_x = 0.0;
+   ed->rel1.relative_y = 0.0;
+   ed->rel1.offset_x = 0;
+   ed->rel1.offset_y = 0;
+   ed->rel1.id_x = -1;
+   ed->rel1.id_y = -1;
+   ed->rel2.relative_x = 1.0;
+   ed->rel2.relative_y = 1.0;
+   ed->rel2.offset_x = -1;
+   ed->rel2.offset_y = -1;
+   ed->rel2.id_x = -1;
+   ed->rel2.id_y = -1;
+   ed->image.id = -1;
+   ed->fill.smooth = 1;
+   ed->fill.pos_rel_x = 0.0;
+   ed->fill.pos_abs_x = 0;
+   ed->fill.rel_x = 1.0;
+   ed->fill.abs_x = 0;
+   ed->fill.pos_rel_y = 0.0;
+   ed->fill.pos_abs_y = 0;
+   ed->fill.rel_y = 1.0;
+   ed->fill.abs_y = 0;
+   ed->fill.angle = 0;
+   ed->fill.spread = 0;
+   ed->fill.type = EDJE_FILL_TYPE_SCALE;
+   ed->color_class = NULL;
+   ed->color.r = 255;
+   ed->color.g = 255;
+   ed->color.b = 255;
+   ed->color.a = 255;
+   ed->color2.r = 0;
+   ed->color2.g = 0;
+   ed->color2.b = 0;
+   ed->color2.a = 255;
+   ed->color3.r = 0;
+   ed->color3.g = 0;
+   ed->color3.b = 0;
+   ed->color3.a = 128;
+   ed->text.align.x = 0.5;
+   ed->text.align.y = 0.5;
+   ed->text.id_source = -1;
+   ed->text.id_text_source = -1;
+   ed->gradient.rel1.relative_x = 0;
+   ed->gradient.rel1.relative_y = 0;
+   ed->gradient.rel1.offset_x = 0;
+   ed->gradient.rel1.offset_y = 0;
+   ed->gradient.rel2.relative_x = 1;
+   ed->gradient.rel2.relative_y = 1;
+   ed->gradient.rel2.offset_x = -1;
+   ed->gradient.rel2.offset_y = -1;
+}
+
+/**
+    @page edcref
+    @property
+        inherit
+    @parameters
+        [another description's name] [another description's index]
+    @effect
+        When set, the description will inherit all the properties from the
+        named description. The properties defined in this part will override
+        the inherited properties, reducing the amount of necessary code for
+        simple state changes. Note: inheritance in Edje is single level only.
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_description_inherit(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+   Edje_Part_Description *ed, *parent = NULL;
+   Evas_List *l;
+   char *parent_name, *state_name;
+   double parent_val, state_val;
+
+   check_arg_count(2);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+
+   /* inherit may not be used in the default description */
+   if (!ep->other_desc)
+     {
+       fprintf(stderr, "%s: Error. parse error %s:%i. "
+               "inherit may not be used in the default description\n",
+               progname, file_in, line - 1);
+       exit(-1);
+     }
+
+   ed = evas_list_data(evas_list_last(ep->other_desc));
+
+   if (!ed->state.name)
+     {
+       fprintf(stderr, "%s: Error. parse error %s:%i. "
+               "inherit may only be used after state\n",
+               progname, file_in, line - 1);
+       exit(-1);
+     }
+
+   /* find the description that we inherit from */
+   parent_name = parse_str(0);
+   parent_val = parse_float_range(1, 0.0, 1.0);
+
+   if (!strcmp (parent_name, "default") && parent_val == 0.0)
+     parent = ep->default_desc;
+   else
+     {
+       double min_dst = 999.0;
+
+       if (!strcmp(parent_name, "default"))
+         {
+            parent = ep->default_desc;
+            min_dst = ABS(ep->default_desc->state.value - parent_val);
+         }
+
+       for (l = ep->other_desc; l; l = l->next)
+         {
+            Edje_Part_Description *d = l->data;
+
+            if (!strcmp (d->state.name, parent_name))
+              {
+                 double dst;
+
+                 dst = ABS(d->state.value - parent_val);
+                 if (dst < min_dst)
+                   {
+                      parent = d;
+                      min_dst = dst;
+                   }
+              }
+         }
+     }
+
+   if (!parent)
+     {
+       fprintf (stderr, "%s: Error. parse error %s:%i. "
+             "cannot find referenced part state %s %lf\n",
+             ep->name, file_in, line - 1, parent_name, parent_val);
+       exit(-1);
+     }
+
+   free (parent_name);
+
+   /* now do a full copy, only state info will be kept */
+   state_name = ed->state.name;
+   state_val = ed->state.value;
+
+   *ed = *parent;
+
+   ed->state.name = state_name;
+   ed->state.value = state_val;
+
+   data_queue_part_slave_lookup(&parent->rel1.id_x, &ed->rel1.id_x);
+   data_queue_part_slave_lookup(&parent->rel1.id_y, &ed->rel1.id_y);
+   data_queue_part_slave_lookup(&parent->rel2.id_x, &ed->rel2.id_x);
+   data_queue_part_slave_lookup(&parent->rel2.id_y, &ed->rel2.id_y);
+   data_queue_image_slave_lookup(&parent->image.id, &ed->image.id);
+   data_queue_spectrum_slave_lookup(&parent->gradient.id, &ed->gradient.id);
+
+   /* make sure all the allocated memory is getting copied, not just
+    * referenced
+    */
+   ed->image.tween_list = NULL;
+
+   for (l = parent->image.tween_list; l; l = l->next)
+     {
+       Edje_Part_Image_Id *iid, *iid_new;
+
+       iid = l->data;
+       iid_new = mem_alloc(SZ(Edje_Part_Image_Id));
+       data_queue_image_slave_lookup(&(iid->id), &(iid_new->id));
+       ed->image.tween_list = evas_list_append(ed->image.tween_list, iid_new);
+     }
+
+#define STRDUP(x) x ? strdup(x) : NULL
+
+   ed->color_class = STRDUP(ed->color_class);
+   ed->text.text = STRDUP(ed->text.text);
+   ed->text.text_class = STRDUP(ed->text.text_class);
+   ed->text.font = STRDUP(ed->text.font);
+#undef STRDUP
+
+   data_queue_part_slave_lookup(&(parent->text.id_source), &(ed->text.id_source));
+   data_queue_part_slave_lookup(&(parent->text.id_text_source), &(ed->text.id_text_source));
+}
+
+/**
+    @page edcref
+    @property
+        state
+    @parameters
+        [a name for the description] [an index]
+    @effect
+        Sets a name used to identify a description inside a given part.
+        Multiple descriptions are used to declare different states of the same
+        part, like "clicked" or "invisible". All states declarations are also
+        coupled with an index number between 0.0 and 1.0. All parts must have
+        at least one description named "default 0.0".
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_description_state(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+   Edje_Part_Description *ed;
+   char *s;
+
+   check_arg_count(2);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+   ed = ep->default_desc;
+   if (ep->other_desc) ed = evas_list_data(evas_list_last(ep->other_desc));
+
+   s = parse_str(0);
+   if (!strcmp (s, "custom"))
+     {
+       fprintf(stderr, "%s: Error. parse error %s:%i. "
+               "invalid state name: '%s'.\n",
+               progname, file_in, line - 1, s);
+       exit(-1);
+     }
+
+   ed->state.name = s;
+   ed->state.value = parse_float_range(1, 0.0, 1.0);
+}
+
+/**
+    @page edcref
+    @property
+        visible
+    @parameters
+        [0 or 1]
+    @effect
+        Takes a boolean value specifying whether part is visible (1) or not
+        (0). Non-visible parts do not emit signals. The default value is 1.
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_description_visible(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+   Edje_Part_Description *ed;
+
+   check_arg_count(1);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+   ed = ep->default_desc;
+   if (ep->other_desc) ed = evas_list_data(evas_list_last(ep->other_desc));
+   ed->visible = parse_bool(0);
+}
+
+/**
+    @page edcref
+    @property
+        align
+    @parameters
+        [X axis] [Y axis]
+    @effect
+        When the displayed object's size is smaller than its container, this
+        property moves it relatively along both axis inside its container. The
+        default value is "0.5 0.5".
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_description_align(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+   Edje_Part_Description *ed;
+
+   check_arg_count(2);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+   ed = ep->default_desc;
+   if (ep->other_desc) ed = evas_list_data(evas_list_last(ep->other_desc));
+   ed->align.x = parse_float_range(0, 0.0, 1.0);
+   ed->align.y = parse_float_range(1, 0.0, 1.0);
+}
+
+/**
+    @page edcref
+    @property
+        fixed
+    @parameters
+        [width, 0 or 1] [height, 0 or 1]
+    @effect
+        When the "min" or "max" properties are set, fixed enables or disables
+        resizing for each dimension. The default value is "0 0"
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_description_fixed(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+   Edje_Part_Description *ed;
+
+   check_arg_count(2);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+   ed = ep->default_desc;
+   if (ep->other_desc) ed = evas_list_data(evas_list_last(ep->other_desc));
+   ed->fixed.w = parse_float_range(0, 0, 1);
+   ed->fixed.h = parse_float_range(1, 0, 1);
+}
+
+/**
+    @page edcref
+    @property
+        min
+    @parameters
+        [width] [height]
+    @effect
+        The minimum size of the state.
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_description_min(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+   Edje_Part_Description *ed;
+
+   check_arg_count(2);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+   ed = ep->default_desc;
+   if (ep->other_desc) ed = evas_list_data(evas_list_last(ep->other_desc));
+   ed->min.w = parse_float_range(0, 0, 0x7fffffff);
+   ed->min.h = parse_float_range(1, 0, 0x7fffffff);
+}
+
+/**
+    @page edcref
+    @property
+        max
+    @parameters
+        [width] [height]
+    @effect
+        The maximum size of the state.
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_description_max(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+   Edje_Part_Description *ed;
+
+   check_arg_count(2);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+   ed = ep->default_desc;
+   if (ep->other_desc) ed = evas_list_data(evas_list_last(ep->other_desc));
+   ed->max.w = parse_float_range(0, 0, 0x7fffffff);
+   ed->max.h = parse_float_range(1, 0, 0x7fffffff);
+}
+
+/**
+    @page edcref
+    @property
+        step
+    @parameters
+        [width] [height]
+    @effect
+        Restricts resizing of each dimension to values divisibles by its value.
+        This causes the part to jump from value to value while resizing. The
+        default value is "0 0" disabling stepping.
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_description_step(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+   Edje_Part_Description *ed;
+
+   check_arg_count(2);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+   ed = ep->default_desc;
+   if (ep->other_desc) ed = evas_list_data(evas_list_last(ep->other_desc));
+   ed->step.x = parse_float_range(0, 0, 0x7fffffff);
+   ed->step.y = parse_float_range(1, 0, 0x7fffffff);
+}
+
+/**
+    @page edcref
+    @property
+        aspect
+    @parameters
+        [min] [max]
+    @effect
+        Normally width and height can be resized to any values independently.
+        The aspect property forces the width to height ratio to be kept between
+        the minimum and maximum set. For example, "1.0 1.0" will increase the
+        width a pixel for every pixel added to heigh. The default value is
+        "0.0 0.0" disabling aspect.
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_description_aspect(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+   Edje_Part_Description *ed;
+
+   check_arg_count(2);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+   ed = ep->default_desc;
+   if (ep->other_desc) ed = evas_list_data(evas_list_last(ep->other_desc));
+   ed->aspect.min = parse_float_range(0, 0.0, 999999999.0);
+   ed->aspect.max = parse_float_range(1, 0.0, 999999999.0);
+}
+
+/**
+    @page edcref
+    @property
+        aspect_preference
+    @parameters
+        [DIMENSION]
+    @effect
+        Sets the scope of the "aspect" property to a given dimension. Available
+        options are BOTH, VERTICAL, HORIZONTAL and NONE
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_description_aspect_preference(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+   Edje_Part_Description *ed;
+
+   check_arg_count(1);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+   ed = ep->default_desc;
+   if (ep->other_desc) ed = evas_list_data(evas_list_last(ep->other_desc));
+   ed->aspect.prefer =  parse_enum(0,
+                                  "NONE", EDJE_ASPECT_PREFER_NONE,
+                                  "VERTICAL", EDJE_ASPECT_PREFER_VERTICAL,
+                                  "HORIZONTAL", EDJE_ASPECT_PREFER_HORIZONTAL,
+                                  "BOTH", EDJE_ASPECT_PREFER_BOTH,
+                                  NULL);
+}
+
+/**
+    @page edcref
+    @property
+        color_class
+    @parameters
+        [color class name]
+    @effect
+        The part will use the color values of the named color_class, these
+        values can be overrided by the "color", "color2" and "color3"
+        properties set below.
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_description_color_class(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+   Edje_Part_Description *ed;
+
+   check_arg_count(1);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+   ed = ep->default_desc;
+   if (ep->other_desc) ed = evas_list_data(evas_list_last(ep->other_desc));
+   ed->color_class = parse_str(0);
+}
+
+/**
+    @page edcref
+    @property
+        color
+    @parameters
+        [red] [green] [blue] [alpha]
+    @effect
+        Sets the main color to the specified values (between 0 and 255).
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_description_color(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+   Edje_Part_Description *ed;
+
+   check_arg_count(4);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+   ed = ep->default_desc;
+   if (ep->other_desc) ed = evas_list_data(evas_list_last(ep->other_desc));
+   ed->color.r = parse_int_range(0, 0, 255);
+   ed->color.g = parse_int_range(1, 0, 255);
+   ed->color.b = parse_int_range(2, 0, 255);
+   ed->color.a = parse_int_range(3, 0, 255);
+}
+
+/**
+    @page edcref
+    @property
+        color2
+    @parameters
+        [red] [green] [blue] [alpha]
+    @effect
+        Sets the text shadow color to the specified values (0 to 255).
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_description_color2(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+   Edje_Part_Description *ed;
+
+   check_arg_count(4);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+   ed = ep->default_desc;
+   if (ep->other_desc) ed = evas_list_data(evas_list_last(ep->other_desc));
+   ed->color2.r = parse_int_range(0, 0, 255);
+   ed->color2.g = parse_int_range(1, 0, 255);
+   ed->color2.b = parse_int_range(2, 0, 255);
+   ed->color2.a = parse_int_range(3, 0, 255);
+}
+
+/**
+    @page edcref
+    @property
+        color3
+    @parameters
+        [red] [green] [blue] [alpha]
+    @effect
+        Sets the text outline color to the specified values (0 to 255).
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_description_color3(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+   Edje_Part_Description *ed;
+
+   check_arg_count(4);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+   ed = ep->default_desc;
+   if (ep->other_desc) ed = evas_list_data(evas_list_last(ep->other_desc));
+   ed->color3.r = parse_int_range(0, 0, 255);
+   ed->color3.g = parse_int_range(1, 0, 255);
+   ed->color3.b = parse_int_range(2, 0, 255);
+   ed->color3.a = parse_int_range(3, 0, 255);
+}
+
+/**
+    @page edcref
+    @block
+        rel1/rel2
+    @context
+        description {
+            ..
+            rel1 {
+                relative: 0.0 0.0;
+                offset:     0   0;
+            }
+            ..
+            rel2 {
+                relative: 1.0 1.0;
+                offset:    -1  -1;
+            }
+            ..
+        }
+    @description
+        The rel1 and rel2 blocks are used to define the position of each corner
+        of the part's container. With rel1 being the left-up corner and rel2
+        being the right-down corner.
+    @endblock
+
+    @property
+        relative
+    @parameters
+        [X axis] [Y axis]
+    @effect
+        Moves a corner to a relative position inside the container of the
+        relative "to" part. Values from 0.0 (0%, begining) to 1.0 (100%, end)
+        of each axis.
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_description_rel1_relative(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+   Edje_Part_Description *ed;
+
+   check_arg_count(2);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+   ed = ep->default_desc;
+   if (ep->other_desc) ed = evas_list_data(evas_list_last(ep->other_desc));
+   ed->rel1.relative_x = parse_float(0);
+   ed->rel1.relative_y = parse_float(1);
+}
+
+/**
+    @page edcref
+    @property
+        offset
+    @parameters
+        [X axis] [Y axis]
+    @effect
+        Affects the corner postion a fixed number of pixels along each axis.
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_description_rel1_offset(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+   Edje_Part_Description *ed;
+
+   check_arg_count(2);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+   ed = ep->default_desc;
+   if (ep->other_desc) ed = evas_list_data(evas_list_last(ep->other_desc));
+   ed->rel1.offset_x = parse_int(0);
+   ed->rel1.offset_y = parse_int(1);
+}
+
+/**
+    @page edcref
+    @property
+        to
+    @parameters
+        [another part's name]
+    @effect
+        Causes a corner to be positioned relatively to another part's
+        container.
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_description_rel1_to(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+   Edje_Part_Description *ed;
+
+   check_arg_count(1);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+   ed = ep->default_desc;
+   if (ep->other_desc) ed = evas_list_data(evas_list_last(ep->other_desc));
+     {
+       char *name;
+
+       name = parse_str(0);
+       data_queue_part_lookup(pc, name, &(ed->rel1.id_x));
+       data_queue_part_lookup(pc, name, &(ed->rel1.id_y));
+       free(name);
+     }
+}
+
+/**
+    @page edcref
+    @property
+        to_x
+    @parameters
+        [another part's name]
+    @effect
+        Causes a corner to be positioned relatively to the X axis of another
+        part's container. Simply put affects the first parameter of "relative".
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_description_rel1_to_x(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+   Edje_Part_Description *ed;
+
+   check_arg_count(1);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+   ed = ep->default_desc;
+   if (ep->other_desc) ed = evas_list_data(evas_list_last(ep->other_desc));
+     {
+       char *name;
+
+       name = parse_str(0);
+       data_queue_part_lookup(pc, name, &(ed->rel1.id_x));
+       free(name);
+     }
+}
+
+/**
+    @page edcref
+    @property
+        to_y
+    @parameters
+        [another part's name]
+    @effect
+        Causes a corner to be positioned relatively to the Y axis of another
+        part's container. Simply put, affects the second parameter of
+        "relative".
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_description_rel1_to_y(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+   Edje_Part_Description *ed;
+
+   check_arg_count(1);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+   ed = ep->default_desc;
+   if (ep->other_desc) ed = evas_list_data(evas_list_last(ep->other_desc));
+     {
+       char *name;
+
+       name = parse_str(0);
+       data_queue_part_lookup(pc, name, &(ed->rel1.id_y));
+       free(name);
+     }
+}
+
+static void
+st_collections_group_parts_part_description_rel2_relative(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+   Edje_Part_Description *ed;
+
+   check_arg_count(2);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+   ed = ep->default_desc;
+   if (ep->other_desc) ed = evas_list_data(evas_list_last(ep->other_desc));
+   ed->rel2.relative_x = parse_float(0);
+   ed->rel2.relative_y = parse_float(1);
+}
+
+static void
+st_collections_group_parts_part_description_rel2_offset(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+   Edje_Part_Description *ed;
+
+   check_arg_count(2);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+   ed = ep->default_desc;
+   if (ep->other_desc) ed = evas_list_data(evas_list_last(ep->other_desc));
+   ed->rel2.offset_x = parse_int(0);
+   ed->rel2.offset_y = parse_int(1);
+}
+
+static void
+st_collections_group_parts_part_description_rel2_to(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+   Edje_Part_Description *ed;
+
+   check_arg_count(1);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+   ed = ep->default_desc;
+   if (ep->other_desc) ed = evas_list_data(evas_list_last(ep->other_desc));
+     {
+       char *name;
+
+       name = parse_str(0);
+       data_queue_part_lookup(pc, name, &(ed->rel2.id_x));
+       data_queue_part_lookup(pc, name, &(ed->rel2.id_y));
+       free(name);
+     }
+}
+
+static void
+st_collections_group_parts_part_description_rel2_to_x(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+   Edje_Part_Description *ed;
+
+   check_arg_count(1);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+   ed = ep->default_desc;
+   if (ep->other_desc) ed = evas_list_data(evas_list_last(ep->other_desc));
+     {
+       char *name;
+
+       name = parse_str(0);
+       data_queue_part_lookup(pc, name, &(ed->rel2.id_x));
+       free(name);
+     }
+}
+
+static void
+st_collections_group_parts_part_description_rel2_to_y(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+   Edje_Part_Description *ed;
+
+   check_arg_count(1);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+   ed = ep->default_desc;
+   if (ep->other_desc) ed = evas_list_data(evas_list_last(ep->other_desc));
+     {
+       char *name;
+
+       name = parse_str(0);
+       data_queue_part_lookup(pc, name, &(ed->rel2.id_y));
+       free(name);
+     }
+}
+
+/**
+    @page edcref
+    @block
+        image
+    @context
+        description {
+            ..
+            image {
+                normal: "filename.ext";
+                tween:  "filename2.ext";
+                ..
+                tween:  "filenameN.ext";
+                border:  left right top bottom;
+                middle:  0-1;
+            }
+            ..
+        }
+    @description
+    @endblock
+
+    @property
+        normal
+    @parameters
+        [image's filename]
+    @effect
+        Name of image to be used as previously declared in the  images block.
+        In an animation, this is the first and last image displayed. It's
+        required in any image part
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_description_image_normal(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+   Edje_Part_Description *ed;
+
+   check_arg_count(1);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+
+   if (ep->type != EDJE_PART_TYPE_IMAGE)
+     {
+       fprintf(stderr, "%s: Error. parse error %s:%i. "
+               "image attributes in non-IMAGE part.\n",
+               progname, file_in, line - 1);
+       exit(-1);
+     }
+
+   ed = ep->default_desc;
+   if (ep->other_desc) ed = evas_list_data(evas_list_last(ep->other_desc));
+     {
+       char *name;
+
+       name = parse_str(0);
+       data_queue_image_lookup(name, &(ed->image.id));
+       free(name);
+     }
+}
+
+/**
+    @page edcref
+    @property
+        tween
+    @parameters
+        [image's filename]
+    @effect
+        Name of an image to be used in an animation loop, an image block can
+        have none, one or multiple tween declarations. Images are displayed in
+        the order they are listed.
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_description_image_tween(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+   Edje_Part_Description *ed;
+
+   check_arg_count(1);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+
+   if (ep->type != EDJE_PART_TYPE_IMAGE)
+     {
+       fprintf(stderr, "%s: Error. parse error %s:%i. "
+               "image attributes in non-IMAGE part.\n",
+               progname, file_in, line - 1);
+       exit(-1);
+     }
+
+   ed = ep->default_desc;
+   if (ep->other_desc) ed = evas_list_data(evas_list_last(ep->other_desc));
+     {
+       char *name;
+       Edje_Part_Image_Id *iid;
+
+       iid = mem_alloc(SZ(Edje_Part_Image_Id));
+       ed->image.tween_list = evas_list_append(ed->image.tween_list, iid);
+       name = parse_str(0);
+       data_queue_image_lookup(name, &(iid->id));
+       free(name);
+     }
+}
+
+/**
+    @page edcref
+    @property
+        border
+    @parameters
+        [left] [right] [top] [bottom]
+    @effect
+        If set, the area (in pixels) of each side of the image will be
+        displayed as a fixed size border, from the side -> inwards, preventing
+        the corners from being changed on a resize.
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_description_image_border(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+   Edje_Part_Description *ed;
+
+   check_arg_count(4);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+
+   if (ep->type != EDJE_PART_TYPE_IMAGE)
+     {
+       fprintf(stderr, "%s: Error. parse error %s:%i. "
+               "image attributes in non-IMAGE part.\n",
+               progname, file_in, line - 1);
+       exit(-1);
+     }
+
+   ed = ep->default_desc;
+   if (ep->other_desc) ed = evas_list_data(evas_list_last(ep->other_desc));
+   ed->border.l = parse_int_range(0, 0, 0x7fffffff);
+   ed->border.r = parse_int_range(1, 0, 0x7fffffff);
+   ed->border.t = parse_int_range(2, 0, 0x7fffffff);
+   ed->border.b = parse_int_range(3, 0, 0x7fffffff);
+}
+
+/**
+    @page edcref
+    @property
+        middle
+    @parameters
+        [0 or 1]
+    @effect
+        If border is set, this boolean value tells Edje if the rest of the
+        image (not covered by the defined border) will be displayed or not.
+        The default value is 1.
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_description_image_middle(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+   Edje_Part_Description *ed;
+
+   check_arg_count(1);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+
+   if (ep->type != EDJE_PART_TYPE_IMAGE)
+     {
+       fprintf(stderr, "%s: Error. parse error %s:%i. "
+               "image attributes in non-IMAGE part.\n",
+               progname, file_in, line - 1);
+       exit(-1);
+     }
+
+   ed = ep->default_desc;
+   if (ep->other_desc) ed = evas_list_data(evas_list_last(ep->other_desc));
+   ed->border.no_fill = !parse_bool(0);
+}
+
+/**
+    @page edcref
+    @block
+        fill
+    @context
+        description {
+            ..
+            fill {
+                smooth: 0-1;
+                origin {
+                    relative: X-axis Y-axis;
+                    offset:   X-axis Y-axis;
+                }
+                size {
+                    relative: width  height;
+                    offset:   width  height;
+                }
+            }
+            ..
+        }
+    @description
+        The fill method is an optional block that defines the way an IMAGE or
+        GRADIENT part is going to be displayed inside its container.
+    @endblock
+
+    @property
+        smooth
+    @parameters
+        [0 or 1]
+    @effect
+        The smooth property takes a boolean value to decide if the image will
+        be smoothed on scaling (1) or not (0). The default value is 1.
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_description_fill_smooth(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+   Edje_Part_Description *ed;
+
+   check_arg_count(1);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+
+   if (ep->type != EDJE_PART_TYPE_IMAGE)
+     {
+       fprintf(stderr, "%s: Error. parse error %s:%i. "
+               "fill.type attribute in non-IMAGE part.\n",
+               progname, file_in, line - 1);
+       exit(-1);
+     }
+
+   ed = ep->default_desc;
+   if (ep->other_desc) ed = evas_list_data(evas_list_last(ep->other_desc));
+   ed->fill.smooth = parse_bool(0);
+}
+
+/**
+    @page edcref
+
+    @property
+        spread
+    @parameters
+        TODO
+    @effect
+        TODO
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_description_fill_spread(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+   Edje_Part_Description *ed;
+
+   check_arg_count(1);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+
+   /* XXX this will need to include IMAGES when spread support is added to evas images */
+   if (ep->type != EDJE_PART_TYPE_GRADIENT)
+     {
+       fprintf(stderr, "%s: Error. parse error %s:%i. "
+               "gradient attributes in non-GRADIENT part.\n",
+               progname, file_in, line - 1);
+       exit(-1);
+     }
+
+   ed = ep->default_desc;
+   if (ep->other_desc) ed = evas_list_data(evas_list_last(ep->other_desc));
+   ed->fill.spread = parse_int_range(0, 0, 1);
+}
+
+/**
+    @page edcref
+
+    @property
+        angle
+    @parameters
+        TODO
+    @effect
+        TODO
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_description_fill_angle(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+   Edje_Part_Description *ed;
+
+   check_arg_count(1);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+
+   /* XXX this will need to include IMAGES when angle support is added to evas images */
+   if (ep->type != EDJE_PART_TYPE_GRADIENT)
+     {
+       fprintf(stderr, "%s: Error. parse error %s:%i. "
+               "gradient attributes in non-GRADIENT part.\n",
+               progname, file_in, line - 1);
+       exit(-1);
+     }
+
+   ed = ep->default_desc;
+   if (ep->other_desc) ed = evas_list_data(evas_list_last(ep->other_desc));
+   ed->fill.angle = parse_int_range(0, 0, 360);
+}
+
+/**
+    @page edcref
+
+    @property
+        type
+    @parameters
+        TODO
+    @effect
+        TODO
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_description_fill_type(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+   Edje_Part_Description *ed;
+
+   check_arg_count(1);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+   ed = ep->default_desc;
+   if (ep->other_desc) ed = evas_list_data(evas_list_last(ep->other_desc));
+
+   if (ep->type != EDJE_PART_TYPE_IMAGE)
+     {
+       fprintf(stderr, "%s: Error. parse error %s:%i. "
+               "fill attributes in non-IMAGE part.\n",
+               progname, file_in, line - 1);
+       exit(-1);
+     }
+
+   ed->fill.type = parse_enum(0,
+                              "SCALE", EDJE_FILL_TYPE_SCALE,
+                              "TILE", EDJE_FILL_TYPE_TILE,
+                              NULL);
+}
+
+/**
+    @page edcref
+    @block
+        origin
+    @context
+        description {
+            ..
+            fill {
+                ..
+                origin {
+                    relative: 0.0 0.0;
+                    offset:   0   0;
+                }
+                ..
+            }
+            ..
+        }
+    @description
+        The origin block is used to place the starting point, inside the
+        displayed element, that will be used to render the tile. By default,
+        the origin is set at the element's left-up corner.
+    @endblock
+
+    @property
+        relative
+    @parameters
+        [X axis] [Y axis]
+    @effect
+        Sets the starting point relatively to displayed element's content.
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_description_fill_origin_relative(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+   Edje_Part_Description *ed;
+
+   check_arg_count(2);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+
+   if (ep->type != EDJE_PART_TYPE_IMAGE && ep->type != EDJE_PART_TYPE_GRADIENT)
+     {
+       fprintf(stderr, "%s: Error. parse error %s:%i. "
+               "fill attributes in non-IMAGE part.\n",
+               progname, file_in, line - 1);
+       exit(-1);
+     }
+
+   ed = ep->default_desc;
+   if (ep->other_desc) ed = evas_list_data(evas_list_last(ep->other_desc));
+   ed->fill.pos_rel_x = parse_float_range(0, -999999999.0, 999999999.0);
+   ed->fill.pos_rel_y = parse_float_range(1, -999999999.0, 999999999.0);
+}
+
+/**
+    @page edcref
+    @property
+        offset
+    @parameters
+        [X axis] [Y axis]
+    @effect
+        Affects the starting point a fixed number of pixels along each axis.
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_description_fill_origin_offset(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+   Edje_Part_Description *ed;
+
+   check_arg_count(2);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+
+   if (ep->type != EDJE_PART_TYPE_IMAGE && ep->type != EDJE_PART_TYPE_GRADIENT)
+     {
+       fprintf(stderr, "%s: Error. parse error %s:%i. "
+               "fill attributes in non-IMAGE part.\n",
+               progname, file_in, line - 1);
+       exit(-1);
+     }
+
+   ed = ep->default_desc;
+   if (ep->other_desc) ed = evas_list_data(evas_list_last(ep->other_desc));
+   ed->fill.pos_abs_x = parse_int(0);
+   ed->fill.pos_abs_y = parse_int(1);
+}
+
+/**
+    @page edcref
+    @block
+        size
+    @context
+        description {
+            ..
+            fill {
+                ..
+                size {
+                    relative: 1.0 1.0;
+                    offset:  -1  -1;
+                }
+                ..
+            }
+            ..
+        }
+    @description
+        The size block defines the tile size of the content that will be
+        displayed.
+    @endblock
+
+    @property
+        relative
+    @parameters
+        [width] [height]
+    @effect
+        Takes a pair of decimal values that represent the a percentual value
+        of the original size of the element. For example, "0.5 0.5" represents
+        half the size, while "2.0 2.0" represents the double. The default
+        value is "1.0 1.0".
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_description_fill_size_relative(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+   Edje_Part_Description *ed;
+
+   check_arg_count(2);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+   ed = ep->default_desc;
+   if (ep->other_desc) ed = evas_list_data(evas_list_last(ep->other_desc));
+
+   if (ep->type != EDJE_PART_TYPE_IMAGE && ep->type != EDJE_PART_TYPE_GRADIENT)
+     {
+       fprintf(stderr, "%s: Error. parse error %s:%i. "
+               "fill attributes in non-IMAGE part.\n",
+               progname, file_in, line - 1);
+       exit(-1);
+     }
+
+   ed->fill.rel_x = parse_float_range(0, 0.0, 999999999.0);
+   ed->fill.rel_y = parse_float_range(1, 0.0, 999999999.0);
+}
+
+/**
+    @page edcref
+    @property
+        offset
+    @parameters
+        [X axis] [Y axis]
+    @effect
+        Affects the size of the tile a fixed number of pixels along each axis.
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_description_fill_size_offset(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+   Edje_Part_Description *ed;
+
+   check_arg_count(2);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+   ed = ep->default_desc;
+   if (ep->other_desc) ed = evas_list_data(evas_list_last(ep->other_desc));
+
+   if (ep->type != EDJE_PART_TYPE_IMAGE && ep->type != EDJE_PART_TYPE_GRADIENT)
+     {
+       fprintf(stderr, "%s: Error. parse error %s:%i. "
+               "fill attributes in non-IMAGE part.\n",
+               progname, file_in, line - 1);
+       exit(-1);
+     }
+
+   ed->fill.abs_x = parse_int(0);
+   ed->fill.abs_y = parse_int(1);
+}
+
+/**
+    @page edcref
+
+    @block
+        text
+    @context
+        part {
+            description {
+                ..
+                text {
+                    text:        "some string of text to display";
+                    font:        "font_name";
+                    size:         SIZE;
+                    text_class:  "class_name";
+                    fit:          horizontal vertical;
+                    min:          horizontal vertical;
+                    max:          horizontal vertical;
+                    align:        X-axis     Y-axis;
+                    source:      "part_name";
+                    text_source: "text_part_name";
+                    elipsis:      0.0-1.0;
+                    style:       "stylename";
+                }
+                ..
+            }
+        }
+    @description
+    @endblock
+
+    @property
+        text
+    @parameters
+        [a string of text, or nothing]
+    @effect
+        Sets the default content of a text part, normally the application is
+        the one changing its value.
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_description_text_text(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+   Edje_Part_Description *ed;
+   char *str = NULL;
+   int i;
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+
+   if ((ep->type != EDJE_PART_TYPE_TEXT) &&
+       (ep->type != EDJE_PART_TYPE_TEXTBLOCK))
+     {
+       fprintf(stderr, "%s: Error. parse error %s:%i. "
+               "text attributes in non-TEXT part.\n",
+               progname, file_in, line - 1);
+       exit(-1);
+     }
+
+   ed = ep->default_desc;
+   if (ep->other_desc) ed = evas_list_data(evas_list_last(ep->other_desc));
+   for (i = 0; ;i++)
+     {
+       char *s;
+
+       if (!is_param(i)) break;
+       s = parse_str(i);
+       if (!str) str = s;
+       else
+         {
+            str = realloc(str, strlen(str) + strlen(s) + 1);
+            strcat(str, s);
+            free(s);
+         }
+     }
+   ed->text.text = str;
+}
+
+/**
+    @page edcref
+
+    @property
+        text_class
+    @parameters
+        [text class name]
+    @effect
+        Similar to color_class, this is the name used by the application
+        to alter the font family and size at runtime.
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_description_text_text_class(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+   Edje_Part_Description *ed;
+
+   check_arg_count(1);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+
+   if ((ep->type != EDJE_PART_TYPE_TEXT) &&
+       (ep->type != EDJE_PART_TYPE_TEXTBLOCK))
+     {
+       fprintf(stderr, "%s: Error. parse error %s:%i. "
+               "text attributes in non-TEXT part.\n",
+               progname, file_in, line - 1);
+       exit(-1);
+     }
+
+   ed = ep->default_desc;
+   if (ep->other_desc) ed = evas_list_data(evas_list_last(ep->other_desc));
+   ed->text.text_class = parse_str(0);
+}
+
+/**
+    @page edcref
+
+    @property
+        font
+    @parameters
+        [font alias]
+    @effect
+        This sets the font family to one of the aliases set up in the "fonts"
+        block. Can be overrided by the application.
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_description_text_font(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+   Edje_Part_Description *ed;
+
+   check_arg_count(1);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+
+   if (ep->type != EDJE_PART_TYPE_TEXT)
+     {
+       fprintf(stderr, "%s: Error. parse error %s:%i. "
+               "text attributes in non-TEXT part.\n",
+               progname, file_in, line - 1);
+       exit(-1);
+     }
+
+   ed = ep->default_desc;
+   if (ep->other_desc) ed = evas_list_data(evas_list_last(ep->other_desc));
+   ed->text.font = parse_str(0);
+}
+
+/**
+    @page edcref
+
+    @property
+        style
+    @parameters
+        [the style name]
+    @effect
+        Causes the part to use the default style and tags defined in the
+        "style" block with the specified name.
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_description_text_style(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+   Edje_Part_Description *ed;
+
+   check_arg_count(1);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+
+   if (ep->type != EDJE_PART_TYPE_TEXTBLOCK)
+     {
+       fprintf(stderr, "%s: Error. parse error %s:%i. "
+               "text attributes in non-TEXTBLOCK part.\n",
+               progname, file_in, line - 1);
+       exit(-1);
+     }
+
+   ed = ep->default_desc;
+   if (ep->other_desc) ed = evas_list_data(evas_list_last(ep->other_desc));
+   ed->text.style = parse_str(0);
+}
+
+/**
+    @page edcref
+
+    @property
+        size
+    @parameters
+        [font size in points (pt)]
+    @effect
+        Sets the default font size for the text part. Can be overrided by the
+        application.
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_description_text_size(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+   Edje_Part_Description *ed;
+
+   check_arg_count(1);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+
+   if (ep->type != EDJE_PART_TYPE_TEXT)
+     {
+       fprintf(stderr, "%s: Error. parse error %s:%i. "
+               "text attributes in non-TEXT part.\n",
+               progname, file_in, line - 1);
+       exit(-1);
+     }
+
+   ed = ep->default_desc;
+   if (ep->other_desc) ed = evas_list_data(evas_list_last(ep->other_desc));
+   ed->text.size = parse_int_range(0, 0, 255);
+}
+
+/**
+    @page edcref
+
+    @property
+        fit
+    @parameters
+        [horizontal] [vertical]
+    @effect
+        When any of the parameters is set to 1 edje will resize the text for it
+        to fit in it's container. Both are disabled by default.
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_description_text_fit(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+   Edje_Part_Description *ed;
+
+   check_arg_count(2);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+
+   if (ep->type != EDJE_PART_TYPE_TEXT)
+     {
+       fprintf(stderr, "%s: Error. parse error %s:%i. "
+               "text attributes in non-TEXT part.\n",
+               progname, file_in, line - 1);
+       exit(-1);
+     }
+
+   ed = ep->default_desc;
+   if (ep->other_desc) ed = evas_list_data(evas_list_last(ep->other_desc));
+   ed->text.fit_x = parse_bool(0);
+   ed->text.fit_y = parse_bool(1);
+}
+
+/**
+    @page edcref
+
+    @property
+        min
+    @parameters
+        [horizontal] [vertical]
+    @effect
+        When any of the parameters is enabled (1) it forces the minimum size of
+        the container to be equal to the minimum size of the text. The default
+        value is "0 0".
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_description_text_min(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+   Edje_Part_Description *ed;
+
+   check_arg_count(2);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+
+   if ((ep->type != EDJE_PART_TYPE_TEXT) &&
+       (ep->type != EDJE_PART_TYPE_TEXTBLOCK))
+     {
+       fprintf(stderr, "%s: Error. parse error %s:%i. "
+               "text attributes in non-TEXT part.\n",
+               progname, file_in, line - 1);
+       exit(-1);
+     }
+
+   ed = ep->default_desc;
+   if (ep->other_desc) ed = evas_list_data(evas_list_last(ep->other_desc));
+   ed->text.min_x = parse_bool(0);
+   ed->text.min_y = parse_bool(1);
+}
+
+/**
+    @page edcref
+
+    @property
+        max
+    @parameters
+        [horizontal] [vertical]
+    @effect
+        When any of the parameters is enabled (1) it forces the maximum size of
+        the container to be equal to the maximum size of the text. The default
+        value is "0 0".
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_description_text_max(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+   Edje_Part_Description *ed;
+
+   check_arg_count(2);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+
+   if ((ep->type != EDJE_PART_TYPE_TEXT) &&
+       (ep->type != EDJE_PART_TYPE_TEXTBLOCK))
+     {
+       fprintf(stderr, "%s: Error. parse error %s:%i. "
+               "text attributes in non-TEXT part.\n",
+               progname, file_in, line - 1);
+       exit(-1);
+     }
+
+   ed = ep->default_desc;
+   if (ep->other_desc) ed = evas_list_data(evas_list_last(ep->other_desc));
+   ed->text.max_x = parse_bool(0);
+   ed->text.max_y = parse_bool(1);
+}
+
+/**
+    @page edcref
+
+    @property
+        align
+    @parameters
+        [horizontal] [vertical]
+    @effect
+        Change the position of the point of balance inside the container. The
+        default value is 0.5 0.5.
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_description_text_align(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+   Edje_Part_Description *ed;
+
+   check_arg_count(2);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+
+   if (ep->type != EDJE_PART_TYPE_TEXT)
+     {
+       fprintf(stderr, "%s: Error. parse error %s:%i. "
+               "text attributes in non-TEXT part.\n",
+               progname, file_in, line - 1);
+       exit(-1);
+     }
+
+   ed = ep->default_desc;
+   if (ep->other_desc) ed = evas_list_data(evas_list_last(ep->other_desc));
+   ed->text.align.x = parse_float_range(0, 0.0, 1.0);
+   ed->text.align.y = parse_float_range(1, 0.0, 1.0);
+}
+
+/**
+    @page edcref
+
+    @property
+        source
+    @parameters
+        [another TEXT part's name]
+    @effect
+        Causes the part to use the text properties (like font and size) of
+        another part and update them as they change.
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_description_text_source(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+   Edje_Part_Description *ed;
+
+   check_arg_count(1);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+
+   if ((ep->type != EDJE_PART_TYPE_TEXT) &&
+       (ep->type != EDJE_PART_TYPE_TEXTBLOCK))
+     {
+       fprintf(stderr, "%s: Error. parse error %s:%i. "
+               "text attributes in non-TEXT part.\n",
+               progname, file_in, line - 1);
+       exit(-1);
+     }
+
+   ed = ep->default_desc;
+   if (ep->other_desc) ed = evas_list_data(evas_list_last(ep->other_desc));
+     {
+       char *name;
+
+       name = parse_str(0);
+       data_queue_part_lookup(pc, name, &(ed->text.id_source));
+       free(name);
+     }
+}
+
+/**
+    @page edcref
+
+    @property
+        text_source
+    @parameters
+        [another TEXT part's name]
+    @effect
+        Causes the part to display the text content of another part and update
+        them as they change.
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_description_text_text_source(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+   Edje_Part_Description *ed;
+
+   check_arg_count(1);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+
+   if ((ep->type != EDJE_PART_TYPE_TEXT) &&
+       (ep->type != EDJE_PART_TYPE_TEXTBLOCK))
+     {
+       fprintf(stderr, "%s: Error. parse error %s:%i. "
+               "text attributes in non-TEXT part.\n",
+               progname, file_in, line - 1);
+       exit(-1);
+     }
+
+   ed = ep->default_desc;
+   if (ep->other_desc) ed = evas_list_data(evas_list_last(ep->other_desc));
+     {
+       char *name;
+
+       name = parse_str(0);
+       data_queue_part_lookup(pc, name, &(ed->text.id_text_source));
+       free(name);
+     }
+}
+
+/**
+    @page edcref
+
+    @property
+        text_elipsis
+    @parameters
+        [point of balance]
+    @effect
+        Used to balance the text in a relative point from 0.0 to 1.0, this
+        point is the last section of the string to be cut out in case of a
+        resize that is smaller than the text itself. The default value is 0.0.
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_description_text_elipsis(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+   Edje_Part_Description *ed;
+
+   check_arg_count(1);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+
+   if (ep->type != EDJE_PART_TYPE_TEXT)
+     {
+       fprintf(stderr, "%s: Error. parse error %s:%i. "
+               "text attributes in non-TEXT part.\n",
+               progname, file_in, line - 1);
+       exit(-1);
+     }
+
+   ed = ep->default_desc;
+   if (ep->other_desc) ed = evas_list_data(evas_list_last(ep->other_desc));
+   ed->text.elipsis = parse_float_range(0, 0.0, 1.0);
+}
+
+/**
+    @page edcref
+
+    @block
+        gradient
+    @context
+        part {
+            description {
+                ..
+                gradient {
+                    type:    "linear";
+                    spectrum "spectrumName";
+                    rel1 {
+                        relative: 0.0 0.0;
+                        offset:     0   0;
+                    }
+                    rel2
+                        relative: 1.0 1.0;
+                        offset:    -1  -1;
+                    }
+                }
+                ..
+            }
+        }
+    @description
+        A gradient block is used to display a given "spectrum" inside a 
+        container. The container's shape is a rect but this not mean the
+        gradient is restricted to a rectangular shape.  Gradients can use 
+        "rel1" and "rel2" blocks to layout the initial and final point 
+        relatively inside the container.
+    @endblock
+
+    @property
+        type
+    @parameters
+        [the name of the type]
+    @effect
+        Alters the gradient's rendering algorithm between:
+            @li linear (default)  
+            @li radial
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_description_gradient_type(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+   Edje_Part_Description *ed;
+
+   check_arg_count(1);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+
+   if (ep->type != EDJE_PART_TYPE_GRADIENT)
+     {
+       fprintf(stderr, "%s: Error. parse error %s:%i. "
+               "gradient attributes in non-GRADIENT part.\n",
+               progname, file_in, line - 1);
+       exit(-1);
+     }
+
+   ed = ep->default_desc;
+   if (ep->other_desc) ed = evas_list_data(evas_list_last(ep->other_desc));
+   ed->gradient.type  = parse_str(0);
+}
+
+/**
+    @page edcref
+
+    @property
+        spectrum
+    @parameters
+        [an existing spectrum name]
+    @effect
+        Causes the gradient to display the colors as defined by a given 
+        "spectrum" in the "spectra" block.
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_description_gradient_spectrum(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+   Edje_Part_Description *ed;
+
+   check_arg_count(1);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+
+   if (ep->type != EDJE_PART_TYPE_GRADIENT)
+     {
+       fprintf(stderr, "%s: Error. parse error %s:%i. "
+               "gradient attributes in non-GRADIENT part.\n",
+               progname, file_in, line - 1);
+       exit(-1);
+     }
+
+   ed = ep->default_desc;
+   if (ep->other_desc) ed = evas_list_data(evas_list_last(ep->other_desc));
+
+     {
+       char *name;
+
+       name = parse_str(0);
+       data_queue_spectrum_lookup(name, &(ed->gradient.id));
+       free(name);
+     }
+}
+
+/**
+    @page edcref
+
+    @property
+        relative
+    @parameters
+        [a relative X coordinate] [a relative Y coordinate]
+    @effect
+        Inside rel1 places the initial point, or first color, of the gradient 
+        relatively to the gradient's container. Inside rel2 places the final 
+        point, or last color.
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_description_gradient_rel1_relative(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+   Edje_Part_Description *ed;
+
+   check_arg_count(2);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+
+   if (ep->type != EDJE_PART_TYPE_GRADIENT)
+     {
+       fprintf(stderr, "%s: Error. parse error %s:%i. "
+               "gradient attributes in non-GRADIENT part.\n",
+               progname, file_in, line - 1);
+       exit(-1);
+     }
+
+   ed = ep->default_desc;
+   if (ep->other_desc) ed = evas_list_data(evas_list_last(ep->other_desc));
+
+     {
+       ed->gradient.use_rel = 1;
+       ed->gradient.rel1.relative_x = parse_float(0);
+       ed->gradient.rel1.relative_y = parse_float(1);
+     }
+}
+
+/**
+    @page edcref
+
+    @property
+        offset
+    @parameters
+        [X axis] [Y axis]
+    @effect
+        Inside rel1 moves the initial point, or first color, of the gradient
+        a fixed number of pixels along either axis. Inside rel2 moves the final
+        point, or last color.
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_description_gradient_rel1_offset(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+   Edje_Part_Description *ed;
+
+   check_arg_count(2);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+
+   if (ep->type != EDJE_PART_TYPE_GRADIENT)
+     {
+       fprintf(stderr, "%s: Error. parse error %s:%i. "
+               "gradient attributes in non-GRADIENT part.\n",
+               progname, file_in, line - 1);
+       exit(-1);
+     }
+
+   ed = ep->default_desc;
+   if (ep->other_desc) ed = evas_list_data(evas_list_last(ep->other_desc));
+
+     {
+       ed->gradient.use_rel = 1;
+       ed->gradient.rel1.offset_x = parse_int(0);
+       ed->gradient.rel1.offset_y = parse_int(1);
+     }
+}
+
+static void
+st_collections_group_parts_part_description_gradient_rel2_relative(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+   Edje_Part_Description *ed;
+
+   check_arg_count(2);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+
+   if (ep->type != EDJE_PART_TYPE_GRADIENT)
+     {
+       fprintf(stderr, "%s: Error. parse error %s:%i. "
+               "gradient attributes in non-GRADIENT part.\n",
+               progname, file_in, line - 1);
+       exit(-1);
+     }
+
+   ed = ep->default_desc;
+   if (ep->other_desc) ed = evas_list_data(evas_list_last(ep->other_desc));
+
+     {
+       ed->gradient.use_rel = 1;
+       ed->gradient.rel2.relative_x = parse_float(0);
+       ed->gradient.rel2.relative_y = parse_float(1);
+     }
+}
+
+static void
+st_collections_group_parts_part_description_gradient_rel2_offset(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+   Edje_Part_Description *ed;
+
+   check_arg_count(2);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+
+   if (ep->type != EDJE_PART_TYPE_GRADIENT)
+     {
+       fprintf(stderr, "%s: Error. parse error %s:%i. "
+               "gradient attributes in non-GRADIENT part.\n",
+               progname, file_in, line - 1);
+       exit(-1);
+     }
+
+   ed = ep->default_desc;
+   if (ep->other_desc) ed = evas_list_data(evas_list_last(ep->other_desc));
+
+     {
+       ed->gradient.use_rel = 1;
+       ed->gradient.rel2.offset_x = parse_int(0);
+       ed->gradient.rel2.offset_y = parse_int(1);
+     }
+}
+
+static void
+ob_collections_group_programs_program(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Program *ep;
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = mem_alloc(SZ(Edje_Program));
+   pc->programs = evas_list_append(pc->programs, ep);
+   ep->id = evas_list_count(pc->programs) - 1;
+   ep->tween.mode = EDJE_TWEEN_MODE_LINEAR;
+   ep->after = NULL;
+}
+
+static void
+st_collections_group_programs_program_name(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Program *ep;
+
+   check_arg_count(1);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->programs));
+   ep->name = parse_str(0);
+     {
+       Evas_List *l;
+
+       for (l = pc->programs; l; l = l->next)
+         {
+            Edje_Program *lep;
+
+            lep = l->data;
+            if ((lep != ep) && (lep->name) && (!strcmp(lep->name, ep->name)))
+              {
+                 fprintf(stderr, "%s: Error. parse error %s:%i. There is already a program of the name %s\n",
+                         progname, file_in, line - 1, ep->name);
+                 exit(-1);
+              }
+         }
+     }
+}
+
+static void
+st_collections_group_programs_program_signal(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Program *ep;
+
+   check_arg_count(1);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->programs));
+   ep->signal = parse_str(0);
+}
+
+static void
+st_collections_group_programs_program_source(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Program *ep;
+
+   check_arg_count(1);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->programs));
+   ep->source = parse_str(0);
+}
+
+static void
+st_collections_group_programs_program_in(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Program *ep;
+
+   check_arg_count(2);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->programs));
+   ep->in.from = parse_float_range(0, 0.0, 999999999.0);
+   ep->in.range = parse_float_range(1, 0.0, 999999999.0);
+}
+
+static void
+st_collections_group_programs_program_action(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Program *ep;
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->programs));
+   ep->action = parse_enum(0,
+                          "STATE_SET", EDJE_ACTION_TYPE_STATE_SET,
+                          "ACTION_STOP", EDJE_ACTION_TYPE_ACTION_STOP,
+                          "SIGNAL_EMIT", EDJE_ACTION_TYPE_SIGNAL_EMIT,
+                          "DRAG_VAL_SET", EDJE_ACTION_TYPE_DRAG_VAL_SET,
+                          "DRAG_VAL_STEP", EDJE_ACTION_TYPE_DRAG_VAL_STEP,
+                          "DRAG_VAL_PAGE", EDJE_ACTION_TYPE_DRAG_VAL_PAGE,
+                          "SCRIPT", EDJE_ACTION_TYPE_SCRIPT,
+                          NULL);
+   if (ep->action == EDJE_ACTION_TYPE_STATE_SET)
+     {
+       ep->state = parse_str(1);
+       ep->value = parse_float_range(2, 0.0, 1.0);
+     }
+   else if (ep->action == EDJE_ACTION_TYPE_SIGNAL_EMIT)
+     {
+       ep->state = parse_str(1);
+       ep->state2 = parse_str(2);
+     }
+   else if (ep->action == EDJE_ACTION_TYPE_DRAG_VAL_SET)
+     {
+       ep->value = parse_float(1);
+       ep->value2 = parse_float(2);
+     }
+   else if (ep->action == EDJE_ACTION_TYPE_DRAG_VAL_STEP)
+     {
+       ep->value = parse_float(1);
+       ep->value2 = parse_float(2);
+     }
+   else if (ep->action == EDJE_ACTION_TYPE_DRAG_VAL_PAGE)
+     {
+       ep->value = parse_float(1);
+       ep->value2 = parse_float(2);
+     }
+
+   switch (ep->action) {
+      case EDJE_ACTION_TYPE_ACTION_STOP:
+        check_arg_count(1);
+        break;
+      case EDJE_ACTION_TYPE_SCRIPT:
+        /* FIXME: what's this? people usually just use script{}, no? */
+        break;
+      default:
+        check_arg_count(3);
+   }
+}
+
+static void
+st_collections_group_programs_program_transition(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Program *ep;
+
+   check_arg_count(2);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->programs));
+   ep->tween.mode = parse_enum(0,
+                              "LINEAR", EDJE_TWEEN_MODE_LINEAR,
+                              "SINUSOIDAL", EDJE_TWEEN_MODE_SINUSOIDAL,
+                              "ACCELERATE", EDJE_TWEEN_MODE_ACCELERATE,
+                              "DECELERATE", EDJE_TWEEN_MODE_DECELERATE,
+                              NULL);
+   ep->tween.time = parse_float_range(1, 0.0, 999999999.0);
+}
+
+static void
+st_collections_group_programs_program_target(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Program *ep;
+
+   check_arg_count(1);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->programs));
+     {
+       Edje_Program_Target *et;
+       char *name;
+
+       et = mem_alloc(SZ(Edje_Program_Target));
+       ep->targets = evas_list_append(ep->targets, et);
+
+       name = parse_str(0);
+       if (ep->action == EDJE_ACTION_TYPE_STATE_SET)
+         data_queue_part_lookup(pc, name, &(et->id));
+       else if (ep->action == EDJE_ACTION_TYPE_ACTION_STOP)
+         data_queue_program_lookup(pc, name, &(et->id));
+       else if (ep->action == EDJE_ACTION_TYPE_DRAG_VAL_SET)
+         data_queue_part_lookup(pc, name, &(et->id));
+       else if (ep->action == EDJE_ACTION_TYPE_DRAG_VAL_STEP)
+         data_queue_part_lookup(pc, name, &(et->id));
+       else if (ep->action == EDJE_ACTION_TYPE_DRAG_VAL_PAGE)
+         data_queue_part_lookup(pc, name, &(et->id));
+       else
+         {
+            fprintf(stderr, "%s: Error. parse error %s:%i. "
+                  "target may only be used after action\n",
+                  progname, file_in, line - 1);
+            exit(-1);
+         }
+       free(name);
+     }
+}
+
+static void
+st_collections_group_programs_program_after(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Program *ep;
+
+   check_arg_count(1);
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->programs));
+     {
+       Edje_Program_After *pa;
+       char *name;
+
+       name = parse_str(0);
+
+       pa = mem_alloc(SZ(Edje_Program_After));
+       pa->id = -1;
+       ep->after = evas_list_append(ep->after, pa);
+
+       data_queue_program_lookup(pc, name, &(pa->id));
+       free(name);
+     }
+}
+
+static void
+ob_collections_group_programs_program_script(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Program *ep;
+   Code *cd;
+
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->programs));
+   cd = evas_list_data(evas_list_last(codes));
+
+   if (!is_verbatim()) track_verbatim(1);
+   else
+     {
+       char *s;
+
+       s = get_verbatim();
+       if (s)
+         {
+            Code_Program *cp;
+
+            cp = mem_alloc(SZ(Code_Program));
+            cp->l1 = get_verbatim_line1();
+            cp->l2 = get_verbatim_line2();
+            cp->id = ep->id;
+            cp->script = s;
+            cd->programs = evas_list_append(cd->programs, cp);
+            set_verbatim(NULL, 0, 0);
+            ep->action = EDJE_ACTION_TYPE_SCRIPT;
+         }
+     }
+}
+/**
+    @page edcref
+    </table>
+*/
diff --git a/src/bin/edje_cc_mem.c b/src/bin/edje_cc_mem.c
new file mode 100644 (file)
index 0000000..074d343
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#include "edje_cc.h"
+
+void *
+mem_alloc(size_t size)
+{
+   void *mem;
+
+   mem = calloc(1, size);
+   if (mem) return mem;
+   fprintf(stderr, "%s: Error. %s:%i memory allocation of %i bytes failed. %s\n",
+          progname, file_in, line, size, strerror(errno));
+   exit(-1);
+   return NULL;
+}
+
+char *
+mem_strdup(const char *s)
+{
+   void *str;
+
+   str = strdup(s);
+   if (str) return str;
+   fprintf(stderr, "%s: Error. %s:%i memory allocation of %i bytes failed. %s. string being duplicated: \"%s\"\n",
+          progname, file_in, line, strlen(s) + 1, strerror(errno), s);
+   exit(-1);
+   return NULL;
+}
diff --git a/src/bin/edje_cc_out.c b/src/bin/edje_cc_out.c
new file mode 100644 (file)
index 0000000..b22a788
--- /dev/null
@@ -0,0 +1,1288 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#include "edje_cc.h"
+
+typedef struct _Part_Lookup Part_Lookup;
+typedef struct _Program_Lookup Program_Lookup;
+typedef struct _Group_Lookup Group_Lookup;
+typedef struct _String_Lookup Image_Lookup;
+typedef struct _String_Lookup Spectrum_Lookup;
+typedef struct _Slave_Lookup Slave_Lookup;
+typedef struct _Code_Lookup Code_Lookup;
+
+struct _Part_Lookup
+{
+   Edje_Part_Collection *pc;
+   char *name;
+   int *dest;
+};
+
+struct _Program_Lookup
+{
+   Edje_Part_Collection *pc;
+   char *name;
+   int *dest;
+};
+
+struct _Group_Lookup
+{
+   char *name;
+};
+
+struct _String_Lookup
+{
+   char *name;
+   int *dest;
+};
+
+struct _Slave_Lookup
+{
+   int *master;
+   int *slave;
+};
+
+struct _Code_Lookup
+{
+   char *ptr;
+   int   len;
+   int   val;
+};
+
+static void data_queue_image_pc_lookup(Edje_Part_Collection *pc, char *name, char *ptr, int len);
+static void data_process_string(Edje_Part_Collection *pc, const char *prefix, char *s, void (*func)(Edje_Part_Collection *pc, char *name, char *ptr, int len));
+
+Edje_File *edje_file = NULL;
+Evas_List *edje_collections = NULL;
+Evas_List *fonts = NULL;
+Evas_List *codes = NULL;
+Evas_List *code_lookups = NULL;
+Evas_List *aliases = NULL;
+
+static Eet_Data_Descriptor *edd_edje_file = NULL;
+static Eet_Data_Descriptor *edd_edje_image_directory = NULL;
+static Eet_Data_Descriptor *edd_edje_image_directory_entry = NULL;
+static Eet_Data_Descriptor *edd_edje_spectrum_directory = NULL;
+static Eet_Data_Descriptor *edd_edje_spectrum_directory_entry = NULL;
+static Eet_Data_Descriptor *edd_edje_program = NULL;
+static Eet_Data_Descriptor *edd_edje_program_target = NULL;
+static Eet_Data_Descriptor *edd_edje_part_collection_directory = NULL;
+static Eet_Data_Descriptor *edd_edje_part_collection_directory_entry = NULL;
+static Eet_Data_Descriptor *edd_edje_part_collection = NULL;
+static Eet_Data_Descriptor *edd_edje_part = NULL;
+static Eet_Data_Descriptor *edd_edje_part_description = NULL;
+static Eet_Data_Descriptor *edd_edje_part_image_id = NULL;
+static Eet_Data_Descriptor *edd_edje_spectrum_color = NULL;
+
+static Evas_List *part_lookups = NULL;
+static Evas_List *program_lookups = NULL;
+static Evas_List *group_lookups = NULL;
+static Evas_List *image_lookups = NULL;
+static Evas_List *spectrum_lookups = NULL;
+static Evas_List *part_slave_lookups = NULL;
+static Evas_List *image_slave_lookups= NULL;
+static Evas_List *spectrum_slave_lookups= NULL;
+
+#define ABORT_WRITE(eet_file, file) \
+   eet_close(eet_file); \
+   unlink(file); \
+   exit(-1);
+
+void
+data_setup(void)
+{
+   edd_edje_file = _edje_edd_edje_file;
+   edd_edje_image_directory = _edje_edd_edje_image_directory;
+   edd_edje_image_directory_entry = _edje_edd_edje_image_directory_entry;
+   edd_edje_spectrum_directory = _edje_edd_edje_spectrum_directory;
+   edd_edje_spectrum_directory_entry = _edje_edd_edje_spectrum_directory_entry;
+   edd_edje_program = _edje_edd_edje_program;
+   edd_edje_program_target = _edje_edd_edje_program_target;
+   edd_edje_part_collection_directory = _edje_edd_edje_part_collection_directory;
+   edd_edje_part_collection_directory_entry = _edje_edd_edje_part_collection_directory_entry;
+   edd_edje_part_collection = _edje_edd_edje_part_collection;
+   edd_edje_part = _edje_edd_edje_part;
+   edd_edje_part_description = _edje_edd_edje_part_description;
+   edd_edje_part_image_id = _edje_edd_edje_part_image_id;
+   edd_edje_spectrum_color = _edje_edd_edje_spectrum_color;
+}
+
+static void
+check_image_part_desc (Edje_Part_Collection *pc, Edje_Part *ep,
+                       Edje_Part_Description *epd, Eet_File *ef)
+{
+   Evas_List *l;
+
+   return;
+   if (epd->image.id == -1)
+     {
+       fprintf(stderr, "%s: Error. collection %i: image attributes missing "
+             "for part \"%s\", description \"%s\" %f\n",
+             progname, pc->id, ep->name, epd->state.name, epd->state.value);
+       ABORT_WRITE(ef, file_out);
+     }
+
+   for (l = epd->image.tween_list; l; l = l->next)
+     {
+       Edje_Part_Image_Id *iid = l->data;
+
+       if (iid->id == -1)
+         {
+            fprintf(stderr, "%s: Error. collection %i: tween image id missing "
+                  "for part \"%s\", description \"%s\" %f\n",
+                  progname, pc->id, ep->name, epd->state.name,
+                  epd->state.value);
+            ABORT_WRITE(ef, file_out);
+         }
+     }
+}
+
+static void
+check_part (Edje_Part_Collection *pc, Edje_Part *ep, Eet_File *ef)
+{
+   Edje_Part_Description *epd = ep->default_desc;
+   Evas_List *l;
+
+   if (!epd)
+     {
+       fprintf(stderr, "%s: Error. collection %i: default description missing "
+             "for part \"%s\"\n", progname, pc->id, ep->name);
+       ABORT_WRITE(ef, file_out);
+     }
+
+   if (ep->type == EDJE_PART_TYPE_IMAGE)
+     {
+       check_image_part_desc (pc, ep, epd, ef);
+
+       for (l = ep->other_desc; l; l = l->next)
+         check_image_part_desc (pc, ep, l->data, ef);
+     }
+}
+
+static void
+check_program (Edje_Part_Collection *pc, Edje_Program *ep, Eet_File *ef)
+{
+   switch (ep->action)
+     {
+      case EDJE_ACTION_TYPE_STATE_SET:
+      case EDJE_ACTION_TYPE_ACTION_STOP:
+      case EDJE_ACTION_TYPE_DRAG_VAL_SET:
+      case EDJE_ACTION_TYPE_DRAG_VAL_STEP:
+      case EDJE_ACTION_TYPE_DRAG_VAL_PAGE:
+        if (!ep->targets)
+          {
+             fprintf(stderr, "%s: Error. collection %i: "
+                   "target missing in program %s\n",
+                   progname, pc->id, ep->name);
+             ABORT_WRITE(ef, file_out);
+          }
+        break;
+      default:
+        break;
+     }
+}
+
+static void
+check_spectrum (Edje_Spectrum_Directory_Entry *se, Eet_File *ef)
+{
+   if (!se->entry)
+     fprintf(stderr, "%s: Error. Spectrum missing a name.\n", progname);
+   else if (!se->color_list)
+     fprintf(stderr, "%s: Error. Spectrum %s is empty. At least one color must be given.", progname, se->entry);
+   else
+     return;
+
+   ABORT_WRITE(ef, file_out);
+}
+
+void
+data_write(void)
+{
+   Eet_File *ef;
+   Evas_List *l;
+   int bytes;
+   int input_bytes;
+   int total_bytes;
+   int src_bytes;
+   int fmap_bytes;
+   int input_raw_bytes;
+   int image_num;
+   int font_num;
+   int collection_num;
+   int i;
+
+   bytes = 0;
+   input_bytes = 0;
+   total_bytes = 0;
+   src_bytes = 0;
+   fmap_bytes = 0;
+   input_raw_bytes = 0;
+   image_num = 0;
+   font_num = 0;
+   collection_num = 0;
+   ef = eet_open(file_out, EET_FILE_MODE_WRITE);
+   if (!ef)
+     {
+       fprintf(stderr, "%s: Error. unable to open \"%s\" for writing output\n",
+               progname, file_out);
+       exit(-1);
+     }
+   if (edje_file)
+     {
+
+       if (edje_file->collection_dir)
+         {
+            /* copy aliases into collection directory */
+            while (aliases)
+              {
+                 edje_file->collection_dir->entries = evas_list_append(edje_file->collection_dir->entries, aliases->data);
+                 aliases = evas_list_remove_list(aliases, aliases);
+              }
+         }
+       bytes = eet_data_write(ef, edd_edje_file, "edje_file", edje_file, 1);
+       if (bytes <= 0)
+         {
+            fprintf(stderr, "%s: Error. unable to write \"edje_file\" entry to \"%s\" \n",
+                    progname, file_out);
+            ABORT_WRITE(ef, file_out);
+         }
+       else
+         total_bytes += bytes;
+     }
+   if (verbose)
+     {
+       printf("%s: Wrote %9i bytes (%4iKb) for \"edje_file\" header\n",
+              progname, bytes, (bytes + 512) / 1024);
+     }
+   for (l = fonts; l; l = l->next)
+     {
+       Font *fn;
+       void *fdata = NULL;
+       int fsize = 0;
+       Evas_List *ll;
+       FILE *f;
+
+       fn = l->data;
+       f = fopen(fn->file, "rb");
+       if (f)
+         {
+            long pos;
+
+            fseek(f, 0, SEEK_END);
+            pos = ftell(f);
+            rewind(f);
+            fdata = malloc(pos);
+            if (fdata)
+              {
+                 if (fread(fdata, pos, 1, f) != 1)
+                   {
+                      fprintf(stderr, "%s: Error. unable to read all of font file \"%s\"\n",
+                              progname, fn->file);
+                      ABORT_WRITE(ef, file_out);
+                   }
+                 fsize = pos;
+              }
+            fclose(f);
+         }
+       else
+         {
+            for (ll = fnt_dirs; ll; ll = ll->next)
+              {
+                 char buf[4096];
+
+                 snprintf(buf, sizeof(buf), "%s/%s", (char *)(ll->data), fn->file);
+                 f = fopen(buf, "rb");
+                 if (f)
+                   {
+                      long pos;
+
+                      fseek(f, 0, SEEK_END);
+                      pos = ftell(f);
+                      rewind(f);
+                      fdata = malloc(pos);
+                      if (fdata)
+                        {
+                           if (fread(fdata, pos, 1, f) != 1)
+                             {
+                                fprintf(stderr, "%s: Error. unable to read all of font file \"%s\"\n",
+                                        progname, buf);
+                                ABORT_WRITE(ef, file_out);
+                             }
+                           fsize = pos;
+                        }
+                      fclose(f);
+                      if (fdata) break;
+                   }
+              }
+         }
+       if (!fdata)
+         {
+            fprintf(stderr, "%s: Error. unable to load font part \"%s\" entry to %s \n",
+                    progname, fn->file, file_out);
+            ABORT_WRITE(ef, file_out);
+         }
+       else
+         {
+            char buf[4096];
+
+            snprintf(buf, sizeof(buf), "fonts/%s", fn->name);
+            bytes = eet_write(ef, buf, fdata, fsize, 1);
+            if (bytes <= 0)
+              {
+                 fprintf(stderr, "%s: Error. unable to write font part \"%s\" as \"%s\" part entry to %s \n",
+                         progname, fn->file, buf, file_out);
+                 ABORT_WRITE(ef, file_out);
+              }
+            else
+              {
+                 font_num++;
+                 total_bytes += bytes;
+                 input_bytes += fsize;
+                 input_raw_bytes += fsize;
+              }
+            if (verbose)
+              {
+                 printf("%s: Wrote %9i bytes (%4iKb) for \"%s\" font entry \"%s\" compress: [real: %2.1f%%]\n",
+                        progname, bytes, (bytes + 512) / 1024, buf, fn->file,
+                        100 - (100 * (double)bytes) / ((double)(fsize))
+                        );
+              }
+            free(fdata);
+         }
+     }
+   if ((edje_file) && (edje_file->image_dir))
+     {
+       Ecore_Evas *ee;
+       Evas *evas;
+
+       ecore_init();
+       ecore_evas_init();
+       ee = ecore_evas_buffer_new(1, 1);
+       if (!ee)
+         {
+            fprintf(stderr, "Error. cannot create buffer engine canvas for image load.\n");
+            ABORT_WRITE(ef, file_out);
+         }
+       evas = ecore_evas_get(ee);
+       for (l = edje_file->image_dir->entries; l; l = l->next)
+         {
+            Edje_Image_Directory_Entry *img;
+
+            img = l->data;
+            if (img->source_type == EDJE_IMAGE_SOURCE_TYPE_EXTERNAL)
+              {
+              }
+            else
+              {
+                 Evas_Object *im;
+                 Evas_List *ll;
+
+                 im = NULL;
+                 for (ll = img_dirs; ll; ll = ll->next)
+                   {
+                      char buf[4096];
+
+                      snprintf(buf, sizeof(buf), "%s/%s",
+                               (char *)(ll->data), img->entry);
+                      im = evas_object_image_add(evas);
+                      if (im)
+                        {
+                           evas_object_image_file_set(im, buf, NULL);
+                           if (evas_object_image_load_error_get(im) ==
+                               EVAS_LOAD_ERROR_NONE)
+                             {
+                                break;
+                             }
+                           evas_object_del(im);
+                           im = NULL;
+                        }
+                   }
+                 if (!im)
+                   {
+                      im = evas_object_image_add(evas);
+                      if (im)
+                        {
+                           evas_object_image_file_set(im, img->entry, NULL);
+                           if (evas_object_image_load_error_get(im) !=
+                               EVAS_LOAD_ERROR_NONE)
+                             {
+                                evas_object_del(im);
+                                im = NULL;
+                             }
+                        }
+                   }
+                 if (im)
+                   {
+                      void *im_data;
+                      int  im_w, im_h;
+                      int  im_alpha;
+                      char buf[256];
+
+                      evas_object_image_size_get(im, &im_w, &im_h);
+                      im_alpha = evas_object_image_alpha_get(im);
+                      im_data = evas_object_image_data_get(im, 0);
+                      if ((im_data) && (im_w > 0) && (im_h > 0))
+                        {
+                           int mode, qual;
+
+                           snprintf(buf, sizeof(buf), "images/%i", img->id);
+                           mode = 2;
+                           qual = 80;
+                           if ((img->source_type == EDJE_IMAGE_SOURCE_TYPE_INLINE_PERFECT) &&
+                               (img->source_param == 0))
+                             mode = 0; /* RAW */
+                           else if ((img->source_type == EDJE_IMAGE_SOURCE_TYPE_INLINE_PERFECT) &&
+                                    (img->source_param == 1))
+                             mode = 1; /* COMPRESS */
+                           else
+                             mode = 2; /* LOSSY */
+                           if ((mode == 0) && (no_raw))
+                             {
+                                mode = 1; /* promote compression */
+                                img->source_param = 95;
+                             }
+                           if ((mode == 2) && (no_lossy)) mode = 1; /* demote compression */
+                           if ((mode == 1) && (no_comp))
+                             {
+                                if (no_lossy) mode = 0; /* demote compression */
+                                else if (no_raw)
+                                  {
+                                     img->source_param = 90;
+                                     mode = 2; /* no choice. lossy */
+                                  }
+                             }
+                           if (mode == 2)
+                             {
+                                qual = img->source_param;
+                                if (qual < min_quality) qual = min_quality;
+                                if (qual > max_quality) qual = max_quality;
+                             }
+                           if (mode == 0)
+                             bytes = eet_data_image_write(ef, buf,
+                                                          im_data, im_w, im_h,
+                                                          im_alpha,
+                                                          0, 0, 0);
+                           else if (mode == 1)
+                             bytes = eet_data_image_write(ef, buf,
+                                                          im_data, im_w, im_h,
+                                                          im_alpha,
+                                                          1, 0, 0);
+                           else if (mode == 2)
+                             bytes = eet_data_image_write(ef, buf,
+                                                          im_data, im_w, im_h,
+                                                          im_alpha,
+                                                          0, qual, 1);
+                           if (bytes <= 0)
+                             {
+                                fprintf(stderr, "%s: Error. unable to write image part \"%s\" as \"%s\" part entry to %s\n",
+                                        progname, img->entry, buf, file_out);
+                                ABORT_WRITE(ef, file_out);
+                             }
+                           else
+                             {
+                                image_num++;
+                                total_bytes += bytes;
+                             }
+                        }
+                      else
+                        {
+                           fprintf(stderr, "%s: Error. unable to load image for image part \"%s\" as \"%s\" part entry to %s\n",
+                                   progname, img->entry, buf, file_out);
+                           ABORT_WRITE(ef, file_out);
+                        }
+                      if (verbose)
+                        {
+                           struct stat st;
+                           const char *file = NULL;
+
+                           evas_object_image_file_get(im, &file, NULL);
+                           if ((file) && (stat(file, &st) != 0))
+                             st.st_size = 0;
+                           input_bytes += st.st_size;
+                           input_raw_bytes += im_w * im_h * 4;
+                           printf("%s: Wrote %9i bytes (%4iKb) for \"%s\" image entry \"%s\" compress: [raw: %2.1f%%] [real: %2.1f%%]\n",
+                                  progname, bytes, (bytes + 512) / 1024, buf, img->entry,
+                                  100 - (100 * (double)bytes) / ((double)(im_w * im_h * 4)),
+                                  100 - (100 * (double)bytes) / ((double)(st.st_size))
+                                  );
+                        }
+                      evas_object_del(im);
+                   }
+                 else
+                   {
+                      fprintf(stderr, "%s: Error. unable to load image for image \"%s\" part entry to %s. Missing PNG or JPEG loader modules for Evas or file does not exist, or is not readable.\n",
+                              progname, img->entry, file_out);
+                      ABORT_WRITE(ef, file_out);
+                   }
+              }
+         }
+       ecore_evas_free(ee);
+       ecore_evas_shutdown();
+       ecore_shutdown();
+     }
+
+   /* check that all groups have names */
+   if (edje_file->collection_dir)
+     {
+       for (l = edje_file->collection_dir->entries; l; l = l->next)
+         {
+            Edje_Part_Collection_Directory_Entry *de;
+            de = l->data;
+            if (!de->entry)
+              {
+                 fprintf(stderr, "%s: Error. collection %i: name missing.\n",
+                       progname, de->id);
+                 ABORT_WRITE(ef, file_out);
+              }
+         }
+     }
+   /* check that all spectra are valid */
+   if (edje_file->spectrum_dir)
+     {
+       for (l = edje_file->spectrum_dir->entries; l; l = l->next)
+         {
+            Edje_Spectrum_Directory_Entry *se;
+            se = l->data;
+            check_spectrum(se, ef);
+         }
+     }
+   /* sanity checks for parts and programs */
+   for (l = edje_collections; l; l = l->next)
+     {
+       Edje_Part_Collection *pc;
+       Evas_List *ll;
+
+       pc = l->data;
+       for (ll = pc->parts; ll; ll = ll->next)
+         check_part (pc, ll->data, ef);
+       for (ll = pc->programs; ll; ll = ll->next)
+         check_program (pc, ll->data, ef);
+     }
+   for (l = edje_collections; l; l = l->next)
+     {
+       Edje_Part_Collection *pc;
+       char buf[4096];
+
+       pc = l->data;
+       snprintf(buf, sizeof(buf), "collections/%i", pc->id);
+       bytes = eet_data_write(ef, edd_edje_part_collection, buf, pc, 1);
+       if (bytes <= 0)
+         {
+            fprintf(stderr, "%s: Error. unable to write \"%s\" part entry to %s \n",
+                    progname, buf, file_out);
+            ABORT_WRITE(ef, file_out);
+         }
+       else
+         {
+            collection_num++;
+            total_bytes += bytes;
+         }
+       if (verbose)
+         {
+            printf("%s: Wrote %9i bytes (%4iKb) for \"%s\" collection entry\n",
+                   progname, bytes, (bytes + 512) / 1024, buf);
+         }
+     }
+   for (i = 0, l = codes; l; l = l->next, i++)
+     {
+       Code *cd;
+       int ln = 0;
+
+       cd = l->data;
+       if ((cd->shared) || (cd->programs))
+         {
+            char tmpn[4096];
+            int fd;
+            char *tmpdir;
+
+#ifdef HAVE_EVIL
+            tmpdir = evil_tmpdir_get();
+#else
+            tmpdir = "/tmp";
+#endif
+             snprintf(tmpn, PATH_MAX, "%s/edje_cc.sma-tmp-XXXXXX", tmpdir);
+            fd = mkstemp(tmpn);
+            if (fd >= 0)
+              {
+                 FILE *f;
+                 char buf[4096];
+                 char tmpo[4096];
+                 int ret;
+
+                 f = fopen(tmpn, "wb");
+                 if (f)
+                   {
+                      Evas_List *ll;
+
+                      fprintf(f, "#include <edje>\n");
+                      ln = 2;
+                      if (cd->shared)
+                        {
+                           while (ln < (cd->l1 - 1))
+                             {
+                                fprintf(f, " \n");
+                                ln++;
+                             }
+                             {
+                                char *sp;
+                                int hash = 0;
+                                int newlined = 0;
+
+                                for (sp = cd->shared; *sp; sp++)
+                                  {
+                                     if ((sp[0] == '#') && (newlined))
+                                       {
+                                          hash = 1;
+                                       }
+                                     newlined = 0;
+                                     if (sp[0] == '\n') newlined = 1;
+                                     if (!hash) fputc(sp[0], f);
+                                     else if (sp[0] == '\n') hash = 0;
+                                  }
+                                fputc('\n', f);
+                             }
+                           ln += cd->l2 - cd->l1 + 1;
+                        }
+                      for (ll = cd->programs; ll; ll = ll->next)
+                        {
+                           Code_Program *cp;
+
+                           cp = ll->data;
+                           if (cp->script)
+                             {
+                                while (ln < (cp->l1 - 1))
+                                  {
+                                     fprintf(f, " \n");
+                                     ln++;
+                                  }
+                                /* FIXME: this prototype needs to be */
+                                /* formalised and set in stone */
+                                fprintf(f, "public _p%i(sig[], src[]) {", cp->id);
+                                  {
+                                     char *sp;
+                                     int hash = 0;
+                                     int newlined = 0;
+
+                                     for (sp = cp->script; *sp; sp++)
+                                       {
+                                          if ((sp[0] == '#') && (newlined))
+                                            {
+                                               hash = 1;
+                                            }
+                                          newlined = 0;
+                                          if (sp[0] == '\n') newlined = 1;
+                                          if (!hash) fputc(sp[0], f);
+                                          else if (sp[0] == '\n') hash = 0;
+                                       }
+                                  }
+                                fprintf(f, "}");
+                                ln += cp->l2 - cp->l1 + 1;
+                             }
+                        }
+                      fclose(f);
+                   }
+                 close(fd);
+                  snprintf(tmpo, PATH_MAX, "%s/edje_cc.amx-tmp-XXXXXX", tmpdir);
+                 fd = mkstemp(tmpo);
+                 if (fd >= 0)
+                   {
+                      snprintf(buf, sizeof(buf),
+                               "embryo_cc -i %s/include -o %s %s",
+                               e_prefix_data_get(), tmpo, tmpn);
+                      ret = system(buf);
+                      /* accept warnings in the embryo code */
+                      if (ret < 0 || ret > 1)
+                        {
+                           fprintf(stderr, "%s: Warning. Compiling script code not clean.\n",
+                                   progname);
+                           ABORT_WRITE(ef, file_out);
+                        }
+                      close(fd);
+                   }
+                 f = fopen(tmpo, "rb");
+                 if (f)
+                   {
+                      int size;
+                      void *data;
+
+                      fseek(f, 0, SEEK_END);
+                      size = ftell(f);
+                      rewind(f);
+                      if (size > 0)
+                        {
+                           int bt;
+
+                           data = malloc(size);
+                           if (data)
+                             {
+                                if (fread(data, size, 1, f) != 1)
+                                  {
+                                     fprintf(stderr, "%s: Error. unable to read all of script object \"%s\"\n",
+                                             progname, tmpo);
+                                     ABORT_WRITE(ef, file_out);
+                                  }
+                                snprintf(buf, sizeof(buf), "scripts/%i", i);
+                                bt = eet_write(ef, buf, data, size, 1);
+                                free(data);
+                             }
+                        }
+                      fclose(f);
+                   }
+                 unlink(tmpn);
+                 unlink(tmpo);
+              }
+         }
+     }
+   src_bytes = source_append(ef);
+   total_bytes += src_bytes;
+   fmap_bytes = source_fontmap_save(ef, fonts);
+   total_bytes += fmap_bytes;
+   eet_close(ef);
+   if (verbose)
+     {
+       struct stat st;
+
+       if (stat(file_in, &st) != 0)
+         st.st_size = 0;
+       input_bytes += st.st_size;
+       input_raw_bytes += st.st_size;
+       printf("Summary:\n"
+              "  Wrote %i collections\n"
+              "  Wrote %i images\n"
+              "  Wrote %i fonts\n"
+              "  Wrote %i bytes (%iKb) of original source data\n"
+              "  Wrote %i bytes (%iKb) of original source font map\n"
+              "Conservative compression summary:\n"
+              "  Wrote total %i bytes (%iKb) from %i (%iKb) input data\n"
+              "  Output file is %3.1f%% the size of the input data\n"
+              "  Saved %i bytes (%iKb)\n"
+              "Raw compression summary:\n"
+              "  Wrote total %i bytes (%iKb) from %i (%iKb) raw input data\n"
+              "  Output file is %3.1f%% the size of the raw input data\n"
+              "  Saved %i bytes (%iKb)\n"
+              ,
+              collection_num,
+              image_num,
+              font_num,
+              src_bytes, (src_bytes + 512) / 1024,
+              fmap_bytes, (fmap_bytes + 512) / 1024,
+              total_bytes, (total_bytes + 512) / 1024,
+              input_bytes, (input_bytes + 512) / 1024,
+              (100.0 * (double)total_bytes) / (double)input_bytes,
+              input_bytes - total_bytes,
+              (input_bytes - total_bytes + 512) / 1024,
+              total_bytes, (total_bytes + 512) / 1024,
+              input_raw_bytes, (input_raw_bytes + 512) / 1024,
+              (100.0 * (double)total_bytes) / (double)input_raw_bytes,
+              input_raw_bytes - total_bytes,
+              (input_raw_bytes - total_bytes + 512) / 1024);
+     }
+}
+
+void
+data_queue_group_lookup(char *name)
+{
+   Group_Lookup *gl;
+
+   gl = mem_alloc(SZ(Group_Lookup));
+   group_lookups = evas_list_append(group_lookups, gl);
+   gl->name = mem_strdup(name);
+}
+
+void
+data_queue_part_lookup(Edje_Part_Collection *pc, char *name, int *dest)
+{
+   Part_Lookup *pl;
+
+   pl = mem_alloc(SZ(Part_Lookup));
+   part_lookups = evas_list_append(part_lookups, pl);
+   pl->pc = pc;
+   pl->name = mem_strdup(name);
+   pl->dest = dest;
+}
+
+void
+data_queue_program_lookup(Edje_Part_Collection *pc, char *name, int *dest)
+{
+   Program_Lookup *pl;
+
+   pl = mem_alloc(SZ(Program_Lookup));
+   program_lookups = evas_list_append(program_lookups, pl);
+   pl->pc = pc;
+   pl->name = mem_strdup(name);
+   pl->dest = dest;
+}
+
+void
+data_queue_image_lookup(char *name, int *dest)
+{
+   Image_Lookup *il;
+
+   il = mem_alloc(SZ(Image_Lookup));
+   image_lookups = evas_list_append(image_lookups, il);
+   il->name = mem_strdup(name);
+   il->dest = dest;
+}
+
+void
+data_queue_spectrum_lookup(char *name, int *dest)
+{
+   Spectrum_Lookup *sl;
+
+   sl = mem_alloc(SZ(Spectrum_Lookup));
+   spectrum_lookups = evas_list_append(spectrum_lookups, sl);
+   sl->name = mem_strdup(name);
+   sl->dest = dest;
+}
+
+void
+data_queue_part_slave_lookup(int *master, int *slave)
+{
+   Slave_Lookup *sl;
+
+   sl = mem_alloc(SZ(Slave_Lookup));
+   part_slave_lookups = evas_list_append(part_slave_lookups, sl);
+   sl->master = master;
+   sl->slave = slave;
+}
+
+void
+data_queue_image_slave_lookup(int *master, int *slave)
+{
+   Slave_Lookup *sl;
+
+   sl = mem_alloc(SZ(Slave_Lookup));
+   image_slave_lookups = evas_list_append(image_slave_lookups, sl);
+   sl->master = master;
+   sl->slave = slave;
+}
+
+void
+data_queue_spectrum_slave_lookup(int *master, int *slave)
+{
+   Slave_Lookup *sl;
+
+   sl = mem_alloc(SZ(Slave_Lookup));
+   spectrum_slave_lookups = evas_list_append(spectrum_slave_lookups, sl);
+   sl->master = master;
+   sl->slave = slave;
+}
+
+void
+handle_slave_lookup(Evas_List *list, int *master, int value)
+{
+   Evas_List *l;
+
+   for (l = list; l; l = l->next)
+   {
+      Slave_Lookup *sl = l->data;
+
+      if (sl->master == master)
+        *sl->slave = value;
+   }
+}
+
+void
+data_process_lookups(void)
+{
+   Evas_List *l;
+
+   while (part_lookups)
+     {
+       Part_Lookup *pl;
+
+       pl = part_lookups->data;
+
+       for (l = pl->pc->parts; l; l = l->next)
+         {
+            Edje_Part *ep;
+
+            ep = l->data;
+            if ((ep->name) && (!strcmp(ep->name, pl->name)))
+              {
+                 handle_slave_lookup(part_slave_lookups, pl->dest, ep->id);
+                 *(pl->dest) = ep->id;
+                 break;
+              }
+         }
+       if (!l)
+         {
+            fprintf(stderr, "%s: Error. unable to find part name %s\n",
+                    progname, pl->name);
+            exit(-1);
+         }
+       part_lookups = evas_list_remove(part_lookups, pl);
+       free(pl->name);
+       free(pl);
+     }
+
+   while (program_lookups)
+     {
+       Program_Lookup *pl;
+
+       pl = program_lookups->data;
+
+       for (l = pl->pc->programs; l; l = l->next)
+         {
+            Edje_Program *ep;
+
+            ep = l->data;
+            if ((ep->name) && (!strcmp(ep->name, pl->name)))
+              {
+                 *(pl->dest) = ep->id;
+                 break;
+              }
+         }
+       if (!l)
+         {
+            fprintf(stderr, "%s: Error. unable to find program name %s\n",
+                    progname, pl->name);
+            exit(-1);
+         }
+       program_lookups = evas_list_remove(program_lookups, pl);
+       free(pl->name);
+       free(pl);
+     }
+
+   while (group_lookups)
+     {
+        Group_Lookup *gl;
+
+        gl = group_lookups->data;
+        for (l = edje_file->collection_dir->entries; l; l = l->next)
+          {
+             Edje_Part_Collection_Directory_Entry *de;
+             de = l->data;
+             if (!strcmp(de->entry, gl->name))
+               {
+                  break;
+               }
+          }
+        if (!l)
+          {
+             fprintf(stderr, "%s: Error. unable to find group name %s\n",
+                     progname, gl->name);
+             exit(-1);
+          }
+        group_lookups = evas_list_remove(group_lookups, gl);
+        free(gl->name);
+        free(gl);
+     }
+
+   while (image_lookups)
+     {
+       Image_Lookup *il;
+
+       il = image_lookups->data;
+
+       if (!edje_file->image_dir)
+         l = NULL;
+       else
+         {
+            for (l = edje_file->image_dir->entries; l; l = l->next)
+              {
+                 Edje_Image_Directory_Entry *de;
+
+                 de = l->data;
+                 if ((de->entry) && (!strcmp(de->entry, il->name)))
+                   {
+                      handle_slave_lookup(image_slave_lookups, il->dest, de->id);
+                      if (de->source_type == EDJE_IMAGE_SOURCE_TYPE_EXTERNAL)
+                        *(il->dest) = -de->id - 1;
+                      else
+                        *(il->dest) = de->id;
+                      break;
+                   }
+              }
+         }
+
+       if (!l)
+         {
+            fprintf(stderr, "%s: Error. unable to find image name %s\n",
+                    progname, il->name);
+            exit(-1);
+         }
+       image_lookups = evas_list_remove(image_lookups, il);
+       free(il->name);
+       free(il);
+     }
+
+   while (spectrum_lookups)
+     {
+       Spectrum_Lookup *il;
+
+       il = spectrum_lookups->data;
+
+       if (!edje_file->spectrum_dir)
+         l = NULL;
+       else
+         {
+            for (l = edje_file->spectrum_dir->entries; l; l = l->next)
+              {
+                 Edje_Spectrum_Directory_Entry *de;
+
+                 de = l->data;
+                 *(il->dest) = 1;
+                 if ((de->entry) && (!strcmp(de->entry, il->name)))
+                   {
+                      handle_slave_lookup(spectrum_slave_lookups, il->dest, de->id);
+                      *(il->dest) = de->id;
+                      break;
+                   }
+              }
+         }
+
+       if (!l)
+         {
+            fprintf(stderr, "%s: Error. unable to find spectrum name %s\n",
+                    progname, il->name);
+            exit(-1);
+         }
+       spectrum_lookups = evas_list_remove(spectrum_lookups, il);
+       free(il->name);
+       free(il);
+     }
+
+   while (part_slave_lookups)
+     {
+       free(part_slave_lookups->data);
+       part_slave_lookups = evas_list_remove_list(part_slave_lookups, part_slave_lookups);
+     }
+
+   while (image_slave_lookups)
+     {
+       free(image_slave_lookups->data);
+       image_slave_lookups = evas_list_remove_list(image_slave_lookups, image_slave_lookups);
+     }
+
+   while (spectrum_slave_lookups)
+     {
+       free(spectrum_slave_lookups->data);
+       spectrum_slave_lookups = evas_list_remove_list(spectrum_slave_lookups, spectrum_slave_lookups);
+     }
+}
+
+static void
+data_process_string(Edje_Part_Collection *pc, const char *prefix, char *s, void (*func)(Edje_Part_Collection *pc, char *name, char* ptr, int len))
+{
+   char *p;
+   char *key;
+   int keyl;
+   int quote, escape;
+
+   key = alloca(strlen(prefix) + 2 + 1);
+   if (!key) return;
+   strcpy(key, prefix);
+   strcat(key, ":\"");
+   keyl = strlen(key);
+   quote = 0;
+   escape = 0;
+   for (p = s; (p) && (*p); p++)
+     {
+       if (!quote)
+         {
+            if (*p == '\"')
+              {
+                 quote = 1;
+                 p++;
+              }
+         }
+       if (!quote)
+         {
+            if (!strncmp(p, key, keyl))
+              {
+                  char *ptr;
+                  int len;
+                  int inesc = 0;
+                 char *name;
+
+                  ptr = p;
+                  p += keyl;
+                 while ((*p))
+                   {
+                      if (!inesc)
+                        {
+                           if (*p == '\\') inesc = 1;
+                           else if (*p == '\"')
+                             {
+                                /* string concatenation, see below */
+                                if (*(p + 1) != '\"')
+                                  break;
+                                else
+                                  p++;
+                             }
+                        }
+                       else
+                            inesc = 0;
+                       p++;
+                   }
+                 len = p - ptr + 1;
+                 name = alloca(len);
+                 if (name)
+                   {
+                      char *pp;
+                      int i;
+
+                      name[0] = 0;
+                      pp = ptr + keyl;
+                      inesc = 0;
+                      i = 0;
+                      while (*pp)
+                        {
+                           if (!inesc)
+                             {
+                                if (*pp == '\\') inesc = 1;
+                                else if (*pp == '\"')
+                                  {
+                                     /* concat strings like "foo""bar" to "foobar" */
+                                     if (*(pp + 1) == '\"')
+                                       pp++;
+                                     else
+                                       {
+                                          name[i] = 0;
+                                          break;
+                                       }
+                                  }
+                                else
+                                  {
+                                     name[i] = *pp;
+                                     name[i + 1] = 0;
+                                     i++;
+                                  }
+                             }
+                           else
+                              inesc = 0;
+                           pp++;
+                       }
+                     func(pc, name, ptr, len);
+                  }
+              }
+         }
+       else
+         {
+            if (!escape)
+              {
+                 if (*p == '\"') quote = 0;
+                 else if (*p == '\\') escape = 1;
+              }
+            else if (escape)
+              {
+                 escape = 0;
+              }
+         }
+     }
+}
+
+static void
+_data_queue_part_lookup(Edje_Part_Collection *pc, char *name, char *ptr, int len)
+{
+   Code_Lookup *cl;
+   cl = mem_alloc(SZ(Code_Lookup));
+   cl->ptr = ptr;
+   cl->len = len;
+
+   data_queue_part_lookup(pc, name, &(cl->val));
+
+   code_lookups = evas_list_append(code_lookups, cl);
+}
+static void
+_data_queue_program_lookup(Edje_Part_Collection *pc, char *name, char *ptr, int len)
+{
+   Code_Lookup *cl;
+   cl = mem_alloc(SZ(Code_Lookup));
+   cl->ptr = ptr;
+   cl->len = len;
+
+   data_queue_program_lookup(pc, name, &(cl->val));
+
+   code_lookups = evas_list_append(code_lookups, cl);
+}
+static void
+_data_queue_group_lookup(Edje_Part_Collection *pc, char *name, char *ptr, int len)
+{
+   data_queue_group_lookup(name);      
+}
+static void
+_data_queue_image_pc_lookup(Edje_Part_Collection *pc, char *name, char *ptr, int len)
+{
+   Code_Lookup *cl;
+   cl = mem_alloc(SZ(Code_Lookup));
+   cl->ptr = ptr;
+   cl->len = len;
+
+   data_queue_image_lookup(name, &(cl->val));
+
+   code_lookups = evas_list_append(code_lookups, cl);
+}
+
+static void
+_data_queue_spectrum_pc_lookup(Edje_Part_Collection *pc, char *name, int *dest)
+{
+   data_queue_spectrum_lookup(name, dest);
+}
+
+void
+data_process_scripts(void)
+{
+   Evas_List *l, *l2;
+
+   for (l = codes, l2 = edje_collections; (l) && (l2); l = l->next, l2 = l2->next)
+     {
+       Code *cd;
+       Edje_Part_Collection *pc;
+
+       cd = l->data;
+       pc = l2->data;
+       if ((cd->shared) || (cd->programs))
+         {
+            Evas_List *ll;
+
+            if (cd->shared)
+              {
+                 data_process_string(pc, "PART",    cd->shared, _data_queue_part_lookup);
+                 data_process_string(pc, "PROGRAM", cd->shared, _data_queue_program_lookup);
+                 data_process_string(pc, "IMAGE",   cd->shared, _data_queue_image_pc_lookup);
+                 data_process_string(pc, "GROUP",   cd->shared, _data_queue_group_lookup);
+              }
+            for (ll = cd->programs; ll; ll = ll->next)
+              {
+                 Code_Program *cp;
+
+                 cp = ll->data;
+                 if (cp->script)
+                   {
+                      data_process_string(pc, "PART",    cp->script, _data_queue_part_lookup);
+                      data_process_string(pc, "PROGRAM", cp->script, _data_queue_program_lookup);
+                      data_process_string(pc, "IMAGE",   cp->script, _data_queue_image_pc_lookup);
+                      data_process_string(pc, "GROUP",   cp->script, _data_queue_group_lookup);
+                   }
+              }
+         }
+     }
+}
+
+void
+data_process_script_lookups(void)
+{
+   Evas_List *l;
+
+   for (l = code_lookups; l; l = l->next)
+     {
+       Code_Lookup *cl;
+       char buf[256];
+       int i, n;
+
+       cl = l->data;
+       snprintf(buf, sizeof(buf), "%i", cl->val);
+       n = strlen(buf);
+       if (n > cl->len)
+         {
+            fprintf(stderr, "%s: Error. The unexpected happened. A numeric replacement string was larger than the original!\n",
+                    progname);
+            exit(-1);
+         }
+       for (i = 0; i < cl->len; i++) cl->ptr[i] = ' ';
+       strncpy(cl->ptr, buf, n);
+     }
+}
diff --git a/src/bin/edje_cc_parse.c b/src/bin/edje_cc_parse.c
new file mode 100644 (file)
index 0000000..7210ce8
--- /dev/null
@@ -0,0 +1,1427 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#include "edje_cc.h"
+
+static void  new_object(void);
+static void  new_statement(void);
+static char *perform_math (char *input);
+static int   isdelim(char c);
+static char *next_token(char *p, char *end, char **new_p, int *delim);
+static char *stack_id(void);
+static void  stack_chop_top(void);
+static void  parse(char *data, off_t size);
+
+/* simple expression parsing protos */
+static int my_atoi(const char * s);
+static char * _alphai(char *s, int * val);
+static char * _betai(char *s, int * val);
+static char * _gammai(char *s, int * val);
+static char * _deltai(char *s, int * val);
+static char * _get_numi(char *s, int * val);
+static int _is_numi(char c);
+static int _is_op1i(char c);
+static int _is_op2i(char c);
+static int _calci(char op, int a, int b);
+
+static double my_atof(const char * s);
+static char * _alphaf(char *s, double * val);
+static char * _betaf(char *s, double * val);
+static char * _gammaf(char *s, double * val);
+static char * _deltaf(char *s, double * val);
+static char * _get_numf(char *s, double * val);
+static int _is_numf(char c);
+static int _is_op1f(char c);
+static int _is_op2f(char c);
+static double _calcf(char op, double a, double b);
+static int strstrip(const char *in, char *out, size_t size);
+
+
+int        line = 0;
+Evas_List *stack = NULL;
+Evas_List *params = NULL;
+
+static char  file_buf[4096];
+static int   verbatim = 0;
+static int   verbatim_line1 = 0;
+static int   verbatim_line2 = 0;
+static char *verbatim_str = NULL;
+
+static void
+new_object(void)
+{
+   char *id;
+   int i;
+   int handled = 0;
+
+   id = stack_id();
+   for (i = 0; i < object_handler_num(); i++)
+     {
+       if (!strcmp(object_handlers[i].type, id))
+         {
+            handled = 1;
+            if (object_handlers[i].func)
+              {
+                 object_handlers[i].func();
+              }
+            break;
+         }
+     }
+   if (!handled)
+     {
+       for (i = 0; i < statement_handler_num(); i++)
+         {
+            if (!strcmp(statement_handlers[i].type, id))
+              {
+                 free(id);
+                 return;
+              }
+         }
+     }
+   if (!handled)
+     {
+       fprintf(stderr, "%s: Error. %s:%i unhandled keyword %s\n",
+               progname, file_in, line - 1,
+               (char *)evas_list_data(evas_list_last(stack)));
+       exit(-1);
+     }
+   free(id);
+}
+
+static void
+new_statement(void)
+{
+   char *id;
+   int i;
+   int handled = 0;
+
+   id = stack_id();
+   for (i = 0; i < statement_handler_num(); i++)
+     {
+       if (!strcmp(statement_handlers[i].type, id))
+         {
+            handled = 1;
+            if (statement_handlers[i].func)
+              {
+                 statement_handlers[i].func();
+              }
+            break;
+         }
+     }
+   if (!handled)
+     {
+       fprintf(stderr, "%s: Error. %s:%i unhandled keyword %s\n",
+               progname, file_in, line - 1,
+               (char *)evas_list_data(evas_list_last(stack)));
+       exit(-1);
+     }
+   free(id);
+}
+
+static char *
+perform_math (char *input)
+{
+   char buf[256];
+   double res;
+
+   /* FIXME
+    * Always apply floating-point arithmetic.
+    * Does this cause problems for integer parameters?
+    *
+    * What we should do is, loop over the string and figure out whether
+    * there are floating point operands, too and then switch to
+    * floating point math.
+    */
+   res = my_atof (input);
+   snprintf (buf, sizeof (buf), "%lf", res);
+
+   return strdup (buf);
+}
+
+static int
+isdelim(char c)
+{
+   const char *delims = "{},;:";
+   char *d;
+
+   d = (char *)delims;
+   while (*d)
+     {
+       if (c == *d) return 1;
+       d++;
+     }
+   return 0;
+}
+
+static char *
+next_token(char *p, char *end, char **new_p, int *delim)
+{
+   char *tok_start = NULL, *tok_end = NULL, *tok = NULL, *sa_start = NULL;
+   int in_tok = 0;
+   int in_quote = 0;
+   int in_parens = 0;
+   int in_comment_ss  = 0;
+   int in_comment_cpp = 0;
+   int in_comment_sa  = 0;
+   int had_quote = 0;
+   int is_escaped = 0;
+   char *cpp_token_line = NULL;
+   char *cpp_token_file = NULL;
+
+   *delim = 0;
+   if (p >= end) return NULL;
+   while (p < end)
+     {
+       if (*p == '\n')
+         {
+            in_comment_ss = 0;
+            in_comment_cpp = 0;
+            cpp_token_line = NULL;
+            cpp_token_file = NULL;
+            line++;
+         }
+       if ((!in_comment_ss) && (!in_comment_sa))
+         {
+            if ((!in_quote) && (*p == '/') && (p < (end - 1)) && (*(p + 1) == '/'))
+              in_comment_ss = 1;
+            if ((!in_quote) && (*p == '#'))
+              in_comment_cpp = 1;
+            if ((!in_quote) && (*p == '/') && (p < (end - 1)) && (*(p + 1) == '*'))
+              {
+                 in_comment_sa = 1;
+                 sa_start = p;
+              }
+         }
+       if ((in_comment_cpp) && (*p == '#'))
+         {
+            char *pp, fl[4096];
+            char *tmpstr = NULL;
+            int   l, nm;
+
+            /* handle cpp comments */
+            /* their line format is
+             * # <line no. of next line> <filename from next line on> [??]
+             */
+            cpp_token_line = NULL;
+            cpp_token_file = NULL;
+
+            pp = p;
+            while ((pp < end) && (*pp != '\n'))
+              {
+                 pp++;
+              }
+            l = pp - p;
+            tmpstr = alloca(l + 1);
+            if (!tmpstr)
+              {
+                 fprintf(stderr, "%s: Error. %s:%i malloc %i bytes failed\n",
+                         progname, file_in, line - 1, l + 1);
+                 exit(-1);
+              }
+            strncpy(tmpstr, p, l);
+            tmpstr[l] = 0;
+            l = sscanf(tmpstr, "%*s %i \"%[^\"]\"", &nm, fl);
+            if (l == 2)
+              {
+                 strcpy(file_buf, fl);
+                 line = nm;
+                 file_in = file_buf;
+              }
+         }
+       else if ((!in_comment_ss) && (!in_comment_sa) && (!in_comment_cpp))
+         {
+            if (!in_tok)
+              {
+                 if (!in_quote)
+                   {
+                      if (!isspace(*p))
+                        {
+                           if (*p == '"')
+                             {
+                                in_quote = 1;
+                                had_quote = 1;
+                             }
+                           else if (*p == '(')
+                             in_parens++;
+
+                           in_tok = 1;
+                           tok_start = p;
+                           if (isdelim(*p)) *delim = 1;
+                        }
+                   }
+              }
+            else
+              {
+                 if (in_quote)
+                   {
+                      if ((*p) == '\\')
+                        is_escaped = !is_escaped;
+                      else if (((*p) == '"') && (!is_escaped))
+                        {
+                           in_quote = 0;
+                           had_quote = 1;
+                        }
+                      else if (is_escaped)
+                        is_escaped = 0;
+                   }
+                 else if (in_parens)
+                   {
+                      if (((*p) == ')') && (!is_escaped))
+                        in_parens--;
+                   }
+                 else
+                   {
+                      if (*p == '"')
+                        {
+                           in_quote = 1;
+                           had_quote = 1;
+                        }
+                      else if (*p == '(')
+                        in_parens++;
+
+                      /* check for end-of-token */
+                      if (
+                          (isspace(*p)) ||
+                          ((*delim) && (!isdelim(*p))) ||
+                          (isdelim(*p))
+                          )
+                        {
+                           in_tok = 0;
+                           tok_end = p - 1;
+                           if (*p == '\n') line--;
+                           goto done;
+                        }
+                   }
+              }
+         }
+       if (in_comment_sa)
+         {
+            if ((*p == '/') && (*(p - 1) == '*') && ((p - sa_start) > 2))
+              in_comment_sa = 0;
+         }
+       p++;
+     }
+   if (!in_tok) return NULL;
+   tok_end = p - 1;
+
+   done:
+   *new_p = p;
+
+   tok = mem_alloc(tok_end - tok_start + 2);
+   strncpy(tok, tok_start, tok_end - tok_start + 1);
+   tok[tok_end - tok_start + 1] = 0;
+
+   if (had_quote)
+     {
+       is_escaped = 0;
+       p = tok;
+
+       while (*p)
+         {
+            if ((*p == '\"') && (!is_escaped))
+              {
+                 memmove(p, p + 1, strlen(p));
+              }
+            else if ((*p == '\\') && (*(p + 1) == 'n'))
+              {
+                 memmove(p, p + 1, strlen(p));
+                 *p = '\n';
+              }
+            else if ((*p == '\\') && (*(p + 1) == 't'))
+              {
+                 memmove(p, p + 1, strlen(p));
+                 *p = '\t';
+              }
+            else if (*p == '\\')
+              {
+                 memmove(p, p + 1, strlen(p));
+                 if (*p == '\\') p++;
+                 else is_escaped = 1;
+              }
+            else
+              {
+                 if (is_escaped) is_escaped = 0;
+                 p++;
+              }
+         }
+     }
+   else if (tok && *tok == '(')
+     {
+       char *tmp;
+       tmp = tok;
+       tok = perform_math(tok);
+       free(tmp);
+     }
+
+   return tok;
+}
+
+static char *
+stack_id(void)
+{
+   char *id;
+   int len;
+   Evas_List *l;
+
+   len = 0;
+   for (l = stack; l; l = l->next)
+     len += strlen(l->data) + 1;
+   id = mem_alloc(len);
+   id[0] = 0;
+   for (l = stack; l; l = l->next)
+     {
+       strcat(id, l->data);
+       if (l->next) strcat(id, ".");
+     }
+   return id;
+}
+
+static void
+stack_chop_top(void)
+{
+   char *top;
+
+   /* remove top from stack */
+   top = evas_list_data(evas_list_last(stack));
+   if (top)
+     {
+       free(top);
+       stack = evas_list_remove(stack, top);
+     }
+   else
+     {
+       fprintf(stderr, "%s: Error. parse error %s:%i. } marker without matching { marker\n",
+               progname, file_in, line - 1);
+       exit(-1);
+     }
+}
+
+static void
+parse(char *data, off_t size)
+{
+   char *p, *end, *token;
+   int delim = 0;
+   int do_params = 0;
+
+   if (verbose)
+     {
+       printf("%s: Parsing input file\n",
+              progname);
+     }
+   p = data;
+   end = data + size;
+   line = 1;
+   while ((token = next_token(p, end, &p, &delim)) != NULL)
+     {
+       /* if we are in param mode, the only delimiter
+        * we'll accept is the semicolon
+        */
+       if (do_params && delim && *token != ';')
+         {
+            fprintf(stderr, "%s: Error. parse error %s:%i. %c marker before ; marker\n",
+                  progname, file_in, line - 1, *token);
+            exit(-1);
+         }
+       else if (delim)
+         {
+            if (*token == ',' || *token == ':') do_params = 1;
+            else if (*token == '}')
+              {
+                 if (do_params)
+                   {
+                      fprintf(stderr, "%s: Error. parse error %s:%i. } marker before ; marker\n",
+                              progname, file_in, line - 1);
+                      exit(-1);
+                   }
+                 else
+                   stack_chop_top();
+              }
+            else if (*token == ';')
+              {
+                 if (do_params)
+                   {
+                      do_params = 0;
+                      new_statement();
+                      /* clear out params */
+                      while (params)
+                        {
+                           free(params->data);
+                           params = evas_list_remove(params, params->data);
+                        }
+                      /* remove top from stack */
+                      stack_chop_top();
+                   }
+              }
+            else if (*token == '{')
+              {
+                 if (do_params)
+                   {
+                      fprintf(stderr, "%s: Error. parse error %s:%i. { marker before ; marker\n",
+                              progname, file_in, line - 1);
+                      exit(-1);
+                   }
+              }
+            free(token);
+         }
+       else
+         {
+            if (do_params)
+              params = evas_list_append(params, token);
+            else
+              {
+                 stack = evas_list_append(stack, token);
+                 new_object();
+                 if ((verbatim == 1) && (p < (end - 2)))
+                   {
+                      int escaped = 0;
+                      int inquotes = 0;
+                      int insquotes = 0;
+                      int squigglie = 1;
+                      int l1 = 0, l2 = 0;
+                      char *verbatim_1;
+                      char *verbatim_2;
+
+                      l1 = line;
+                      while ((p[0] != '{') && (p < end))
+                        {
+                           if (*p == '\n') line++;
+                           p++;
+                        }
+                      p++;
+                      verbatim_1 = p;
+                      verbatim_2 = NULL;
+                      for (; p < end; p++)
+                        {
+                           if (*p == '\n') line++;
+                           if (escaped) escaped = 0;
+                           if (!escaped)
+                             {
+                                if (p[0] == '\\') escaped = 1;
+                                else if (p[0] == '\"')
+                                  {
+                                     if (!insquotes)
+                                       {
+                                          if (inquotes) inquotes = 0;
+                                          else inquotes = 1;
+                                       }
+                                  }
+                                else if (p[0] == '\'')
+                                  {
+                                     if (!inquotes)
+                                       {
+                                          if (insquotes) insquotes = 0;
+                                          else insquotes = 1;
+                                       }
+                                  }
+                                else if ((!inquotes) && (!insquotes))
+                                  {
+                                     if      (p[0] == '{') squigglie++;
+                                     else if (p[0] == '}') squigglie--;
+                                     if (squigglie == 0)
+                                       {
+                                          verbatim_2 = p - 1;
+                                          l2 = line;
+                                          break;
+                                       }
+                                  }
+                             }
+                        }
+                      if (verbatim_2 > verbatim_1)
+                        {
+                           int l;
+                           char *v;
+
+                           l = verbatim_2 - verbatim_1 + 1;
+                           v = malloc(l + 1);
+                           strncpy(v, verbatim_1, l);
+                           v[l] = 0;
+                           set_verbatim(v, l1, l2);
+                        }
+                      else
+                        {
+                           fprintf(stderr, "%s: Error. parse error %s:%i. { marker does not have matching } marker\n",
+                                   progname, file_in, line - 1);
+                           exit(-1);
+                        }
+                      new_object();
+                      verbatim = 0;
+                   }
+              }
+         }
+     }
+   if (verbose)
+     {
+       printf("%s: Parsing done\n",
+              progname);
+     }
+}
+
+static char *clean_file = NULL;
+static void
+clean_tmp_file(void)
+{
+   if (clean_file) unlink(clean_file);
+}
+
+int
+is_verbatim(void)
+{
+   return verbatim;
+}
+
+void
+track_verbatim(int on)
+{
+   verbatim = on;
+}
+
+void
+set_verbatim(char *s, int l1, int l2)
+{
+   verbatim_line1 = l1;
+   verbatim_line2 = l2;
+   verbatim_str = s;
+}
+
+char *
+get_verbatim(void)
+{
+   return verbatim_str;
+}
+
+int
+get_verbatim_line1(void)
+{
+   return verbatim_line1;
+}
+
+int
+get_verbatim_line2(void)
+{
+   return verbatim_line2;
+}
+
+void
+compile(void)
+{
+   char buf[4096];
+   char inc[4096];
+   static char tmpn[4096];
+   int fd;
+   off_t size;
+   char *data, *p;
+   const char *tmpdir;
+
+#ifdef HAVE_EVIL
+   tmpdir = evil_tmpdir_get();
+#else
+   tmpdir = "/tmp";
+#endif
+
+   strncpy(inc, file_in, 4000);
+   inc[4001] = 0;
+   p = strrchr(inc, '/');
+   if (!p) strcpy(inc, "./");
+   else *p = 0;
+   snprintf (tmpn, PATH_MAX, "%s/edje_cc.edc-tmp-XXXXXX", tmpdir);
+   fd = mkstemp(tmpn);
+   if (fd >= 0)
+     {
+       int ret;
+       char *def;
+
+       clean_file = tmpn;
+       close(fd);
+       atexit(clean_tmp_file);
+       if (!defines)
+         def = mem_strdup("");
+       else
+         {
+            Evas_List *l;
+            int len;
+
+            len = 0;
+            for (l = defines; l; l = l->next)
+              {
+                 len += strlen(l->data) + 1;
+              }
+            def = mem_alloc(len + 1);
+            def[0] = 0;
+            for (l = defines; l; l = l->next)
+              {
+                 strcat(def, l->data);
+                 strcat(def, " ");
+              }
+         }
+
+       /*
+        * Run the input through the C pre-processor.
+        *
+        * On some BSD based systems (MacOS, OpenBSD), the default cpp
+        * in the path is a wrapper script that chokes on the -o option.
+        * If the preprocessor is invoked via gcc -E, it will treat
+        * file_in as a linker file. The safest route seems to be to
+        * run cpp with the output as the second non-option argument.
+        *
+        * Redirecting the output is required for MacOS 10.3, and works fine
+        * on other systems.
+        */
+       snprintf(buf, sizeof(buf), "cat %s | cpp -I%s %s > %s",
+                file_in, inc, def, tmpn);
+       ret = system(buf);
+       if (ret < 0)
+         {
+            snprintf(buf, sizeof(buf), "gcc -I%s %s -E -o %s %s",
+                     inc, def, tmpn, file_in);
+            ret = system(buf);
+         }
+       if (ret == EXIT_SUCCESS)
+         file_in = tmpn;
+       free(def);
+/* OLD CODE
+       snprintf(buf, sizeof(buf), "cat %s | cpp -I%s %s -E -o %s",
+                file_in, inc, def, tmpn);
+       ret = system(buf);
+       if (ret < 0)
+         {
+            snprintf(buf, sizeof(buf), "gcc -I%s %s -E -o %s %s",
+                     inc, def, tmpn, file_in);
+            ret = system(buf);
+         }
+       if (ret >= 0) file_in = tmpn;
+       free(def);
+ */
+     }
+   fd = open(file_in, O_RDONLY | O_BINARY);
+   if (fd < 0)
+     {
+       fprintf(stderr, "%s: Error. cannot open file \"%s\" for input. %s\n",
+               progname, file_in, strerror(errno));
+       exit(-1);
+     }
+   if (verbose)
+     {
+       printf("%s: Opening \"%s\" for input\n",
+              progname, file_in);
+     }
+
+   size = lseek(fd, 0, SEEK_END);
+   lseek(fd, 0, SEEK_SET);
+   data = malloc(size);
+   if (data && (read(fd, data, size) == size))
+       parse(data, size);
+   else
+     {
+       fprintf(stderr, "%s: Error. cannot read file \"%s\". %s\n",
+               progname, file_in, strerror(errno));
+       exit(-1);
+     }
+   free(data);
+   close(fd);
+}
+
+int
+is_param(int n)
+{
+   char *str;
+
+   str = evas_list_nth(params, n);
+   if (str) return 1;
+   return 0;
+}
+
+int
+is_num(int n)
+{
+   char *str;
+   long int ret;
+   char *end;
+
+   str = evas_list_nth(params, n);
+   if (!str)
+     {
+       fprintf(stderr, "%s: Error. %s:%i no parameter supplied as argument %i\n",
+               progname, file_in, line - 1, n + 1);
+       exit(-1);
+     }
+   if (str[0] == 0) return 0;
+   end = str;
+   ret = strtol(str, &end, 0);
+   if ((end != str) && (end[0] == 0)) return 1;
+   return 0;
+}
+
+char *
+parse_str(int n)
+{
+   char *str;
+   char *s;
+
+   str = evas_list_nth(params, n);
+   if (!str)
+     {
+       fprintf(stderr, "%s: Error. %s:%i no parameter supplied as argument %i\n",
+               progname, file_in, line - 1, n + 1);
+       exit(-1);
+     }
+   s = mem_strdup(str);
+   return s;
+}
+
+static int
+_parse_enum(char *str, va_list va)
+{
+   va_list va2;
+   va_copy(va2, va); /* iterator for the error message */
+
+   for (;;)
+     {
+       char *s;
+       int   v;
+
+       s = va_arg(va, char *);
+
+       /* End of the list, nothing matched. */
+       if (!s)
+         {
+            fprintf(stderr, "%s: Error. %s:%i token %s not one of:",
+                    progname, file_in, line - 1, str);
+            s = va_arg(va2, char *);
+            while (s)
+              {
+                 v = va_arg(va2, int);
+                 fprintf(stderr, " %s", s);
+                 s = va_arg(va2, char *);
+                 if (!s) break;
+              }
+            fprintf(stderr, "\n");
+            va_end(va2);
+            va_end(va);
+            exit(-1);
+         }
+
+       v = va_arg(va, int);
+       if (!strcmp(s, str))
+         {
+            va_end(va2);
+            va_end(va);
+            return v;
+         }
+     }
+   va_end(va2);
+   va_end(va);
+   return 0;
+}
+
+int
+parse_enum(int n, ...)
+{
+   char *str;
+   int result;
+   va_list va;
+
+   str = evas_list_nth(params, n);
+   if (!str)
+     {
+       fprintf(stderr, "%s: Error. %s:%i no parameter supplied as argument %i\n",
+               progname, file_in, line - 1, n + 1);
+       exit(-1);
+     }
+
+   va_start(va, n);
+   result = _parse_enum(str, va);
+   va_end(va);
+
+   return result;
+}
+
+int
+parse_flags(int n, ...)
+{
+   Evas_List *lst;
+   int result = 0;
+   va_list va;
+
+   va_start(va, n);
+   for (lst = evas_list_nth_list(params, n); lst != NULL; lst = lst->next)
+     result |= _parse_enum(lst->data, va);
+   va_end(va);
+
+   return result;
+}
+
+int
+parse_int(int n)
+{
+   char *str;
+   int i;
+
+   str = evas_list_nth(params, n);
+   if (!str)
+     {
+       fprintf(stderr, "%s: Error. %s:%i no parameter supplied as argument %i\n",
+               progname, file_in, line - 1, n + 1);
+       exit(-1);
+     }
+   i = my_atoi(str);
+   return i;
+}
+
+int
+parse_int_range(int n, int f, int t)
+{
+   char *str;
+   int i;
+
+   str = evas_list_nth(params, n);
+   if (!str)
+     {
+       fprintf(stderr, "%s: Error. %s:%i no parameter supplied as argument %i\n",
+               progname, file_in, line - 1, n + 1);
+       exit(-1);
+     }
+   i = my_atoi(str);
+   if ((i < f) || (i > t))
+     {
+       fprintf(stderr, "%s: Error. %s:%i integer %i out of range of %i to %i inclusive\n",
+               progname, file_in, line - 1, i, f, t);
+       exit(-1);
+     }
+   return i;
+}
+
+int
+parse_bool(int n)
+{
+   char *str, buf[4096];
+   int i;
+
+   str = evas_list_nth(params, n);
+   if (!str)
+     {
+       fprintf(stderr, "%s: Error. %s:%i no parameter supplied as argument %i\n",
+               progname, file_in, line - 1, n + 1);
+       exit(-1);
+     }
+
+   if (!strstrip(str, buf, sizeof (buf)))
+     {
+       fprintf(stderr, "%s: Error. %s:%i expression is too long\n",
+               progname, file_in, line - 1);
+       return 0;
+     }
+
+   if (!strcasecmp(buf, "false") || !strcasecmp(buf, "off"))
+      return 0;
+   if (!strcasecmp(buf, "true") || !strcasecmp(buf, "on"))
+      return 1;
+
+   i = my_atoi(str);
+   if ((i < 0) || (i > 1))
+     {
+       fprintf(stderr, "%s: Error. %s:%i integer %i out of range of 0 to 1 inclusive\n",
+               progname, file_in, line - 1, i);
+       exit(-1);
+     }
+   return i;
+}
+
+double
+parse_float(int n)
+{
+   char *str;
+   double i;
+
+   str = evas_list_nth(params, n);
+   if (!str)
+     {
+       fprintf(stderr, "%s: Error. %s:%i no parameter supplied as argument %i\n",
+               progname, file_in, line - 1, n + 1);
+       exit(-1);
+     }
+   i = my_atof(str);
+   return i;
+}
+
+double
+parse_float_range(int n, double f, double t)
+{
+   char *str;
+   double i;
+
+   str = evas_list_nth(params, n);
+   if (!str)
+     {
+       fprintf(stderr, "%s: Error. %s:%i no parameter supplied as argument %i\n",
+               progname, file_in, line - 1, n + 1);
+       exit(-1);
+     }
+   i = my_atof(str);
+   if ((i < f) || (i > t))
+     {
+       fprintf(stderr, "%s: Error. %s:%i float %3.3f out of range of %3.3f to %3.3f inclusive\n",
+               progname, file_in, line - 1, i, f, t);
+       exit(-1);
+     }
+   return i;
+}
+
+void
+check_arg_count(int required_args)
+{
+   int num_args = evas_list_count (params);
+
+   if (num_args != required_args)
+     {
+       fprintf(stderr, "%s: Error. %s:%i got %i arguments, but expected %i\n",
+             progname, file_in, line - 1, num_args, required_args);
+       exit(-1);
+     }
+}
+
+void
+check_min_arg_count(int min_required_args)
+{
+   int num_args = evas_list_count (params);
+
+   if (num_args < min_required_args)
+     {
+       fprintf(stderr, "%s: Error. %s:%i got %i arguments, "
+               "but expected at least %i\n",
+               progname, file_in, line - 1, num_args, min_required_args);
+       exit(-1);
+     }
+}
+
+/* simple expression parsing stuff */
+
+/*
+ * alpha ::= beta + beta || beta
+ * beta  ::= gamma + gamma || gamma
+ * gamma ::= num || delta
+ * delta ::= '(' alpha ')'
+ *
+ */
+
+/* int set of function */
+
+static int
+my_atoi(const char * s)
+{
+   int res = 0;
+   char buf[4096];
+
+   if (!s)
+     return 0;
+
+   if (!strstrip(s, buf, sizeof (buf)))
+     {
+       fprintf(stderr, "%s: Error. %s:%i expression is too long\n",
+               progname, file_in, line - 1);
+       return 0;
+     }
+
+   _alphai(buf, &res);
+   return res;
+}
+
+static char *
+_deltai(char *s, int * val)
+{
+   if (!val) return NULL;
+
+   if ('(' != s[0])
+     {
+       fprintf(stderr, "%s: Error. %s:%i unexpected character at %s\n",
+               progname, file_in, line - 1, s);
+       return s;
+     }
+   else
+     {
+       s++;
+       s = _alphai(s, val);
+       s++;
+       return s;
+     }
+
+   return s;
+}
+
+static char *
+_gammai(char *s, int * val)
+{
+   if (!val) return NULL;
+
+   if (_is_numi(s[0]))
+     {
+       s = _get_numi(s, val);
+       return s;
+     }
+   else if ('(' == s[0])
+     {
+       s = _deltai(s, val);
+       return s;
+     }
+   else
+     fprintf(stderr, "%s: Error. %s:%i unexpected character at %s\n",
+            progname, file_in, line - 1, s);
+   return s;
+}
+
+static char *
+_betai(char *s, int * val)
+{
+   int a1, a2;
+   char op;
+
+   if (!val)
+     return NULL;
+
+   s = _gammai(s, &a1);
+
+   while (_is_op1i(s[0]))
+     {
+       op = s[0];
+       s++;
+       s = _gammai(s, &a2);
+       a1 = _calci(op, a1, a2);
+     }
+
+   (*val) = a1;
+
+   return s;
+}
+
+static char *
+_alphai(char *s, int * val)
+{
+   int a1, a2;
+   char op;
+
+   if (!val)
+     return NULL;
+
+   s = _betai(s, &a1);
+
+   while (_is_op2i(s[0]))
+     {
+       op = s[0];
+       s++;
+       s = _betai(s, &a2);
+       a1 = _calci(op, a1, a2);
+     }
+
+   (*val) = a1;
+   return s;
+}
+
+char *
+_get_numi(char *s, int * val)
+{
+   char buf[4096];
+   int pos = 0;
+
+   if (!val)
+     return s;
+
+   while (
+         (('0' <= s[pos]) && ('9' >= s[pos])) ||
+         ((0 == pos) && ('-' == s[pos]))
+         )
+     {
+       buf[pos] = s[pos];
+       pos++;
+     }
+
+   buf[pos] = '\0';
+   (*val) = atoi(buf);
+   return (s+pos);
+}
+
+int
+_is_numi(char c)
+{
+   if (((c >= '0') && (c <= '9')) || ('-' == c) || ('+' == c))
+     return 1;
+   else
+     return 0;
+}
+
+int
+_is_op1i(char c)
+{
+   switch(c)
+     {
+      case '*':;
+      case '/': return 1;
+      default: return 0;
+     }
+   return 0;
+}
+
+int
+_is_op2i(char c)
+{
+   switch(c)
+     {
+      case '+':;
+      case '-': return 1;
+      default: return 0;
+     }
+   return 0;
+}
+
+int
+_calci(char op, int a, int b)
+{
+   switch(op)
+     {
+      case '+':
+       a += b;
+       return a;
+      case '-':
+       a -= b;
+       return a;
+      case '/':
+       if(0 != b)
+         a /= b;
+       else
+         fprintf(stderr, "%s: Error. %s:%i divide by zero\n",
+                 progname, file_in, line - 1);
+       return a;
+      case '*':
+       a *= b;
+       return a;
+      default:
+       fprintf(stderr, "%s: Error. %s:%i unexpected character '%c'\n",
+               progname, file_in, line - 1, op);
+       return a;
+     }
+}
+
+/* float set of functoins */
+
+double
+my_atof(const char * s)
+{
+   double res = 0;
+   char buf[4096];
+
+   if (!s)
+     return 0;
+
+   if (!strstrip(s, buf, sizeof (buf)))
+     {
+       fprintf(stderr, "%s: Error. %s:%i expression is too long\n",
+               progname, file_in, line - 1);
+       return 0;
+     }
+
+   _alphaf(buf, &res);
+   return res;
+}
+
+static char *
+_deltaf(char *s, double * val)
+{
+   if (!val) return NULL;
+
+   if ('(' != s[0])
+     {
+       fprintf(stderr, "%s: Error. %s:%i unexpected character at %s\n",
+               progname, file_in, line - 1, s);
+       return s;
+     }
+   else
+     {
+       s++;
+       s = _alphaf(s, val);
+       s++;
+       return s;
+     }
+
+   return s;
+}
+
+static char *
+_gammaf(char *s, double * val)
+{
+   if (!val) return NULL;
+
+   if (_is_numf(s[0]))
+     {
+       s = _get_numf(s, val);
+       return s;
+     }
+   else if ('(' == s[0])
+     {
+       s = _deltaf(s, val);
+       return s;
+     }
+   else
+     fprintf(stderr, "%s: Error. %s:%i unexpected character at %s\n",
+            progname, file_in, line - 1, s);
+   return s;
+}
+
+static char *
+_betaf(char *s, double * val)
+{
+   double a1=0, a2=0;
+   char op;
+
+   if (!val)
+     return NULL;
+
+   s = _gammaf(s, &a1);
+
+   while (_is_op1f(s[0]))
+     {
+       op = s[0];
+       s++;
+       s = _gammaf(s, &a2);
+       a1 = _calcf(op, a1, a2);
+     }
+
+   (*val) = a1;
+
+   return s;
+}
+
+static char *
+_alphaf(char *s, double * val)
+{
+   double a1=0, a2=0;
+   char op;
+
+   if (!val)
+     return NULL;
+
+   s = _betaf(s, &a1);
+
+   while (_is_op2f(s[0]))
+     {
+       op = s[0];
+       s++;
+       s = _betaf(s, &a2);
+       a1 = _calcf(op, a1, a2);
+     }
+
+   (*val) = a1;
+
+   return s;
+}
+
+static char *
+_get_numf(char *s, double * val)
+{
+   char buf[4096];
+   int pos = 0;
+
+   if (!val)
+     return s;
+
+   while (
+         (('0' <= s[pos]) && ('9' >= s[pos])) ||
+         ('.' == s[pos]) ||
+         ((0 == pos) && ('-' == s[pos]))
+         )
+     {
+       buf[pos] = s[pos];
+       pos++;
+     }
+
+   buf[pos] = '\0';
+   (*val) = atof(buf);
+   return (s+pos);
+}
+
+static int
+_is_numf(char c)
+{
+   if (((c >= '0') && (c <= '9'))
+       || ('-' == c)
+       || ('.' == c)
+       || ('+' == c))
+     return 1;
+   else
+     return 0;
+}
+
+static int
+_is_op1f(char c)
+{
+   switch(c)
+     {
+      case '*':;
+      case '/': return 1;
+      default: return 0;
+     }
+   return 0;
+}
+
+static int
+_is_op2f(char c)
+{
+   switch(c)
+     {
+      case '+':;
+      case '-': return 1;
+      default: return 0;
+     }
+   return 0;
+}
+
+static double
+_calcf(char op, double a, double b)
+{
+   switch(op)
+     {
+      case '+':
+       a += b;
+       return a;
+      case '-':
+       a -= b;
+       return a;
+      case '/':
+       if (b != 0) a /= b;
+       else
+         fprintf(stderr, "%s: Error. %s:%i divide by zero\n",
+                 progname, file_in, line - 1);
+       return a;
+      case '*':
+       a *= b;
+       return a;
+      default:
+       fprintf(stderr, "%s: Error. %s:%i unexpected character '%c'\n",
+               progname, file_in, line - 1, op);
+       return a;
+     }
+}
+
+static int
+strstrip(const char *in, char *out, size_t size)
+{
+   if ((size -1 ) < strlen(in))
+     {
+       fprintf(stderr, "%s: Error. %s:%i expression is too long\n",
+               progname, file_in, line - 1);
+       return 0;
+     }
+
+   /* remove spaces and tabs */
+   while (*in)
+     {
+       if ((0x20 != *in) && (0x09 != *in))
+         {
+            *out = *in;
+            out++;
+         }
+       in++;
+     }
+
+   *out = '\0';
+
+   return 1;
+}
diff --git a/src/bin/edje_cc_sources.c b/src/bin/edje_cc_sources.c
new file mode 100644 (file)
index 0000000..31368f3
--- /dev/null
@@ -0,0 +1,262 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#include "edje_cc.h"
+
+static Eet_Data_Descriptor *_srcfile_edd = NULL;
+static Eet_Data_Descriptor *_srcfile_list_edd = NULL;
+
+static Eet_Data_Descriptor *_font_edd = NULL;
+static Eet_Data_Descriptor *_font_list_edd = NULL;
+
+static SrcFile_List srcfiles = {NULL};
+
+#define NEWD(str, typ) \
+      { eddc.name = str; eddc.size = sizeof(typ); }
+
+static char *
+_edje_str_direct_alloc(const char *str)
+{
+   return (char *)str;
+}
+
+static void
+_edje_str_direct_free(const char *str)
+{
+}
+
+void
+source_edd(void)
+{
+   Eet_Data_Descriptor_Class eddc;
+
+   eddc.version = EET_DATA_DESCRIPTOR_CLASS_VERSION;
+   eddc.func.mem_alloc = NULL;
+   eddc.func.mem_free = NULL;
+   eddc.func.str_alloc = evas_stringshare_add;
+   eddc.func.str_free = evas_stringshare_del;
+   eddc.func.list_next = evas_list_next;
+   eddc.func.list_append = evas_list_append;
+   eddc.func.list_data = evas_list_data;
+   eddc.func.list_free = evas_list_free;
+   eddc.func.hash_foreach = evas_hash_foreach;
+   eddc.func.hash_add = evas_hash_add;
+   eddc.func.hash_free = evas_hash_free;
+   eddc.func.str_direct_alloc = _edje_str_direct_alloc;
+   eddc.func.str_direct_free = _edje_str_direct_free;
+
+   NEWD("srcfile", SrcFile);
+   _srcfile_edd = eet_data_descriptor3_new(&eddc);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_srcfile_edd, SrcFile, "name", name, EET_T_INLINED_STRING);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_srcfile_edd, SrcFile, "file", file, EET_T_INLINED_STRING);
+
+   NEWD("srcfile_list", SrcFile_List);
+   _srcfile_list_edd = eet_data_descriptor3_new(&eddc);
+   EET_DATA_DESCRIPTOR_ADD_LIST(_srcfile_list_edd, SrcFile_List, "list", list, _srcfile_edd);
+
+   NEWD("font", Font);
+   _font_edd = eet_data_descriptor3_new(&eddc);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_font_edd, Font, "file", file, EET_T_INLINED_STRING);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_font_edd, Font, "name", name, EET_T_INLINED_STRING);
+
+   NEWD("font_list", Font_List);
+   _font_list_edd = eet_data_descriptor3_new(&eddc);
+   EET_DATA_DESCRIPTOR_ADD_LIST(_font_list_edd, Font_List, "list", list, _font_edd);
+}
+
+static void source_fetch_file(const char *fil, const char *filname);
+
+static void
+source_fetch_file(const char *fil, const char *filname)
+{
+   FILE *f;
+   char buf[16 * 1024], *dir = NULL;
+   long sz;
+   ssize_t dir_len = 0;
+   SrcFile *sf;
+
+   f = fopen(fil, "rb");
+   if (!f)
+     {
+       fprintf(stderr, "%s: Warning. Cannot open file '%s'\n",
+             progname, fil);
+       exit(-1);
+     }
+
+   fseek(f, 0, SEEK_END);
+   sz = ftell(f);
+   fseek(f, 0, SEEK_SET);
+   sf = mem_alloc(SZ(SrcFile));
+   sf->name = mem_strdup(filname);
+   sf->file = mem_alloc(sz + 1);
+   fread(sf->file, sz, 1, f);
+   sf->file[sz] = '\0';
+   fseek(f, 0, SEEK_SET);
+   srcfiles.list = evas_list_append(srcfiles.list, sf);
+
+   while (fgets(buf, sizeof(buf), f))
+     {
+       char *p, *pp;
+       int got_hash = 0;
+       int forgetit = 0;
+       int haveinclude = 0;
+       char *file = NULL, *fname = NULL;
+
+       p = buf;
+       while ((!forgetit) && (*p))
+         {
+            if (!got_hash)
+              {
+                 if (!isspace(*p))
+                   {
+                      if (*p == '#')
+                        got_hash = 1;
+                      else
+                        forgetit = 1;
+                   }
+                 p++;
+              }
+
+            if (!haveinclude)
+              {
+                 if (!isspace(*p))
+                   {
+                      if (!strncmp(p, "include", 7))
+                        {
+                           haveinclude = 1;
+                           p += 7;
+                        }
+                      /* HACK! the logic above should be fixed so
+                       * preprocessor statements don't have to begin
+                       * in column 0.
+                       * otoh, edje_cc should print a warning in that case,
+                       * since according to the standard, preprocessor
+                       * statements need to be put in column 0.
+                       */
+                      else if (!strncmp(p, "#include", 8))
+                        {
+                           haveinclude = 1;
+                           p += 8;
+                        }
+                      else
+                        forgetit = 1;
+                   }
+              }
+            else
+              {
+                 if (!isspace(*p))
+                   {
+                      char end = '\0';
+
+                      if (*p == '"') end = '"';
+                      else if (*p == '<') end = '>';
+
+                      if (end)
+                        {
+                           pp = strchr(p + 1, end);
+                           if (!pp)
+                             forgetit = 1;
+                           else
+                             {
+                                char *slash;
+                                ssize_t l = 0;
+
+                                /* get the directory of the current file
+                                 * if we haven't already done so
+                                 */
+                                if ((!dir) && (strrchr(fil, '/')))
+                                  {
+                                     dir = mem_strdup(fil);
+                                     slash = strrchr(dir, '/');
+                                     *slash = '\0';
+                                     dir_len = strlen(dir);
+                                  }
+
+                                l = pp - p + dir_len + 1;
+                                file = mem_alloc(l);
+
+                                if (!dir_len)
+                                  {
+                                     snprintf(file, l - 1, "%s", p + 1);
+                                     file[l - 2] = 0;
+                                  }
+                                else
+                                  {
+                                     snprintf(file, l, "%s/%s", dir, p + 1);
+                                     file[l - 1] = 0;
+                                  }
+
+
+                                fname = strdup(p + 1);
+                                pp = strrchr(fname, end);
+                                if (pp) *pp = 0;
+                                forgetit = 1;
+                             }
+                        }
+                      else
+                        forgetit = 1;
+                   }
+                 else
+                   p++;
+              }
+
+            got_hash = 0;
+         }
+       if ((file) && (fname))
+         {
+            source_fetch_file(file, fname);
+            free(file);
+            free(fname);
+         }
+     }
+   free(dir);
+   fclose(f);
+}
+
+void
+source_fetch(void)
+{
+   char buf[PATH_MAX] = {0}, *ptr;
+
+   ptr = strrchr(file_in, '/');
+   if (ptr)
+     {
+       snprintf(buf, sizeof (buf), "%s", ptr + 1);
+     }
+
+   source_fetch_file(file_in, buf[0] ? buf : file_in);
+}
+
+int
+source_append(Eet_File *ef)
+{
+   return eet_data_write(ef, _srcfile_list_edd, "edje_sources", &srcfiles, 0);
+}
+
+SrcFile_List *
+source_load(Eet_File *ef)
+{
+   SrcFile_List *s;
+
+   s = eet_data_read(ef, _srcfile_list_edd, "edje_sources");
+   return s;
+}
+
+int
+source_fontmap_save(Eet_File *ef, Evas_List *fonts)
+{
+   Font_List fl;
+
+   fl.list = fonts;
+   return eet_data_write(ef, _font_list_edd, "edje_source_fontmap", &fl, 0);
+}
+
+Font_List *
+source_fontmap_load(Eet_File *ef)
+{
+   Font_List *fl;
+
+   fl = eet_data_read(ef, _font_list_edd, "edje_source_fontmap");
+   return fl;
+}
diff --git a/src/bin/edje_decc.c b/src/bin/edje_decc.c
new file mode 100644 (file)
index 0000000..d9e5e24
--- /dev/null
@@ -0,0 +1,363 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+/* ugly ugly. avert your eyes. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <Ecore_File.h>
+
+#include "edje_decc.h"
+
+char *progname = NULL;
+char *file_in = NULL;
+char *file_out = NULL;
+
+Edje_File *edje_file = NULL;
+SrcFile_List *srcfiles = NULL;
+Font_List *fontlist = NULL;
+
+int line = 0;
+
+int        decomp(void);
+void       output(void);
+static int compiler_cmd_is_sane();
+static int root_filename_is_sane();
+
+static void
+main_help(void)
+{
+   printf
+     ("Usage:\n"
+      "\t%s input_file.edj [-main-out file.edc]\n"
+      "\n"
+      ,progname);
+}
+
+Eet_File *ef;
+Eet_Dictionary *ed;
+
+int
+main(int argc, char **argv)
+{
+   int i;
+
+   setlocale(LC_NUMERIC, "C");
+
+   progname = argv[0];
+   for (i = 1; i < argc; i++)
+     {
+       if (!file_in)
+         file_in = argv[i];
+       else if ((!strcmp(argv[i], "-main-out")) && (i < (argc - 1)))
+         {
+            i++;
+            file_out = argv[i];
+         }
+     }
+   if (!file_in)
+     {
+       fprintf(stderr, "%s: Error: no input file specified.\n", progname);
+       main_help();
+       exit(-1);
+     }
+
+   edje_init();
+   eet_init();
+   source_edd();
+
+   if (!decomp()) return -1;
+   output();
+
+   eet_close(ef);
+   eet_shutdown();
+   return 0;
+}
+
+int
+decomp(void)
+{
+   ef = eet_open(file_in, EET_FILE_MODE_READ);
+   if (!ef)
+     {
+       printf("ERROR: cannot open %s\n", file_in);
+       return 0;
+     }
+
+   srcfiles = source_load(ef);
+   if (!srcfiles || !srcfiles->list)
+     {
+       printf("ERROR: %s has no decompile information\n", file_in);
+       eet_close(ef);
+       return 0;
+     }
+   if (!srcfiles->list->data || !root_filename_is_sane())
+     {
+       printf("ERROR: Invalid root filename: '%s'\n", (char *) srcfiles->list->data);
+       eet_close(ef);
+       return 0;
+     }
+   edje_file = eet_data_read(ef, _edje_edd_edje_file, "edje_file");
+   if (!edje_file)
+     {
+       printf("ERROR: %s does not appear to be an edje file\n", file_in);
+       eet_close(ef);
+       return 0;
+     }
+   if (!edje_file->compiler)
+     {
+       edje_file->compiler = strdup("edje_cc");
+     }
+   else if (!compiler_cmd_is_sane())
+     {
+       printf("ERROR: invalid compiler executable: '%s'\n", edje_file->compiler);
+       eet_close(ef);
+       return 0;
+     }
+   fontlist = source_fontmap_load(ef);
+   return 1;
+}
+
+void
+output(void)
+{
+   Evas_List *l;
+   Eet_File *ef;
+   char *outdir, *p;
+
+   p = strrchr(file_in, '/');
+   if (p)
+     outdir = strdup(p + 1);
+   else
+     outdir = strdup(file_in);
+   p = strrchr(outdir, '.');
+   if (p) *p = 0;
+
+   ecore_file_mkpath(outdir);
+
+   ef = eet_open(file_in, EET_FILE_MODE_READ);
+
+   if (edje_file->image_dir)
+     {
+       for (l = edje_file->image_dir->entries; l; l = l->next)
+         {
+            Edje_Image_Directory_Entry *ei;
+
+            ei = l->data;
+            if ((ei->source_type > EDJE_IMAGE_SOURCE_TYPE_NONE) &&
+                (ei->source_type < EDJE_IMAGE_SOURCE_TYPE_LAST) &&
+                (ei->source_type != EDJE_IMAGE_SOURCE_TYPE_EXTERNAL) &&
+                (ei->entry))
+              {
+                 Ecore_Evas *ee;
+                 Evas *evas;
+                 Evas_Object *im;
+                 char buf[4096];
+                 char out[4096];
+                 char *pp;
+
+                 ecore_init();
+                 ecore_evas_init();
+                 ee = ecore_evas_buffer_new(1, 1);
+                 if (!ee)
+                   {
+                      fprintf(stderr, "Error. cannot create buffer engine canvas for image save.\n");
+                      exit(-1);
+                   }
+                 evas = ecore_evas_get(ee);
+                 im = evas_object_image_add(evas);
+                 if (!im)
+                   {
+                      fprintf(stderr, "Error. cannot create image object for save.\n");
+                      exit(-1);
+                   }
+                 snprintf(buf, sizeof(buf), "images/%i", ei->id);
+                 evas_object_image_file_set(im, file_in, buf);
+                 snprintf(out, sizeof(out), "%s/%s", outdir, ei->entry);
+                 printf("Output Image: %s\n", out);
+                 pp = strdup(out);
+                 p = strrchr(pp, '/');
+                 *p = 0;
+                 if (strstr(pp, "../"))
+                   {
+                      printf("ERROR: potential security violation. attempt to write in parent dir.\n");
+                      exit(-1);
+                   }
+                 ecore_file_mkpath(pp);
+                 free(pp);
+                 if (!evas_object_image_save(im, out, NULL, "quality=100 compress=9"))
+                   {
+                      printf("ERROR: cannot write file %s. Perhaps missing JPEG or PNG saver modules for Evas.\n", out);
+                      exit(-1);
+                   }
+                 evas_object_del(im);
+                 ecore_evas_free(ee);
+                 ecore_evas_shutdown();
+                 ecore_shutdown();
+              }
+         }
+     }
+
+   for (l = srcfiles->list; l; l = l->next)
+     {
+       SrcFile *sf;
+       char out[4096];
+       FILE *f;
+       char *pp;
+
+       sf = l->data;
+       snprintf(out, sizeof(out), "%s/%s", outdir, sf->name);
+       printf("Output Source File: %s\n", out);
+       pp = strdup(out);
+       p = strrchr(pp, '/');
+       *p = 0;
+       if (strstr(pp, "../"))
+         {
+            printf("ERROR: potential security violation. attempt to write in parent dir.\n");
+            exit (-1);
+         }
+       ecore_file_mkpath(pp);
+       free(pp);
+       if (strstr(out, "../"))
+         {
+            printf("ERROR: potential security violation. attempt to write in parent dir.\n");
+            exit (-1);
+         }
+       f = fopen(out, "wb");
+       if (!f)
+         {
+            printf("ERROR: unable to write file (%s).\n", out);
+            exit (-1);
+         }
+
+       /* if the file is empty, sf->file will be NULL.
+        * note that that's not an error
+        */
+       if (sf->file) fputs(sf->file, f);
+       fclose(f);
+     }
+   if (fontlist)
+     {
+       for (l = fontlist->list; l; l = l->next)
+         {
+            Font *fn;
+            void *font;
+            int fontsize;
+            char out[4096];
+
+            fn = l->data;
+            snprintf(out, sizeof(out), "fonts/%s", fn->name);
+            font = eet_read(ef, out, &fontsize);
+            if (font)
+              {
+                 FILE *f;
+                 char *pp;
+
+                 snprintf(out, sizeof(out), "%s/%s", outdir, fn->file);
+                 printf("Output Font: %s\n", out);
+                 pp = strdup(out);
+                 p = strrchr(pp, '/');
+                 *p = 0;
+                 if (strstr(pp, "../"))
+                   {
+                      printf("ERROR: potential security violation. attempt to write in parent dir.\n");
+                      exit (-1);
+                   }
+                 ecore_file_mkpath(pp);
+                 free(pp);
+                 if (strstr(out, "../"))
+                   {
+                      printf("ERROR: potential security violation. attempt to write in parent dir.\n");
+                      exit (-1);
+                   }
+                 f = fopen(out, "wb");
+                 fwrite(font, fontsize, 1, f);
+                 fclose(f);
+                 free(font);
+              }
+         }
+     }
+     {
+       char out[4096];
+       FILE *f;
+       SrcFile *sf = srcfiles->list->data;
+
+       snprintf(out, sizeof(out), "%s/build.sh", outdir);
+       printf("Output Build Script: %s\n", out);
+       if (strstr(out, "../"))
+         {
+            printf("ERROR: potential security violation. attempt to write in parent dir.\n");
+            exit (-1);
+         }
+       f = fopen(out, "wb");
+       fprintf(f, "#!/bin/sh\n");
+       fprintf(f, "%s $@ -id . -fd . %s -o %s.edj\n", edje_file->compiler, sf->name, outdir);
+       fclose(f);
+
+       if (file_out)
+         {
+            snprintf(out, sizeof(out), "%s/%s", outdir, file_out);
+            symlink(sf->name, out);
+         }
+
+       chmod(out, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP);
+
+       printf("\n*** CAUTION ***\n"
+             "Please check the build script for anything malicious "
+             "before running it!\n\n");
+     }
+   eet_close(ef);
+}
+
+static int
+compiler_cmd_is_sane()
+{
+   char *c = edje_file->compiler, *ptr;
+
+   if (!c || !*c)
+     {
+       return 0;
+     }
+
+   for (ptr = c; ptr && *ptr; ptr++)
+     {
+       /* only allow [a-z][A-Z][0-9]_- */
+       if (!isalnum(*ptr) && *ptr != '_' && *ptr != '-')
+         {
+            return 0;
+         }
+     }
+
+   return 1;
+}
+
+static int
+root_filename_is_sane()
+{
+   SrcFile *sf = srcfiles->list->data;
+   char *f = sf->name, *ptr;
+
+   if (!f || !*f)
+     {
+       return 0;
+     }
+
+   for (ptr = f; ptr && *ptr; ptr++)
+     {
+       /* only allow [a-z][A-Z][0-9]_-./ */
+       switch (*ptr)
+         {
+          case '_': case '-':  case '.': case '/':
+             break;
+          default:
+             if (!isalnum(*ptr))
+               {
+                  return 0;
+               }
+         }
+     }
+   return 1;
+}
diff --git a/src/bin/edje_decc.h b/src/bin/edje_decc.h
new file mode 100644 (file)
index 0000000..a07a103
--- /dev/null
@@ -0,0 +1,45 @@
+#ifndef EDJE_DECC_H
+#define EDJE_DECC_H
+
+#include "edje_main.h"
+
+/* types */
+typedef struct _Font                  Font;
+typedef struct _Font_List             Font_List;
+typedef struct _SrcFile               SrcFile;
+typedef struct _SrcFile_List          SrcFile_List;
+
+struct _Font
+{
+   char *file;
+   char *name;
+};
+
+struct _Font_List
+{
+   Evas_List *list;
+};
+
+struct _SrcFile
+{
+   char *name;
+   char *file;
+};
+
+struct _SrcFile_List
+{
+   Evas_List *list;
+};
+
+void    source_edd(void);
+void    source_fetch(void);
+int     source_append(Eet_File *ef);
+SrcFile_List *source_load(Eet_File *ef);
+int     source_fontmap_save(Eet_File *ef, Evas_List *fonts);
+Font_List *source_fontmap_load(Eet_File *ef);
+
+void   *mem_alloc(size_t size);
+char   *mem_strdup(const char *s);
+#define SZ sizeof
+
+#endif
diff --git a/src/bin/edje_main.h b/src/bin/edje_main.h
new file mode 100644 (file)
index 0000000..195af10
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef EDJE_MAIN_H
+#define EDJE_MAIN_H
+
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <fcntl.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <sys/mman.h>
+
+#include <Ecore_Evas.h>
+
+#include "edje_private.h"
+#include "edje_prefix.h"
+
+#endif
diff --git a/src/bin/edje_prefix.c b/src/bin/edje_prefix.c
new file mode 100644 (file)
index 0000000..2241fef
--- /dev/null
@@ -0,0 +1,449 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/param.h>
+#include <math.h>
+#include <limits.h>
+#include <ctype.h>
+#include <time.h>
+#include <dirent.h>
+
+#include "edje_prefix.h"
+
+#ifdef _WIN32
+# define EDJE_DIR_SEPARATOR '\\'
+# define EDJE_DIR_SEPARATOR_S "\\"
+#else
+# define EDJE_DIR_SEPARATOR '/'
+# define EDJE_DIR_SEPARATOR_S "/"
+#endif /* _WIN32 */
+
+/* local subsystem functions */
+static int _e_prefix_share_hunt(void);
+static int _e_prefix_fallbacks(void);
+static int _e_prefix_try_proc(void);
+static int _e_prefix_try_argv(char *argv0);
+
+/* local subsystem globals */
+static char *_exe_path = NULL;
+static char *_prefix_path = NULL;
+static char *_prefix_path_bin = NULL;
+static char *_prefix_path_data = NULL;
+static char *_prefix_path_lib = NULL;
+
+#define E_FREE(p) { if (p) {free(p); p = NULL;} }
+
+/*#define PREFIX_CACHE_FILE 1*/
+#define SHARE_D "share/edje"
+#define MAGIC_FILE "include/edje.inc"
+#define MAGIC_DAT SHARE_D"/"MAGIC_FILE
+
+/* externally accessible functions */
+int
+e_prefix_determine(char *argv0)
+{
+   char *p, buf[4096];
+   struct stat st;
+
+   e_prefix_shutdown();
+
+   /* if user provides E_PREFIX - then use that or also more specific sub
+    * dirs for bin, lib, data and locale */
+   if (getenv("E_PREFIX"))
+     {
+       _prefix_path = strdup(getenv("E_PREFIX"));
+       if (getenv("E_BIN_DIR"))
+         snprintf(buf, sizeof(buf), "%s" EDJE_DIR_SEPARATOR_S "bin", getenv("E_BIN_DIR"));
+       else
+         snprintf(buf, sizeof(buf), "%s" EDJE_DIR_SEPARATOR_S "bin", _prefix_path);
+       _prefix_path_bin = strdup(buf);
+
+       if (getenv("E_LIB_DIR"))
+         snprintf(buf, sizeof(buf), "%s" EDJE_DIR_SEPARATOR_S "lib", getenv("E_LIB_DIR"));
+       else
+         snprintf(buf, sizeof(buf), "%s" EDJE_DIR_SEPARATOR_S "lib", _prefix_path);
+       _prefix_path_lib = strdup(buf);
+
+       if (getenv("E_DATA_DIR"))
+         snprintf(buf, sizeof(buf), "%s" EDJE_DIR_SEPARATOR_S SHARE_D, getenv("E_DATA_DIR"));
+       else
+         snprintf(buf, sizeof(buf), "%s" EDJE_DIR_SEPARATOR_S SHARE_D, _prefix_path);
+       _prefix_path_data = strdup(buf);
+       return 1;
+     }
+   /* no env var - examine process and possible argv0 */
+   if (!_e_prefix_try_proc())
+     {
+       if (!_e_prefix_try_argv(argv0))
+         {
+            _e_prefix_fallbacks();
+            return 0;
+         }
+     }
+   /* _exe_path is now a full absolute path TO this exe - figure out rest */
+   /*   if
+    * exe        = /blah/whatever/bin/exe
+    *   then
+    * prefix     = /blah/whatever
+    * bin_dir    = /blah/whatever/bin
+    * data_dir   = /blah/whatever/share/enlightenment
+    * lib_dir    = /blah/whatever/lib
+    */
+   p = strrchr(_exe_path, EDJE_DIR_SEPARATOR);
+   if (p)
+     {
+       p--;
+       while (p >= _exe_path)
+         {
+            if (*p == EDJE_DIR_SEPARATOR)
+              {
+                 _prefix_path = malloc(p - _exe_path + 1);
+                 if (_prefix_path)
+                   {
+                      strncpy(_prefix_path, _exe_path, p - _exe_path);
+                      _prefix_path[p - _exe_path] = 0;
+
+                      /* bin and lib always together */
+                      snprintf(buf, sizeof(buf), "%s" EDJE_DIR_SEPARATOR_S "bin", _prefix_path);
+                      _prefix_path_bin = strdup(buf);
+                      snprintf(buf, sizeof(buf), "%s" EDJE_DIR_SEPARATOR_S "lib", _prefix_path);
+                      _prefix_path_lib = strdup(buf);
+
+                      /* check if AUTHORS file is there - then our guess is right */
+                      snprintf(buf, sizeof(buf), "%s" EDJE_DIR_SEPARATOR_S MAGIC_DAT, _prefix_path);
+                      if (stat(buf, &st) == 0)
+                        {
+                           snprintf(buf, sizeof(buf), "%s" EDJE_DIR_SEPARATOR_S SHARE_D, _prefix_path);
+                           _prefix_path_data = strdup(buf);
+                        }
+                      /* AUTHORS file not there. time to start hunting! */
+                      else
+                        {
+                           if (_e_prefix_share_hunt())
+                             {
+                                return 1;
+                             }
+                           else
+                             {
+                                e_prefix_fallback();
+                                return 0;
+                             }
+                        }
+                      return 1;
+                   }
+                 else
+                   {
+                      e_prefix_fallback();
+                      return 0;
+                   }
+              }
+            p--;
+         }
+     }
+   e_prefix_fallback();
+   return 0;
+}
+
+void
+e_prefix_shutdown(void)
+{
+   E_FREE(_exe_path);
+   E_FREE(_prefix_path);
+   E_FREE(_prefix_path_bin);
+   E_FREE(_prefix_path_data);
+   E_FREE(_prefix_path_lib);
+}
+
+void
+e_prefix_fallback(void)
+{
+   e_prefix_shutdown();
+   _e_prefix_fallbacks();
+}
+
+const char *
+e_prefix_get(void)
+{
+   return _prefix_path;
+}
+
+const char *
+e_prefix_bin_get(void)
+{
+   return _prefix_path_bin;
+}
+
+const char *
+e_prefix_data_get(void)
+{
+   return _prefix_path_data;
+}
+
+const char *
+e_prefix_lib_get(void)
+{
+   return _prefix_path_lib;
+}
+
+/* local subsystem functions */
+static int
+_e_prefix_share_hunt(void)
+{
+   char buf[4096], buf2[4096], *p;
+   struct stat st;
+
+   /* sometimes this isnt the case - so we need to do a more exhaustive search
+    * through more parent and subdirs. hre is an example i have seen:
+    *
+    * /blah/whatever/exec/bin/exe
+    * ->
+    * /blah/whatever/exec/bin
+    * /blah/whatever/common/share/enlightenment
+    * /blah/whatever/exec/lib
+    */
+
+   /* this is pure black magic to try and find data shares */
+   /* 2. cache file doesn't exist or is invalid - we need to search - this is
+    * where the real black magic begins */
+
+   /* BLACK MAGIC 1:
+    * /blah/whatever/dir1/bin
+    * /blah/whatever/dir2/share/enlightenment
+    */
+   if (!_prefix_path_data)
+     {
+       DIR                *dirp;
+       struct dirent      *dp;
+
+       snprintf(buf, sizeof(buf), "%s", _prefix_path);
+       p = strrchr(buf, '/');
+       if (p) *p = 0;
+       dirp = opendir(buf);
+       if (dirp)
+         {
+            char *file;
+
+            while ((dp = readdir(dirp)))
+              {
+                 if ((strcmp(dp->d_name, ".")) && (strcmp(dp->d_name, "..")))
+                   {
+                      file = dp->d_name;
+                      snprintf(buf2, sizeof(buf2), "%s/%s/"MAGIC_DAT, buf, file);
+                      if (stat(buf2, &st) == 0)
+                        {
+                           snprintf(buf2, sizeof(buf2), "%s/%s/"SHARE_D, buf, file);
+                           _prefix_path_data = strdup(buf2);
+                           break;
+                        }
+                   }
+              }
+            closedir(dirp);
+         }
+     }
+
+   /* BLACK MAGIC 2:
+    * /blah/whatever/dir1/bin
+    * /blah/whatever/share/enlightenment
+    */
+   if (!_prefix_path_data)
+     {
+       snprintf(buf, sizeof(buf), "%s", _prefix_path);
+       p = strrchr(buf, '/');
+       if (p) *p = 0;
+       snprintf(buf2, sizeof(buf2), "%s/"MAGIC_DAT, buf);
+       if (stat(buf, &st) == 0)
+         {
+            snprintf(buf2, sizeof(buf2), "%s/"SHARE_D, buf);
+            _prefix_path_data = strdup(buf2);
+         }
+     }
+
+   /* add more black magic as required as we discover weridnesss - remember
+    * this is to save users having to set environment variables to tell
+    * e where it lives, so e auto-adapts. so these code snippets are just
+    * logic to figure that out for the user
+    */
+
+   /* done. we found it - write cache file */
+   if (_prefix_path_data)
+     {
+       return 1;
+     }
+   /* fail. everything failed */
+   return 0;
+}
+
+static int
+_e_prefix_fallbacks(void)
+{
+   char *p;
+
+   _prefix_path = strdup(PACKAGE_BIN_DIR);
+   p = strrchr(_prefix_path, '/');
+   if (p) *p = 0;
+   _prefix_path_bin    = strdup(PACKAGE_BIN_DIR);
+   _prefix_path_data   = strdup(PACKAGE_DATA_DIR);
+   _prefix_path_lib    = strdup(PACKAGE_LIB_DIR);
+   printf("WARNING: Edje could not determine its installed prefix\n"
+         "         and is falling back on the compiled in default:\n"
+         "           %s\n"
+         "         You might like to try setting the following environment variables:\n"
+         "           E_PREFIX     - points to the base prefix of install\n"
+         "           E_BIN_DIR    - optional in addition to E_PREFIX to provide\n"
+         "                          a more specific binary directory\n"
+         "           E_LIB_DIR    - optional in addition to E_PREFIX to provide\n"
+         "                          a more specific library dir\n"
+         "           E_DATA_DIR   - optional in addition to E_PREFIX to provide\n"
+         "                          a more specific location for shared data\n"
+         ,
+         _prefix_path);
+   return 1;
+}
+
+static int
+_e_prefix_try_proc(void)
+{
+   FILE *f;
+   char buf[4096];
+   void *func = NULL;
+
+   func = (void *)_e_prefix_try_proc;
+   f = fopen("/proc/self/maps", "rb");
+   if (!f) return 0;
+   while (fgets(buf, sizeof(buf), f))
+     {
+       int len;
+       char *p, mode[5] = "";
+       unsigned long ptr1 = 0, ptr2 = 0;
+
+       len = strlen(buf);
+       if (buf[len - 1] == '\n')
+         {
+            buf[len - 1] = 0;
+            len--;
+         }
+       if (sscanf(buf, "%lx-%lx %4s", &ptr1, &ptr2, mode) == 3)
+         {
+            if (!strcmp(mode, "r-xp"))
+              {
+                 if (((void *)ptr1 <= func) && (func < (void *)ptr2))
+                   {
+                      p = strchr(buf, '/');
+                      if (p)
+                        {
+                           if (len > 10)
+                             {
+                                if (!strcmp(buf + len - 10, " (deleted)"))
+                                  buf[len - 10] = 0;
+                             }
+                           _exe_path = strdup(p);
+                           fclose(f);
+                           return 1;
+                        }
+                      else
+                        break;
+                   }
+              }
+         }
+     }
+   fclose(f);
+   return 0;
+}
+
+static int
+_e_prefix_try_argv(char *argv0)
+{
+   char *path, *p, *cp, *s;
+   int len, lenexe;
+   char buf[4096], buf2[4096], buf3[4096];
+
+   /* 1. is argv0 abs path? */
+#ifdef _WIN32
+   if (argv0[1] == ':')
+#else
+   if (argv0[0] == '/')
+#endif
+     {
+       _exe_path = strdup(argv0);
+       if (access(_exe_path, X_OK) == 0) return 1;
+       free(_exe_path);
+       _exe_path = NULL;
+       return 0;
+     }
+   /* 2. relative path */
+   if (strchr(argv0, '/'))
+     {
+       if (getcwd(buf3, sizeof(buf3)))
+         {
+            snprintf(buf2, sizeof(buf2), "%s/%s", buf3, argv0);
+            if (realpath(buf2, buf))
+              {
+                 _exe_path = strdup(buf);
+                 if (access(_exe_path, X_OK) == 0) return 1;
+                 free(_exe_path);
+                 _exe_path = NULL;
+              }
+         }
+     }
+   /* 3. argv0 no path - look in PATH */
+   path = getenv("PATH");
+   if (!path) return 0;
+   p = path;
+   cp = p;
+   lenexe = strlen(argv0);
+   while ((p = strchr(cp, ':')))
+     {
+       len = p - cp;
+       s = malloc(len + 1 + lenexe + 1);
+       if (s)
+         {
+            strncpy(s, cp, len);
+            s[len] = '/';
+            strcpy(s + len + 1, argv0);
+            if (realpath(s, buf))
+              {
+                 if (access(buf, X_OK) == 0)
+                   {
+                      _exe_path = strdup(buf);
+                      free(s);
+                      return 1;
+                   }
+              }
+            free(s);
+         }
+        cp = p + 1;
+     }
+   len = strlen(cp);
+   s = malloc(len + 1 + lenexe + 1);
+   if (s)
+     {
+       strncpy(s, cp, len);
+       s[len] = '/';
+       strcpy(s + len + 1, argv0);
+       if (realpath(s, buf))
+         {
+            if (access(buf, X_OK) == 0)
+              {
+                 _exe_path = strdup(buf);
+                 free(s);
+                 return 1;
+              }
+         }
+       free(s);
+     }
+   /* 4. big problems. arg[0] != executable - weird execution */
+   return 0;
+}
diff --git a/src/bin/edje_prefix.h b/src/bin/edje_prefix.h
new file mode 100644 (file)
index 0000000..4bea3f9
--- /dev/null
@@ -0,0 +1,11 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+int         e_prefix_determine(char *argv0);
+void        e_prefix_shutdown(void);
+void        e_prefix_fallback(void);
+const char *e_prefix_get(void);
+const char *e_prefix_bin_get(void);
+const char *e_prefix_data_get(void);
+const char *e_prefix_lib_get(void);
diff --git a/src/bin/edje_recc b/src/bin/edje_recc
new file mode 100644 (file)
index 0000000..2ae81ad
--- /dev/null
@@ -0,0 +1,69 @@
+#!/bin/sh
+
+set -e
+
+usage () {
+  echo "Usage:"
+  echo "        edje_recc [OPTIONS] input_file.edj"
+  echo ""
+  echo "Where OPTIONS is one or more of:"
+  echo ""
+  echo "-v                       Verbose output"
+  echo "-no-lossy                Do NOT allow images to be lossy"
+  echo "-no-comp                 Do NOT allow images to be lossless compression"
+  echo "-no-raw                  Do NOT allow images to be zero compression"
+  echo "-min-quality VAL         Do NOT allow lossy images with quality < VAL (0-100)"
+  echo "-max-quality VAL         Do NOT allow lossy images with quality > VAL (0-100)"
+  exit -1
+}
+
+if [ $# -lt 1 ]; then
+  usage
+fi
+
+OPT=""
+if [ $# -ge 1 ]; then
+  for I in $@; do
+    case "$I" in
+      -h)
+        usage
+      ;;
+
+      -help)
+        usage
+      ;;
+
+      --help)
+        usage
+      ;;
+
+      *.edj)
+        IN=$I
+      ;;
+
+      *)
+        OPT=$OPT" "$I
+      ;;
+    esac
+  done
+fi
+
+if [ -z "$IN" ]; then
+  echo "ERROR: NO input file.edj provided!"
+  echo ""
+  usage;
+fi
+
+F=`basename $IN`
+B=`basename $F .edj`
+T="./...edje_tmp"
+rm -rf $T
+mkdir -p $T
+cp $IN $T
+cd $T
+edje_decc $F
+cd $B
+./build.sh $OPT
+cd ../..
+mv $T/$B/$F $IN
+rm -rf $T
diff --git a/src/lib/.cvsignore b/src/lib/.cvsignore
new file mode 100644 (file)
index 0000000..09980ae
--- /dev/null
@@ -0,0 +1,6 @@
+.deps
+.libs
+Makefile
+Makefile.in
+*.lo
+*.la
diff --git a/src/lib/Edje.h b/src/lib/Edje.h
new file mode 100644 (file)
index 0000000..c44cc98
--- /dev/null
@@ -0,0 +1,263 @@
+#ifndef _EDJE_H
+#define _EDJE_H
+
+#include <Evas.h>
+
+#ifdef EAPI
+# undef EAPI
+#endif
+
+#ifdef _WIN32
+# ifdef EFL_EDJE_BUILD
+#  ifdef DLL_EXPORT
+#   define EAPI __declspec(dllexport)
+#  else
+#   define EAPI
+#  endif /* ! DLL_EXPORT */
+# else
+#  define EAPI __declspec(dllimport)
+# endif /* ! EFL_EDJE_BUILD */
+#else
+# ifdef __GNUC__
+#  if __GNUC__ >= 4
+#   define EAPI __attribute__ ((visibility("default")))
+#  else
+#   define EAPI
+#  endif
+# else
+#  define EAPI
+# endif
+#endif
+
+/* FIXDOC: Define these? */
+enum _Edje_Message_Type
+{
+   EDJE_MESSAGE_NONE = 0,
+
+     EDJE_MESSAGE_SIGNAL = 1, /* DONT USE THIS */
+
+     EDJE_MESSAGE_STRING = 2,
+     EDJE_MESSAGE_INT = 3,
+     EDJE_MESSAGE_FLOAT = 4,
+
+     EDJE_MESSAGE_STRING_SET = 5,
+     EDJE_MESSAGE_INT_SET = 6,
+     EDJE_MESSAGE_FLOAT_SET = 7,
+
+     EDJE_MESSAGE_STRING_INT = 8,
+     EDJE_MESSAGE_STRING_FLOAT = 9,
+
+     EDJE_MESSAGE_STRING_INT_SET = 10,
+     EDJE_MESSAGE_STRING_FLOAT_SET = 11
+};
+typedef enum _Edje_Message_Type Edje_Message_Type;
+
+enum _Edje_Aspect_Control
+{
+   EDJE_ASPECT_CONTROL_NONE = 0,
+   EDJE_ASPECT_CONTROL_NEITHER = 1,
+   EDJE_ASPECT_CONTROL_HORIZONTAL = 2,
+   EDJE_ASPECT_CONTROL_VERTICAL = 3,
+   EDJE_ASPECT_CONTROL_BOTH = 4
+};
+typedef enum _Edje_Aspect_Control Edje_Aspect_Control;
+
+typedef struct _Edje_Message_String           Edje_Message_String;
+typedef struct _Edje_Message_Int              Edje_Message_Int;
+typedef struct _Edje_Message_Float            Edje_Message_Float;
+typedef struct _Edje_Message_String_Set       Edje_Message_String_Set;
+typedef struct _Edje_Message_Int_Set          Edje_Message_Int_Set;
+typedef struct _Edje_Message_Float_Set        Edje_Message_Float_Set;
+typedef struct _Edje_Message_String_Int       Edje_Message_String_Int;
+typedef struct _Edje_Message_String_Float     Edje_Message_String_Float;
+typedef struct _Edje_Message_String_Int_Set   Edje_Message_String_Int_Set;
+typedef struct _Edje_Message_String_Float_Set Edje_Message_String_Float_Set;
+
+struct _Edje_Message_String
+{
+   char *str;
+};
+
+struct _Edje_Message_Int
+{
+   int val;
+};
+
+struct _Edje_Message_Float
+{
+   double val;
+};
+
+struct _Edje_Message_String_Set
+{
+   int count;
+   char *str[1];
+};
+
+struct _Edje_Message_Int_Set
+{
+   int count;
+   int val[1];
+};
+
+struct _Edje_Message_Float_Set
+{
+   int count;
+   double val[1];
+};
+
+struct _Edje_Message_String_Int
+{
+   char *str;
+   int val;
+};
+
+struct _Edje_Message_String_Float
+{
+   char *str;
+   double val;
+};
+
+struct _Edje_Message_String_Int_Set
+{
+   char *str;
+   int count;
+   int val[1];
+};
+
+struct _Edje_Message_String_Float_Set
+{
+   char *str;
+   int count;
+   double val[1];
+};
+
+enum
+{
+   EDJE_DRAG_DIR_NONE = 0,
+     EDJE_DRAG_DIR_X = 1,
+     EDJE_DRAG_DIR_Y = 2,
+     EDJE_DRAG_DIR_XY = 3
+};
+
+enum
+{
+   EDJE_LOAD_ERROR_NONE = 0,
+     EDJE_LOAD_ERROR_GENERIC = 1,
+     EDJE_LOAD_ERROR_DOES_NOT_EXIST = 2,
+     EDJE_LOAD_ERROR_PERMISSION_DENIED = 3,
+     EDJE_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED = 4,
+     EDJE_LOAD_ERROR_CORRUPT_FILE = 5,
+     EDJE_LOAD_ERROR_UNKNOWN_FORMAT = 6,
+     EDJE_LOAD_ERROR_INCOMPATIBLE_FILE = 7,
+     EDJE_LOAD_ERROR_UNKNOWN_COLLECTION = 8,
+     EDJE_LOAD_ERROR_RECURSIVE_REFERENCE = 9
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+   /* edje_main.c */
+   EAPI int          edje_init                       (void);
+   EAPI int          edje_shutdown                   (void);
+
+   /* edje_program.c */
+   EAPI void         edje_frametime_set              (double t);
+   EAPI double       edje_frametime_get              (void);
+
+   /* edje_util.c */
+   EAPI void         edje_freeze                     (void);
+   EAPI void         edje_thaw                       (void);
+   EAPI void         edje_fontset_append_set         (const char *fonts);
+   EAPI const char  *edje_fontset_append_get         (void);
+
+   /* edje_load.c */
+   EAPI Evas_List   *edje_file_collection_list       (const char *file);
+   EAPI void         edje_file_collection_list_free  (Evas_List *lst);
+   EAPI int          edje_file_group_exists          (const char *file, const char *glob);
+   EAPI char        *edje_file_data_get              (const char *file, const char *key);
+   EAPI void         edje_file_cache_set             (int count);
+   EAPI int          edje_file_cache_get             (void);
+   EAPI void         edje_file_cache_flush           (void);
+   EAPI void         edje_collection_cache_set       (int count);
+   EAPI int          edje_collection_cache_get       (void);
+   EAPI void         edje_collection_cache_flush     (void);
+
+
+   /* edje_util.c */
+   EAPI void         edje_color_class_set(const char *color_class, int r, int g, int b, int a, int r2, int g2, int b2, int a2, int r3, int g3, int b3, int a3);
+   EAPI void         edje_color_class_del(const char *color_class);
+   EAPI Evas_List *  edje_color_class_list(void);
+   EAPI void         edje_text_class_set(const char *text_class, const char *font, Evas_Font_Size size);
+   EAPI void         edje_text_class_del(const char *text_class);
+   EAPI Evas_List *  edje_text_class_list(void);
+   EAPI void         edje_extern_object_min_size_set (Evas_Object *obj, Evas_Coord minw, Evas_Coord minh);
+   EAPI void         edje_extern_object_max_size_set (Evas_Object *obj, Evas_Coord maxw, Evas_Coord maxh);
+   EAPI void         edje_extern_object_aspect_set(Evas_Object *obj, Edje_Aspect_Control aspect, Evas_Coord aw, Evas_Coord ah);
+
+   /* edje_smart.c */
+   EAPI Evas_Object *edje_object_add                 (Evas *evas);
+
+   /* edje_util.c */
+   EAPI const char  *edje_object_data_get            (const Evas_Object *obj, const char *key);
+
+   /* edje_load.c */
+   EAPI int          edje_object_file_set            (Evas_Object *obj, const char *file, const char *group);
+   EAPI void         edje_object_file_get            (const Evas_Object *obj, const char **file, const char **group);
+   EAPI int          edje_object_load_error_get      (const Evas_Object *obj);
+
+   /* edje_program.c */
+   EAPI void         edje_object_signal_callback_add (Evas_Object *obj, const char *emission, const char *source, void (*func) (void *data, Evas_Object *obj, const char *emission, const char *source), void *data);
+   EAPI void        *edje_object_signal_callback_del (Evas_Object *obj, const char *emission, const char *source, void (*func) (void *data, Evas_Object *obj, const char *emission, const char *source));
+   EAPI void         edje_object_signal_emit         (Evas_Object *obj, const char *emission, const char *source);
+   EAPI void         edje_object_play_set            (Evas_Object *obj, int play);
+   EAPI int          edje_object_play_get            (const Evas_Object *obj);
+   EAPI void         edje_object_animation_set       (Evas_Object *obj, int on);
+   EAPI int          edje_object_animation_get       (const Evas_Object *obj);
+
+   /* edje_util.c */
+   EAPI int          edje_object_freeze              (Evas_Object *obj);
+   EAPI int          edje_object_thaw                (Evas_Object *obj);
+   EAPI void         edje_object_color_class_set     (Evas_Object *obj, const char *color_class, int r, int g, int b, int a, int r2, int g2, int b2, int a2, int r3, int g3, int b3, int a3);
+   EAPI void         edje_object_color_class_del     (Evas_Object *obj, const char *color_class);
+   EAPI void         edje_object_text_class_set      (Evas_Object *obj, const char *text_class, const char *font, Evas_Font_Size size);
+   EAPI void         edje_object_size_min_get        (const Evas_Object *obj, Evas_Coord *minw, Evas_Coord *minh);
+   EAPI void         edje_object_size_max_get        (const Evas_Object *obj, Evas_Coord *maxw, Evas_Coord *maxh);
+   EAPI void         edje_object_calc_force          (Evas_Object *obj);
+   EAPI void         edje_object_size_min_calc       (Evas_Object *obj, Evas_Coord *minw, Evas_Coord *minh);
+   EAPI void         edje_object_size_min_restricted_calc(Evas_Object *obj, Evas_Coord *minw, Evas_Coord *minh, Evas_Coord restrictedw, Evas_Coord restrictedh);
+   EAPI int          edje_object_part_exists         (const Evas_Object *obj, const char *part);
+   EAPI const Evas_Object *edje_object_part_object_get     (const Evas_Object *obj, const char *part);
+   EAPI void         edje_object_part_geometry_get   (const Evas_Object *obj, const char *part, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h);
+   EAPI void         edje_object_text_change_cb_set  (Evas_Object *obj, void (*func) (void *data, Evas_Object *obj, const char *part), void *data);
+   EAPI void         edje_object_part_text_set       (Evas_Object *obj, const char *part, const char *text);
+   EAPI const char  *edje_object_part_text_get       (const Evas_Object *obj, const char *part);
+   EAPI void         edje_object_part_swallow        (Evas_Object *obj, const char *part, Evas_Object *obj_swallow);
+   EAPI void         edje_object_part_unswallow      (Evas_Object *obj, Evas_Object *obj_swallow);
+   EAPI Evas_Object *edje_object_part_swallow_get    (const Evas_Object *obj, const char *part);
+   EAPI const char  *edje_object_part_state_get      (const Evas_Object *obj, const char *part, double *val_ret);
+   EAPI int          edje_object_part_drag_dir_get   (const Evas_Object *obj, const char *part);
+   EAPI void         edje_object_part_drag_value_set (Evas_Object *obj, const char *part, double dx, double dy);
+   EAPI void         edje_object_part_drag_value_get (const Evas_Object *obj, const char *part, double *dx, double *dy);
+   EAPI void         edje_object_part_drag_size_set  (Evas_Object *obj, const char *part, double dw, double dh);
+   EAPI void         edje_object_part_drag_size_get  (const Evas_Object *obj, const char *part, double *dw, double *dh);
+   EAPI void         edje_object_part_drag_step_set  (Evas_Object *obj, const char *part, double dx, double dy);
+   EAPI void         edje_object_part_drag_step_get  (const Evas_Object *obj, const char *part, double *dx, double *dy);
+   EAPI void         edje_object_part_drag_page_set  (Evas_Object *obj, const char *part, double dx, double dy);
+   EAPI void         edje_object_part_drag_page_get  (const Evas_Object *obj, const char *part, double *dx, double *dy);
+   EAPI void         edje_object_part_drag_step      (Evas_Object *obj, const char *part, double dx, double dy);
+   EAPI void         edje_object_part_drag_page      (Evas_Object *obj, const char *part, double dx, double dy);
+
+   /* edje_message_queue.c */
+   EAPI void         edje_object_message_send           (Evas_Object *obj, Edje_Message_Type type, int id, void *msg);
+   EAPI void         edje_object_message_handler_set    (Evas_Object *obj, void (*func) (void *data, Evas_Object *obj, Edje_Message_Type type, int id, void *msg), void *data);
+   EAPI void         edje_object_message_signal_process (Evas_Object *obj);
+
+   EAPI void         edje_message_signal_process        (void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/lib/Edje_Edit.h b/src/lib/Edje_Edit.h
new file mode 100644 (file)
index 0000000..3c72dbd
--- /dev/null
@@ -0,0 +1,1828 @@
+#ifndef _EDJE_EDIT_H
+#define _EDJE_EDIT_H
+
+#include <Evas.h>
+
+#ifdef EAPI
+# undef EAPI
+#endif
+
+#ifdef _WIN32
+# ifdef EFL_EDJE_BUILD
+#  ifdef DLL_EXPORT
+#   define EAPI __declspec(dllexport)
+#  else
+#   define EAPI
+#  endif /* ! DLL_EXPORT */
+# else
+#  define EAPI __declspec(dllimport)
+# endif /* ! EFL_EDJE_BUILD */
+#else
+# ifdef __GNUC__
+#  if __GNUC__ >= 4
+#   define EAPI __attribute__ ((visibility("default")))
+#  else
+#   define EAPI
+#  endif
+# else
+#  define EAPI
+# endif
+#endif
+
+
+enum {
+   EDJE_EDIT_IMAGE_COMP_RAW,
+   EDJE_EDIT_IMAGE_COMP_USER,
+   EDJE_EDIT_IMAGE_COMP_COMP,
+   EDJE_EDIT_IMAGE_COMP_LOSSY
+};
+
+/**
+ * @file
+ * @brief Functions to deal with edje internal object. Don't use in standard
+ * situations. The use of any of the edje_edit_* functions can break your
+ * theme ability, remember that the program must be separated from the interface!
+ *
+ * The API can be used to query or set every part of an edje object in real time.
+ * You can manage every aspect of parts, part states, programs, script and whatever
+ * is contained in the edje file. For a reference of what all parameter means
+ * look at the complete @ref edcref.
+ *
+ * All the functions that deals with part states include the state value inside
+ * the returned strings (ex: "defaut 0.00"). For this reason there aren't
+ * functions to set/get a state value, you have to pass the value inside the
+ * name string (always in the form "state x.xx").
+ *
+ * Don't forget to free all the strings and the lists returned by any edje_edit_*()
+ * functions using edje_edit_string_free() and edje_edit_string_list_free() when
+ * you don't need anymore.
+ *
+ * Example: print all the part in a loaded edje_object
+ * @code
+ *  Evas_List *parts, *l;
+ *
+ *  parts = edje_edit_parts_list_get(edje_object);
+ *  while(l = parts; l; l = l->next)
+ *  {
+ *     printf("Part: %s\n", (char*)l->data);
+ *  }
+ *  edje_edit_string_list_free(parts);
+ * @endcode
+ *
+ * Example: Change the color of a rect inside an edje file
+ * @code
+ * Evas_Object *edje;
+ *
+ * edje = edje_object_add(evas);
+ * edje_object_file_set(edje,"edj/file/name", "group to load");
+ * edje_edit_state_color_set(edje, "MyRectName", "default 0.00", 255, 255, 0, 255);
+ * edje_edit_save(edje);
+ * @endcode
+ *
+*/
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/******************************************************************************/
+/**************************   GENERAL API   ***********************************/
+/******************************************************************************/
+/** @name General API
+ *  General functions that don't fit in other cateories.
+ */ //@{
+
+/** Free a generic Evas_List of (char *) allocated by an edje_edit_*_get() function.*/
+EAPI void
+edje_edit_string_list_free(
+   Evas_List *lst          ///< The list to free. Will also free all the strings.
+);
+
+/** Free a generic string (char *) allocated by an edje_edit_*_get() function.*/
+EAPI void
+edje_edit_string_free(
+   const char *str         ///< The string to free.
+);
+
+/**Save the modified edje object back to his file.
+ * Use this function when you are done with your editing, all the change made
+ * to the current loaded group will be saved back to the original file.
+ *
+ * NOTE: for now this as 2 limitations
+ *    -the saved edje file cannot be decompiled anymore
+ *    -you will lost your #define in the edc source
+ */
+EAPI int                   ///@return 1 on success, 0 on failure
+edje_edit_save(
+   Evas_Object *obj        ///< The edje object to save
+);
+
+/**Print on standard output many information about the internal status
+ * of the edje object.
+ * This is probably only usefull to debug.
+ */
+EAPI void
+edje_edit_print_internal_status(
+   Evas_Object *obj        ///< The edje object to inspect
+);
+
+//@}
+/******************************************************************************/
+/**************************   GROUPS API   ************************************/
+/******************************************************************************/
+/** @name Groups API
+ *  Functions to deal with groups property (see @ref edcref).
+ */ //@{
+
+/**Create a new empty group in the given edje.
+ * If a group with the same name exist none is created.
+ */
+EAPI unsigned char         ///@return 1 on success, 0 on failure
+edje_edit_group_add(
+   Evas_Object *obj,       ///< The edje object
+   const char  *name       ///< The name for the new empty group
+);
+
+/**Delete the current group from the given edje.
+ * You can only delete the currently loaded group.
+ * All the parts and the programs inside the group will be deleted as well,
+ * but not image or font embedded in the edje.
+ */
+EAPI unsigned char         ///@return 1 on success, 0 on failure
+edje_edit_group_del(
+   Evas_Object *obj        ///< The edje object
+);
+
+/**Check if a group with the given name exist in the edje.
+ */
+EAPI unsigned char         ///< 1 if the group exist, 0 otherwise.
+edje_edit_group_exist(
+   Evas_Object *obj,       ///< The edje object
+   const char *group       ///< The name of the group
+);
+
+/**Set a new name for the current open group.
+ * You can only rename a group that is currently loaded
+ * Note that the relative getter function don't exist as it don't make sense ;)
+ */
+EAPI unsigned char         ///@return 1 on success, 0 on failure
+edje_edit_group_name_set(
+   Evas_Object *obj,       ///< The edje object
+   const char  *new_name   ///< The new name for the group
+);
+/**Get the group min width*/
+EAPI int                  ///@return The minw value or -1 on errors
+edje_edit_group_min_w_get(
+   Evas_Object *obj       ///< The edje object
+);
+/**Set the group min width*/
+EAPI void
+edje_edit_group_min_w_set(
+   Evas_Object *obj,       ///< The edje object
+   int w                   ///< The new group minimum width in pixel
+);
+/**Get the group min height*/
+EAPI int                  ///@return The minh value or -1 on errors
+edje_edit_group_min_h_get(
+   Evas_Object *obj       ///< The edje object
+);
+/**Set the group min height*/
+EAPI void
+edje_edit_group_min_h_set(
+   Evas_Object *obj,       ///< The edje object
+   int h                   ///< The new group minimum height in pixel
+);
+/**Get the group max width*/
+EAPI int                  ///@return The maxw value or -1 on errors
+edje_edit_group_max_w_get(
+   Evas_Object *obj       ///< The edje object
+);
+/**Set the group max width*/
+EAPI void
+edje_edit_group_max_w_set(
+   Evas_Object *obj,       ///< The edje object
+   int w                   ///< The new group maximum width in pixel
+);
+/**Get the group max height*/
+EAPI int                  ///@return The maxh value or -1 on errors
+edje_edit_group_max_h_get(
+   Evas_Object *obj       ///< The edje object
+);
+/**Set the group max height*/
+EAPI void
+edje_edit_group_max_h_set(
+   Evas_Object *obj,       ///< The edje object
+   int h                   ///< The new group maximum height in pixel
+);
+
+//@}
+/******************************************************************************/
+/**************************   PARTS API   *************************************/
+/******************************************************************************/
+/** @name Parts API
+ *  Functions to deal with part objects (see @ref edcref).
+ */ //@{
+
+/**Get the list of all the parts in the given edje object.
+ * Use edje_edit_string_list_free() when you don't need it anymore.
+ */
+EAPI Evas_List *           ///@return An Evas_List* of string (char *)containing all the part names.
+edje_edit_parts_list_get(
+   Evas_Object *obj        ///< The edje object
+);
+
+/**Create a new part in the given edje
+ * If another part with the same name just exists nothing is created and FALSE is returned.
+ * Note that this function also create a default description for the part.
+ */
+EAPI unsigned char         ///@return TRUE on success, FALSE if the part can't be created
+edje_edit_part_add(
+   Evas_Object *obj,       ///< The edje object
+   const char *name,       ///< The name for the new part
+   unsigned char type      ///< The type of the part to create (One of: EDJE_PART_TYPE_NONE, EDJE_PART_TYPE_RECTANGLE, EDJE_PART_TYPE_TEXT,EDJE_PART_TYPE_IMAGE, EDJE_PART_TYPE_SWALLOW, EDJE_PART_TYPE_TEXTBLOCK,EDJE_PART_TYPE_GRADIENT or EDJE_PART_TYPE_GROUP)
+);
+
+/**Delete the given part from the edje
+ * All the reference to this part will be zeroed.
+ * A group must have at least one part, so it's not possible to
+ * remove the last remaining part.
+ */
+EAPI unsigned char         ///@return 1 on success, 0 if the part can't be removed
+edje_edit_part_del(
+   Evas_Object *obj,       ///< The edje object
+   const char *part        ///< The name of the part to remove
+);
+
+/**Check if a part with the given name exist in the edje object.
+ */
+EAPI unsigned char         ///< 1 if the part exist, 0 otherwise.
+edje_edit_part_exist(
+   Evas_Object *obj,       ///< The edje object
+   const char *part        ///< The name of the part
+);
+
+/**Move the given part below the previous one.*/
+EAPI unsigned char         ///@return 1 on success, 0 on failure
+edje_edit_part_restack_below(
+   Evas_Object *obj,       ///< The edje object
+   const char *part        ///< The name of the part to restack
+);
+
+/**Move the given part above the next one.*/
+EAPI unsigned char         ///@return 1 on success, 0 on failure
+edje_edit_part_restack_above(
+   Evas_Object *obj,       ///< The edje object
+   const char *part        ///< The name of the part to restack
+);
+
+/**Set a new name for part.
+ * Note that the relative getter function don't exist as it don't make sense ;)
+ */
+EAPI unsigned char         ///@return 1 on success, 0 on failure
+edje_edit_part_name_set(
+   Evas_Object *obj,       ///< The edje object
+   const char  *part,      ///< The name of the part to rename
+   const char  *new_name   ///< The new name for the part
+);
+
+/**Get the type of a part */
+EAPI unsigned char         ///@return One of: EDJE_PART_TYPE_NONE, EDJE_PART_TYPE_RECTANGLE, EDJE_PART_TYPE_TEXT,EDJE_PART_TYPE_IMAGE, EDJE_PART_TYPE_SWALLOW, EDJE_PART_TYPE_TEXTBLOCK,EDJE_PART_TYPE_GRADIENT or EDJE_PART_TYPE_GROUP
+edje_edit_part_type_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *part        ///< The name of the part
+);
+
+/**Get the clip_to part.
+ * NULL is returned on errors and if the part don't have a clip.
+ */
+EAPI const char *          ///@return The name of the part to clip part to. Use edje_edit_string_free() when you don't need it anymore.
+edje_edit_part_clip_to_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *part        ///< The name of the part
+);
+
+/**Set a part to clip part to.
+ * If clip_to is NULL then the clipping value will be cancelled (unset clipping)
+ */
+EAPI unsigned char         ///@return 1 on success, 0 otherwise.
+edje_edit_part_clip_to_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *clip_to     ///< The name of the part to clip part to.
+);
+
+/**Get the source of part.
+ * Source is used in part of type EDJE_PART_TYPE_GROUP to specify the group to
+ * 'autoswallow' inside the given part.
+ */
+EAPI const char *          ///@return The name of the group to source the given part. Use edje_edit_string_free() when you don't need it anymore.
+edje_edit_part_source_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *part        ///< The name of the part
+);
+
+/**Set the source of part.
+ * Source is used in part of type EDJE_PART_TYPE_GROUP to specify the group to
+ * 'autoswallow' inside the given part.
+ * NOTE: This is not applied now. You must reload the edje to see the change.
+ */
+EAPI unsigned char         ///@return 1 on success, 0 otherwise.
+edje_edit_part_source_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *source      ///< The name of the group to autoswallow in the given part
+);
+
+/**Get the effect for a given part. */
+EAPI unsigned char         ///@return One of: EDJE_TEXT_EFFECT_NONE, _PLAIN, _OUTLINE, _SOFT_OUTLINE, _SHADOW, _SOFT_SHADOW, _OUTLINE_SHADOW, _OUTLINE_SOFT_SHADOW, _FAR_SHADOW, _FAR_SOFT_SHADOW, _GLOW.
+edje_edit_part_effect_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *part        ///< The name of the part
+);
+
+/**Set the effect for a given part. */
+EAPI void
+edje_edit_part_effect_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   unsigned char effect    ///< The effect to set. See edje_edit_part_effect_get() for possible value
+);
+
+/**Get the current selected state in part. */
+EAPI const char *          ///@return The name of the selected state including the float value. Use edje_edit_string_free() when you don't need it anymore.
+edje_edit_part_selected_state_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *part        ///< The name of the part
+);
+
+/**Set the current state in part.*/
+EAPI unsigned char         ///@return 1 on success, 0 otherwise.
+edje_edit_part_selected_state_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state       ///< The name of the state to set (including the float value)
+);
+
+/**Get mouse_events for part.*/
+EAPI unsigned char         ///@return 1 if part accept mouse events, 0 if not
+edje_edit_part_mouse_events_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *part        ///< The name of the part
+);
+
+/**Set mouse_events for part.*/
+EAPI void
+edje_edit_part_mouse_events_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   unsigned char mouse_events ///< If set to 1 part will accept mouse events, 0 to ignore all mouse events from part.
+);
+
+/**Get repeat_events for part.*/
+EAPI unsigned char         ///@return 1 if part will pass all events to the other parts, 0 if not
+edje_edit_part_repeat_events_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *part        ///< The name of the part
+);
+
+/**Set repeat_events for part. */
+EAPI void
+edje_edit_part_repeat_events_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   unsigned char repeat_events /**< If set to 1 part will repeat
+                                 * all the received mouse events to other parts.
+                                 * If set to 0 the events received will not propagate to other parts.*/
+);
+
+/**Get ignore_flags for part.*/
+EAPI Evas_Event_Flags        ///@return event flags ignored
+edje_edit_part_ignore_flags_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *part        ///< The name of the part
+);
+
+/**Set repeat_events for part. */
+EAPI void
+edje_edit_part_ignore_flags_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   Evas_Event_Flags ignore_flags ///< event flags to be ignored
+);
+
+
+//@}
+/******************************************************************************/
+/**************************   STATES API   ************************************/
+/******************************************************************************/
+/** @name States API
+ *  Functions to deal with part states (see @ref edcref).
+ */ //@{
+
+/**Get the list of all the states in the given part.*/
+EAPI Evas_List *           /**@return An Evas_List* of string (char *)containing all the states names found
+                            * in part, including the float value (ex: "default 0.00").
+                            * Use edje_edit_string_list_free() when you don't need it anymore. */
+edje_edit_part_states_list_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *part        ///< The name of the part
+);
+
+/**Set a new name for the given state in the given part.
+ * Note that state and new_name must include the floating value inside the string (ex. "default 0.00")
+ */
+EAPI int
+edje_edit_state_name_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part that contain state
+   const char *state,      ///< The current name of the state
+   const char *new_name    ///< The new name to assign (including the value)
+);
+
+/**Create a new state to the give part
+ */
+EAPI void
+edje_edit_state_add(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *name        ///< The name for the new state (not including the state value)
+);
+
+/**Delete the given part state from the edje
+ */
+EAPI void
+edje_edit_state_del(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part that contain state
+   const char *state       ///< The current name of the state (including the state value)
+);
+
+/**Check if a part state with the given name exist.
+ */
+EAPI unsigned char         ///< 1 if the part state exist, 0 otherwise.
+edje_edit_state_exist(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state       ///< The name of the state to check (including the state value)
+);
+
+/**Get the rel1 relative x value of state*/
+EAPI double                ///@return The 'rel1 relative X' value of the part state
+edje_edit_state_rel1_relative_x_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state       ///< The name of the part state (ex. "default 0.00")
+);
+/**Get the rel1 relative y value of state*/
+EAPI double                ///@return The 'rel1 relative Y' value of the part state
+edje_edit_state_rel1_relative_y_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state       ///< The name of the 'part state' (ex. "default 0.00")
+);
+/**Get the rel2 relative x value of state*/
+EAPI double                ///@return The 'rel2 relative X' value of the part state
+edje_edit_state_rel2_relative_x_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state       ///< The name of the 'part state' (ex. "default 0.00")
+);
+/**Get the rel2 relative y value of state*/
+EAPI double                ///@return The 'rel2 relative Y' value of the part state
+edje_edit_state_rel2_relative_y_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state       ///< The name of the 'part state' (ex. "default 0.00")
+);
+
+/**Set the rel1 relative x value of state*/
+EAPI void
+edje_edit_state_rel1_relative_x_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state,      ///< The name of the 'part state' (ex. "default 0.00")
+   double x                ///< The new 'rel1 relative X' value to set
+);
+/**Set the rel1 relative y value of state*/
+EAPI void
+edje_edit_state_rel1_relative_y_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state,      ///< The name of the 'part state' (ex. "default 0.00")
+   double y                ///< The new 'rel1 relative Y' value to set
+);
+/**Set the rel2 relative x value of state*/
+EAPI void
+edje_edit_state_rel2_relative_x_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state,      ///< The name of the 'part state' (ex. "default 0.00")
+   double x                ///< The new 'rel2 relative X' value to set
+);
+/**Set the rel2 relative y value of state*/
+EAPI void
+edje_edit_state_rel2_relative_y_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state,      ///< The name of the 'part state' (ex. "default 0.00")
+   double y                ///< The new 'rel2 relative Y' value to set
+);
+
+/**Get the rel1 offset x value of state*/
+EAPI int                   /// @return The 'rel1 offset X' value of the part state
+edje_edit_state_rel1_offset_x_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state       ///< The name of the 'part state' (ex. "default 0.00")
+);
+/**Get the rel1 offset y value of state*/
+EAPI int                   /// @return The 'rel1 offset Y' value of the part state
+edje_edit_state_rel1_offset_y_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state       ///< The name of the 'part state' (ex. "default 0.00")
+);
+/**Get the rel2 offset x value of state*/
+EAPI int                   /// @return The 'rel2 offset X' value of the part state
+edje_edit_state_rel2_offset_x_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state       ///< The name of the 'part state' (ex. "default 0.00")
+);
+/**Get the rel2 offset y value of state*/
+EAPI int                   /// @return The 'rel2 offset Y' value of the part state
+edje_edit_state_rel2_offset_y_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state       ///< The name of the 'part state' (ex. "default 0.00")
+);
+
+/**Set the rel1 offset x value of state*/
+EAPI void
+edje_edit_state_rel1_offset_x_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state,      ///< The name of the 'part state' (ex. "default 0.00")
+   double x                ///< The new 'rel1 offset X' value to set
+);
+/**Get the rel1 offset y value of state*/
+EAPI void
+edje_edit_state_rel1_offset_y_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state,      ///< The name of the 'part state' (ex. "default 0.00")
+   double y                ///< The new 'rel1 offset Y' value to set
+);
+/**Get the rel2 offset x value of state*/
+EAPI void
+edje_edit_state_rel2_offset_x_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state,      ///< The name of the 'part state' (ex. "default 0.00")
+   double x                ///< The new 'rel2 offset X' value to set
+);
+/**Get the rel2 offset y value of state*/
+EAPI void
+edje_edit_state_rel2_offset_y_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state,      ///< The name of the 'part state' (ex. "default 0.00")
+   double y                ///< The new 'rel2 offset Y' value to set
+);
+
+/**Get the part name rel1x is relative to. The function return NULL if the part is relative to the whole interface.*/
+EAPI const char *          ///@return The name of the part to apply the relativity
+edje_edit_state_rel1_to_x_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state       ///< The name of the 'part state' (ex. "default 0.00")
+);
+/**Get the part name rel1y is relative to. The function return NULL if the part is relative to the whole interface.*/
+EAPI const char *          ///@return The name of the part to apply the relativity
+edje_edit_state_rel1_to_y_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state       ///< The name of the 'part state' (ex. "default 0.00")
+);
+/**Get the part name rel2x is relative to. The function return NULL if the part is relative to the whole interface.*/
+EAPI const char *         ///@return The name of the part to apply the relativity
+edje_edit_state_rel2_to_x_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state       ///< The name of the 'part state' (ex. "default 0.00")
+);
+/**Get the part name rel2y is relative to. The function return NULL if the part is relative to the whole interface.*/
+EAPI const char *         ///@return The name of the part to apply the relativity
+edje_edit_state_rel2_to_y_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state       ///< The name of the 'part state' (ex. "default 0.00")
+);
+
+/**Set the part rel1x is relative to. Set rel_to to NULL make the part relative to the whole interface.*/
+EAPI void
+edje_edit_state_rel1_to_x_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state,      ///< The name of the 'part state' (ex. "default 0.00")
+   const char *rel_to      ///< The name of the part that is used as container/parent
+);
+/**Set the part rel1y is relative to. Set rel_to to NULL make the part relative to the whole interface.*/
+EAPI void
+edje_edit_state_rel1_to_y_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state,      ///< The name of the 'part state' (ex. "default 0.00")
+   const char *rel_to      ///< The name of the part that is used as container/parent
+);
+/**Set the part rel2x is relative to. Set rel_to to NULL make the part relative to the whole interface.*/
+EAPI void
+edje_edit_state_rel2_to_x_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state,      ///< The name of the 'part state' (ex. "default 0.00")
+   const char *rel_to      ///< The name of the part that is used as container/parent
+);
+/**Set the part rel2y is relative to. Set rel_to to NULL make the part relative to the whole interface.*/
+EAPI void
+edje_edit_state_rel2_to_y_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state,      ///< The name of the 'part state' (ex. "default 0.00")
+   const char *rel_to      ///< The name of the part that is used as container/parent
+);
+
+/**Get the color of a part state. Pass NULL to any of [r,g,b,a] to get only the others.*/
+EAPI void
+edje_edit_state_color_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state,      ///< The name of the 'part state' (ex. "default 0.00")
+   int *r,                 ///< A pointer to store the red value
+   int *g,                 ///< A pointer to store the green value
+   int *b,                 ///< A pointer to store the blue value
+   int *a                  ///< A pointer to store the alpha value
+);
+/**Get the color2 of a part state. Pass NULL to any of [r,g,b,a] to get only the others.*/
+EAPI void
+edje_edit_state_color2_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state,      ///< The name of the 'part state' (ex. "default 0.00")
+   int *r,                 ///< A pointer to store the red value
+   int *g,                 ///< A pointer to store the green value
+   int *b,                 ///< A pointer to store the blue value
+   int *a                  ///< A pointer to store the alpha value
+);
+/**Get the color3 of a part state. Pass NULL to any of [r,g,b,a] to get only the others.*/
+EAPI void
+edje_edit_state_color3_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state,      ///< The name of the 'part state' (ex. "default 0.00")
+   int *r,                 ///< A pointer to store the red value
+   int *g,                 ///< A pointer to store the green value
+   int *b,                 ///< A pointer to store the blue value
+   int *a                  ///< A pointer to store the alpha value
+);
+
+/**Set the color of a part state. Pass -1 to any of [r,g,b,a] to leave the value untouched.*/
+EAPI void
+edje_edit_state_color_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state,      ///< The name of the 'part state' (ex. "default 0.00")
+   int r,                  ///< The red value of the color
+   int g,                  ///< The green value of the color
+   int b,                  ///< The blue value of the color
+   int a                   ///< The alpha value of the color
+);
+/**Set the color2 of a part state. Pass -1 to any of [r,g,b,a] to leave the value untouched.*/
+EAPI void
+edje_edit_state_color2_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state,      ///< The name of the 'part state' (ex. "default 0.00")
+   int r,                  ///< The red value of the color
+   int g,                  ///< The green value of the color
+   int b,                  ///< The blue value of the color
+   int a                   ///< The alpha value of the color
+);
+/**Set the color3 of a part state. Pass -1 to any of [r,g,b,a] to leave the value untouched.*/
+EAPI void
+edje_edit_state_color3_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state,      ///< The name of the 'part state' (ex. "default 0.00")
+   int r,                  ///< The red value of the color
+   int g,                  ///< The green value of the color
+   int b,                  ///< The blue value of the color
+   int a                   ///< The alpha value of the color
+);
+
+/**Get the align_x value of a part state.*/
+EAPI double                ///@return The horizontal align value for the given state
+edje_edit_state_align_x_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state       ///< The name of the 'part state' (ex. "default 0.00")
+);
+/**Get the align_y value of a part state.*/
+EAPI double                ///@return The vertical align value for the given state
+edje_edit_state_align_y_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state       ///< The name of the 'part state' (ex. "default 0.00")
+);
+/**Set the align_x value of a part state.*/
+EAPI void
+edje_edit_state_align_x_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state,      ///< The name of the 'part state' (ex. "default 0.00")
+   double align            ///< The new horizontal align to set
+);
+/**Set the align_y value of a part state.*/
+EAPI void
+edje_edit_state_align_y_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state,      ///< The name of the 'part state' (ex. "default 0.00")
+   double align            ///< The new vertical align to set
+);
+/**Get the min_w value of a part state.*/
+EAPI int                   ///@return The minimum width of a part state
+edje_edit_state_min_w_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state       ///< The name of the 'part state' (ex. "default 0.00")
+);
+/**Set the min_w value of a part state.*/
+EAPI void
+edje_edit_state_min_w_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state,      ///< The name of the 'part state' (ex. "default 0.00")
+   int min_w               ///< The new minimum width to set for the part state
+);
+/**Get the min_h value of a part state.*/
+EAPI int                   ///@return The minimum height of a part state
+edje_edit_state_min_h_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state       ///< The name of the 'part state' (ex. "default 0.00")
+);
+/**Set the min_h value of a part state.*/
+EAPI void
+edje_edit_state_min_h_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state,      ///< The name of the 'part state' (ex. "default 0.00")
+   int min_h               ///< The new minimum height to set for the part state
+);
+
+/**Get the max_w value of a part state.*/
+EAPI int                   ///@return The maximum width of a part state
+edje_edit_state_max_w_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state       ///< The name of the 'part state' (ex. "default 0.00")
+);
+/**Set the max_w value of a part state.*/
+EAPI void
+edje_edit_state_max_w_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state,      ///< The name of the 'part state' (ex. "default 0.00")
+   int max_w               ///< The new maximum width to set for the part state
+);
+/**Get the max_h value of a part state.*/
+EAPI int                   ///@return The maximum height of a part state
+edje_edit_state_max_h_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state       ///< The name of the 'part state' (ex. "default 0.00")
+);
+/**Set the max_h value of a part state.*/
+EAPI void
+edje_edit_state_max_h_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state,      ///< The name of the 'part state' (ex. "default 0.00")
+   int max_h               ///< The new maximum height to set for the part state
+);
+
+/**Get the minimum aspect value of a part state.*/
+EAPI double                ///@return The aspect minimum value of a part state
+edje_edit_state_aspect_min_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state       ///< The name of the 'part state' (ex. "default 0.00")
+);
+/**Get the maximum aspect value of a part state.*/
+EAPI double                ///@return The aspect maximum value of a part state
+edje_edit_state_aspect_max_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state       ///< The name of the 'part state' (ex. "default 0.00")
+);
+/**Set the minimum aspect value of a part state.*/
+EAPI void
+edje_edit_state_aspect_min_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state,      ///< The name of the 'part state' (ex. "default 0.00")
+   double aspect           ///< The new minimum aspect value to set
+);
+/**Set the maximum aspect value of a part state.*/
+EAPI void
+edje_edit_state_aspect_max_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state,      ///< The name of the 'part state' (ex. "default 0.00")
+   double aspect           ///< The new maximum aspect value to set
+);
+/**Get the aspect preference value of a part state.*/
+EAPI unsigned char         ///@return The aspect preference (0=none, 1=vertical, 2=horizontal, 3=both)
+edje_edit_state_aspect_pref_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state       ///< The name of the 'part state' (ex. "default 0.00")
+);
+/**Set the aspect preference value of a part state.*/
+EAPI void
+edje_edit_state_aspect_pref_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state,      ///< The name of the 'part state' (ex. "default 0.00")
+   unsigned char pref      ///< The new aspect preference to set (0=none, 1=vertical, 2=horizontal, 3=both)
+);
+
+/**Get the fill origin relative x value of a part state.*/
+EAPI double                ///@return The fill offset x relative to area
+edje_edit_state_fill_origin_relative_x_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state       ///< The name of the 'part state' (ex. "default 0.00")
+);
+
+/**Get the fill origin relative y value of a part state.*/
+EAPI double                ///@return The fill origin y relative to area
+edje_edit_state_fill_origin_relative_y_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state       ///< The name of the 'part state' (ex. "default 0.00")
+);
+
+/**Get the fill origin offset x value of a part state.*/
+EAPI int                   ///@return The fill origin offset x relative to area
+edje_edit_state_fill_origin_offset_x_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state       ///< The name of the 'part state' (ex. "default 0.00")
+);
+
+/**Get the fill origin offset y value of a part state.*/
+EAPI int                   ///@return The fill origin offset y relative to area
+edje_edit_state_fill_origin_offset_y_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state       ///< The name of the 'part state' (ex. "default 0.00")
+);
+
+/**Set the fill origin relative x value of a part state.*/
+EAPI void
+edje_edit_state_fill_origin_relative_x_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state,      ///< The name of the 'part state' (ex. "default 0.00")
+   double x                ///< The new value to set
+);
+
+/**Set the fill origin relative y value of a part state.*/
+EAPI void
+edje_edit_state_fill_origin_relative_y_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state,      ///< The name of the 'part state' (ex. "default 0.00")
+   double x                ///< The new value to set
+);
+
+/**Set the fill origin offset x value of a part state.*/
+EAPI void
+edje_edit_state_fill_origin_offset_x_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state,      ///< The name of the 'part state' (ex. "default 0.00")
+   double x                ///< The new value to set
+);
+
+/**Set the fill origin offset x value of a part state.*/
+EAPI void
+edje_edit_state_fill_origin_offset_y_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state,      ///< The name of the 'part state' (ex. "default 0.00")
+   double y                ///< The new value to set
+);
+
+/**Get the fill size relative x value of a part state.*/
+EAPI double                ///@return The fill size offset x relative to area
+edje_edit_state_fill_size_relative_x_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state       ///< The name of the 'part state' (ex. "default 0.00")
+);
+
+/**Get the fill size relative y value of a part state.*/
+EAPI double                ///@return The fill size y relative to area
+edje_edit_state_fill_size_relative_y_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state       ///< The name of the 'part state' (ex. "default 0.00")
+);
+
+/**Get the fill size offset x value of a part state.*/
+EAPI int                    ///@return The fill size offset x relative to area
+edje_edit_state_fill_size_offset_x_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state       ///< The name of the 'part state' (ex. "default 0.00")
+);
+
+/**Get the fill size offset y value of a part state.*/
+EAPI int                    ///@return The fill size offset y relative to area
+edje_edit_state_fill_size_offset_y_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state       ///< The name of the 'part state' (ex. "default 0.00")
+);
+
+/**Set the fill size relative x value of a part state.*/
+EAPI void
+edje_edit_state_fill_size_relative_x_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state,      ///< The name of the 'part state' (ex. "default 0.00")
+   double x                ///< The new value to set
+);
+
+/**Set the fill size relative y value of a part state.*/
+EAPI void
+edje_edit_state_fill_size_relative_y_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state,      ///< The name of the 'part state' (ex. "default 0.00")
+   double x                ///< The new value to set
+);
+
+/**Set the fill size offset x value of a part state.*/
+EAPI void
+edje_edit_state_fill_size_offset_x_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state,      ///< The name of the 'part state' (ex. "default 0.00")
+   double x                ///< The new value to set
+);
+
+/**Set the fill size offset x value of a part state.*/
+EAPI void
+edje_edit_state_fill_size_offset_y_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state,      ///< The name of the 'part state' (ex. "default 0.00")
+   double y                ///< The new value to set
+);
+
+//@}
+/******************************************************************************/
+/**************************   TEXT API   ************************************/
+/******************************************************************************/
+/** @name Text API
+ *  Functions to deal with text objects (see @ref edcref).
+ */ //@{
+
+/**Get the text of a part state. Remember to free the returned string with edje_edit_string_free(). */
+EAPI const char *          ///@return A newly allocated string containing the text for the given state
+edje_edit_state_text_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state       ///< The name of the 'part state' (ex. "default 0.00")
+);
+
+/**Set the text of a part state.*/
+EAPI void
+edje_edit_state_text_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state,      ///< The name of the 'part state' (ex. "default 0.00")
+   const char *text        ///< The new text to assign
+);
+
+/**Get the text size of a part state. The function will return -1 on errors.*/
+EAPI int                   ///@return The font size in pixel or -1 on errors.
+edje_edit_state_text_size_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state       ///< The name of the 'part state' (ex. "default 0.00")
+);
+
+/**Set the text size of a part state.*/
+EAPI void
+edje_edit_state_text_size_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state,      ///< The name of the 'part state' (ex. "default 0.00")
+   int size                ///< The new font size to set (in pixel)
+);
+
+/**Get the text horizontal align of a part state. The value range is from 0.0(right) to 1.0(left)*/
+EAPI double                ///@return The text align X value
+edje_edit_state_text_align_x_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state       ///< The name of the 'part state' (ex. "default 0.00")
+);
+
+/**Get the text vertical align of a part state. The value range is from 0.0(top) to 1.0(bottom)*/
+EAPI double                ///@return The text align Y value
+edje_edit_state_text_align_y_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state       ///< The name of the 'part state' (ex. "default 0.00")
+);
+
+/**Set the text horizontal align of a part state. The value range is from 0.0(right) to 1.0(left)*/
+EAPI void
+edje_edit_state_text_align_x_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state,      ///< The name of the 'part state' (ex. "default 0.00")
+   double align            ///< The new text align X value
+);
+
+/**Set the text vertical align of a part state. The value range is from 0.0(top) to 1.0(bottom)*/
+EAPI void
+edje_edit_state_text_align_y_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state,      ///< The name of the 'part state' (ex. "default 0.00")
+   double align            ///< The new text align Y value
+);
+
+/**Get the list of all the fonts in the given edje.
+ * Use edje_edit_string_list_free() when you don't need the list anymore.
+ */
+EAPI Evas_List *          ///@return An Evas_List* of string (char *)containing all the fonts names found in the edje file.
+edje_edit_fonts_list_get(
+   Evas_Object *obj       ///< The edje object
+);
+
+/**Add a new ttf font to the edje file.
+ * The newly created font will be available to all the groups in the edje, not only the current one.
+ * If font can't be load FALSE is returned.
+ */
+EAPI unsigned char         ///@return TRUE on success or FALSE on failure
+edje_edit_font_add(
+   Evas_Object *obj,       ///< The edje object
+   const char* path        ///< The file path to load the ttf font from
+);
+
+/**Get font name for a given part state. Remember to free the returned string using edje_edit_string_free().*/
+EAPI const char *          ///@return The name of the font used in the given part state
+edje_edit_state_font_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state       ///< The name of the 'part state' (ex. "default 0.00")
+);
+
+/**Set font name for a given part state. */
+EAPI void
+edje_edit_state_font_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state,      ///< The name of the 'part state' (ex. "default 0.00")
+   const char *font        ///< The name of the font to use in the given part state
+);
+
+//@}
+/******************************************************************************/
+/**************************   IMAGES API   ************************************/
+/******************************************************************************/
+/** @name Images API
+ *  Functions to deal with image objects (see @ref edcref).
+ */ //@{
+
+/**Get the list of all the images in the given edje.
+ * Use edje_edit_string_list_free() when you don't need the list anymore.
+ */
+EAPI Evas_List *          ///@return An Evas_List* of string (char *)containing all the images names found in the edje file.
+edje_edit_images_list_get(
+   Evas_Object *obj       ///< The edje object
+);
+
+/**Add an new image to the image collection
+ *
+ * This function add the given image inside the edje. Don't add a new image part
+ * but only put the image inside the edje file. It actually write directly to
+ * the file so you don't have to save (and you can't undo!).
+ * After you have to create a new image_part that use this image. Note that all
+ * the parts in the edje share the same image collection, thus you can/must use
+ * the same image for different part.
+ *
+ * The format of the image files that can be loaded depend on the evas engine on your system
+ */
+EAPI unsigned char         ///@return TRUE on success or FALSE on failure
+edje_edit_image_add(
+   Evas_Object *obj,       ///< The edje object
+   const char* path        ///< The name of the image file to include in the edje
+);
+
+/**Get normal image name for a given part state. Remember to free the returned string using edje_edit_string_free().*/
+EAPI const char *          ///@return The name of the image used by state
+edje_edit_state_image_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state       ///< The name of the 'part state' (ex. "default 0.00")
+);
+
+/**Set normal image for a given part state.*/
+EAPI void
+edje_edit_state_image_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state,      ///< The name of the 'part state' (ex. "default 0.00")
+   const char *image       ///< The name of the image for the given state (must be an image contained in the edje file)
+);
+
+/**Get image id for a given image name. Could be usefull to directly load the image from the eet file.*/
+EAPI int                   ///< The ID of the givan image name
+edje_edit_image_id_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *image_name
+);
+
+/**Get compression type for the given image.*/
+EAPI int                  ///@return One of EDJE_EDIT_IMAGE_COMP_RAW, EDJE_EDIT_IMAGE_COMP_USER, EDJE_EDIT_IMAGE_COMP_COMP or EDJE_EDIT_IMAGE_COMP_LOSSY
+edje_edit_image_compression_type_get(
+   Evas_Object *obj,      ///< The edje object
+   const char *image      ///< The name of the image
+);
+
+/**Get compression rate for the given image.*/
+EAPI int                  ///@return the compression rate if the image is EDJE_EDIT_IMAGE_COMP_LOSSY. Or < 0 on errors
+edje_edit_image_compression_rate_get(
+   Evas_Object *obj,      ///< The edje object
+   const char *image      ///< The name of the image
+);
+
+/**Get the image border of a part state. Pass NULL to any of [r,g,b,a] to get only the others.*/
+EAPI void
+edje_edit_state_image_border_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state,      ///< The name of the 'part state' (ex. "default 0.00")
+   int *l,                 ///< A pointer to store the left value
+   int *r,                 ///< A pointer to store the right value
+   int *t,                 ///< A pointer to store the top value
+   int *b                  ///< A pointer to store the bottom value
+);
+
+/**Set the image border of a part state. Pass -1 to any of [l,r,t,b] to leave the value untouched.*/
+EAPI void
+edje_edit_state_image_border_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state,      ///< The name of the 'part state' (ex. "default 0.00")
+   int l,                  ///< The new left border (or -1)
+   int r,                  ///< The new right border (or -1)
+   int t,                  ///< The new top border (or -1)
+   int b                   ///< The new bottom border (or -1)
+);
+
+/**Get the list of all the tweens images in the given part state.
+ * Use edje_edit_string_list_free() when you don't need it anymore.
+ */
+EAPI Evas_List *           ///@return A string list containing all the image name that form a tween animation in the given part state
+edje_edit_state_tweens_list_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state       ///< The name of the 'part state' (ex. "default 0.00")
+);
+
+/**Add a new tween frame to the given part state
+ * The tween param must be the name of an existing image.
+ */
+EAPI unsigned char         ///@return 1 on success, 0 otherwise
+edje_edit_state_tween_add(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state,      ///< The name of the 'part state' (ex. "default 0.00")
+   const char *tween       ///< The name of the image to add.
+);
+
+/**Remove the first tween with the given name.
+ * If none is removed the function return 0.
+ * The image is not removed from the edje.
+ */
+EAPI unsigned char         ///@return 1 on success, 0 otherwise
+edje_edit_state_tween_del(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state,      ///< The name of the 'part state' (ex. "default 0.00")
+   const char *tween       ///< The name of the image to remove from the tween list.
+);
+
+//@}
+/******************************************************************************/
+/*************************   SPECTRUM API   ***********************************/
+/******************************************************************************/
+/** @name Spectrum API
+ *  Functions to manage spectrum (see @ref edcref).
+ */ //@{
+
+/**Get the list of all the spectrum in the given edje object.
+ * Use edje_edit_string_list_free() when you don't need it anymore.
+ */
+EAPI Evas_List *           ///@return An Evas_List* of string(char *) containing all the spectra names.
+edje_edit_spectrum_list_get(
+   Evas_Object *obj        ///< The edje object
+);
+
+/**Add a new spectra in the given edje object.*/
+EAPI unsigned char         ///@return 1 on success, 0 otherwise
+edje_edit_spectra_add(
+   Evas_Object *obj,       ///< The edje object
+   const char* name        ///< The name of the new spectra
+);
+
+/**Delete the given spectra from the edje object.*/
+EAPI unsigned char         ///@return 1 on success, 0 otherwise
+edje_edit_spectra_del(
+   Evas_Object *obj,       ///< The edje object
+   const char* spectra     ///< The name of the spectra to delete
+);
+
+/**Change the name of the given spectra.*/
+EAPI unsigned char         ///@return 1 on success, 0 otherwise
+edje_edit_spectra_name_set(
+   Evas_Object *obj,       ///< The edje object
+   const char* spectra,    ///< The current name of the spectra
+   const char* name        ///< The new name to assign
+);
+
+/**Get the number of stops in the given spectra.*/
+EAPI int                   ///@return The number of stops, or 0 on errors
+edje_edit_spectra_stop_num_get(
+   Evas_Object *obj,       ///< The edje object
+   const char* spectra     ///< The name of the spectra
+);
+
+/**Set the number of stops in the given spectra.*/
+EAPI unsigned char         ///@return 1 on success, 0 otherwise
+edje_edit_spectra_stop_num_set(
+   Evas_Object *obj,       ///< The edje object
+   const char* spectra,    ///< The name of the spectra
+   int num                 ///< The number of stops you want
+);
+
+/**Get the colors of the given stop.*/
+EAPI unsigned char         ///@return 1 on success, 0 otherwise
+edje_edit_spectra_stop_color_get(
+   Evas_Object *obj,       ///< The edje object
+   const char* spectra,    ///< The name of the spectra
+   int stop_number,        ///< The number of the stop
+   int *r,                 ///< Where to store the red color value
+   int *g,                 ///< Where to store the green color value
+   int *b,                 ///< Where to store the blue color value
+   int *a,                 ///< Where to store the alpha color value
+   int *d                  ///< Where to store the delta stop value
+);
+
+/**Set the colors of the given stop.*/
+EAPI unsigned char         ///@return 1 on success, 0 otherwise
+edje_edit_spectra_stop_color_set(
+   Evas_Object *obj,       ///< The edje object
+   const char* spectra,    ///< The name of the spectra
+   int stop_number,        ///< The number of the stop
+   int r,                  ///< The red color value to set
+   int g,                  ///< The green color value to set
+   int b,                  ///< The blue color value to set
+   int a,                  ///< The alpha color value to set
+   int d                   ///< The delta stop value to set
+);
+
+
+//@}
+/******************************************************************************/
+/*************************   GRADIENT API   ***********************************/
+/******************************************************************************/
+/** @name Gradient API
+ *  Functions to deal with gradient objects (see @ref edcref).
+ */ //@{
+
+/**Get the type of gradient. Remember to free the string with edje_edit_string_free().*/
+EAPI const char *          ///@return The type of gradient used in state
+edje_edit_state_gradient_type_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state       ///< The name of the 'part state' (ex. "default 0.00")
+);
+
+/**Set the type of gradient.
+ * Gradient type can be on of the following: linear, linear.diag, linear.codiag, radial, rectangular, angular, sinusoidal
+ */
+EAPI unsigned char         ///@return 1 on success, 0 otherwise
+edje_edit_state_gradient_type_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state,      ///< The name of the 'part state' (ex. "default 0.00")
+   const char *type        ///< The type of gradient to use
+);
+
+/**Get if the current gradient use the fill properties or the gradient_rel as params.*/
+EAPI unsigned char         ///@return 1 if use fill, 0 if use gradient_rel
+edje_edit_state_gradient_use_fill_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state       ///< The name of the 'part state' (ex. "default 0.00")
+);
+
+/**Get the spectra used by part state. Remember to free the string with edje_edit_string_free()*/
+EAPI const char *          ///@return The spectra name used in state
+edje_edit_state_gradient_spectra_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state       ///< The name of the 'part state' (ex. "default 0.00")
+);
+
+/**Set the spectra used by part state.*/
+EAPI unsigned char         ///@return 1 on success, 0 otherwise
+edje_edit_state_gradient_spectra_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state,      ///< The name of the 'part state' (ex. "default 0.00")
+   const char* spectra     ///< The spectra name to assign
+);
+
+/**Get the gradien rel1 relative x value */
+EAPI double                ///@return The gradien rel1 relative x value
+edje_edit_state_gradient_rel1_relative_x_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state       ///< The name of the 'part state' (ex. "default 0.00")
+);
+
+/**Get the gradien rel1 relative y value */
+EAPI double                ///@return The gradien rel1 relative y value
+edje_edit_state_gradient_rel1_relative_y_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state       ///< The name of the 'part state' (ex. "default 0.00")
+);
+
+/**Get the gradien rel2 relative x value */
+EAPI double                ///@return The gradien rel2 relative x value
+edje_edit_state_gradient_rel2_relative_x_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state       ///< The name of the 'part state' (ex. "default 0.00")
+);
+
+/**Get the gradien rel2 relative y value */
+EAPI double                ///@return The gradien rel2 relative y value
+edje_edit_state_gradient_rel2_relative_y_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state       ///< The name of the 'part state' (ex. "default 0.00")
+);
+
+/**Set the gradien rel1 relative x value */
+EAPI unsigned char         ///@return 1 on success, 0 otherwise
+edje_edit_state_gradient_rel1_relative_x_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state,      ///< The name of the 'part state' (ex. "default 0.00")
+   double val
+);
+
+/**Set the gradien rel1 relative y value */
+EAPI unsigned char         ///@return 1 on success, 0 otherwise
+edje_edit_state_gradient_rel1_relative_y_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state,      ///< The name of the 'part state' (ex. "default 0.00")
+   double val
+);
+
+/**Set the gradien rel2 relative x value */
+EAPI unsigned char         ///@return 1 on success, 0 otherwise
+edje_edit_state_gradient_rel2_relative_x_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state,      ///< The name of the 'part state' (ex. "default 0.00")
+   double val
+);
+
+/**Set the gradien rel2 relative y value */
+EAPI unsigned char         ///@return 1 on success, 0 otherwise
+edje_edit_state_gradient_rel2_relative_y_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state,      ///< The name of the 'part state' (ex. "default 0.00")
+   double val
+);
+
+/**Get the gradien rel1 offset x value */
+EAPI int                   ///@return The gradient rel1 offset x value
+edje_edit_state_gradient_rel1_offset_x_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state       ///< The name of the 'part state' (ex. "default 0.00")
+);
+
+/**Get the gradien rel1 offset y value */
+EAPI int                   ///@return The gradient rel1 offset y value
+edje_edit_state_gradient_rel1_offset_y_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state       ///< The name of the 'part state' (ex. "default 0.00")
+);
+
+/**Get the gradien rel2 offset x value */
+EAPI int                   ///@return The gradient rel2 offset x value
+edje_edit_state_gradient_rel2_offset_x_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state       ///< The name of the 'part state' (ex. "default 0.00")
+);
+
+/**Get the gradien rel2 offset y value */
+EAPI int                   ///@return The gradient rel2 offset y value
+edje_edit_state_gradient_rel2_offset_y_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state       ///< The name of the 'part state' (ex. "default 0.00")
+);
+
+/**Set the gradien rel1 offset x value */
+EAPI unsigned char         ///@return 1 on success, 0 otherwise
+edje_edit_state_gradient_rel1_offset_x_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state,      ///< The name of the 'part state' (ex. "default 0.00")
+   int val
+);
+
+/**Set the gradien rel1 offset y value */
+EAPI unsigned char         ///@return 1 on success, 0 otherwise
+edje_edit_state_gradient_rel1_offset_y_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state,      ///< The name of the 'part state' (ex. "default 0.00")
+   int val
+);
+
+/**Set the gradien rel2 offset x value */
+EAPI unsigned char         ///@return 1 on success, 0 otherwise
+edje_edit_state_gradient_rel2_offset_x_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state,      ///< The name of the 'part state' (ex. "default 0.00")
+   int val
+);
+
+/**Set the gradien rel2 offset y value */
+EAPI unsigned char         ///@return 1 on success, 0 otherwise
+edje_edit_state_gradient_rel2_offset_y_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *part,       ///< The name of the part
+   const char *state,      ///< The name of the 'part state' (ex. "default 0.00")
+   int val
+);
+
+//@}
+/******************************************************************************/
+/*************************   PROGRAMS API   ***********************************/
+/******************************************************************************/
+/** @name Programs API
+ *  Functions to deal with programs (see @ref edcref).
+ */ //@{
+
+/**Get the list of all the programs in the given edje object.
+ * @param obj The edje object
+ * @return An Evas_List* of string (char *)containing all the program names.
+ * Use edje_edit_string_list_free() when you don't need it anymore.
+ */
+EAPI Evas_List *          ///@return A string list containing all the program names
+edje_edit_programs_list_get(
+   Evas_Object *obj       ///< The edje object
+);
+
+/**Add a new program to the edje file
+ * If a program with the same name just exist the function will fail.
+ */
+EAPI unsigned char         ///@return 1 on success or 0 on errors
+edje_edit_program_add(
+   Evas_Object *obj,       ///< The edje object
+   const char *name        ///< The name of the new program
+);
+
+/**Remove the given program from the edje file.
+ */
+EAPI unsigned char         ///@return 1 on success or 0 on errors
+edje_edit_program_del(
+   Evas_Object *obj,       ///< The edje object
+   const char *prog        ///< The name of the program to remove
+);
+
+/**Check if a program with the given name exist in the edje object.
+ */
+EAPI unsigned char         ///< 1 if the program exist, 0 otherwise.
+edje_edit_program_exist(
+   Evas_Object *obj,       ///< The edje object
+   const char *prog        ///< The name of the program
+);
+
+/**Run the given program. */
+EAPI unsigned char         ///< 1 on success, 0 otherwise.
+edje_edit_program_run(
+   Evas_Object *obj,       ///< The edje object
+   const char *prog        ///< The name of the program to execute
+);
+
+/**Set a new name for the given program */
+EAPI unsigned char        ///@return 1 on success or 0 on errors
+edje_edit_program_name_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *prog,       ///< The program name
+   const char *new_name    ///< The new name to assign
+);
+
+/**Get source of a given program. Remember to free the returned string using edje_edit_string_free().*/
+EAPI const char *          ///@return The source value for prog
+edje_edit_program_source_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *prog        ///< The program name
+);
+
+/**Set source of the given program. */
+EAPI unsigned char         ///@return 1 on success or 0 on errors
+edje_edit_program_source_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *prog,       ///< The program name
+   const char *source      ///< The new source value
+);
+
+/**Get signal of a given program. Remember to free the returned string using edje_edit_string_free().*/
+EAPI const char *          ///@return The signal value for prog
+edje_edit_program_signal_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *prog        ///< The program name
+);
+
+/**Set signal of the given program. */
+EAPI unsigned char         ///@return 1 on success or 0 on errors
+edje_edit_program_signal_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *prog,       ///< The program name
+   const char *signal      ///< The new signal value
+);
+
+/**Get in.from of a given program.*/
+EAPI double                ///@return The delay
+edje_edit_program_in_from_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *prog        ///< The program name
+);
+
+/**Set in.from of a given program.*/
+EAPI unsigned char         ///@return 1 on success or 0 on errors
+edje_edit_program_in_from_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *prog,       ///< The program name
+   double seconds          ///< Number of seconds to delay the program execution
+);
+
+/**Get in.range of a given program.*/
+EAPI double                ///@return The delay random
+edje_edit_program_in_range_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *prog        ///< The program name
+);
+
+/**Set in.range of a given program.*/
+EAPI unsigned char         ///@return 1 on success or 0 on errors
+edje_edit_program_in_range_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *prog,       ///< The program name
+   double seconds          ///< Max random number of seconds to delay
+);
+
+/**Get the action of a given program.
+ * Action can be one of EDJE_ACTION_TYPE_NONE, _STATE_SET, ACTION_STOP, SIGNAL_EMIT, DRAG_VAL_SET, _DRAG_VAL_STEP, _DRAG_VAL_PAGE, _SCRIPT
+ */
+EAPI int                   ///@return The action type, or -1 on errors
+edje_edit_program_action_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *prog        ///< The program name
+);
+
+/**Set the action of a given program.
+ * Action can be one of EDJE_ACTION_TYPE_NONE, _STATE_SET, ACTION_STOP, SIGNAL_EMIT, DRAG_VAL_SET, _DRAG_VAL_STEP, _DRAG_VAL_PAGE, _SCRIPT
+ */
+EAPI unsigned char         ///@return 1 on success or 0 on errors
+edje_edit_program_action_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *prog,       ///< The program name
+   int action              ///< The new action type
+);
+
+/**Get the list of the targets for the given program
+ * Return a list of target name
+ * Use edje_edit_string_list_free() when you don't need it anymore.
+ */
+EAPI Evas_List*            ///@return An Evas_List of char*, or NULL on error
+edje_edit_program_targets_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *prog        ///< The program name
+);
+
+/**Add a new target name to the list of 'targets' in the given program.
+ * If program action is EDJE_ACTION_TYPE_ACTION_STOP then 'target' must be an existing program name.
+ * If action is EDJE_ACTION_TYPE_STATE_SET then 'target' must be an existing part name.
+ */
+EAPI unsigned char         ///@return 1 on success or 0 on errors
+edje_edit_program_target_add(
+   Evas_Object *obj,       ///< The edje object
+   const char *prog,       ///< The program name
+   const char *target      ///< The name of another program or another part
+);
+
+/**Clear the 'targets' list of the given program */
+EAPI unsigned char         ///@return 1 on success or 0 on errors
+edje_edit_program_targets_clear(
+   Evas_Object *obj,       ///< The edje object
+   const char *prog        ///< The program name
+);
+
+/**Get the list of action that will be run after the give program
+ * Return a list of program name.
+ * Use edje_edit_string_list_free() when you don't need it anymore.
+ */
+EAPI Evas_List*            ///@return An Evas_List of char*, or NULL on error
+edje_edit_program_afters_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *prog        ///< The program name
+);
+
+/**Add a new program name to the list of 'afters' in the given program.
+ * All the programs listed in 'afters' will be executed after program execution.
+ */
+EAPI unsigned char         ///@return 1 on success or 0 on errors
+edje_edit_program_after_add(
+   Evas_Object *obj,       ///< The edje object
+   const char *prog,       ///< The program name
+   const char *after       ///< The name of another program to add to the afters list
+);
+
+/**Clear the 'afters' list of the given program */
+EAPI unsigned char         ///@return 1 on success or 0 on errors
+edje_edit_program_afters_clear(
+   Evas_Object *obj,       ///< The edje object
+   const char *prog        ///< The program name
+);
+
+/**Get the state for the given program
+ * In a STATE_SET action this is the name of state to set.
+ * In a SIGNAL_EMIT action is the name of the signal to emit.
+ */
+EAPI const char*           ///@return The name of state for prog
+edje_edit_program_state_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *prog        ///< The program name
+);
+
+/**Set the state for the given program
+ * In a STATE_SET action this is the name of state to set.
+ * In a SIGNAL_EMIT action is the name of the signal to emit.
+ */
+EAPI unsigned char         ///@return 1 on success or 0 on errors
+edje_edit_program_state_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *prog,       ///< The program name
+   const char *state       ///< The state to set (not including the state value)
+);
+
+/**Get the value of state for the given program.
+ * In a STATE_SET action this is the value of state to set.
+ * Not used on SIGNAL_EMIT action.
+ */
+EAPI double                ///@return The value of state for prog
+edje_edit_program_value_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *prog        ///< The program name
+);
+
+/**Set the value of state for the given program.
+ * In a STATE_SET action this is the value of state to set.
+ * Not used on SIGNAL_EMIT action.
+ */
+EAPI unsigned char         ///@return 1 on success or 0 on errors
+edje_edit_program_value_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *prog,       ///< The program name
+   double value            ///< The value to set
+);
+
+/**Get the state2 for the given program
+ * In a STATE_SET action is not used
+ * In a SIGNAL_EMIT action is the source of the emitted signal.
+ */
+EAPI const char*           ///@return The source to emit for prog
+edje_edit_program_state2_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *prog        ///< The program name
+);
+
+/**Set the state2 for the given program
+ * In a STATE_SET action is not used
+ * In a SIGNAL_EMIT action is the source of the emitted signal.
+ */
+EAPI unsigned char         ///@return 1 on success or 0 on errors
+edje_edit_program_state2_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *prog,       ///< The program name
+   const char *state2      ///< The state2 value to set
+);
+
+/**Get the value of state2 for the given program.
+ * I don't know what this is used for. :P
+ */
+EAPI double                ///@return The value of state2 for prog
+edje_edit_program_value2_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *prog        ///< The program name
+);
+
+/**Set the value2 of state for the given program.
+ * This is used in DRAG_ACTION
+ */
+EAPI unsigned char         ///@return 1 on success or 0 on errors
+edje_edit_program_value2_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *prog,       ///< The program name
+   double value            ///< The value to set
+);
+
+/**Get the type of transition to use when apply animations.
+ * Can be one of: EDJE_TWEEN_MODE_NONE, EDJE_TWEEN_MODE_LINEAR, EDJE_TWEEN_MODE_SINUSOIDAL, EDJE_TWEEN_MODE_ACCELERATE or EDJE_TWEEN_MODE_DECELERATE.
+ */
+EAPI int                   ///@return The type of transition used by program
+edje_edit_program_transition_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *prog        ///< The program name
+);
+
+/**Set the type of transition to use when apply animations.
+ * Can be one of: EDJE_TWEEN_MODE_NONE, EDJE_TWEEN_MODE_LINEAR, EDJE_TWEEN_MODE_SINUSOIDAL, EDJE_TWEEN_MODE_ACCELERATE or EDJE_TWEEN_MODE_DECELERATE.
+ */
+EAPI unsigned char         ///@return 1 on success or 0 on errors
+edje_edit_program_transition_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *prog,       ///< The program name
+   int transition          ///< The transition type to set
+);
+
+/**Get the duration of the transition in seconds.*/
+EAPI double                ///@return The duration of the transition
+edje_edit_program_transition_time_get(
+   Evas_Object *obj,       ///< The edje object
+   const char *prog        ///< The program name
+);
+
+/**Set the duration of the transition in seconds.*/
+EAPI unsigned char         ///@return 1 on success or 0 on errors
+edje_edit_program_transition_time_set(
+   Evas_Object *obj,       ///< The edje object
+   const char *prog,       ///< The program name
+   double seconds          ///< The duration of the transition (in seconds)
+);
+
+//@}
+/******************************************************************************/
+/**************************   SCRIPTS API   ***********************************/
+/******************************************************************************/
+/** @name Scripts API
+ *  Functions to deal with embryo scripts (see @ref edcref).
+ */ //@{
+EAPI const char* edje_edit_script_get(Evas_Object *obj);
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
new file mode 100644 (file)
index 0000000..0002e7d
--- /dev/null
@@ -0,0 +1,48 @@
+
+MAINTAINERCLEANFILES = Makefile.in
+
+AM_CPPFLAGS = \
+-I. \
+-I$(top_srcdir) \
+-I$(top_srcdir)/src/bin \
+-I$(top_srcdir)/src/lib \
+-DPACKAGE_BIN_DIR=\"$(bindir)\" \
+-DPACKAGE_LIB_DIR=\"$(libdir)\" \
+-DPACKAGE_DATA_DIR=\"$(datadir)/$(PACKAGE)\" \
+@EDJE_CFLAGS@ \
+@EVIL_CFLAGS@
+
+lib_LTLIBRARIES      = \
+libedje.la
+
+include_HEADERS      =  \
+Edje.h \
+Edje_Edit.h
+
+libedje_la_SOURCES  = \
+edje_calc.c \
+edje_callbacks.c \
+edje_data.c \
+edje_embryo.c \
+edje_load.c \
+edje_main.c \
+edje_misc.c \
+edje_program.c \
+edje_smart.c \
+edje_text.c \
+edje_util.c \
+edje_var.c \
+edje_container.c \
+edje_container.h \
+edje_message_queue.c \
+edje_private.h \
+edje_cache.c \
+edje_match.c \
+edje_textblock_styles.c \
+edje_edit.c \
+edje_script_only.c
+
+libedje_la_CFLAGS = @WIN32_CFLAGS@
+libedje_la_LIBADD = @EDJE_LIBS@ -lm
+libedje_la_DEPENDENCIES = $(top_builddir)/config.h
+libedje_la_LDFLAGS = @lt_no_undefined@ @lt_enable_auto_import@ -version-info @version_info@
diff --git a/src/lib/edje_cache.c b/src/lib/edje_cache.c
new file mode 100644 (file)
index 0000000..7853b50
--- /dev/null
@@ -0,0 +1,440 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#include "edje_private.h"
+
+static Evas_Hash   *_edje_file_hash = NULL;
+static int          _edje_file_cache_size = 16;
+static Evas_List   *_edje_file_cache = NULL;
+
+static int          _edje_collection_cache_size = 16;
+
+static Edje_Part_Collection *
+_edje_file_coll_open(Edje_File *edf, const char *coll)
+{
+   Edje_Part_Collection *edc = NULL;
+   Evas_List *l = NULL;
+   int id = -1, size = 0;
+   char buf[256];
+   void *data;
+
+   for (l = edf->collection_dir->entries; l; l = l->next)
+     {
+       Edje_Part_Collection_Directory_Entry *ce;
+
+       ce = l->data;
+       if ((ce->entry) && (!strcmp(ce->entry, coll)))
+         {
+            id = ce->id;
+            break;
+         }
+     }
+   if (id < 0) return NULL;
+
+   snprintf(buf, sizeof(buf), "collections/%i", id);
+   edc = eet_data_read(edf->ef, _edje_edd_edje_part_collection, buf);
+   if (!edc) return NULL;
+
+   snprintf(buf, sizeof(buf), "scripts/%i", id);
+   data = eet_read(edf->ef, buf, &size);
+
+   if (data)
+     {
+       edc->script = embryo_program_new(data, size);
+       free(data);
+     }
+
+   edc->part = evas_stringshare_add(coll);
+   edc->references = 1;
+   edf->collection_hash = evas_hash_add(edf->collection_hash, coll, edc);
+   return edc;
+}
+
+static int
+_edje_font_hash(Edje_File *edf)
+{
+   int count = 0;
+
+   if (edf->font_dir)
+     {
+       Evas_List *l;
+       for (l = edf->font_dir->entries; l; l = evas_list_next(l))
+         {
+            Edje_Font_Directory_Entry  *fnt;
+            int                         length;
+            char                       *tmp;
+
+            fnt = l->data;
+            length = strlen(fnt->entry) + 7;
+            tmp = alloca(length);
+
+            snprintf(tmp, length, "fonts/%s", fnt->entry);
+            fnt->path = evas_stringshare_add(tmp);
+             if (edf->free_strings)
+               evas_stringshare_del(fnt->entry);
+            fnt->entry = fnt->path + 6;
+            edf->font_hash = evas_hash_direct_add(edf->font_hash, fnt->entry, fnt);
+
+            count++;
+         }
+     }
+   return count;
+}
+
+static Edje_File *
+_edje_file_open(const char *file, const char *coll, int *error_ret, Edje_Part_Collection **edc_ret)
+{
+   Edje_File *edf;
+   Edje_Part_Collection *edc;
+   Eet_File *ef;
+   Evas_List *l;
+   struct stat st;
+
+   if (stat(file, &st) != 0)
+     {
+       *error_ret = EDJE_LOAD_ERROR_DOES_NOT_EXIST;
+       return NULL;
+     }
+
+   ef = eet_open(file, EET_FILE_MODE_READ);
+   if (!ef)
+     {
+       *error_ret = EDJE_LOAD_ERROR_UNKNOWN_FORMAT;
+       return NULL;
+     }
+   edf = eet_data_read(ef, _edje_edd_edje_file, "edje_file");
+   if (!edf)
+     {
+       *error_ret = EDJE_LOAD_ERROR_CORRUPT_FILE;
+       eet_close(ef);
+       return NULL;
+     }
+
+   edf->free_strings = eet_dictionary_get(ef) ? 0 : 1;
+
+   edf->ef = ef;
+
+   if (edf->version != EDJE_FILE_VERSION)
+     {
+       *error_ret = EDJE_LOAD_ERROR_INCOMPATIBLE_FILE;
+       _edje_file_free(edf);
+       return NULL;
+     }
+   if (!edf->collection_dir)
+     {
+       *error_ret = EDJE_LOAD_ERROR_CORRUPT_FILE;
+       _edje_file_free(edf);
+       return NULL;
+     }
+
+   edf->path = evas_stringshare_add(file);
+   edf->references = 1;
+
+   _edje_textblock_style_parse_and_fix(edf);
+
+   for (l = edf->data; l; l = evas_list_remove(l, l->data))
+     {
+       Edje_Data *di = l->data;
+       edf->data_cache = evas_hash_add(edf->data_cache, evas_stringshare_add(di->key), di->value);
+       free(di);
+     }
+   edf->data = NULL;
+
+   if (coll)
+     {
+       edc = _edje_file_coll_open(edf, coll);
+       if (!edc)
+         {
+            *error_ret = EDJE_LOAD_ERROR_UNKNOWN_COLLECTION;
+         }
+       if (edc_ret) *edc_ret = edc;
+     }
+
+   edf->font_hash = NULL;
+
+   _edje_font_hash(edf);
+
+   return edf;
+}
+
+Edje_File *
+_edje_cache_file_coll_open(const char *file, const char *coll, int *error_ret, Edje_Part_Collection **edc_ret)
+{
+   Edje_File *edf;
+   Evas_List *l, *hist;
+   Edje_Part_Collection *edc;
+
+   edf = evas_hash_find(_edje_file_hash, file);
+   if (edf)
+     {
+       edf->references++;
+     }
+   else
+     {
+       for (l = _edje_file_cache; l; l = l->next)
+         {
+            edf = l->data;
+            if (!strcmp(edf->path, file))
+              {
+                 edf->references = 1;
+                 _edje_file_cache = evas_list_remove_list(_edje_file_cache, l);
+                 _edje_file_hash = evas_hash_add(_edje_file_hash, file, edf);
+                 break;
+              }
+            edf = NULL;
+         }
+     }
+   if (!edf)
+     {
+       edf = _edje_file_open(file, coll, error_ret, edc_ret);
+       if (!edf) return NULL;
+       _edje_file_hash = evas_hash_add(_edje_file_hash, file, edf);
+       return edf;
+     }
+
+   if (!coll) return edf;
+
+   edc = evas_hash_find(edf->collection_hash, coll);
+   if (edc)
+     {
+       edc->references++;
+     }
+   else
+     {
+       for (l = edf->collection_cache; l; l = l->next)
+         {
+            edc = l->data;
+            if (!strcmp(edc->part, coll))
+              {
+                 edc->references = 1;
+                 edf->collection_cache = evas_list_remove_list(edf->collection_cache, l);
+                 edf->collection_hash = evas_hash_add(edf->collection_hash, coll, edc);
+                 break;
+              }
+            edc = NULL;
+         }
+     }
+   if (!edc)
+     {
+       edc = _edje_file_coll_open(edf, coll);
+       if (!edc)
+         {
+            *error_ret = EDJE_LOAD_ERROR_UNKNOWN_COLLECTION;
+         }
+       else
+         {
+            for (l = edc->parts; l; l = l->next)
+              {
+                 Edje_Part *ep, *ep2;
+
+                 /* Register any color classes in this parts descriptions. */
+                 ep = l->data;
+                 hist = NULL;
+                 hist = evas_list_append(hist, ep);
+                 ep2 = ep;
+                 while (ep2->dragable.confine_id >= 0)
+                   {
+                      ep2 = evas_list_nth(edc->parts, ep2->dragable.confine_id);
+                      if (evas_list_find(hist, ep2))
+                        {
+                           printf("EDJE ERROR: confine_to loops. invalidating loop.\n");
+                           ep2->dragable.confine_id = -1;
+                           break;
+                        }
+                      hist = evas_list_append(hist, ep2);
+                   }
+                 evas_list_free(hist);
+                 hist = NULL;
+                 hist = evas_list_append(hist, ep);
+                 ep2 = ep;
+                 while (ep2->dragable.events_id >= 0)
+                   {
+                      Edje_Part* prev;
+
+                      prev = ep2;
+
+                      ep2 = evas_list_nth(edc->parts, ep2->dragable.events_id);
+                      if (!ep2->dragable.x && !ep2->dragable.y)
+                        {
+                           prev->dragable.events_id = -1;
+                           break;
+                        }
+
+                      if (evas_list_find(hist, ep2))
+                        {
+                           printf("EDJE ERROR: events_to loops. invalidating loop.\n");
+                           ep2->dragable.events_id = -1;
+                           break;
+                        }
+                      hist = evas_list_append(hist, ep2);
+                   }
+                 evas_list_free(hist);
+                 hist = NULL;
+                 hist = evas_list_append(hist, ep);
+                 ep2 = ep;
+                 while (ep2->clip_to_id >= 0)
+                   {
+                      ep2 = evas_list_nth(edc->parts, ep2->clip_to_id);
+                      if (evas_list_find(hist, ep2))
+                        {
+                           printf("EDJE ERROR: clip_to loops. invalidating loop.\n");
+                           ep2->clip_to_id = -1;
+                           break;
+                        }
+                      hist = evas_list_append(hist, ep2);
+                   }
+                 evas_list_free(hist);
+                 hist = NULL;
+              }
+         }
+     }
+   if (edc_ret) *edc_ret = edc;
+
+   return edf;
+}
+
+void
+_edje_cache_coll_clean(Edje_File *edf)
+{
+   int count;
+
+   count = evas_list_count(edf->collection_cache);
+   while ((edf->collection_cache) && (count > _edje_collection_cache_size))
+     {
+       Edje_Part_Collection *edc;
+
+       edc = evas_list_last(edf->collection_cache)->data;
+       edf->collection_cache = evas_list_remove_list(edf->collection_cache, evas_list_last(edf->collection_cache));
+       _edje_collection_free(edf, edc);
+       count = evas_list_count(edf->collection_cache);
+     }
+}
+
+void
+_edje_cache_coll_flush(Edje_File *edf)
+{
+   while (edf->collection_cache)
+     {
+       Edje_Part_Collection *edc;
+
+       edc = evas_list_last(edf->collection_cache)->data;
+       edf->collection_cache = evas_list_remove_list(edf->collection_cache, evas_list_last(edf->collection_cache));
+       _edje_collection_free(edf, edc);
+     }
+}
+
+void
+_edje_cache_coll_unref(Edje_File *edf, Edje_Part_Collection *edc)
+{
+   edc->references--;
+   if (edc->references != 0) return;
+   edf->collection_hash = evas_hash_del(edf->collection_hash, edc->part, edc);
+   edf->collection_cache = evas_list_prepend(edf->collection_cache, edc);
+   _edje_cache_coll_clean(edf);
+}
+
+static void
+_edje_cache_file_clean(void)
+{
+   int count;
+
+   count = evas_list_count(_edje_file_cache);
+   while ((_edje_file_cache) && (count > _edje_file_cache_size))
+     {
+       Edje_File *edf;
+
+       edf = evas_list_last(_edje_file_cache)->data;
+       _edje_file_cache = evas_list_remove_list(_edje_file_cache, evas_list_last(_edje_file_cache));
+       _edje_file_free(edf);
+       count = evas_list_count(_edje_file_cache);
+     }
+}
+
+void
+_edje_cache_file_unref(Edje_File *edf)
+{
+   edf->references--;
+   if (edf->references != 0) return;
+   _edje_file_hash = evas_hash_del(_edje_file_hash, edf->path, edf);
+   _edje_file_cache = evas_list_prepend(_edje_file_cache, edf);
+   _edje_cache_file_clean();
+}
+
+void
+_edje_file_cache_shutdown(void)
+{
+   edje_file_cache_flush();
+}
+
+
+
+
+
+
+EAPI void
+edje_file_cache_set(int count)
+{
+   if (count < 0) count = 0;
+   _edje_file_cache_size = count;
+   _edje_cache_file_clean();
+}
+
+EAPI int
+edje_file_cache_get(void)
+{
+   return _edje_file_cache_size;
+}
+
+EAPI void
+edje_file_cache_flush(void)
+{
+   int ps;
+
+   ps = _edje_file_cache_size;
+   _edje_file_cache_size = 0;
+   _edje_cache_file_clean();
+   _edje_file_cache_size = ps;
+}
+
+EAPI void
+edje_collection_cache_set(int count)
+{
+   Evas_List *l;
+
+   if (count < 0) count = 0;
+   _edje_collection_cache_size = count;
+   for (l = _edje_file_cache; l; l = l->next)
+     {
+       Edje_File *edf;
+
+       edf = l->data;
+       _edje_cache_coll_clean(edf);
+     }
+   /* FIXME: freach in file hash too! */
+}
+
+EAPI int
+edje_collection_cache_get(void)
+{
+   return _edje_collection_cache_size;
+}
+
+EAPI void
+edje_collection_cache_flush(void)
+{
+   int ps;
+   Evas_List *l;
+
+   ps = _edje_collection_cache_size;
+   _edje_collection_cache_size = 0;
+   for (l = _edje_file_cache; l; l = l->next)
+     {
+       Edje_File *edf;
+
+       edf = l->data;
+       _edje_cache_coll_flush(edf);
+     }
+   /* FIXME: freach in file hash too! */
+   _edje_collection_cache_size = ps;
+}
diff --git a/src/lib/edje_calc.c b/src/lib/edje_calc.c
new file mode 100644 (file)
index 0000000..f62f26a
--- /dev/null
@@ -0,0 +1,1511 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#include "edje_private.h"
+
+#define FLAG_NONE 0
+#define FLAG_X    0x01
+#define FLAG_Y    0x02
+#define FLAG_XY   (FLAG_X | FLAG_Y)
+
+static void _edje_part_recalc_single(Edje *ed, Edje_Real_Part *ep, Edje_Part_Description *desc, Edje_Part_Description *chosen_desc, Edje_Real_Part *rel1_to_x, Edje_Real_Part *rel1_to_y, Edje_Real_Part *rel2_to_x, Edje_Real_Part *rel2_to_y, Edje_Real_Part *confine_to, Edje_Calc_Params *params, int flags);
+static void _edje_part_recalc(Edje *ed, Edje_Real_Part *ep, int flags);
+
+void
+_edje_part_pos_set(Edje *ed, Edje_Real_Part *ep, int mode, double pos)
+{
+   double npos;
+
+   pos = CLAMP(pos, 0.0, 1.0);
+
+   npos = 0.0;
+   /* take linear pos along timescale and use interpolation method */
+   switch (mode)
+     {
+      case EDJE_TWEEN_MODE_SINUSOIDAL:
+       npos = (1.0 - cos(pos * PI)) / 2.0;
+       break;
+      case EDJE_TWEEN_MODE_ACCELERATE:
+       npos = 1.0 - sin((PI / 2.0) + (pos * PI / 2.0));
+       break;
+      case EDJE_TWEEN_MODE_DECELERATE:
+       npos = sin(pos * PI / 2.0);
+       break;
+      case EDJE_TWEEN_MODE_LINEAR:
+       npos = pos;
+       break;
+      default:
+       break;
+     }
+   if (npos == ep->description_pos) return;
+
+   ep->description_pos = npos;
+
+   ed->dirty = 1;
+}
+
+Edje_Part_Description *
+_edje_part_description_find(Edje *ed, Edje_Real_Part *rp, const char *name,
+                            double val)
+{
+   Edje_Part *ep = rp->part;
+   Edje_Part_Description *ret = NULL;
+   Evas_List *l;
+   double min_dst = 999.0;
+
+   if (!strcmp(name, "default") && val == 0.0)
+     return ep->default_desc;
+
+   if (!strcmp(name, "custom"))
+     return rp->custom.description;
+
+   if (!strcmp(name, "default"))
+     {
+       ret = ep->default_desc;
+       min_dst = ABS(ep->default_desc->state.value - val);
+     }
+
+   for (l = ep->other_desc; l; l = l->next)
+     {
+       Edje_Part_Description *d = l->data;
+
+       if (!strcmp(d->state.name, name))
+         {
+            double dst;
+
+            dst = ABS(d->state.value - val);
+            if (dst < min_dst)
+              {
+                 ret = d;
+                 min_dst = dst;
+              }
+         }
+     }
+
+   return ret;
+}
+
+void
+_edje_part_description_apply(Edje *ed, Edje_Real_Part *ep, const char *d1, double v1, const char *d2, double v2)
+{
+   if (!d1) d1 = "default";
+   if (!d2) d2 = "default";
+
+   ep->param1.description = _edje_part_description_find(ed, ep, d1, v1);
+   if (!ep->param1.description)
+     ep->param1.description = ep->part->default_desc; /* never NULL */
+
+   ep->param2.description = _edje_part_description_find(ed, ep, d2, v2);
+
+   ep->param1.rel1_to_x = ep->param1.rel1_to_y = NULL;
+   ep->param1.rel2_to_x = ep->param1.rel2_to_y = NULL;
+
+   if (ep->param1.description->rel1.id_x >= 0)
+     ep->param1.rel1_to_x = ed->table_parts[ep->param1.description->rel1.id_x % ed->table_parts_size];
+   if (ep->param1.description->rel1.id_y >= 0)
+     ep->param1.rel1_to_y = ed->table_parts[ep->param1.description->rel1.id_y % ed->table_parts_size];
+   if (ep->param1.description->rel2.id_x >= 0)
+     ep->param1.rel2_to_x = ed->table_parts[ep->param1.description->rel2.id_x % ed->table_parts_size];
+   if (ep->param1.description->rel2.id_y >= 0)
+     ep->param1.rel2_to_y = ed->table_parts[ep->param1.description->rel2.id_y % ed->table_parts_size];
+
+   ep->param2.rel1_to_x = ep->param2.rel1_to_y = NULL;
+   ep->param2.rel2_to_x = ep->param2.rel2_to_y = NULL;
+
+   if (ep->param2.description)
+     {
+       if (ep->param2.description->rel1.id_x >= 0)
+         ep->param2.rel1_to_x = ed->table_parts[ep->param2.description->rel1.id_x % ed->table_parts_size];
+       if (ep->param2.description->rel1.id_y >= 0)
+         ep->param2.rel1_to_y = ed->table_parts[ep->param2.description->rel1.id_y % ed->table_parts_size];
+       if (ep->param2.description->rel2.id_x >= 0)
+         ep->param2.rel2_to_x = ed->table_parts[ep->param2.description->rel2.id_x % ed->table_parts_size];
+       if (ep->param2.description->rel2.id_y >= 0)
+         ep->param2.rel2_to_y = ed->table_parts[ep->param2.description->rel2.id_y % ed->table_parts_size];
+     }
+
+   if (ep->description_pos == 0.0)
+     ep->chosen_description = ep->param1.description;
+   else
+     ep->chosen_description = ep->param2.description;
+
+   ed->dirty = 1;
+}
+
+void
+_edje_recalc(Edje *ed)
+{
+   int i;
+
+   if (!ed->dirty) return;
+   if (ed->freeze)
+     {
+       ed->recalc = 1;
+       if (!ed->calc_only) return;
+     }
+   for (i = 0; i < ed->table_parts_size; i++)
+     {
+       Edje_Real_Part *ep;
+
+       ep = ed->table_parts[i];
+       ep->calculated = FLAG_NONE;
+       ep->calculating = FLAG_NONE;
+     }
+   for (i = 0; i < ed->table_parts_size; i++)
+     {
+       Edje_Real_Part *ep;
+
+       ep = ed->table_parts[i];
+       if (ep->calculated != FLAG_XY)
+         _edje_part_recalc(ed, ep, (~ep->calculated) & FLAG_XY);
+     }
+   ed->dirty = 0;
+   if (!ed->calc_only) ed->recalc = 0;
+}
+
+int
+_edje_part_dragable_calc(Edje *ed, Edje_Real_Part *ep, double *x, double *y)
+{
+   if ((ep->part->dragable.x != 0) || (ep->part->dragable.y != 0))
+     {
+       if (ep->confine_to)
+         {
+            double dx, dy, dw, dh;
+            int ret = 0;
+
+            if ((ep->part->dragable.x != 0) &&
+                (ep->part->dragable.y != 0 )) ret = 3;
+            else if (ep->part->dragable.x != 0) ret = 1;
+            else if (ep->part->dragable.y != 0) ret = 2;
+
+            dx = ep->x - ep->confine_to->x;
+            dw = ep->confine_to->w - ep->w;
+            if (dw != 0.0) dx /= dw;
+            else dx = 0.0;
+
+            dy = ep->y - ep->confine_to->y;
+            dh = ep->confine_to->h - ep->h;
+            if (dh != 0) dy /= dh;
+            else dy = 0.0;
+
+            if (x) *x = dx;
+            if (y) *y = dy;
+
+            return ret;
+         }
+       else
+         {
+            if (x) *x = (double)(ep->drag.tmp.x + ep->drag.x);
+            if (y) *y = (double)(ep->drag.tmp.y + ep->drag.y);
+            return 0;
+         }
+     }
+   if (x) *x = 0.0;
+   if (y) *y = 0.0;
+   return 0;
+   ed = NULL;
+}
+
+void
+_edje_dragable_pos_set(Edje *ed, Edje_Real_Part *ep, double x, double y)
+{
+   /* check whether this part is dragable at all */
+   if (!ep->part->dragable.x && !ep->part->dragable.y) return;
+
+   /* instead of checking for equality, we really should check that
+    * the difference is greater than foo, but I have no idea what
+    * value we would set foo to, because it would depend on the
+    * size of the dragable...
+    */
+   if (ep->drag.x != x || ep->drag.tmp.x)
+     {
+       ep->drag.x = x;
+       ep->drag.tmp.x = 0;
+       ep->drag.need_reset = 0;
+       ed->dirty = 1;
+     }
+
+   if (ep->drag.y != y || ep->drag.tmp.y)
+     {
+       ep->drag.y = y;
+       ep->drag.tmp.y = 0;
+       ep->drag.need_reset = 0;
+       ed->dirty = 1;
+     }
+
+   _edje_recalc(ed); /* won't do anything if dirty flag isn't set */
+}
+
+static void
+_edje_part_recalc_single(Edje *ed,
+                        Edje_Real_Part *ep,
+                        Edje_Part_Description *desc,
+                        Edje_Part_Description *chosen_desc,
+                        Edje_Real_Part *rel1_to_x,
+                        Edje_Real_Part *rel1_to_y,
+                        Edje_Real_Part *rel2_to_x,
+                        Edje_Real_Part *rel2_to_y,
+                        Edje_Real_Part *confine_to,
+                        Edje_Calc_Params *params,
+                        int flags)
+{
+   int minw = 0, minh = 0, maxw = 0, maxh = 0;
+
+   flags = FLAG_XY;
+
+//   if (flags & FLAG_X)
+     {
+       minw = desc->min.w;
+       if (ep->swallow_params.min.w > desc->min.w) minw = ep->swallow_params.min.w;
+
+       /* XXX TODO: remove need of EDJE_INF_MAX_W, see edje_util.c */
+       if ((ep->swallow_params.max.w <= 0) ||
+           (ep->swallow_params.max.w == EDJE_INF_MAX_W))
+         maxw = desc->max.w;
+       else
+         {
+            if (desc->max.w <= 0)
+              maxw = ep->swallow_params.max.w;
+            else
+              maxw = MIN(ep->swallow_params.max.w, desc->max.w);
+         }
+     }
+//   if (flags & FLAG_Y)
+     {
+       minh = desc->min.h;
+       if (ep->swallow_params.min.h > desc->min.h) minh = ep->swallow_params.min.h;
+
+       /* XXX TODO: remove need of EDJE_INF_MAX_H, see edje_util.c */
+       if ((ep->swallow_params.max.h <= 0) ||
+           (ep->swallow_params.max.h == EDJE_INF_MAX_H))
+         maxh = desc->max.h;
+       else
+         {
+            if (desc->max.h <= 0)
+              maxh = ep->swallow_params.max.h;
+            else
+              maxh = MIN(ep->swallow_params.max.h, desc->max.h);
+         }
+     }
+   /* relative coords of top left & bottom right */
+   if (flags & FLAG_X)
+     {
+       if (rel1_to_x)
+         params->x = desc->rel1.offset_x +
+         rel1_to_x->x + (desc->rel1.relative_x * rel1_to_x->w);
+       else
+         params->x = desc->rel1.offset_x +
+         (desc->rel1.relative_x * ed->w);
+       if (rel2_to_x)
+         params->w = desc->rel2.offset_x +
+         rel2_to_x->x + (desc->rel2.relative_x * rel2_to_x->w) -
+         params->x + 1;
+       else
+         params->w = desc->rel2.offset_x +
+         (desc->rel2.relative_x * ed->w) -
+         params->x + 1;
+     }
+   if (flags & FLAG_Y)
+     {
+       if (rel1_to_y)
+         params->y = desc->rel1.offset_y +
+         rel1_to_y->y + (desc->rel1.relative_y * rel1_to_y->h);
+       else
+         params->y = desc->rel1.offset_y +
+         (desc->rel1.relative_y * ed->h);
+       if (rel2_to_y)
+         params->h = desc->rel2.offset_y +
+         rel2_to_y->y + (desc->rel2.relative_y * rel2_to_y->h) -
+         params->y + 1;
+       else
+         params->h = desc->rel2.offset_y +
+         (desc->rel2.relative_y * ed->h) -
+         params->y + 1;
+     }
+
+   /* aspect */
+   if ((params->h > 0) &&
+       (((flags | ep->calculated) & FLAG_XY) == FLAG_XY))
+     {
+       int apref;
+       double aspect, amax, amin;
+       double new_w = 0, new_h = 0, want_x, want_y, want_w, want_h;
+
+       want_x = params->x;
+       want_w = new_w = params->w;
+
+       want_y = params->y;
+       want_h = new_h = params->h;
+
+       aspect = (double)params->w / (double)params->h;
+       apref = desc->aspect.prefer;
+       amax = desc->aspect.max;
+       amin = desc->aspect.min;
+       if ((ep->swallow_params.aspect.w > 0) &&
+           (ep->swallow_params.aspect.h > 0))
+         amin = amax =
+         (double)ep->swallow_params.aspect.w /
+         (double)ep->swallow_params.aspect.h;
+       if (ep->swallow_params.aspect.mode > EDJE_ASPECT_CONTROL_NONE)
+         {
+            switch (ep->swallow_params.aspect.mode)
+              {
+               case EDJE_ASPECT_CONTROL_NEITHER:
+                 apref = EDJE_ASPECT_PREFER_NONE;
+                 break;
+               case EDJE_ASPECT_CONTROL_HORIZONTAL:
+                 apref = EDJE_ASPECT_PREFER_HORIZONTAL;
+                 break;
+               case EDJE_ASPECT_CONTROL_VERTICAL:
+                 apref = EDJE_ASPECT_PREFER_VERTICAL;
+                 break;
+               case EDJE_ASPECT_CONTROL_BOTH:
+                 apref = EDJE_ASPECT_PREFER_BOTH;
+                 break;
+               default:
+                 break;
+              }
+         }
+       if (apref == EDJE_ASPECT_PREFER_NONE) /* keep botth dimensions in check */
+         {
+            /* adjust for min aspect (width / height) */
+            if ((amin > 0.0) && (aspect < amin))
+              {
+                 new_h = (params->w / amin);
+                 new_w = (params->h * amin);
+              }
+            /* adjust for max aspect (width / height) */
+            if ((amax > 0.0) && (aspect > amax))
+              {
+                 new_h = (params->w / amax);
+                 new_w = (params->h * amax);
+              }
+            if ((amax > 0.0) && (new_w < params->w))
+              {
+                 new_w = params->w;
+                 new_h = params->w / amax;
+              }
+            if ((amax > 0.0) && (new_h < params->h))
+              {
+                 new_w = params->h * amax;
+                 new_h = params->h;
+              }
+         } /* prefer vertical size as determiner */
+       else if (apref == EDJE_ASPECT_PREFER_VERTICAL) /* keep both dimensions in check */
+         {
+            /* adjust for max aspect (width / height) */
+            if ((amax > 0.0) && (aspect > amax))
+              new_w = (params->h * amax);
+            /* adjust for min aspect (width / height) */
+            if ((amin > 0.0) && (aspect < amin))
+              new_w = (params->h * amin);
+         } /* prefer horizontal size as determiner */
+       else if (apref == EDJE_ASPECT_PREFER_HORIZONTAL) /* keep both dimensions in check */
+         {
+            /* adjust for max aspect (width / height) */
+            if ((amax > 0.0) && (aspect > amax))
+              new_h = (params->w / amax);
+            /* adjust for min aspect (width / height) */
+            if ((amin > 0.0) && (aspect < amin))
+              new_h = (params->w / amin);
+         }
+       else if (apref == EDJE_ASPECT_PREFER_BOTH) /* keep both dimensions in check */
+         {
+            /* adjust for max aspect (width / height) */
+            if ((amax > 0.0) && (aspect > amax))
+              {
+                 new_w = (params->h * amax);
+                 new_h = (params->w / amax);
+              }
+            /* adjust for min aspect (width / height) */
+            if ((amin > 0.0) && (aspect < amin))
+              {
+                 new_w = (params->h * amin);
+                 new_h = (params->w / amin);
+              }
+         }
+
+        if (!((amin > 0.0) && (amax > 0.0) && (apref == EDJE_ASPECT_PREFER_NONE)))
+         {
+            if ((maxw >= 0) && (new_w > maxw)) new_w = maxw;
+            if (new_w < minw) new_w = minw;
+
+            if ((maxh >= 0) && (new_h > maxh)) new_h = maxh;
+            if (new_h < minh) new_h = minh;
+         }
+
+       /* do real adjustment */
+       if (apref == EDJE_ASPECT_PREFER_BOTH)
+         {
+            if (amin == 0.0) amin = amax;
+            if (amin != 0.0)
+              {
+                 /* fix h and vary w */
+                 if (new_w > params->w)
+                   {
+//               params->w = new_w;
+// EXCEEDS BOUNDS in W
+                      new_h = (params->w / amin);
+                      new_w = params->w;
+                      if (new_h > params->h)
+                        {
+                           new_h = params->h;
+                           new_w = (params->h * amin);
+                        }
+                   }
+                 /* fix w and vary h */
+                 else
+                   {
+//               params->h = new_h;
+// EXCEEDS BOUNDS in H
+                      new_h = params->h;
+                      new_w = (params->h * amin);
+                      if (new_w > params->w)
+                        {
+                           new_h = (params->w / amin);
+                           new_w = params->w;
+                        }
+                   }
+                 params->w = new_w;
+                 params->h = new_h;
+              }
+         }
+       else
+         {
+            if ((amin > 0.0) && (amax > 0.0) && (apref == EDJE_ASPECT_PREFER_NONE))
+              {
+                 params->w = new_w;
+                 params->h = new_h;
+              }
+            else if ((params->h - new_h) > (params->w - new_w))
+              {
+                 if (params->h < new_h)
+                   params->h = new_h;
+                 else if (params->h > new_h)
+                   params->h = new_h;
+                 if (apref == EDJE_ASPECT_PREFER_VERTICAL)
+                   params->w = new_w;
+              }
+            else
+              {
+                 if (params->w < new_w)
+                   params->w = new_w;
+                 else if (params->w > new_w)
+                   params->w = new_w;
+                 if (apref == EDJE_ASPECT_PREFER_HORIZONTAL)
+                   params->h = new_h;
+              }
+         }
+       params->x = want_x + ((want_w - params->w) * desc->align.x);
+       params->y = want_y + ((want_h - params->h) * desc->align.y);
+     }
+
+   /* size step */
+   if (flags & FLAG_X)
+     {
+       if (desc->step.x > 0)
+         {
+            int steps;
+            int new_w;
+
+            steps = params->w / desc->step.x;
+            new_w = desc->step.x * steps;
+            if (params->w > new_w)
+              {
+                 params->x = params->x +
+                   ((params->w - new_w) * desc->align.x);
+                 params->w = new_w;
+              }
+         }
+     }
+   if (flags & FLAG_Y)
+     {
+       if (desc->step.y > 0)
+         {
+            int steps;
+            int new_h;
+
+            steps = params->h / desc->step.y;
+            new_h = desc->step.y * steps;
+            if (params->h > new_h)
+              {
+                 params->y = params->y +
+                   ((params->h - new_h) * desc->align.y);
+                 params->h = new_h;
+              }
+         }
+     }
+   /* if we have text that wants to make the min size the text size... */
+   if ((chosen_desc) && (ep->part->type == EDJE_PART_TYPE_TEXTBLOCK))
+     {
+       Evas_Coord tw, th, ins_l, ins_r, ins_t, ins_b;
+       const char *text = "";
+       const char *style = "";
+       Edje_Style *stl  = NULL;
+       Evas_List *l;
+
+       if (chosen_desc->text.id_source >= 0)
+         {
+            ep->text.source = ed->table_parts[chosen_desc->text.id_source % ed->table_parts_size];
+            if (ep->text.source->chosen_description->text.style)
+              style = ep->text.source->chosen_description->text.style;
+         }
+       else
+         {
+            ep->text.source = NULL;
+            if (chosen_desc->text.style)
+              style = chosen_desc->text.style;
+         }
+
+       if (chosen_desc->text.id_text_source >= 0)
+         {
+            ep->text.text_source = ed->table_parts[chosen_desc->text.id_text_source % ed->table_parts_size];
+            text = ep->text.text_source->chosen_description->text.text;
+            if (ep->text.text_source->text.text) text = ep->text.text_source->text.text;
+         }
+       else
+         {
+            ep->text.text_source = NULL;
+            text = chosen_desc->text.text;
+            if (ep->text.text) text = ep->text.text;
+         }
+
+       for (l = ed->file->styles; l; l = l->next)
+         {
+            stl = l->data;
+            if ((stl->name) && (!strcmp(stl->name, style))) break;
+            stl = NULL;
+         }
+
+       if (stl)
+         {
+            const char *ptxt;
+
+            if (evas_object_textblock_style_get(ep->object) != stl->style)
+              evas_object_textblock_style_set(ep->object, stl->style);
+            ptxt = evas_object_textblock_text_markup_get(ep->object);
+            if (((!ptxt) && (text)) ||
+                ((ptxt) && (text) && (strcmp(ptxt, text))) ||
+                ((ptxt) && (!text)))
+              evas_object_textblock_text_markup_set(ep->object, text);
+            if ((chosen_desc->text.min_x) || (chosen_desc->text.min_y))
+              {
+                 int mw = 0, mh = 0;
+
+                 tw = th = 0;
+                 if (!chosen_desc->text.min_x)
+                   {
+                      evas_object_resize(ep->object, params->w, params->h);
+                      evas_object_textblock_size_formatted_get(ep->object, &tw, &th);
+                   }
+                 else
+                   evas_object_textblock_size_native_get(ep->object, &tw, &th);
+                 evas_object_textblock_style_insets_get(ep->object, &ins_l, &ins_r, &ins_t, &ins_b);
+                 mw = ins_l + tw + ins_r;
+                 mh = ins_t + th + ins_b;
+                 if (chosen_desc->text.min_x)
+                   {
+                      if (mw > minw) minw = mw;
+                   }
+                 if (chosen_desc->text.min_y)
+                   {
+                      if (mh > minh) minh = mh;
+                   }
+              }
+         }
+       if ((chosen_desc->text.max_x) || (chosen_desc->text.max_y))
+         {
+            int mw = 0, mh = 0;
+
+            tw = th = 0;
+            if (!chosen_desc->text.max_x)
+              {
+                 evas_object_resize(ep->object, params->w, params->h);
+                 evas_object_textblock_size_formatted_get(ep->object, &tw, &th);
+              }
+            else
+              evas_object_textblock_size_native_get(ep->object, &tw, &th);
+            evas_object_textblock_style_insets_get(ep->object, &ins_l, &ins_r, &ins_t, &ins_b);
+            mw = ins_l + tw + ins_r;
+            mh = ins_t + th + ins_b;
+            if (chosen_desc->text.max_x)
+              {
+                 if (mw > maxw) maxw = mw;
+              }
+            if (chosen_desc->text.max_y)
+              {
+                 if (mh > maxw) maxh = mh;
+              }
+         }
+     }
+   else if ((chosen_desc) && (ep->part->type == EDJE_PART_TYPE_TEXT))
+     {
+       const char      *text;
+       const char      *font;
+       char            *sfont = NULL;
+       int              size;
+       Evas_Coord       tw, th;
+       int              inlined_font = 0;
+
+       /* Update a object_text part */
+
+       if (chosen_desc->text.id_source >= 0)
+         ep->text.source = ed->table_parts[chosen_desc->text.id_source % ed->table_parts_size];
+       else
+         ep->text.source = NULL;
+
+       if (chosen_desc->text.id_text_source >= 0)
+         ep->text.text_source = ed->table_parts[chosen_desc->text.id_text_source % ed->table_parts_size];
+       else
+         ep->text.text_source = NULL;
+
+       if (ep->text.text_source)
+         text = ep->text.text_source->chosen_description->text.text;
+       else
+         text = chosen_desc->text.text;
+
+       if (ep->text.source)
+         font = _edje_text_class_font_get(ed, ep->text.source->chosen_description, &size, &sfont);
+       else
+         font = _edje_text_class_font_get(ed, chosen_desc, &size, &sfont);
+
+       if (!font) font = "";
+
+       if (ep->text.text_source)
+         {
+            if (ep->text.text_source->text.text) text = ep->text.text_source->text.text;
+         }
+       else
+         {
+            if (ep->text.text) text = ep->text.text;
+         }
+
+       if (ep->text.source)
+         {
+            if (ep->text.source->text.font) font = ep->text.source->text.font;
+            if (ep->text.source->text.size > 0) size = ep->text.source->text.size;
+         }
+       else
+         {
+            if (ep->text.font) font = ep->text.font;
+            if (ep->text.size > 0) size = ep->text.size;
+         }
+       if (!text) text = "";
+
+        /* check if the font is embedded in the .eet */
+       if (ed->file->font_hash)
+         {
+            Edje_Font_Directory_Entry *fnt;
+
+            fnt = evas_hash_find(ed->file->font_hash, font);
+
+            if (fnt)
+              {
+                 font = fnt->path;
+                 inlined_font = 1;
+              }
+         }
+       if (inlined_font) evas_object_text_font_source_set(ep->object, ed->path);
+       else evas_object_text_font_source_set(ep->object, NULL);
+
+       if ((_edje_fontset_append) && (font))
+         {
+            char *font2;
+
+            font2 = malloc(strlen(font) + 1 + strlen(_edje_fontset_append) + 1);
+            if (font2)
+              {
+                 strcpy(font2, font);
+                 strcat(font2, ",");
+                 strcat(font2, _edje_fontset_append);
+                 evas_object_text_font_set(ep->object, font2, size);
+                 free(font2);
+              }
+         }
+       else
+         evas_object_text_font_set(ep->object, font, size);
+       if ((chosen_desc->text.min_x) || (chosen_desc->text.min_y) ||
+           (chosen_desc->text.max_x) || (chosen_desc->text.max_y))
+         {
+            int mw, mh;
+            Evas_Text_Style_Type style;
+            const Evas_Text_Style_Type styles[] = {
+               EVAS_TEXT_STYLE_PLAIN,
+               EVAS_TEXT_STYLE_PLAIN,
+               EVAS_TEXT_STYLE_OUTLINE,
+               EVAS_TEXT_STYLE_SOFT_OUTLINE,
+               EVAS_TEXT_STYLE_SHADOW,
+               EVAS_TEXT_STYLE_SOFT_SHADOW,
+               EVAS_TEXT_STYLE_OUTLINE_SHADOW,
+               EVAS_TEXT_STYLE_OUTLINE_SOFT_SHADOW,
+               EVAS_TEXT_STYLE_FAR_SHADOW,
+               EVAS_TEXT_STYLE_FAR_SOFT_SHADOW,
+               EVAS_TEXT_STYLE_GLOW
+            };
+
+            if (ep->part->effect < EDJE_TEXT_EFFECT_LAST)
+              style = styles[ep->part->effect];
+            else
+              style = EVAS_TEXT_STYLE_PLAIN;
+
+            evas_object_text_style_set(ep->object, style);
+            evas_object_text_text_set(ep->object, text);
+            evas_object_geometry_get(ep->object, NULL, NULL, &tw, &th);
+            if (chosen_desc->text.max_x)
+              {
+                 int l, r;
+                 evas_object_text_style_pad_get(ep->object, &l, &r, NULL, NULL);
+                 mw = tw + l + r;
+                 if ((maxw < 0) || (mw < maxw)) maxw = mw;
+              }
+            if (chosen_desc->text.max_y)
+              {
+                 int t, b;
+                 evas_object_text_style_pad_get(ep->object, NULL, NULL, &t, &b);
+                 mh = th + t + b;
+                 if ((maxh < 0) || (mh < maxh)) maxh = mh;
+              }
+            if (chosen_desc->text.min_x)
+              {
+                 int l, r;
+                 evas_object_text_style_pad_get(ep->object, &l, &r, NULL, NULL);
+                 mw = tw + l + r;
+                 if (mw > minw) minw = mw;
+              }
+            if (chosen_desc->text.min_y)
+              {
+                 int t, b;
+                 evas_object_text_style_pad_get(ep->object, NULL, NULL, &t, &b);
+                 mh = th + t + b;
+                 if (mh > minh) minh = mh;
+              }
+         }
+       if (sfont) free(sfont);
+     }
+   /* rememebr what our size is BEFORE we go limit it */
+   params->req.x = params->x;
+   params->req.y = params->y;
+   params->req.w = params->w;
+   params->req.h = params->h;
+   /* adjust for min size */
+   if (flags & FLAG_X)
+     {
+       if (minw >= 0)
+         {
+            if (params->w < minw)
+              {
+                 params->x = params->x +
+                   ((params->w - minw) * desc->align.x);
+                 params->w = minw;
+              }
+         }
+     }
+   if (flags & FLAG_Y)
+     {
+       if (minh >= 0)
+         {
+            if (params->h < minh)
+              {
+                 params->y = params->y +
+                   ((params->h - minh) * desc->align.y);
+                 params->h = minh;
+              }
+         }
+     }
+   /* adjust for max size */
+   if (flags & FLAG_X)
+     {
+       if (maxw >= 0)
+         {
+            if (params->w > maxw)
+              {
+                 params->x = params->x +
+                   ((params->w - maxw) * desc->align.x);
+                 params->w = maxw;
+              }
+         }
+     }
+   if (flags & FLAG_Y)
+     {
+       if (maxh >= 0)
+         {
+            if (params->h > maxh)
+              {
+                 params->y = params->y +
+                   ((params->h - maxh) * desc->align.y);
+                 params->h = maxh;
+              }
+         }
+     }
+   /* confine */
+   if (confine_to)
+     {
+       int offset;
+       int step;
+       double v;
+
+       /* complex dragable params */
+       if (flags & FLAG_X)
+         {
+            v = ep->drag.size.x * confine_to->w;
+
+            if ((minw > 0) && (v < minw)) params->w = minw;
+            else if ((maxw >= 0) && (v > maxw)) params->w = maxw;
+            else params->w = v;
+
+            offset = (ep->drag.x * (confine_to->w - params->w)) +
+              ep->drag.tmp.x;
+            if (ep->part->dragable.step_x > 0)
+              {
+                 params->x = confine_to->x +
+                   ((offset / ep->part->dragable.step_x) * ep->part->dragable.step_x);
+              }
+            else if (ep->part->dragable.count_x > 0)
+              {
+                 step = (confine_to->w - params->w) / ep->part->dragable.count_x;
+                 if (step < 1) step = 1;
+                 params->x = confine_to->x +
+                   ((offset / step) * step);
+              }
+            params->req_drag.x = params->x;
+            params->req_drag.w = params->w;
+         }
+       if (flags & FLAG_Y)
+         {
+            v = ep->drag.size.y * confine_to->h;
+
+            if ((minh > 0) && (v < minh)) params->h = minh;
+            else if ((maxh >= 0) && (v > maxh)) params->h = maxh;
+            else params->h = v;
+
+            offset = (ep->drag.y * (confine_to->h - params->h)) +
+              ep->drag.tmp.y;
+            if (ep->part->dragable.step_y > 0)
+              {
+                 params->y = confine_to->y +
+                   ((offset / ep->part->dragable.step_y) * ep->part->dragable.step_y);
+              }
+            else if (ep->part->dragable.count_y > 0)
+              {
+                 step = (confine_to->h - params->h) / ep->part->dragable.count_y;
+                 if (step < 1) step = 1;
+                 params->y = confine_to->y +
+                   ((offset / step) * step);
+              }
+            params->req_drag.y = params->y;
+            params->req_drag.h = params->h;
+         }
+       /* limit to confine */
+       if (flags & FLAG_X)
+         {
+            if (params->x < confine_to->x)
+              {
+                 params->x = confine_to->x;
+              }
+            if ((params->x + params->w) > (confine_to->x + confine_to->w))
+              {
+                 params->x = confine_to->x + (confine_to->w - params->w);
+              }
+         }
+       if (flags & FLAG_Y)
+         {
+            if (params->y < confine_to->y)
+              {
+                 params->y = confine_to->y;
+              }
+            if ((params->y + params->h) > (confine_to->y + confine_to->h))
+              {
+                 params->y = confine_to->y + (confine_to->h - params->h);
+              }
+         }
+     }
+   else
+     {
+       /* simple dragable params */
+       if (flags & FLAG_X)
+         {
+            params->x += ep->drag.x + ep->drag.tmp.x;
+            params->req_drag.x = params->x;
+            params->req_drag.w = params->w;
+         }
+       if (flags & FLAG_Y)
+         {
+            params->y += ep->drag.y + ep->drag.tmp.y;
+            params->req_drag.y = params->y;
+            params->req_drag.h = params->h;
+         }
+     }
+   /* fill */
+
+   if (ep->part->type == EDJE_PART_TYPE_GRADIENT && desc->gradient.use_rel && (!desc->gradient.type || !strcmp(desc->gradient.type, "linear")))
+     {
+       int x2, y2;
+       int dx, dy;
+       double m;
+       int angle;
+
+       params->fill.x = desc->gradient.rel1.offset_x + (params->w * desc->gradient.rel1.relative_x);
+       params->fill.y = desc->gradient.rel1.offset_y + (params->h * desc->gradient.rel1.relative_y);
+
+       x2 = desc->gradient.rel2.offset_x + (params->w * desc->gradient.rel2.relative_x);
+       y2 = desc->gradient.rel2.offset_y + (params->h * desc->gradient.rel2.relative_y);
+
+       params->fill.w = 1; /* doesn't matter for linear grads */
+
+       dy = y2 - params->fill.y;
+       dx = x2 - params->fill.x;
+       params->fill.h = sqrt(dx * dx + dy * dy);
+
+       params->fill.spread = desc->fill.spread;
+
+       if (dx == 0 && dy == 0)
+         {
+            angle = 0;
+         }
+       else if (dx == 0)
+         {
+            if (dy > 0) angle = 0;
+            else angle = 180;
+         }
+       else if (dy == 0)
+         {
+            if (dx > 0) angle = 270;
+            else angle = 90;
+         }
+       else
+         {
+            m = (double)dx / (double)dy;
+            angle = atan(m) * 180 / M_PI;
+            if (dy < 0)
+              angle = 180 - angle;
+            else
+              angle = 360 - angle;
+         }
+       params->fill.angle = angle;
+     }
+   else
+     {
+       params->smooth = desc->fill.smooth;
+       if (flags & FLAG_X)
+         {
+            int fw;
+
+             if (desc->fill.type == EDJE_FILL_TYPE_TILE)
+              evas_object_image_size_get(ep->object, &fw, NULL);
+            else
+              fw = params->w;
+
+            params->fill.x = desc->fill.pos_abs_x + (fw * desc->fill.pos_rel_x);
+            params->fill.w = desc->fill.abs_x + (fw * desc->fill.rel_x);
+         }
+       if (flags & FLAG_Y)
+         {
+            int fh;
+             if (desc->fill.type == EDJE_FILL_TYPE_TILE)
+              evas_object_image_size_get(ep->object, NULL, &fh);
+            else
+              fh = params->h;
+
+            params->fill.y = desc->fill.pos_abs_y + (fh * desc->fill.pos_rel_y);
+            params->fill.h = desc->fill.abs_y + (fh * desc->fill.rel_y);
+         }
+       params->fill.angle = desc->fill.angle;
+       params->fill.spread = desc->fill.spread;
+     }
+   /* colors */
+
+   params->color.r = desc->color.r;
+   params->color.g = desc->color.g;
+   params->color.b = desc->color.b;
+   params->color.a = desc->color.a;
+   params->color2.r = desc->color2.r;
+   params->color2.g = desc->color2.g;
+   params->color2.b = desc->color2.b;
+   params->color2.a = desc->color2.a;
+   params->color3.r = desc->color3.r;
+   params->color3.g = desc->color3.g;
+   params->color3.b = desc->color3.b;
+   params->color3.a = desc->color3.a;
+
+   if ((desc->color_class) && (*desc->color_class))
+     {
+       Edje_Color_Class *cc;
+
+       cc = _edje_color_class_find(ed, desc->color_class);
+       if (cc)
+         {
+            params->color.r = (((int)cc->r + 1) * desc->color.r) >> 8;
+            params->color.g = (((int)cc->g + 1) * desc->color.g) >> 8;
+            params->color.b = (((int)cc->b + 1) * desc->color.b) >> 8;
+            params->color.a = (((int)cc->a + 1) * desc->color.a) >> 8;
+            params->color2.r = (((int)cc->r2 + 1) * desc->color2.r) >> 8;
+            params->color2.g = (((int)cc->g2 + 1) * desc->color2.g) >> 8;
+            params->color2.b = (((int)cc->b2 + 1) * desc->color2.b) >> 8;
+            params->color2.a = (((int)cc->a2 + 1) * desc->color2.a) >> 8;
+            params->color3.r = (((int)cc->r3 + 1) * desc->color3.r) >> 8;
+            params->color3.g = (((int)cc->g3 + 1) * desc->color3.g) >> 8;
+            params->color3.b = (((int)cc->b3 + 1) * desc->color3.b) >> 8;
+            params->color3.a = (((int)cc->a3 + 1) * desc->color3.a) >> 8;
+         }
+     }
+
+
+   /* visible */
+   params->visible = desc->visible;
+   /* border */
+   if (flags & FLAG_X)
+     {
+       params->border.l = desc->border.l;
+       params->border.r = desc->border.r;
+     }
+   if (flags & FLAG_Y)
+     {
+       params->border.t = desc->border.t;
+       params->border.b = desc->border.b;
+     }
+   /* text.align */
+   if (flags & FLAG_X)
+     {
+       params->text.align.x = desc->text.align.x;
+     }
+   if (flags & FLAG_Y)
+     {
+       params->text.align.y = desc->text.align.y;
+     }
+   params->text.elipsis = desc->text.elipsis;
+   params->gradient.id = desc->gradient.id;
+   params->gradient.type = desc->gradient.type;
+}
+
+static void
+_edje_gradient_recalc_apply(Edje *ed, Edje_Real_Part *ep, Edje_Calc_Params *p3, Edje_Part_Description *chosen_desc)
+{
+   evas_object_gradient_fill_angle_set(ep->object, p3->fill.angle);
+   evas_object_gradient_fill_spread_set(ep->object, p3->fill.spread);
+   evas_object_gradient_fill_set(ep->object, p3->fill.x, p3->fill.y,
+                                p3->fill.w, p3->fill.h);
+
+   if (p3->gradient.type && p3->gradient.type[0])
+     evas_object_gradient_type_set(ep->object, p3->gradient.type, NULL);
+
+   if (ed->file->spectrum_dir && ed->file->spectrum_dir->entries &&
+       p3->gradient.id != ep->gradient_id)
+     {
+       Edje_Spectrum_Directory_Entry *se;
+       Evas_List *l;
+
+       se = evas_list_nth(ed->file->spectrum_dir->entries, p3->gradient.id);
+       if (se)
+         {
+            evas_object_gradient_clear(ep->object);
+            for (l = se->color_list; l; l = l->next)
+              {
+                 Edje_Spectrum_Color *sc = l->data;
+                 evas_object_gradient_color_stop_add(ep->object, sc->r,
+                                                     sc->g, sc->b, 255,
+                                                     sc->d);
+                 evas_object_gradient_alpha_stop_add(ep->object,
+                                                     sc->a, sc->d);
+              }
+            ep->gradient_id = p3->gradient.id;
+         }
+     }
+}
+
+static int
+_edje_nitoa_rec(char *string, int len, unsigned int value)
+{
+   const char  *array = "0123456789";
+   int          length;
+   int          quotient;
+   int          modulo;
+
+   if (len <= 0) return 0;
+   if (value == 0) return 0;
+
+   quotient = value / 10;
+   modulo = value % 10;
+
+   length = _edje_nitoa_rec(string, len - 1, quotient);
+
+   if (length + 1 > len) return length;
+
+   string[length] = array[modulo];
+
+   return length + 1;
+}
+
+static int
+_edje_nitoa(char *string, int len, int value)
+{
+   int length;
+
+   if (len <= 0) return 0;
+   if (len == 1)
+     {
+       *string = '\0';
+       return 1;
+     }
+
+   if (value < 0)
+     {
+       *string = '-';
+
+       ++string;
+       --len;
+     }
+
+   if (value == 0)
+     {
+       strncpy(string, "0", len);
+       return 1;
+     }
+
+   length = _edje_nitoa_rec(string, len, value);
+   string[length] = '\0';
+
+   return length;
+}
+
+static void
+_edje_image_recalc_apply(Edje *ed, Edje_Real_Part *ep, Edje_Calc_Params *p3, Edje_Part_Description *chosen_desc, double pos)
+{
+   char buf[4096];
+   int image_id;
+   int image_count, image_num;
+
+   evas_object_image_fill_set(ep->object, p3->fill.x, p3->fill.y,
+                             p3->fill.w, p3->fill.h);
+   evas_object_image_smooth_scale_set(ep->object, p3->smooth);
+
+   evas_object_image_border_set(ep->object, p3->border.l, p3->border.r,
+                               p3->border.t, p3->border.b);
+   evas_object_image_border_center_fill_set(ep->object,
+                                           !(chosen_desc->border.no_fill));
+   image_id = ep->param1.description->image.id;
+   if (image_id < 0)
+     {
+       Edje_Image_Directory_Entry *ie;
+
+       if (!ed->file->image_dir) ie = NULL;
+       else ie = evas_list_nth(ed->file->image_dir->entries, (-image_id) - 1);
+       if ((ie) &&
+           (ie->source_type == EDJE_IMAGE_SOURCE_TYPE_EXTERNAL) &&
+           (ie->entry))
+         {
+            evas_object_image_file_set(ep->object, ie->entry, NULL);
+         }
+     }
+   else
+     {
+       image_count = 2;
+       if (ep->param2.description)
+         image_count += evas_list_count(ep->param2.description->image.tween_list);
+       image_num = (pos * ((double)image_count - 0.5));
+       if (image_num > (image_count - 1))
+         image_num = image_count - 1;
+       if (image_num == 0)
+         image_id = ep->param1.description->image.id;
+       else if (image_num == (image_count - 1))
+         image_id = ep->param2.description->image.id;
+       else
+         {
+            Edje_Part_Image_Id *imid;
+
+            imid = evas_list_nth(ep->param2.description->image.tween_list,
+                                 image_num - 1);
+            if (imid) image_id = imid->id;
+         }
+       if (image_id < 0)
+         {
+            printf("EDJE ERROR: part \"%s\" has description, "
+                   "\"%s\" %3.3f with a missing image id!!!\n",
+                   ep->part->name,
+                   ep->param1.description->state.name,
+                   ep->param1.description->state.value);
+         }
+       else
+         {
+            /* Replace snprint("images/%i") == memcpy + itoa */
+#define IMAGES "images/"
+            memcpy(buf, IMAGES, strlen(IMAGES));
+            _edje_nitoa(buf + strlen(IMAGES), sizeof(buf) - strlen(IMAGES), image_id);
+
+            evas_object_image_file_set(ep->object, ed->file->path, buf);
+            if (evas_object_image_load_error_get(ep->object) != EVAS_LOAD_ERROR_NONE)
+              {
+                 printf("EDJE: Error loading image collection \"%s\" from "
+                        "file \"%s\". Missing EET Evas loader module?\n",
+                        buf, ed->file->path);
+                 if (evas_object_image_load_error_get(ep->object) == EVAS_LOAD_ERROR_GENERIC)
+                   printf("Error type: EVAS_LOAD_ERROR_GENERIC\n");
+                 else if (evas_object_image_load_error_get(ep->object) == EVAS_LOAD_ERROR_DOES_NOT_EXIST)
+                   printf("Error type: EVAS_LOAD_ERROR_DOES_NOT_EXIST\n");
+                 else if (evas_object_image_load_error_get(ep->object) == EVAS_LOAD_ERROR_PERMISSION_DENIED)
+                   printf("Error type: EVAS_LOAD_ERROR_PERMISSION_DENIED\n");
+                 else if (evas_object_image_load_error_get(ep->object) == EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED)
+                   printf("Error type: EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED\n");
+                 else if (evas_object_image_load_error_get(ep->object) == EVAS_LOAD_ERROR_CORRUPT_FILE)
+                   printf("Error type: EVAS_LOAD_ERROR_CORRUPT_FILE\n");
+                 else if (evas_object_image_load_error_get(ep->object) == EVAS_LOAD_ERROR_UNKNOWN_FORMAT)
+                   printf("Error type: EVAS_LOAD_ERROR_UNKNOWN_FORMAT\n");
+              }
+         }
+     }
+}
+
+
+static void
+_edje_part_recalc(Edje *ed, Edje_Real_Part *ep, int flags)
+{
+   Edje_Calc_Params p1, p2, p3, *pf;
+   Edje_Part_Description *chosen_desc;
+   double pos = 0.0;
+
+   if ((ep->calculated & FLAG_XY) == FLAG_XY)
+     {
+       return;
+     }
+   if (ep->calculating & flags)
+     {
+#if 1
+       const char *axes = "NONE", *faxes = "NONE";
+
+       if ((ep->calculating & FLAG_X) &&
+           (ep->calculating & FLAG_Y))
+         axes = "XY";
+       else if ((ep->calculating & FLAG_X))
+         axes = "X";
+       else if ((ep->calculating & FLAG_Y))
+         axes = "Y";
+
+       if ((flags & FLAG_X) &&
+           (flags & FLAG_Y))
+         faxes = "XY";
+       else if ((flags & FLAG_X))
+         faxes = "X";
+       else if ((flags & FLAG_Y))
+         faxes = "Y";
+       printf("EDJE ERROR: Circular dependency when calculating part \"%s\"\n"
+              "            Already calculating %s [%02x] axes\n"
+              "            Need to calculate %s [%02x] axes\n",
+              ep->part->name,
+              axes, ep->calculating,
+              faxes, flags);
+#endif
+       return;
+     }
+   if (flags & FLAG_X)
+     {
+       ep->calculating |= flags & FLAG_X;
+       if (ep->param1.rel1_to_x)  _edje_part_recalc(ed, ep->param1.rel1_to_x, FLAG_X);
+       if (ep->param1.rel2_to_x)  _edje_part_recalc(ed, ep->param1.rel2_to_x, FLAG_X);
+       if (ep->param2.rel1_to_x)  _edje_part_recalc(ed, ep->param2.rel1_to_x, FLAG_X);
+       if (ep->param2.rel2_to_x)  _edje_part_recalc(ed, ep->param2.rel2_to_x, FLAG_X);
+     }
+   if (flags & FLAG_Y)
+     {
+       ep->calculating |= flags & FLAG_Y;
+       if (ep->param1.rel1_to_y)  _edje_part_recalc(ed, ep->param1.rel1_to_y, FLAG_Y);
+       if (ep->param1.rel2_to_y)  _edje_part_recalc(ed, ep->param1.rel2_to_y, FLAG_Y);
+       if (ep->param2.rel1_to_y)  _edje_part_recalc(ed, ep->param2.rel1_to_y, FLAG_Y);
+       if (ep->param2.rel2_to_y)  _edje_part_recalc(ed, ep->param2.rel2_to_y, FLAG_Y);
+     }
+   if (ep->confine_to)        _edje_part_recalc(ed, ep->confine_to, flags);
+//   if (ep->text.source)       _edje_part_recalc(ed, ep->text.source, flags);
+//   if (ep->text.text_source)  _edje_part_recalc(ed, ep->text.text_source, flags);
+
+   /* actually calculate now */
+   chosen_desc = ep->chosen_description;
+   if (!chosen_desc)
+     {
+       ep->calculating = FLAG_NONE;
+       ep->calculated |= flags;
+       return;
+     }
+   if (ep->param1.description)
+     _edje_part_recalc_single(ed, ep, ep->param1.description, chosen_desc, ep->param1.rel1_to_x, ep->param1.rel1_to_y, ep->param1.rel2_to_x, ep->param1.rel2_to_y, ep->confine_to, &p1, flags);
+   if (ep->param2.description)
+     {
+       int beginning_pos, part_type;
+
+       _edje_part_recalc_single(ed, ep, ep->param2.description, chosen_desc, ep->param2.rel1_to_x, ep->param2.rel1_to_y, ep->param2.rel2_to_x, ep->param2.rel2_to_y, ep->confine_to, &p2, flags);
+
+       pos = ep->description_pos;
+       beginning_pos = (pos < 0.5);
+       part_type = ep->part->type;
+
+       /* visible is special */
+       if ((p1.visible) && (!p2.visible))
+         p3.visible = (pos != 1.0);
+       else if ((!p1.visible) && (p2.visible))
+         p3.visible = (pos != 0.0);
+       else
+         p3.visible = p1.visible;
+
+       p3.smooth = (beginning_pos) ? p1.smooth : p2.smooth;
+
+       /* FIXME: do x and y separately base on flag */
+#define INTP(_x1, _x2, _p) (((_x1) == (_x2)) ? (_x1) : ((_x1) + (((_x2) - (_x1)) * (_p))))
+       p3.x = INTP(p1.x, p2.x, pos);
+       p3.y = INTP(p1.y, p2.y, pos);
+       p3.w = INTP(p1.w, p2.w, pos);
+       p3.h = INTP(p1.h, p2.h, pos);
+
+       p3.req.x = INTP(p1.req.x, p2.req.x, pos);
+       p3.req.y = INTP(p1.req.y, p2.req.y, pos);
+       p3.req.w = INTP(p1.req.w, p2.req.w, pos);
+       p3.req.h = INTP(p1.req.h, p2.req.h, pos);
+
+       if (ep->part->dragable.x)
+         {
+            p3.req_drag.x = INTP(p1.req_drag.x, p2.req_drag.x, pos);
+            p3.req_drag.w = INTP(p1.req_drag.w, p2.req_drag.w, pos);
+         }
+       if (ep->part->dragable.y)
+         {
+            p3.req_drag.y = INTP(p1.req_drag.y, p2.req_drag.y, pos);
+            p3.req_drag.h = INTP(p1.req_drag.h, p2.req_drag.h, pos);
+         }
+
+       p3.color.r = INTP(p1.color.r, p2.color.r, pos);
+       p3.color.g = INTP(p1.color.g, p2.color.g, pos);
+       p3.color.b = INTP(p1.color.b, p2.color.b, pos);
+       p3.color.a = INTP(p1.color.a, p2.color.a, pos);
+
+       if ((part_type == EDJE_PART_TYPE_IMAGE) ||
+           (part_type == EDJE_PART_TYPE_GRADIENT))
+         {
+            p3.fill.x = INTP(p1.fill.x, p2.fill.x, pos);
+            p3.fill.y = INTP(p1.fill.y, p2.fill.y, pos);
+            p3.fill.w = INTP(p1.fill.w, p2.fill.w, pos);
+            p3.fill.h = INTP(p1.fill.h, p2.fill.h, pos);
+            if (part_type == EDJE_PART_TYPE_GRADIENT)
+              {
+                 p3.fill.angle = INTP(p1.fill.angle, p2.fill.angle, pos);
+                 p3.fill.spread = (beginning_pos) ? p1.fill.spread : p2.fill.spread;
+                 p3.gradient = (beginning_pos) ? p1.gradient : p2.gradient;
+              }
+            else
+              {
+                 p3.border.l = INTP(p1.border.l, p2.border.l, pos);
+                 p3.border.r = INTP(p1.border.r, p2.border.r, pos);
+                 p3.border.t = INTP(p1.border.t, p2.border.t, pos);
+                 p3.border.b = INTP(p1.border.b, p2.border.b, pos);
+              }
+         }
+       else if ((part_type == EDJE_PART_TYPE_TEXT) ||
+                (part_type == EDJE_PART_TYPE_TEXTBLOCK))
+         {
+            p3.color2.r = INTP(p1.color2.r, p2.color2.r, pos);
+            p3.color2.g = INTP(p1.color2.g, p2.color2.g, pos);
+            p3.color2.b = INTP(p1.color2.b, p2.color2.b, pos);
+            p3.color2.a = INTP(p1.color2.a, p2.color2.a, pos);
+
+            p3.color3.r = INTP(p1.color3.r, p2.color3.r, pos);
+            p3.color3.g = INTP(p1.color3.g, p2.color3.g, pos);
+            p3.color3.b = INTP(p1.color3.b, p2.color3.b, pos);
+            p3.color3.a = INTP(p1.color3.a, p2.color3.a, pos);
+
+            p3.text.align.x = INTP(p1.text.align.x, p2.text.align.x, pos);
+            p3.text.align.y = INTP(p1.text.align.y, p2.text.align.y, pos);
+            p3.text.elipsis = INTP(p1.text.elipsis, p2.text.elipsis, pos);
+         }
+
+       pf = &p3;
+     }
+   else
+     {
+       pf = &p1;
+     }
+
+   ep->req = pf->req;
+
+   if (ep->drag.need_reset)
+     {
+       double dx, dy;
+
+       dx = 0;
+       dy = 0;
+       _edje_part_dragable_calc(ed, ep, &dx, &dy);
+        ep->drag.x = dx;
+       ep->drag.y = dy;
+       ep->drag.tmp.x = 0;
+       ep->drag.tmp.y = 0;
+       ep->drag.need_reset = 0;
+     }
+   if (!ed->calc_only)
+     {
+       /* Common move, resize and color_set for all part. */
+       switch (ep->part->type)
+         {
+          case EDJE_PART_TYPE_RECTANGLE:
+          case EDJE_PART_TYPE_IMAGE:
+          case EDJE_PART_TYPE_TEXTBLOCK:
+          case EDJE_PART_TYPE_GRADIENT:
+             evas_object_color_set(ep->object,
+                                   (pf->color.r * pf->color.a) / 255,
+                                   (pf->color.g * pf->color.a) / 255,
+                                   (pf->color.b * pf->color.a) / 255,
+                                   pf->color.a);
+             if (pf->visible) evas_object_show(ep->object);
+             else evas_object_hide(ep->object);
+             /* move and resize are needed for all previous object => no break here. */
+          case EDJE_PART_TYPE_SWALLOW:
+          case EDJE_PART_TYPE_GROUP:
+             /* visibility and color have no meaning on SWALLOW and GROUP part. */
+             evas_object_move(ep->object, ed->x + pf->x, ed->y + pf->y);
+             evas_object_resize(ep->object, pf->w, pf->h);
+             break;
+          case EDJE_PART_TYPE_TEXT:
+             /* This is correctly handle in _edje_text_recalc_apply at the moment. */
+             break;
+         }
+
+       /* Some object need special recalc. */
+       switch (ep->part->type)
+         {
+          case EDJE_PART_TYPE_TEXT:
+             _edje_text_recalc_apply(ed, ep, pf, chosen_desc);
+             break;
+          case EDJE_PART_TYPE_IMAGE:
+             _edje_image_recalc_apply(ed, ep, pf, chosen_desc, pos);
+             break;
+          case EDJE_PART_TYPE_GRADIENT:
+             _edje_gradient_recalc_apply(ed, ep, pf, chosen_desc);
+             break;
+          case EDJE_PART_TYPE_RECTANGLE:
+          case EDJE_PART_TYPE_SWALLOW:
+          case EDJE_PART_TYPE_GROUP:
+          case EDJE_PART_TYPE_TEXTBLOCK:
+             /* Nothing special to do for this type of object. */
+             break;
+         }
+
+       if (ep->swallowed_object)
+         {
+//// the below really is wrong - swallow color shouldnt affect swallowed object
+//// color - the edje color as a WHOLE should though - and that should be
+//// done via the clipper anyway. this created bugs when objects had their
+//// colro set and were swallowed - then had their color changed.
+//          evas_object_color_set(ep->swallowed_object,
+//                                (pf->color.r * pf->color.a) / 255,
+//                                (pf->color.g * pf->color.a) / 255,
+//                                (pf->color.b * pf->color.a) / 255,
+//                                pf->color.a);
+            evas_object_move(ep->swallowed_object, ed->x + pf->x, ed->y + pf->y);
+            evas_object_resize(ep->swallowed_object, pf->w, pf->h);
+            if (pf->visible) evas_object_show(ep->swallowed_object);
+            else evas_object_hide(ep->swallowed_object);
+         }
+     }
+
+   ep->x = pf->x;
+   ep->y = pf->y;
+   ep->w = pf->w;
+   ep->h = pf->h;
+
+   ep->calculated |= flags;
+   ep->calculating = FLAG_NONE;
+}
diff --git a/src/lib/edje_callbacks.c b/src/lib/edje_callbacks.c
new file mode 100644 (file)
index 0000000..342c1a2
--- /dev/null
@@ -0,0 +1,481 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#include "edje_private.h"
+
+void
+_edje_hold_cb(void *data, Evas * e, Evas_Object * obj, void *event_info)
+{
+   Evas_Event_Hold *ev;
+   Edje *ed;
+   Edje_Real_Part *rp;
+
+   ev = event_info;
+   ed = data;
+   rp = evas_object_data_get(obj, "real_part");
+   if (!rp) return;
+   if (ev->hold)
+     _edje_emit(ed, "hold,on", rp->part->name);
+   else
+     _edje_emit(ed, "hold,off", rp->part->name);
+   return;
+   e = NULL;
+}
+
+void
+_edje_mouse_in_cb(void *data, Evas * e, Evas_Object * obj, void *event_info)
+{
+   Evas_Event_Mouse_In *ev;
+   Edje *ed;
+   Edje_Real_Part *rp;
+
+   ev = event_info;
+   ed = data;
+   rp = evas_object_data_get(obj, "real_part");
+   if ((!rp) ||
+       ((ev->event_flags) &&
+       (rp->part->ignore_flags & ev->event_flags))) return;
+   _edje_emit(ed, "mouse,in", rp->part->name);
+   return;
+   e = NULL;
+}
+
+void
+_edje_mouse_out_cb(void *data, Evas * e, Evas_Object * obj, void *event_info)
+{
+   Evas_Event_Mouse_Out *ev;
+   Edje *ed;
+   Edje_Real_Part *rp;
+
+   ev = event_info;
+   ed = data;
+   rp = evas_object_data_get(obj, "real_part");
+   if ((!rp) ||
+       ((ev->event_flags) &&
+       (rp->part->ignore_flags & ev->event_flags))) return;
+   _edje_emit(ed, "mouse,out", rp->part->name);
+   return;
+   e = NULL;
+}
+
+void
+_edje_mouse_down_cb(void *data, Evas * e, Evas_Object * obj, void *event_info)
+{
+   Evas_Event_Mouse_Down *ev;
+   Edje *ed;
+   Edje_Real_Part *rp;
+   char buf[256];
+   int ignored;
+
+   ev = event_info;
+   ed = data;
+   rp = evas_object_data_get(obj, "real_part");
+   if (!rp) return;
+
+   ignored = rp->part->ignore_flags & ev->event_flags;
+
+   _edje_ref(ed);
+   _edje_freeze(ed);
+
+   if ((!ev->event_flags) || (!ignored))
+     {
+       if (ev->flags & EVAS_BUTTON_TRIPLE_CLICK)
+         snprintf(buf, sizeof(buf), "mouse,down,%i,triple", ev->button);
+       else if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
+         snprintf(buf, sizeof(buf), "mouse,down,%i,double", ev->button);
+       else
+         snprintf(buf, sizeof(buf), "mouse,down,%i", ev->button);
+       _edje_emit(ed, buf, rp->part->name);
+     }
+
+   if (rp->events_to)
+     {
+       int x = 0, y = 0;
+       Edje_Real_Part *events;
+
+       events = rp->events_to;
+       evas_object_geometry_get(rp->object, &x, &y, NULL, NULL);
+
+       if ((events->part->dragable.x) || (events->part->dragable.y))
+         {
+            if (events->part->dragable.x)
+              {
+                 events->drag.tmp.x = ev->canvas.x - x - (events->x + events->w / 2);
+                 events->drag.down.x = ev->canvas.x - x;
+                 events->x = ev->canvas.x - x - events->w / 2;
+              }
+            if (events->part->dragable.y)
+              {
+                 events->drag.tmp.y = ev->canvas.y - y - (events->y + events->h / 2);
+                 events->drag.down.y = ev->canvas.y - y;
+                 events->y = ev->canvas.y - y - events->h / 2;
+              }
+
+            if (!ignored)
+              {
+                 snprintf(buf, sizeof(buf), "mouse,down,%i", ev->button);
+                 _edje_emit(ed, buf, events->part->name);
+              }
+            ed->dirty = 1;
+         }
+       _edje_recalc(ed);
+/*
+       _edje_thaw(ed);
+       _edje_unref(ed);
+       _edje_ref(ed);
+       _edje_freeze(ed);
+*/
+       rp = events;
+         {
+            double dx = 0.0, dy = 0.0;
+            int dir;
+
+            dir = _edje_part_dragable_calc(ed, rp, &dx, &dy);
+
+            if ((dx != rp->drag.val.x) || (dy != rp->drag.val.y))
+              {
+                 rp->drag.val.x = dx;
+                 rp->drag.val.y = dy;
+                 if (!ignored)
+                   _edje_emit(ed, "drag", rp->part->name);
+                 ed->dirty = 1;
+                 rp->drag.need_reset = 1;
+                 _edje_recalc(ed);
+              }
+         }
+     }
+
+   if ((rp->part->dragable.x) || (rp->part->dragable.y))
+     {
+       if (rp->drag.down.count == 0)
+         {
+            if (rp->part->dragable.x)
+                rp->drag.down.x = ev->canvas.x;
+            if (rp->part->dragable.y)
+                rp->drag.down.y = ev->canvas.y;
+            if (!ignored)
+              _edje_emit(ed, "drag,start", rp->part->name);
+         }
+       rp->drag.down.count++;
+     }
+   if (rp->clicked_button == 0)
+     {
+       rp->clicked_button = ev->button;
+       rp->still_in = 1;
+     }
+//   _edje_recalc(ed);
+   _edje_thaw(ed);
+   _edje_unref(ed);
+   return;
+   e = NULL;
+}
+
+void
+_edje_mouse_up_cb(void *data, Evas * e, Evas_Object * obj, void *event_info)
+{
+   Evas_Event_Mouse_Up *ev;
+   Edje *ed;
+   Edje_Real_Part *rp;
+   char buf[256];
+   int ignored;
+
+   ev = event_info;
+   ed = data;
+   rp = evas_object_data_get(obj, "real_part");
+   if (!rp) return;
+
+   ignored = rp->part->ignore_flags & ev->event_flags;
+
+   _edje_ref(ed);
+   _edje_freeze(ed);
+
+   if ((!ev->event_flags) || (!ignored))
+     {
+       snprintf(buf, sizeof(buf), "mouse,up,%i", ev->button);
+       _edje_emit(ed, buf, rp->part->name);
+     }
+
+   if (rp->events_to)
+     {
+       rp = rp->events_to;
+       if (!ignored)
+         {
+            snprintf(buf, sizeof(buf), "mouse,up,%i", ev->button);
+            _edje_emit(ed, buf, rp->part->name);
+         }
+     }
+
+   if ((rp->part->dragable.x) || (rp->part->dragable.y))
+     {
+       if (rp->drag.down.count > 0)
+         {
+            rp->drag.down.count--;
+            if (rp->drag.down.count == 0)
+              {
+                 rp->drag.need_reset = 1;
+                 ed->dirty = 1;
+                 if (!ignored)
+                   _edje_emit(ed, "drag,stop", rp->part->name);
+              }
+         }
+     }
+   if ((rp->still_in) && (rp->clicked_button == ev->button) && (!ignored))
+     {
+       snprintf(buf, sizeof(buf), "mouse,clicked,%i", ev->button);
+       _edje_emit(ed, buf, rp->part->name);
+     }
+   rp->clicked_button = 0;
+   rp->still_in = 0;
+
+//   _edje_recalc(ed);
+   _edje_thaw(ed);
+   _edje_unref(ed);
+   return;
+   e = NULL;
+}
+
+void
+_edje_mouse_move_cb(void *data, Evas * e, Evas_Object * obj, void *event_info)
+{
+   Evas_Event_Mouse_Move *ev;
+   Edje *ed;
+   Edje_Real_Part *rp;
+   int ignored;
+
+   ev = event_info;
+   ed = data;
+   rp = evas_object_data_get(obj, "real_part");
+   if (!rp) return;
+   if (rp->events_to) rp = rp->events_to;
+
+   ignored = rp->part->ignore_flags & ev->event_flags;
+
+   _edje_ref(ed);
+   if ((!ev->event_flags) || (!ignored))
+     _edje_emit(ed, "mouse,move", rp->part->name);
+
+   if (rp->still_in)
+     {
+       Evas_Coord x, y, w, h;
+
+       evas_object_geometry_get(obj, &x, &y, &w, &h);
+       if ((ev->cur.canvas.x < x) || (ev->cur.canvas.y < y) ||
+           (ev->cur.canvas.x >= (x + w)) || (ev->cur.canvas.y >= (y + h)))
+         rp->still_in = 0;
+     }
+   else
+     {
+       Evas_Coord x, y, w, h;
+
+       evas_object_geometry_get(obj, &x, &y, &w, &h);
+       if ((ev->cur.canvas.x >= x) && (ev->cur.canvas.y >= y) &&
+           (ev->cur.canvas.x < (x + w)) && (ev->cur.canvas.y < (y + h)))
+         rp->still_in = 1;
+     }
+   _edje_freeze(ed);
+   if ((rp->part->dragable.x) || (rp->part->dragable.y))
+     {
+       if (rp->drag.down.count > 0)
+         {
+            if (rp->part->dragable.x)
+              rp->drag.tmp.x = ev->cur.canvas.x - rp->drag.down.x;
+            if (rp->part->dragable.y)
+              rp->drag.tmp.y = ev->cur.canvas.y - rp->drag.down.y;
+            ed->dirty = 1;
+         }
+       _edje_recalc(ed);
+     }
+   if ((rp->part->dragable.x) || (rp->part->dragable.y))
+     {
+       if (rp->drag.down.count > 0)
+         {
+            double dx, dy;
+            int dir;
+
+            dir = _edje_part_dragable_calc(ed, rp, &dx, &dy);
+            if ((dx != rp->drag.val.x) || (dy != rp->drag.val.y))
+              {
+                 rp->drag.val.x = dx;
+                 rp->drag.val.y = dy;
+                 if (!ignored)
+                   _edje_emit(ed, "drag", rp->part->name);
+                 ed->dirty = 1;
+                 _edje_recalc(ed);
+              }
+         }
+     }
+   _edje_unref(ed);
+   _edje_thaw(ed);
+   return;
+   e = NULL;
+}
+
+void
+_edje_mouse_wheel_cb(void *data, Evas * e, Evas_Object * obj, void *event_info)
+{
+   Evas_Event_Mouse_Wheel *ev;
+   Edje *ed;
+   Edje_Real_Part *rp;
+   char buf[256];
+
+   ev = event_info;
+   ed = data;
+   rp = evas_object_data_get(obj, "real_part");
+   if ((!rp) || 
+       ((ev->event_flags) && 
+       (!(rp->part->ignore_flags & ev->event_flags)))) return;
+
+   snprintf(buf, sizeof(buf), "mouse,wheel,%i,%i", ev->direction, (ev->z < 0) ? (-1) : (1));
+   _edje_emit(ed, buf, rp->part->name);
+   return;
+   e = NULL;
+}
+
+int
+_edje_timer_cb(void *data)
+{
+   double t;
+   Evas_List *l;
+   Evas_List *animl = NULL;
+   Edje *ed;
+
+   t = ecore_time_get();
+   for (l = _edje_animators; l; l = l->next)
+     {
+       ed = l->data;
+       _edje_ref(ed);
+       animl = evas_list_append(animl, l->data);
+     }
+   while (animl)
+     {
+       Evas_List *newl = NULL;
+
+       ed = animl->data;
+       _edje_block(ed);
+       _edje_freeze(ed);
+       animl = evas_list_remove(animl, animl->data);
+       if ((!ed->paused) && (!ed->delete_me))
+         {
+            ed->walking_actions = 1;
+            for (l = ed->actions; l; l = l->next)
+              newl = evas_list_append(newl, l->data);
+            while (newl)
+              {
+                 Edje_Running_Program *runp;
+
+                 runp = newl->data;
+                 newl = evas_list_remove(newl, newl->data);
+                 if (!runp->delete_me)
+                   _edje_program_run_iterate(runp, t);
+                 if (_edje_block_break(ed))
+                   {
+                      evas_list_free(newl);
+                      newl = NULL;
+                      goto break_prog;
+                   }
+              }
+            for (l = ed->actions; l; l = l->next)
+              newl = evas_list_append(newl, l->data);
+            while (newl)
+              {
+                 Edje_Running_Program *runp;
+
+                 runp = newl->data;
+                 newl = evas_list_remove(newl, newl->data);
+                 if (runp->delete_me)
+                   {
+                      _edje_anim_count--;
+                      runp->edje->actions =
+                        evas_list_remove(runp->edje->actions, runp);
+                      if (!runp->edje->actions)
+                        _edje_animators =
+                        evas_list_remove(_edje_animators, runp->edje);
+                      free(runp);
+                   }
+              }
+            ed->walking_actions = 0;
+         }
+       break_prog:
+       _edje_unblock(ed);
+       _edje_thaw(ed);
+       _edje_unref(ed);
+     }
+   if (_edje_anim_count > 0) return 1;
+   _edje_timer = NULL;
+   return 0;
+   data = NULL;
+}
+
+int
+_edje_pending_timer_cb(void *data)
+{
+   Edje_Pending_Program *pp;
+
+   pp = data;
+   pp->edje->pending_actions = evas_list_remove(pp->edje->pending_actions, pp);
+   _edje_program_run(pp->edje, pp->program, 1, "", "");
+   free(pp);
+   return 0;
+}
+
+void
+_edje_callbacks_add(Evas_Object *obj, Edje *ed, Edje_Real_Part *rp)
+{
+   evas_object_event_callback_add(obj,
+                                  EVAS_CALLBACK_HOLD,
+                                  _edje_hold_cb,
+                                  ed);
+   evas_object_event_callback_add(obj,
+                                  EVAS_CALLBACK_MOUSE_IN,
+                                  _edje_mouse_in_cb,
+                                  ed);
+   evas_object_event_callback_add(obj,
+                                  EVAS_CALLBACK_MOUSE_OUT,
+                                  _edje_mouse_out_cb,
+                                  ed);
+   evas_object_event_callback_add(obj,
+                                  EVAS_CALLBACK_MOUSE_DOWN,
+                                  _edje_mouse_down_cb,
+                                  ed);
+   evas_object_event_callback_add(obj,
+                                  EVAS_CALLBACK_MOUSE_UP,
+                                  _edje_mouse_up_cb,
+                                  ed);
+   evas_object_event_callback_add(obj,
+                                  EVAS_CALLBACK_MOUSE_MOVE,
+                                  _edje_mouse_move_cb,
+                                  ed);
+   evas_object_event_callback_add(obj,
+                                  EVAS_CALLBACK_MOUSE_WHEEL,
+                                  _edje_mouse_wheel_cb,
+                                  ed);
+   evas_object_data_set(obj, "real_part", rp);
+}
+
+void
+_edje_callbacks_del(Evas_Object *obj)
+{
+   evas_object_event_callback_del(obj,
+                                  EVAS_CALLBACK_HOLD,
+                                  _edje_hold_cb);
+   evas_object_event_callback_del(obj,
+                                  EVAS_CALLBACK_MOUSE_IN,
+                                  _edje_mouse_in_cb);
+   evas_object_event_callback_del(obj,
+                                  EVAS_CALLBACK_MOUSE_OUT,
+                                  _edje_mouse_out_cb);
+   evas_object_event_callback_del(obj,
+                                  EVAS_CALLBACK_MOUSE_DOWN,
+                                  _edje_mouse_down_cb);
+   evas_object_event_callback_del(obj,
+                                  EVAS_CALLBACK_MOUSE_UP,
+                                  _edje_mouse_up_cb);
+   evas_object_event_callback_del(obj,
+                                  EVAS_CALLBACK_MOUSE_MOVE,
+                                  _edje_mouse_move_cb);
+   evas_object_event_callback_del(obj,
+                                  EVAS_CALLBACK_MOUSE_WHEEL,
+                                  _edje_mouse_wheel_cb);
+   evas_object_data_del(obj, "real_part");
+}
diff --git a/src/lib/edje_container.c b/src/lib/edje_container.c
new file mode 100644 (file)
index 0000000..9a426cc
--- /dev/null
@@ -0,0 +1,868 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#include "edje_private.h"
+#include "edje_container.h"
+
+#if 0
+
+static void
+_edje_container_relayout(Smart_Data *sd)
+{
+   Evas_List *l;
+   Evas_Coord x, y, w, h, sw;
+
+   if (sd->freeze > 0) return;
+   if (!sd->need_layout) return;
+
+   if (sd->w < sd->min_w) sw = sd->min_w;
+   else if (sd->w > sd->max_w) sw = sd->max_w;
+   else sw = sd->w;
+
+   y = 0;
+   x = 0;
+   w = 0;
+   h = 0;
+
+   for (l = sd->children; l; l = l->next)
+     {
+       Edje_Item *ei;
+
+       ei = l->data;
+       if (sd->homogenous) h = sd->min_row_h;
+
+       ei->y = y;
+       ei->h = h;
+//     ei->w = w;
+//     ei->h = h;
+     }
+
+   sd->need_layout = 0;
+}
+
+static void
+_edje_container_recalc(Smart_Data *sd)
+{
+   Evas_List *l;
+   int any_max_h = 0, any_max_w = 0;
+   int i;
+
+   if (sd->freeze > 0) return;
+   if (!sd->changed) return;
+
+   sd->min_h = 0;
+   sd->max_h = -1;
+   sd->min_w = 0;
+   sd->max_w = -1;
+   sd->min_row_h = 0;
+   sd->max_row_h = -1;
+   sd->contents_h = 0;
+   sd->contents_w = 0;
+
+   for (i = 0; i < sd->cols; i++)
+     {
+       sd->min_w += sd->colinfo[i].minw;
+       if (sd->colinfo[i].maxw >= 0)
+         {
+            if (sd->max_w >= 0)
+              sd->max_w += sd->colinfo[i].maxw;
+            else
+              sd->max_w = sd->colinfo[i].maxw;
+         }
+       else
+         any_max_w = 1;
+     }
+   if (any_max_w) sd->max_w = -1;
+
+   if (sd->w < sd->min_w)
+     sd->contents_w = sd->min_w;
+   else if ((sd->max_w >= 0) && (sd->w < sd->max_w))
+     sd->w = sd->max_w;
+
+   for (l = sd->children; l; l = l->next)
+     {
+       Edje_Item *ei;
+
+       ei = l->data;
+       if (ei->minh > sd->min_row_h)
+         sd->min_row_h = ei->minh;
+       if (sd->max_row_h >= 0)
+         {
+            if (ei->maxh >= 0)
+              {
+                 if (sd->max_row_h > ei->maxh)
+                   sd->max_row_h = ei->maxh;
+              }
+            else
+              any_max_h = 1;
+         }
+       sd->min_h += ei->minh;
+       if (ei->maxh >= 0)
+         {
+            if (sd->max_h >= 0)
+              sd->max_h += ei->maxh;
+            else
+              sd->max_h = ei->maxh;
+         }
+       else
+         any_max_h = 1;
+     }
+   if (any_max_h)
+     {
+       sd->max_h = -1;
+       sd->max_row_h = -1;
+     }
+   if (sd->homogenous)
+     {
+       sd->min_h = evas_list_count(sd->children) * sd->min_row_h;
+     }
+
+   sd->changed = 0;
+   sd->change_child = 0;
+   sd->change_child_list = 0;
+   sd->change_cols = 0;
+
+   sd->need_layout = 1;
+   _edje_container_relayout(sd);
+}
+
+static void
+_edje_item_recalc(Edje_Item *ei)
+{
+   int i;
+
+   if (ei->freeze > 0) return;
+   if (!ei->recalc) return;
+   if (!ei->sd) return;
+
+   ei->minh = 0;
+   ei->maxh = -1;
+   for (i = 0; i < ((Smart_Data *)(ei->sd))->cols; i++)
+     {
+       if (ei->cells[i].minh > ei->minh) ei->minh = ei->cells[i].minh;
+       if (ei->cells[i].maxh >= 0)
+         {
+            if (ei->maxh >= 0)
+              {
+                 if (ei->cells[i].maxh < ei->maxh)
+                   ei->maxh = ei->cells[i].maxh;
+              }
+            else
+              ei->maxh = ei->cells[i].maxh;
+         }
+       if (((Smart_Data *)(ei->sd))->colinfo[i].minw < ei->cells[i].minw)
+         ((Smart_Data *)(ei->sd))->colinfo[i].minw = ei->cells[i].minw;
+       if (((Smart_Data *)(ei->sd))->colinfo[i].maxw >= 0)
+         {
+            if (ei->cells[i].maxw >= 0)
+              {
+                 if (((Smart_Data *)(ei->sd))->colinfo[i].maxw > ei->cells[i].maxw)
+                   ((Smart_Data *)(ei->sd))->colinfo[i].maxw = ei->cells[i].maxw;
+              }
+         }
+       else
+         ((Smart_Data *)(ei->sd))->colinfo[i].maxw = ei->cells[i].maxw;
+     }
+
+   ei->recalc = 0;
+
+   _edje_container_recalc(ei->sd);
+}
+
+
+/*****************************/
+
+Edje_Item *
+edje_item_add(Edje_Item_Class *cl, void *data)
+{
+   Edje_Item *ei;
+
+   ei = calloc(sizeof(Edje_Item), 1);
+
+   ei->class = cl;
+   ei->class_data = data;
+
+   return ei;
+}
+
+void
+edje_item_del(Edje_Item *ei)
+{
+   Smart_Data *sd;
+
+   sd = ei->sd;
+   if (ei->object) evas_object_del(ei->object);
+   if (ei->overlay_object) evas_object_del(ei->overlay_object);
+   free(ei);
+   if (!sd) return;
+   sd->changed = 1;
+   sd->change_child_list = 1;
+   _edje_container_recalc(sd);
+}
+
+Evas_Object *
+edje_item_container_get(Edje_Item *ei)
+{
+   if (!ei->sd) return NULL;
+   return ((Smart_Data *)(ei->sd))->smart_obj;
+}
+
+/* an arbitary data pointer to use to track other data */
+
+void
+edje_item_data_set(Edje_Item *ei, void *data)
+{
+   ei->data = data;
+}
+
+void *
+edje_item_data_get(Edje_Item *ei)
+{
+   return ei->data;
+}
+
+/* this object covers the entire item */
+void
+edje_item_overlay_object_set(Edje_Item *ei, Evas_Object *obj)
+{
+   if (ei->overlay_object)
+     {
+       /* FIXME: if it changed - remove...*/
+     }
+   ei->overlay_object = obj;
+   if (ei->sd)
+     evas_object_smart_member_add(((Smart_Data *)(ei->sd))->smart_obj, obj);
+}
+
+Evas_Object *
+edje_item_overlay_object_get(Edje_Item *ei)
+{
+   return ei->overlay_object;
+}
+
+/* this object goes under entire item */
+void
+edje_item_object_set(Edje_Item *ei, Evas_Object *obj)
+{
+   if (ei->object)
+     {
+       /* FIXME: if it changed - remove...*/
+     }
+   ei->object = obj;
+   if (ei->sd)
+     evas_object_smart_member_add(((Smart_Data *)(ei->sd))->smart_obj, obj);
+}
+
+Evas_Object *
+edje_item_object_get(Edje_Item *ei)
+{
+   return ei->object;
+}
+
+/* optionally you can manage each column's object yourself OR let Edje do it */
+void
+edje_item_object_column_set(Edje_Item *ei, int col, Evas_Object *obj)
+{
+   if (ei->cells_num <= (col + 1))
+     {
+       /* FIXME: unsafe realloc */
+       ei->cells = realloc(ei->cells, sizeof(Edje_Item_Cell) * col);
+       ei->cells_num = col + 1;
+     }
+   ei->cells[col].obj = obj;
+}
+
+Evas_Object *
+edje_item_object_column_get(Edje_Item *ei, int col)
+{
+   if (ei->cells_num <= (col + 1)) return NULL;
+   return ei->cells[col].obj;
+}
+
+/* query the item for the items preferred co-ords */
+void
+edje_item_geometry_get(Edje_Item *ei, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
+{
+   if (!ei->sd)
+     {
+       if (x) *x = 0;
+       if (y) *y = 0;
+       if (w) *w = 0;
+       if (h) *h = 0;
+       return;
+     }
+   if (x) *x = ((Smart_Data *)(ei->sd))->x;
+   if (y) *y = ((Smart_Data *)(ei->sd))->y + ei->y;
+   if (w) *w = ((Smart_Data *)(ei->sd))->w;
+   if (h) *h = ei->h;
+}
+
+/* freeze and thaw items if u are about to do a bunch of changes */
+int
+edje_item_freeze(Edje_Item *ei)
+{
+   ei->freeze++;
+   return ei->freeze;
+}
+
+int
+edje_item_thaw(Edje_Item *ei)
+{
+   ei->freeze--;
+   if (ei->freeze > 0) return ei->freeze;
+   if (!ei->sd) return ei->freeze;
+   if (ei->recalc) _edje_item_recalc(ei);
+   return ei->freeze;
+}
+
+/* column info */
+void
+edje_item_column_size_set(Edje_Item *ei, int col, Evas_Coord minw, Evas_Coord maxw, Evas_Coord minh, Evas_Coord maxh)
+{
+   if (ei->cells_num <= (col + 1))
+     {
+       /* FIXME: unsafe realloc */
+       ei->cells = realloc(ei->cells, sizeof(Edje_Item_Cell) * col);
+       ei->cells_num = col + 1;
+     }
+   if ((ei->cells[col].minw == minw) &&
+       (ei->cells[col].minh == minh) &&
+       (ei->cells[col].maxw == maxw) &&
+       (ei->cells[col].maxh == maxh)) return;
+   ei->cells[col].minh = minh;
+   ei->cells[col].maxh = maxh;
+   ei->cells[col].minw = minw;
+   ei->cells[col].maxw = maxw;
+   ei->recalc = 1;
+   if (ei->sd)
+     {
+       ((Smart_Data *)(ei->sd))->changed = 1;
+       ((Smart_Data *)(ei->sd))->change_child = 1;
+     }
+   _edje_item_recalc(ei);
+}
+
+void
+edje_item_column_size_get(Edje_Item *ei, int col, Evas_Coord *minw, Evas_Coord *maxw, Evas_Coord *minh, Evas_Coord *maxh)
+{
+   if (ei->cells_num <= (col + 1))
+     {
+       if (minw) *minw = 0;
+       if (minh) *minh = 0;
+       if (maxw) *maxw = -1;
+       if (maxh) *maxh = -1;
+     }
+   if (minw) *minw = ei->cells[col].minw;
+   if (minh) *minh = ei->cells[col].minh;
+   if (maxw) *maxw = ei->cells[col].maxw;
+   if (maxh) *maxh = ei->cells[col].maxh;
+}
+
+/* selection stuff */
+void
+edje_item_select(Edje_Item *ei)
+{
+   ei->selected = 1;
+   /* FIXME: trigger item to change visually */
+}
+
+void
+edje_item_unselect(Edje_Item *ei)
+{
+   ei->selected = 0;
+   /* FIXME: trigger item to change visually */
+}
+
+/* focus stuff - only 1 can be focuesd */
+void
+edje_item_focus(Edje_Item *ei)
+{
+//   ei->focused = 1;
+}
+
+void
+edje_item_unfocus(Edje_Item *ei)
+{
+//   ei->focused = 0;
+}
+
+/* disable/enable stuff - stops focus and selection working on these items */
+void
+edje_item_enable(Edje_Item *ei)
+{
+//   ei->disabled = 0;
+}
+
+void
+edje_item_disable(Edje_Item *ei)
+{
+//   ei->disabled = 1;
+}
+
+/* item utils */
+int
+edje_item_selected_get(Edje_Item *ei)
+{
+   return ei->selected;
+}
+
+int
+edje_item_focused_get(Edje_Item *ei)
+{
+   return ei->focused;
+}
+
+int
+edje_item_disabled_get(Edje_Item *ei)
+{
+   return ei->disabled;
+}
+
+/***** container calls *****/
+
+int
+edje_container_freeze(Evas_Object *obj)
+{
+   Smart_Data *sd;
+
+   sd = evas_object_smart_data_get(obj);
+   if (!sd) return 0;
+   sd->freeze++;
+   return sd->freeze;
+}
+
+int
+edje_container_thaw(Evas_Object *obj)
+{
+   Smart_Data *sd;
+
+   sd = evas_object_smart_data_get(obj);
+   if (!sd) return 0;
+   sd->freeze--;
+   if (sd->freeze <= 0) _edje_container_recalc(sd);
+   return sd->freeze;
+}
+
+void
+edje_container_item_append(Evas_Object *obj, Edje_Item *ei)
+{
+   Smart_Data *sd;
+
+   sd = evas_object_smart_data_get(obj);
+   if (!sd) return;
+   sd->children = evas_list_append(sd->children, ei);
+   sd->changed = 1;
+   sd->change_child_list = 1;
+   sd->rows = evas_list_count(sd->children);
+   _edje_container_recalc(sd);
+}
+
+void
+edje_container_item_prepend(Evas_Object *obj, Edje_Item *ei)
+{
+   Smart_Data *sd;
+
+   sd = evas_object_smart_data_get(obj);
+   if (!sd) return;
+   sd->children = evas_list_prepend(sd->children, ei);
+   sd->changed = 1;
+   sd->change_child_list = 1;
+   sd->rows = evas_list_count(sd->children);
+   _edje_container_recalc(sd);
+}
+
+void
+edje_container_item_append_relative(Evas_Object *obj, Edje_Item *ei, Edje_Item *rel)
+{
+   Smart_Data *sd;
+
+   sd = evas_object_smart_data_get(obj);
+   if (!sd) return;
+   sd->children = evas_list_append_relative(sd->children, ei, rel);
+   sd->changed = 1;
+   sd->change_child_list = 1;
+   sd->rows = evas_list_count(sd->children);
+   _edje_container_recalc(sd);
+}
+
+void
+edje_container_item_prepend_relative(Evas_Object *obj, Edje_Item *ei, Edje_Item *rel)
+{
+   Smart_Data *sd;
+
+   sd = evas_object_smart_data_get(obj);
+   if (!sd) return;
+   sd->children = evas_list_prepend_relative(sd->children, ei, rel);
+   sd->changed = 1;
+   sd->change_child_list = 1;
+   sd->rows = evas_list_count(sd->children);
+   _edje_container_recalc(sd);
+}
+
+void
+edje_container_item_insert(Evas_Object *obj, Edje_Item *ei, int n)
+{
+   Smart_Data *sd;
+   void *rel;
+
+   sd = evas_object_smart_data_get(obj);
+   if (!sd) return;
+   rel = evas_list_nth(sd->children, n);
+   if (!rel)
+     sd->children = evas_list_append(sd->children, ei);
+   else
+     sd->children = evas_list_append_relative(sd->children, ei, rel);
+   sd->changed = 1;
+   sd->change_child_list = 1;
+   sd->rows = evas_list_count(sd->children);
+   _edje_container_recalc(sd);
+}
+
+void
+edje_container_item_remove(Evas_Object *obj, Edje_Item *ei)
+{
+   Smart_Data *sd;
+
+   sd = evas_object_smart_data_get(obj);
+   if (!sd) return;
+   sd->children = evas_list_remove(sd->children, ei);
+   sd->changed = 1;
+   sd->change_child_list = 1;
+   sd->rows = evas_list_count(sd->children);
+   _edje_container_recalc(sd);
+}
+
+void
+edje_container_columns_set(Evas_Object *obj, int cols)
+{
+   Smart_Data *sd;
+
+   sd = evas_object_smart_data_get(obj);
+   if (!sd) return;
+   if (sd->cols == cols) return;
+   sd->colinfo = realloc(sd->colinfo, cols * sizeof(Smart_Data_Colinfo));
+   if (cols > sd->cols)
+     {
+       int i;
+
+       for (i = sd->cols; i < cols; i++)
+         {
+            sd->colinfo[i].minw = 0;
+            sd->colinfo[i].maxw = -1;
+         }
+     }
+   sd->cols = cols;
+   sd->changed = 1;
+   sd->change_cols = 1;
+   _edje_container_recalc(sd);
+}
+
+int
+edje_container_columns_get(Evas_Object *obj)
+{
+   Smart_Data *sd;
+
+   sd = evas_object_smart_data_get(obj);
+   if (!sd) return 0;
+   return sd->cols;
+}
+
+void
+edje_container_min_size_get(Evas_Object *obj, Evas_Coord *minw, Evas_Coord *minh)
+{
+   Smart_Data *sd;
+
+   sd = evas_object_smart_data_get(obj);
+   if (!sd) return;
+   if (sd->changed)
+     {
+       int freeze;
+
+       freeze = sd->freeze;
+       sd->freeze = 0;
+       _edje_container_recalc(sd);
+       sd->freeze = freeze;
+     }
+   if (minw) *minw = sd->min_w;
+   if (minh) *minh = sd->min_h;
+}
+
+void
+edje_container_max_size_get(Evas_Object *obj, Evas_Coord *maxw, Evas_Coord *maxh)
+{
+   Smart_Data *sd;
+
+   sd = evas_object_smart_data_get(obj);
+   if (!sd) return;
+   if (sd->changed)
+     {
+       int freeze;
+
+       freeze = sd->freeze;
+       sd->freeze = 0;
+       _edje_container_recalc(sd);
+       sd->freeze = freeze;
+     }
+   if (maxw) *maxw = sd->max_w;
+   if (maxh) *maxh = sd->max_h;
+}
+
+void
+edje_containter_align_set(Evas_Object *obj, double halign, double valign)
+{
+   Smart_Data *sd;
+
+   sd = evas_object_smart_data_get(obj);
+   if (!sd) return;
+   if ((sd->align_x == halign) && (sd->align_y == valign)) return;
+   sd->align_x = halign;
+   sd->align_y = valign;
+   sd->need_layout = 1;
+   _edje_container_relayout(sd);
+}
+
+void
+edje_container_align_get(Evas_Object *obj, double *halign, double *valign)
+{
+   Smart_Data *sd;
+
+   sd = evas_object_smart_data_get(obj);
+   if (!sd) return;
+   if (halign) *halign = sd->align_x;
+   if (valign) *valign = sd->align_y;
+}
+
+int
+edje_container_count_get(Evas_Object *obj)
+{
+   Smart_Data *sd;
+
+   sd = evas_object_smart_data_get(obj);
+   if (!sd) return 0;
+   return evas_list_count(sd->children);
+}
+
+Edje_Item *
+edje_container_item_first_get(Evas_Object *obj)
+{
+   Smart_Data *sd;
+
+   sd = evas_object_smart_data_get(obj);
+   if (!sd) return NULL;
+   if (!sd->children) return NULL;
+   return sd->children->data;
+}
+
+Edje_Item *
+edje_container_item_last_get(Evas_Object *obj)
+{
+   Smart_Data *sd;
+
+   sd = evas_object_smart_data_get(obj);
+   if (!sd) return NULL;
+   if (!sd->children) return NULL;
+   return evas_list_last(sd->children)->data;
+}
+
+Edje_Item *
+edje_container_item_nth_get(Evas_Object *obj, int n)
+{
+   Smart_Data *sd;
+
+   sd = evas_object_smart_data_get(obj);
+   if (!sd) return NULL;
+   return evas_list_nth(sd->children, n);
+}
+
+void
+edje_container_homogenous_size_set(Evas_Object *obj, int homog)
+{
+   Smart_Data *sd;
+
+   sd = evas_object_smart_data_get(obj);
+   if (!sd) return;
+   if (((homog) && (sd->homogenous)) ||
+       ((!homog) && (!sd->homogenous))) return;
+   sd->homogenous = homog;
+   sd->changed = 1;
+   sd->change_child = 1;
+   _edje_container_recalc(sd);
+}
+
+int
+edje_container_homogenous_size_get(Evas_Object *obj)
+{
+   Smart_Data *sd;
+
+   sd = evas_object_smart_data_get(obj);
+   if (!sd) return 0;
+   return sd->homogenous;
+}
+
+void
+edje_container_scroll_set(Evas_Object *obj, double pos, double shift)
+{
+   Smart_Data *sd;
+
+   sd = evas_object_smart_data_get(obj);
+   if (!sd) return;
+   if ((sd->scroll_y == pos) && (sd->scroll_x == shift)) return;
+   sd->scroll_y = pos;
+   sd->scroll_x = shift;
+   sd->need_layout = 1;
+   _edje_container_relayout(sd);
+}
+
+void
+edje_container_scroll_get(Evas_Object *obj, double *pos, double *shift)
+{
+   Smart_Data *sd;
+
+   sd = evas_object_smart_data_get(obj);
+   if (!sd) return;
+   if (pos) *pos = sd->scroll_y;
+   if (shift) *shift = sd->scroll_x;
+}
+
+static void _smart_init(void);
+static void _smart_add(Evas_Object * obj);
+static void _smart_del(Evas_Object * obj);
+static void _smart_move(Evas_Object * obj, Evas_Coord x, Evas_Coord y);
+static void _smart_resize(Evas_Object * obj, Evas_Coord w, Evas_Coord h);
+static void _smart_show(Evas_Object * obj);
+static void _smart_hide(Evas_Object * obj);
+static void _smart_color_set(Evas_Object * obj, int r, int g, int b, int a);
+static void _smart_clip_set(Evas_Object * obj, Evas_Object * clip);
+static void _smart_clip_unset(Evas_Object * obj);
+
+static Evas_Smart  *smart = NULL;
+
+Evas_Object *
+edje_container_object_add(Evas *evas)
+{
+   _smart_init();
+   return evas_object_smart_add(evas, smart);
+}
+
+/*******************************************/
+/* Internal smart object required routines */
+/*******************************************/
+static void
+_smart_init(void)
+{
+   if (smart) return;
+     {
+       static const Evas_Smart_Class sc =
+         {
+            E_OBJ_NAME,
+              _smart_add,
+              _smart_del,
+              _smart_move,
+              _smart_resize,
+              _smart_show,
+              _smart_hide,
+              _smart_color_set,
+              _smart_clip_set,
+              _smart_clip_unset,
+              NULL
+         };
+        smart = evas_smart_class_new(&sc);
+     }
+}
+
+static void
+_smart_add(Evas_Object *obj)
+{
+   Smart_Data *sd;
+
+   sd = calloc(1, sizeof(Smart_Data));
+   if (!sd) return;
+//   evas_object_smart_member_add(sd->obj, obj);
+   evas_object_smart_data_set(obj, sd);
+   sd->smart_obj = obj;
+}
+
+static void
+_smart_del(Evas_Object *obj)
+{
+   Smart_Data *sd;
+
+   sd = evas_object_smart_data_get(obj);
+   if (!sd) return;
+   if (sd->colinfo) free(sd->colinfo);
+//   evas_object_del(sd->obj);
+   free(sd);
+}
+
+static void
+_smart_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
+{
+   Smart_Data *sd;
+
+   sd = evas_object_smart_data_get(obj);
+   if (!sd) return;
+//   evas_object_move(sd->obj, x, y);
+}
+
+static void
+_smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
+{
+   Smart_Data *sd;
+
+   sd = evas_object_smart_data_get(obj);
+   if (!sd) return;
+//   evas_object_resize(sd->obj, w, h);
+}
+
+static void
+_smart_show(Evas_Object *obj)
+{
+   Smart_Data *sd;
+
+   sd = evas_object_smart_data_get(obj);
+   if (!sd) return;
+//   evas_object_show(sd->obj);
+}
+
+static void
+_smart_hide(Evas_Object *obj)
+{
+   Smart_Data *sd;
+
+   sd = evas_object_smart_data_get(obj);
+   if (!sd) return;
+//   evas_object_hide(sd->obj);
+}
+
+static void
+_smart_color_set(Evas_Object *obj, int r, int g, int b, int a)
+{
+   Smart_Data *sd;
+
+   sd = evas_object_smart_data_get(obj);
+   if (!sd) return;
+//   evas_object_color_set(sd->obj, r, g, b, a);
+}
+
+static void
+_smart_clip_set(Evas_Object *obj, Evas_Object *clip)
+{
+   Smart_Data *sd;
+
+   sd = evas_object_smart_data_get(obj);
+   if (!sd) return;
+//   evas_object_clip_set(sd->obj, clip);
+}
+
+static void
+_smart_clip_unset(Evas_Object *obj)
+{
+   Smart_Data *sd;
+
+   sd = evas_object_smart_data_get(obj);
+   if (!sd) return;
+//   evas_object_clip_unset(sd->obj);
+}
+
+#endif
diff --git a/src/lib/edje_container.h b/src/lib/edje_container.h
new file mode 100644 (file)
index 0000000..fd2fb10
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#include "edje_private.h"
+
+
+#define E_SMART_OBJ_GET(smart, o, type) \
+     { \
+       char *_e_smart_str; \
+       \
+       if (!o) return; \
+       smart = evas_object_smart_data_get(o); \
+       if (!smart) return; \
+       _e_smart_str = (char *)evas_object_type_get(o); \
+       if (!_e_smart_str) return; \
+       if (strcmp(_e_smart_str, type)) return; \
+     }
+
+#define E_SMART_OBJ_GET_RETURN(smart, o, type, ret) \
+   { \
+      char *_e_smart_str; \
+      \
+      if (!o) return ret; \
+      smart = evas_object_smart_data_get(o); \
+      if (!smart) return ret; \
+      _e_smart_str = (char *)evas_object_type_get(o); \
+      if (!_e_smart_str) return ret; \
+      if (strcmp(_e_smart_str, type)) return ret; \
+   }
+
+#define E_OBJ_NAME "edje_container_object"
+
+typedef struct _Smart_Data         Smart_Data;
+typedef struct _Smart_Data_Colinfo Smart_Data_Colinfo;
+
+struct _Smart_Data
+{
+   Evas_Coord     x, y, w, h;
+   Evas_List     *children;
+   Evas_Object   *smart_obj;
+   int            cols, rows;
+
+   Evas_Coord     contents_w, contents_h;
+   Evas_Coord     min_row_h, max_row_h;
+   Evas_Coord     min_w, max_w, min_h, max_h;
+
+   Smart_Data_Colinfo *colinfo;
+
+   int            freeze;
+
+   double         scroll_x, scroll_y;
+   double         align_x, align_y;
+
+   unsigned char  changed : 1;
+   unsigned char  change_child : 1;
+   unsigned char  change_child_list : 1;
+   unsigned char  change_cols : 1;
+   unsigned char  change_scroll : 1;
+
+   unsigned char  need_layout : 1;
+
+   unsigned char  homogenous : 1;
+};
+
+struct _Smart_Data_Colinfo
+{
+   Evas_Coord minw, maxw;
+};
+
+/* All items are virtual constructs that provide Evas_Objects at some point.
+ * Edje may move, resize, show, hide, clip, unclip, raise, lower etc. this
+ * item AFTER it calls the item's add() method and before it calls the del()
+ * method. Edje may call add() and del() at any time as often items may not
+ * be visible and so may not need to exist at all - they are merely information
+ * used for layout, and nothing more. this helps save cpu and memory keeping
+ * things responsive for BIG lists of items. you create an item from an item
+ * class then ask that item to be appended/prepended etc. to the container.
+ */
+typedef struct _Edje_Item       Edje_Item;
+typedef struct _Edje_Item_Cell  Edje_Item_Cell;
+typedef struct _Edje_Item_Class Edje_Item_Class;
+
+struct _Edje_Item_Class
+{
+   Evas_Object *(*add)      (Edje_Item *ei);
+   void         (*del)      (Edje_Item *ei);
+   void         (*select)   (Edje_Item *ei);
+   void         (*deselect) (Edje_Item *ei);
+   void         (*focus)    (Edje_Item *ei);
+   void         (*unfocus)  (Edje_Item *ei);
+};
+
+/* private */
+struct _Edje_Item
+{
+   Edje_Item_Class *class;
+   void            *class_data;
+
+   void            *sd;
+
+   void            *data;
+
+   Evas_Object     *object;
+   Evas_Object     *overlay_object;
+   int              freeze;
+   Evas_Coord       y, h;
+
+   Evas_Coord       minh, maxh;
+
+   int              cells_num;
+   Edje_Item_Cell  *cells;
+
+   unsigned char    accessible : 1;
+
+   unsigned char    recalc : 1;
+   unsigned char    selected : 1;
+   unsigned char    disabled : 1;
+   unsigned char    focused : 1;
+};
+
+struct _Edje_Item_Cell
+{
+   Evas_Object *obj;
+   Evas_Coord   x, w;
+   Evas_Coord   minw, minh, maxw, maxh;
+};
+
+/* here is an item for a vertical list - with 1 or more columns. this has 3 */
+/* just rotate for a horizontal list */
+
+/*
+ *             COL 0                 COL 1          COL 2
+ *
+ * +-----------------------------+ +-------+ +----------------+
+ * |          pad_top            | |       | |                |
+ * | pad_left  OBJECT  pad_right | |  OBJ  | |     OBJECT     | ROW 0
+ * |         pad_bottom          | |       | |                |
+ * +-----------------------------+ +-------+ +----------------+
+ *               /\              /|\
+ *     space_row ||               +-- space_col
+ *               \/
+ * +-----------------------------+ +-------+ +----------------+
+ * |                             | |       | |                |
+ * |                             | |       | |                | ROW 1
+ * |                             | |       | |                |
+ * +-----------------------------+ +-------+ +----------------+
+ *
+ * spacer object:
+ * 1 Edje object goes in-between each row as a spacer object (opt)
+ * 1 Edje object goes in-between each column as a spacer object (opt)
+ *
+ * surround object:
+ * 1 Edje object goes around each item - item swallowed into "item" part (opt)
+ *   if no "item" part then just underlay it
+ *   on select send "select" "" signal
+ *   on unselect send "unselect" "" signal
+ *   on focus send "focus" "" signal
+ *   on unfocus send "unfocus" signal
+ *
+ *   if any list item/cell is an Edje object emit this to them too.
+ *
+ *   also call callbacks.
+ *   if a surround object emits such a signal itself then call callbacks too
+ *
+ * only 1 or 0 items can be focused
+ * disabled items cannot be focused or selected/deselected
+ *
+ */
diff --git a/src/lib/edje_data.c b/src/lib/edje_data.c
new file mode 100644 (file)
index 0000000..7723834
--- /dev/null
@@ -0,0 +1,394 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#include "edje_private.h"
+
+EAPI Eet_Data_Descriptor *_edje_edd_edje_file = NULL;
+EAPI Eet_Data_Descriptor *_edje_edd_edje_style = NULL;
+EAPI Eet_Data_Descriptor *_edje_edd_edje_style_tag = NULL;
+EAPI Eet_Data_Descriptor *_edje_edd_edje_color_class = NULL;
+EAPI Eet_Data_Descriptor *_edje_edd_edje_data = NULL;
+EAPI Eet_Data_Descriptor *_edje_edd_edje_font_directory = NULL;
+EAPI Eet_Data_Descriptor *_edje_edd_edje_font_directory_entry = NULL;
+EAPI Eet_Data_Descriptor *_edje_edd_edje_image_directory = NULL;
+EAPI Eet_Data_Descriptor *_edje_edd_edje_image_directory_entry = NULL;
+EAPI Eet_Data_Descriptor *_edje_edd_edje_spectrum_directory = NULL;
+EAPI Eet_Data_Descriptor *_edje_edd_edje_spectrum_directory_entry = NULL;
+EAPI Eet_Data_Descriptor *_edje_edd_edje_spectrum_color = NULL;
+EAPI Eet_Data_Descriptor *_edje_edd_edje_program = NULL;
+EAPI Eet_Data_Descriptor *_edje_edd_edje_program_target = NULL;
+EAPI Eet_Data_Descriptor *_edje_edd_edje_program_after = NULL;
+EAPI Eet_Data_Descriptor *_edje_edd_edje_part_collection_directory = NULL;
+EAPI Eet_Data_Descriptor *_edje_edd_edje_part_collection_directory_entry = NULL;
+EAPI Eet_Data_Descriptor *_edje_edd_edje_part_collection = NULL;
+EAPI Eet_Data_Descriptor *_edje_edd_edje_part = NULL;
+EAPI Eet_Data_Descriptor *_edje_edd_edje_part_description = NULL;
+EAPI Eet_Data_Descriptor *_edje_edd_edje_part_image_id = NULL;
+
+#define NEWD(str, typ) \
+   { eddc.name = str; eddc.size = sizeof(typ); }
+
+#define FREED(eed) \
+   if (eed) \
+   { \
+      eet_data_descriptor_free((eed)); \
+      (eed) = NULL; \
+   }
+
+void
+_edje_edd_free(void)
+{
+   FREED(_edje_edd_edje_file);
+   FREED(_edje_edd_edje_style);
+   FREED(_edje_edd_edje_style_tag);
+   FREED(_edje_edd_edje_color_class);
+   FREED(_edje_edd_edje_data);
+   FREED(_edje_edd_edje_font_directory);
+   FREED(_edje_edd_edje_font_directory_entry);
+   FREED(_edje_edd_edje_image_directory);
+   FREED(_edje_edd_edje_image_directory_entry);
+   FREED(_edje_edd_edje_spectrum_directory);
+   FREED(_edje_edd_edje_spectrum_directory_entry);
+   FREED(_edje_edd_edje_spectrum_color);
+   FREED(_edje_edd_edje_program);
+   FREED(_edje_edd_edje_program_target);
+   FREED(_edje_edd_edje_program_after);
+   FREED(_edje_edd_edje_part_collection_directory);
+   FREED(_edje_edd_edje_part_collection_directory_entry);
+   FREED(_edje_edd_edje_part_collection);
+   FREED(_edje_edd_edje_part);
+   FREED(_edje_edd_edje_part_description);
+   FREED(_edje_edd_edje_part_image_id);
+}
+
+static char *
+_edje_str_direct_alloc(const char *str)
+{
+   return (char *)str;
+}
+
+static void
+_edje_str_direct_free(const char *str)
+{
+}
+
+void
+_edje_edd_setup(void)
+{
+   Eet_Data_Descriptor_Class eddc;
+
+   eddc.version = EET_DATA_DESCRIPTOR_CLASS_VERSION;
+   eddc.func.mem_alloc = NULL;
+   eddc.func.mem_free = NULL;
+   eddc.func.str_alloc = (char *(*)(const char *))evas_stringshare_add;
+   eddc.func.str_free = evas_stringshare_del;
+   eddc.func.list_next = (void *(*)(void *))evas_list_next;
+   eddc.func.list_append = (void *(*)(void *, void *))evas_list_append;
+   eddc.func.list_data = (void *(*)(void *))evas_list_data;
+   eddc.func.list_free = (void *(*)(void *))evas_list_free;
+   eddc.func.hash_foreach = (void (*)(void *, int (*)(void *, const char *, void *, void *), void *))evas_hash_foreach;
+   eddc.func.hash_add = (void *(*)(void *, const char *, void *))evas_hash_add;
+   eddc.func.hash_free = (void (*)(void *))evas_hash_free;
+   eddc.func.str_direct_alloc = _edje_str_direct_alloc;
+   eddc.func.str_direct_free = _edje_str_direct_free;
+
+   /* font directory */
+   NEWD("Edje_Font_Directory_Entry",
+       Edje_Font_Directory_Entry);
+   _edje_edd_edje_font_directory_entry =
+     eet_data_descriptor3_new(&eddc);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_font_directory_entry, Edje_Font_Directory_Entry, "entry", entry, EET_T_STRING);
+
+   NEWD("Edje_Font_Directory",
+       Edje_Font_Directory);
+   _edje_edd_edje_font_directory =
+     eet_data_descriptor3_new(&eddc);
+   EET_DATA_DESCRIPTOR_ADD_LIST(_edje_edd_edje_font_directory, Edje_Font_Directory, "entries", entries, _edje_edd_edje_font_directory_entry);
+
+   /* image directory */
+   NEWD("Edje_Image_Directory_Entry",
+       Edje_Image_Directory_Entry);
+   _edje_edd_edje_image_directory_entry =
+     eet_data_descriptor3_new(&eddc);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_image_directory_entry, Edje_Image_Directory_Entry, "entry", entry, EET_T_STRING);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_image_directory_entry, Edje_Image_Directory_Entry, "source_type", source_type, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_image_directory_entry, Edje_Image_Directory_Entry, "source_param", source_param, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_image_directory_entry, Edje_Image_Directory_Entry, "id", id, EET_T_INT);
+
+   NEWD("Edje_Image_Directory",
+       Edje_Image_Directory);
+   _edje_edd_edje_image_directory =
+     eet_data_descriptor3_new(&eddc);
+   EET_DATA_DESCRIPTOR_ADD_LIST(_edje_edd_edje_image_directory, Edje_Image_Directory, "entries", entries, _edje_edd_edje_image_directory_entry);
+
+   /* spectrum directory */
+   NEWD("Edje_Spectrum_Color",
+       Edje_Spectrum_Color);
+   _edje_edd_edje_spectrum_color =
+     eet_data_descriptor3_new(&eddc);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_spectrum_color, Edje_Spectrum_Color, "r", r, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_spectrum_color, Edje_Spectrum_Color, "g", g, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_spectrum_color, Edje_Spectrum_Color, "b", b, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_spectrum_color, Edje_Spectrum_Color, "a", a, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_spectrum_color, Edje_Spectrum_Color, "d", d, EET_T_INT);
+
+   NEWD("Edje_Spectrum_Directory_Entry",
+       Edje_Spectrum_Directory_Entry);
+   _edje_edd_edje_spectrum_directory_entry =
+     eet_data_descriptor3_new(&eddc);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_spectrum_directory_entry, Edje_Spectrum_Directory_Entry, "entry", entry, EET_T_STRING);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_spectrum_directory_entry, Edje_Spectrum_Directory_Entry, "filename", filename, EET_T_STRING);
+   EET_DATA_DESCRIPTOR_ADD_LIST(_edje_edd_edje_spectrum_directory_entry, Edje_Spectrum_Directory_Entry, "color_list", color_list, _edje_edd_edje_spectrum_color);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_spectrum_directory_entry, Edje_Spectrum_Directory_Entry, "id", id, EET_T_INT);
+
+   NEWD("Edje_Spectrum_Directory",
+       Edje_Spectrum_Directory);
+   _edje_edd_edje_spectrum_directory =
+     eet_data_descriptor3_new(&eddc);
+   EET_DATA_DESCRIPTOR_ADD_LIST(_edje_edd_edje_spectrum_directory, Edje_Spectrum_Directory, "entries", entries, _edje_edd_edje_spectrum_directory_entry);
+
+   /* collection directory */
+   NEWD("Edje_Part_Collection_Directory_Entry",
+       Edje_Part_Collection_Directory_Entry);
+   _edje_edd_edje_part_collection_directory_entry =
+     eet_data_descriptor3_new(&eddc);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_collection_directory_entry, Edje_Part_Collection_Directory_Entry, "entry", entry, EET_T_STRING);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_collection_directory_entry, Edje_Part_Collection_Directory_Entry, "id", id, EET_T_INT);
+
+   NEWD("Edje_Part_Collection_Directory",
+       Edje_Part_Collection_Directory);
+   _edje_edd_edje_part_collection_directory =
+     eet_data_descriptor3_new(&eddc);
+   EET_DATA_DESCRIPTOR_ADD_LIST(_edje_edd_edje_part_collection_directory, Edje_Part_Collection_Directory, "entries", entries, _edje_edd_edje_part_collection_directory_entry);
+
+   /* generic data attachment */
+   NEWD("Edje_Data",
+       Edje_Data);
+   _edje_edd_edje_data =
+     eet_data_descriptor3_new(&eddc);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_data, Edje_Data, "key", key, EET_T_STRING);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_data, Edje_Data, "value", value, EET_T_STRING);
+
+   NEWD("Edje_Style_Tag",
+       Edje_Style_Tag);
+   _edje_edd_edje_style_tag =
+     eet_data_descriptor3_new(&eddc);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_style_tag, Edje_Style_Tag, "key", key, EET_T_STRING);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_style_tag, Edje_Style_Tag, "value", value, EET_T_STRING);
+
+   NEWD("Edje_Style",
+       Edje_Style);
+   _edje_edd_edje_style =
+     eet_data_descriptor3_new(&eddc);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_style, Edje_Style, "name", name, EET_T_STRING);
+   EET_DATA_DESCRIPTOR_ADD_LIST(_edje_edd_edje_style, Edje_Style, "tags", tags, _edje_edd_edje_style_tag);
+
+   NEWD("Edje_Color_Class",
+       Edje_Color_Class);
+   _edje_edd_edje_color_class =
+     eet_data_descriptor3_new(&eddc);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_color_class, Edje_Color_Class, "name", name, EET_T_STRING);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_color_class, Edje_Color_Class, "r", r, EET_T_UCHAR);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_color_class, Edje_Color_Class, "g", g, EET_T_UCHAR);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_color_class, Edje_Color_Class, "b", b, EET_T_UCHAR);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_color_class, Edje_Color_Class, "a", a, EET_T_UCHAR);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_color_class, Edje_Color_Class, "r2", r2, EET_T_UCHAR);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_color_class, Edje_Color_Class, "g2", g2, EET_T_UCHAR);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_color_class, Edje_Color_Class, "b2", b2, EET_T_UCHAR);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_color_class, Edje_Color_Class, "a2", a2, EET_T_UCHAR);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_color_class, Edje_Color_Class, "r3", r3, EET_T_UCHAR);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_color_class, Edje_Color_Class, "g3", g3, EET_T_UCHAR);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_color_class, Edje_Color_Class, "b3", b3, EET_T_UCHAR);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_color_class, Edje_Color_Class, "a3", a3, EET_T_UCHAR);
+
+   /* the main file directory */
+   NEWD("Edje_File",
+       Edje_File);
+   _edje_edd_edje_file =
+     eet_data_descriptor3_new(&eddc);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_file, Edje_File, "compiler", compiler, EET_T_STRING);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_file, Edje_File, "version", version, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_file, Edje_File, "feature_ver", feature_ver, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_SUB(_edje_edd_edje_file, Edje_File, "font_dir", font_dir, _edje_edd_edje_font_directory);
+   EET_DATA_DESCRIPTOR_ADD_SUB(_edje_edd_edje_file, Edje_File, "image_dir", image_dir, _edje_edd_edje_image_directory);
+   EET_DATA_DESCRIPTOR_ADD_SUB(_edje_edd_edje_file, Edje_File, "spectrum_dir", spectrum_dir, _edje_edd_edje_spectrum_directory);
+   EET_DATA_DESCRIPTOR_ADD_SUB(_edje_edd_edje_file, Edje_File, "collection_dir", collection_dir, _edje_edd_edje_part_collection_directory);
+   EET_DATA_DESCRIPTOR_ADD_LIST(_edje_edd_edje_file, Edje_File, "data", data, _edje_edd_edje_data);
+   EET_DATA_DESCRIPTOR_ADD_LIST(_edje_edd_edje_file, Edje_File, "styles", styles, _edje_edd_edje_style);
+   EET_DATA_DESCRIPTOR_ADD_LIST(_edje_edd_edje_file, Edje_File, "color_classes", color_classes, _edje_edd_edje_color_class);
+
+   /* parts & programs - loaded induvidually */
+   NEWD("Edje_Program_Target",
+       Edje_Program_Target);
+   _edje_edd_edje_program_target =
+     eet_data_descriptor3_new(&eddc);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_program_target, Edje_Program_Target, "id", id, EET_T_INT);
+
+   NEWD("Edje_Program_After",
+       Edje_Program_After);
+   _edje_edd_edje_program_after =
+     eet_data_descriptor3_new(&eddc);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_program_after,
+                                 Edje_Program_After, "id", id, EET_T_INT);
+
+   NEWD("Edje_Program",
+       Edje_Program);
+   _edje_edd_edje_program =
+     eet_data_descriptor3_new(&eddc);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_program, Edje_Program, "id", id, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_program, Edje_Program, "name", name, EET_T_STRING);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_program, Edje_Program, "signal", signal, EET_T_STRING);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_program, Edje_Program, "source", source, EET_T_STRING);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_program, Edje_Program, "in.from", in.from, EET_T_DOUBLE);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_program, Edje_Program, "in.range", in.range, EET_T_DOUBLE);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_program, Edje_Program, "action", action, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_program, Edje_Program, "state", state, EET_T_STRING);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_program, Edje_Program, "state2", state2, EET_T_STRING);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_program, Edje_Program, "value", value, EET_T_DOUBLE);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_program, Edje_Program, "value2", value2, EET_T_DOUBLE);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_program, Edje_Program, "tween.mode", tween.mode, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_program, Edje_Program, "tween.time", tween.time, EET_T_DOUBLE);
+   EET_DATA_DESCRIPTOR_ADD_LIST(_edje_edd_edje_program, Edje_Program, "targets", targets, _edje_edd_edje_program_target);
+   EET_DATA_DESCRIPTOR_ADD_LIST(_edje_edd_edje_program, Edje_Program, "after", after, _edje_edd_edje_program_after);
+
+   NEWD("Edje_Part_Image_Id",
+       Edje_Part_Image_Id);
+   _edje_edd_edje_part_image_id =
+     eet_data_descriptor3_new(&eddc);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_image_id, Edje_Part_Image_Id, "id", id, EET_T_INT);
+
+   NEWD("Edje_Part_Description",
+       Edje_Part_Description);
+   _edje_edd_edje_part_description =
+     eet_data_descriptor3_new(&eddc);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "state.name", state.name, EET_T_STRING);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "state.value", state.value, EET_T_DOUBLE);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "visible", visible, EET_T_CHAR);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "align.x", align.x, EET_T_DOUBLE);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "align.y", align.y, EET_T_DOUBLE);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "fixed.w", fixed.w, EET_T_UCHAR);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "fixed.h", fixed.h, EET_T_UCHAR);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "min.w", min.w, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "min.h", min.h, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "max.w", max.w, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "max.h", max.h, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "step.x", step.x, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "step.y", step.y, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "aspect.min", aspect.min, EET_T_DOUBLE);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "aspect.max", aspect.max, EET_T_DOUBLE);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "aspect.prefer", aspect.prefer, EET_T_CHAR);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "rel1.relative_x", rel1.relative_x, EET_T_DOUBLE);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "rel1.relative_y", rel1.relative_y, EET_T_DOUBLE);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "rel1.offset_x", rel1.offset_x, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "rel1.offset_y", rel1.offset_y, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "rel1.id_x", rel1.id_x, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "rel1.id_y", rel1.id_y, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "rel2.relative_x", rel2.relative_x, EET_T_DOUBLE);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "rel2.relative_y", rel2.relative_y, EET_T_DOUBLE);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "rel2.offset_x", rel2.offset_x, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "rel2.offset_y", rel2.offset_y, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "rel2.id_x", rel2.id_x, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "rel2.id_y", rel2.id_y, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "image.id", image.id, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_LIST(_edje_edd_edje_part_description, Edje_Part_Description, "image.tween_list", image.tween_list, _edje_edd_edje_part_image_id);
+
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "border.l", border.l, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "border.r", border.r, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "border.t", border.t, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "border.b", border.b, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "border.no_fill", border.no_fill, EET_T_UCHAR);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "fill.smooth", fill.smooth, EET_T_CHAR);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "fill.pos_rel_x", fill.pos_rel_x, EET_T_DOUBLE);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "fill.pos_abs_x", fill.pos_abs_x, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "fill.rel_x", fill.rel_x, EET_T_DOUBLE);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "fill.abs_x", fill.abs_x, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "fill.pos_rel_y", fill.pos_rel_y, EET_T_DOUBLE);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "fill.pos_abs_y", fill.pos_abs_y, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "fill.rel_y", fill.rel_y, EET_T_DOUBLE);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "fill.abs_y", fill.abs_y, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "fill.angle", fill.angle, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "fill.spread", fill.spread, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "fill.type", fill.type, EET_T_CHAR);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "color_class", color_class, EET_T_STRING);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "color.r", color.r, EET_T_UCHAR);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "color.g", color.g, EET_T_UCHAR);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "color.b", color.b, EET_T_UCHAR);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "color.a", color.a, EET_T_UCHAR);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "color2.r", color2.r, EET_T_UCHAR);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "color2.g", color2.g, EET_T_UCHAR);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "color2.b", color2.b, EET_T_UCHAR);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "color2.a", color2.a, EET_T_UCHAR);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "color3.r", color3.r, EET_T_UCHAR);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "color3.g", color3.g, EET_T_UCHAR);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "color3.b", color3.b, EET_T_UCHAR);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "color3.a", color3.a, EET_T_UCHAR);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "text.text", text.text, EET_T_STRING);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "text.text_class", text.text_class, EET_T_STRING);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "text.style", text.style, EET_T_STRING);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "text.font", text.font, EET_T_STRING);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "text.size", text.size, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "text.fit_x", text.fit_x, EET_T_UCHAR);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "text.fit_y", text.fit_y, EET_T_UCHAR);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "text.min_x", text.min_x, EET_T_UCHAR);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "text.min_y", text.min_y, EET_T_UCHAR);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "text.max_x", text.max_x, EET_T_UCHAR);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "text.max_y", text.max_y, EET_T_UCHAR);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "text.align.x", text.align.x, EET_T_DOUBLE);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "text.align.y", text.align.y, EET_T_DOUBLE);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "text.id_source", text.id_source, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "text.id_text_source", text.id_text_source, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "text.elipsis", text.elipsis, EET_T_DOUBLE);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "gradient.id", gradient.id, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "gradient.type", gradient.type, EET_T_STRING);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "gradient.use_rel", gradient.use_rel, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "gradient.rel1.relative_x", gradient.rel1.relative_x, EET_T_DOUBLE);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "gradient.rel1.relative_y", gradient.rel1.relative_y, EET_T_DOUBLE);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "gradient.rel1.offset_x", gradient.rel1.offset_x, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "gradient.rel1.offset_y", gradient.rel1.offset_y, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "gradient.rel2.relative_x", gradient.rel2.relative_x, EET_T_DOUBLE);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "gradient.rel2.relative_y", gradient.rel2.relative_y, EET_T_DOUBLE);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "gradient.rel2.offset_x", gradient.rel2.offset_x, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "gradient.rel2.offset_y", gradient.rel2.offset_y, EET_T_INT);
+
+   NEWD("Edje_Part",
+       Edje_Part);
+   _edje_edd_edje_part =
+     eet_data_descriptor3_new(&eddc);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part, Edje_Part, "name", name, EET_T_STRING);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part, Edje_Part, "id", id, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part, Edje_Part, "type", type, EET_T_CHAR);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part, Edje_Part, "effect", effect, EET_T_CHAR);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part, Edje_Part, "mouse_events", mouse_events, EET_T_CHAR);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part, Edje_Part, "repeat_events", repeat_events, EET_T_CHAR);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part, Edje_Part, "ignore_flags", ignore_flags, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part, Edje_Part, "pointer_mode", pointer_mode, EET_T_CHAR);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part, Edje_Part, "precise_is_inside", precise_is_inside, EET_T_CHAR);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part, Edje_Part, "clip_to_id", clip_to_id, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part, Edje_Part, "use_alternate_font_metrics", use_alternate_font_metrics, EET_T_UCHAR);
+   EET_DATA_DESCRIPTOR_ADD_SUB(_edje_edd_edje_part, Edje_Part, "default_desc", default_desc, _edje_edd_edje_part_description);
+   EET_DATA_DESCRIPTOR_ADD_LIST(_edje_edd_edje_part, Edje_Part, "other_desc", other_desc, _edje_edd_edje_part_description);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part, Edje_Part, "dragable.x", dragable.x, EET_T_CHAR);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part, Edje_Part, "dragable.step_x", dragable.step_x, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part, Edje_Part, "dragable.count_x", dragable.count_x, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part, Edje_Part, "dragable.y", dragable.y, EET_T_CHAR);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part, Edje_Part, "dragable.step_y", dragable.step_y, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part, Edje_Part, "dragable.count_y", dragable.count_y, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part, Edje_Part, "dragable.counfine_id", dragable.confine_id, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part, Edje_Part, "dragable.events_id", dragable.events_id, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part, Edje_Part, "source", source, EET_T_STRING);
+
+   NEWD("Edje_Part_Collection",
+       Edje_Part_Collection);
+   _edje_edd_edje_part_collection  =
+     eet_data_descriptor3_new(&eddc);
+   EET_DATA_DESCRIPTOR_ADD_LIST(_edje_edd_edje_part_collection, Edje_Part_Collection, "programs", programs, _edje_edd_edje_program);
+   EET_DATA_DESCRIPTOR_ADD_LIST(_edje_edd_edje_part_collection, Edje_Part_Collection, "parts", parts, _edje_edd_edje_part);
+   EET_DATA_DESCRIPTOR_ADD_LIST(_edje_edd_edje_part_collection, Edje_Part_Collection, "data", data, _edje_edd_edje_data);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_collection, Edje_Part_Collection, "prop.min.w", prop.min.w, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_collection, Edje_Part_Collection, "prop.min.h", prop.min.h, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_collection, Edje_Part_Collection, "prop.max.w", prop.max.w, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_collection, Edje_Part_Collection, "prop.max.h", prop.max.h, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_collection, Edje_Part_Collection, "id", id, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_collection, Edje_Part_Collection, "script_only", script_only, EET_T_UCHAR);
+}
diff --git a/src/lib/edje_edit.c b/src/lib/edje_edit.c
new file mode 100644 (file)
index 0000000..72504a1
--- /dev/null
@@ -0,0 +1,4297 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+/*
+ * TODO
+ * -----------------------------------------------------------------
+ * Modify edje so that also ebryo source is included in the eet file
+ * Write decompile info (print source) back to edje file
+ * Remove images/fonts
+ * Draggies
+ *
+ */
+
+#include "edje_private.h"
+#include "edje_cc.h"
+
+/* Get ed(Edje*) from obj(Evas_Object*) */
+#define GET_ED_OR_RETURN(RET) \
+   Edje *ed; \
+   ed = _edje_fetch(obj); \
+   if (!ed) return RET;
+
+/* Get rp(Edje_Real_Part*) from obj(Evas_Object*) and part(char*) */
+#define GET_RP_OR_RETURN(RET) \
+   Edje *ed; \
+   Edje_Real_Part *rp; \
+   ed = _edje_fetch(obj); \
+   if (!ed) return RET; \
+   rp = _edje_real_part_get(ed, part); \
+   if (!rp) return RET;
+
+/* Get pd(Edje_Part_Description*) from obj(Evas_Object*), part(char*) and state (char*) */
+#define GET_PD_OR_RETURN(RET) \
+   Edje *ed; \
+   Edje_Part_Description *pd; \
+   ed = _edje_fetch(obj); \
+   if (!ed) return RET; \
+   pd = _edje_part_description_find_byname(ed, part, state); \
+   if (!pd) return RET;
+
+/* Get epr(Edje_Program*) from obj(Evas_Object*) and prog(char*)*/
+#define GET_EPR_OR_RETURN(RET) \
+   Edje_Program *epr; \
+   epr = _edje_program_get_byname(obj, prog); \
+   if (!epr) return RET;
+
+void *
+mem_alloc(size_t size)
+{
+   void *mem;
+
+   mem = calloc(1, size);
+   if (mem) return mem;
+   fprintf(stderr, "Edje_Edit: Error. memory allocation of %i bytes failed. %s\n",
+           size, strerror(errno));
+   exit(-1);
+   return NULL;
+}
+
+char *
+mem_strdup(const char *s)
+{
+   void *str;
+
+   str = strdup(s);
+   if (str) return str;
+   fprintf(stderr, "Edje_Edit: Error. memory allocation of %i bytes failed. %s."
+           "string being duplicated: \"%s\"\n", strlen(s) + 1, strerror(errno), s);
+   exit(-1);
+   return NULL;
+}
+
+
+/*************/
+/* INTERNALS */
+/*************/
+
+static Edje_Part_Description *
+_edje_part_description_find_byname(Edje *ed, const char *part, const char *state) //state include the value in the string (ex. "default 0.00")
+{
+   Edje_Real_Part *rp;
+   Edje_Part_Description *pd;
+   char *delim;
+   double value;
+   char *name;
+
+   if (!ed || !part || !state) return NULL;
+
+   rp = _edje_real_part_get(ed, part);
+   if (!rp) return NULL;
+
+   name = strdup(state);
+   delim = strrchr(name, (int)' ');
+   if (!delim)
+     {
+       free(name);
+       return NULL;
+     }
+
+   if (sscanf(delim, "%lf", &value) != 1)
+     {
+       free(name);
+       return NULL;
+     }
+
+   delim[0] = '\0';
+   //printf("SEARCH DESC(%s): %s %f\n", state, state, value);
+   pd = _edje_part_description_find(ed, rp, name, value);
+
+   free(name);
+
+   if (!pd) return NULL;
+   return pd;
+}
+
+static int
+_edje_image_id_find(Evas_Object *obj, const char *image_name)
+{
+   Edje_Image_Directory_Entry *i;
+   Evas_List *l;
+
+   GET_ED_OR_RETURN(-1);
+
+   if (!ed->file) return -1;
+   if (!ed->file->image_dir) return -1;
+
+   //printf("SEARCH IMAGE %s\n", image_name);
+
+   for (l = ed->file->image_dir->entries; l; l = l->next)
+     {
+       i = l->data;
+       if (strcmp(image_name, i->entry) == 0)
+         {
+            //printf("   Found id: %d \n", i->id);
+            return i->id;
+         }
+     }
+
+   return -1;
+}
+
+static const char *
+_edje_image_name_find(Evas_Object *obj, int image_id)
+{
+   Edje_Image_Directory_Entry *i;
+   Evas_List *l;
+
+   GET_ED_OR_RETURN(NULL);
+
+   if (!ed->file) return NULL;
+   if (!ed->file->image_dir) return NULL;
+
+   //printf("SEARCH IMAGE ID %d\n", image_id);
+
+   for (l = ed->file->image_dir->entries; l; l = l->next)
+     {
+       i = l->data;
+       if (image_id == i->id)
+         return i->entry;
+     }
+
+   return NULL;
+}
+
+static void
+_edje_real_part_free(Edje_Real_Part *rp)
+{
+   Evas_List *l;
+
+   if (!rp) return;
+
+   if (rp->object)
+     {
+       _edje_text_real_part_on_del(rp->edje, rp);
+       _edje_callbacks_del(rp->object);
+       evas_object_del(rp->object);
+     }
+
+   l = rp->extra_objects;
+   while (rp->extra_objects)
+     {
+       evas_object_del(rp->extra_objects->data);
+       rp->extra_objects = evas_list_remove_list(rp->extra_objects,
+                                                 rp->extra_objects);
+     }
+
+   if (rp->swallowed_object)
+     {
+       evas_object_smart_member_del(rp->swallowed_object);
+       evas_object_event_callback_del(rp->swallowed_object,
+                                      EVAS_CALLBACK_FREE,
+                                      _edje_object_part_swallow_free_cb);
+       evas_object_clip_unset(rp->swallowed_object);
+       evas_object_data_del(rp->swallowed_object, "\377 edje.swallowing_part");
+       if (rp->part->mouse_events)
+         _edje_callbacks_del(rp->swallowed_object);
+
+       if (rp->part->type == EDJE_PART_TYPE_GROUP)
+         evas_object_del(rp->swallowed_object);
+
+       rp->swallowed_object = NULL;
+     }
+
+   if (rp->text.text) evas_stringshare_del(rp->text.text);
+   if (rp->text.font) evas_stringshare_del(rp->text.font);
+   if (rp->text.cache.in_str) evas_stringshare_del(rp->text.cache.in_str);
+   if (rp->text.cache.out_str) evas_stringshare_del(rp->text.cache.out_str);
+
+   if (rp->custom.description)
+     _edje_collection_free_part_description_free(rp->custom.description, 0);
+
+   _edje_unref(rp->edje);
+   free(rp);
+}
+
+static unsigned char
+_edje_import_image_file(Edje *ed, const char *path, int id)
+{
+   char buf[256];
+   Evas_Object *im;
+   Eet_File *eetf;
+   void *im_data;
+   int  im_w, im_h;
+   int  im_alpha;
+   int bytes;
+
+   /* Try to load the file */
+   im = evas_object_image_add(ed->evas);
+   if (!im) return 0;
+
+   evas_object_image_file_set(im, path, NULL);
+   if (evas_object_image_load_error_get(im) != EVAS_LOAD_ERROR_NONE)
+     {
+       fprintf(stderr, "Edje_Edit: Error. unable to load image \"%s\"."
+               "Missing PNG or JPEG loader modules for Evas or "
+               "file does not exist, or is not readable.\n", path);
+       evas_object_del(im);
+       im = NULL;
+       return 0;
+     }
+
+   if (!im) return 0;
+
+   /* Write the loaded image to the edje file */
+
+   evas_object_image_size_get(im, &im_w, &im_h);
+   im_alpha = evas_object_image_alpha_get(im);
+   im_data = evas_object_image_data_get(im, 0);
+   if ((!im_data) || !(im_w > 0) || !(im_h > 0))
+     {
+       evas_object_del(im);
+       return 0;
+     }
+
+   /* open the eet file */
+   eetf = eet_open(ed->path, EET_FILE_MODE_READ_WRITE);
+   if (!eetf)
+     {
+       fprintf(stderr,
+               "Edje_Edit: Error. unable to open \"%s\" for writing output\n",
+               ed->path);
+       evas_object_del(im);
+       return 0;
+     }
+
+   snprintf(buf, sizeof(buf), "images/%i", id);
+
+   /* write the image data */
+   printf("***********  Writing images/%i to edj ******************\n", id);
+   bytes = eet_data_image_write(eetf, buf,
+                               im_data, im_w, im_h,
+                               im_alpha,
+                               0, 100, 1);
+   if (bytes <= 0)
+     {
+       fprintf(stderr, "Edje_Edit: Error. unable to write image part \"%s\" "
+       "part entry to %s\n", buf, ed->path);
+       evas_object_del(im);
+       return 0;
+     }
+
+   /* Rewrite Edje_File to edj */
+   evas_object_del(im);
+
+   printf("***********  Writing Edje_File* ed->file ******************\n");
+   bytes = eet_data_write(eetf, _edje_edd_edje_file, "edje_file", ed->file, 1);
+   if (bytes <= 0)
+     {
+       fprintf(stderr, "Edje_Edit: Error. unable to write \"edje_file\" "
+               "entry to \"%s\" \n", ed->path);
+       eet_close(eetf);
+       return 0;
+     }
+
+   eet_close(eetf);
+   return 1;
+}
+
+static int
+_edje_part_id_find(Edje *ed, const char *part)
+{
+   int id;
+
+   for (id = 0; id < ed->table_parts_size; id++)
+     {
+       Edje_Real_Part *rp = ed->table_parts[id];
+
+       if (!strcmp(rp->part->name, part))
+         return id;
+     }
+   return -1;
+}
+
+static void
+_edje_part_id_set(Edje *ed, Edje_Real_Part *rp, int new_id)
+{
+   /* This function change the id of a given real_part.
+    * All the depedency will be updated too.
+    * Also the table_parts is updated, and the current *rp in the table
+    * is lost.
+    * If new Id = -1 then all the depencies will be deleted
+    */
+   int old_id;
+   Edje_Part *part;
+   Evas_List *l, *ll;
+
+   part = rp->part;
+
+   if (!part) return;
+   printf("CHANGE ID OF PART %s TO %d\n", part->name, new_id);
+
+   if (!ed || !part || new_id < -1) return;
+
+   if (part->id == new_id) return;
+
+   old_id = part->id;
+   part->id = new_id;
+
+   /* Fix all the dependecies in all parts... */
+   for (l = ed->collection->parts; l; l = l->next)
+     {
+       Edje_Part *p;
+       Edje_Part_Description *d;
+
+       p = l->data;
+       //printf("   search id: %d in %s\n", old_id, p->name);
+       if (p->clip_to_id == old_id) p->clip_to_id = new_id;
+       if (p->dragable.confine_id == old_id) p->dragable.confine_id = new_id;
+
+       /* ...in default description */
+       d = p->default_desc;
+       //printf("      search in %s (%s)\n", p->name, d->state.name);
+       if (d->rel1.id_x == old_id) d->rel1.id_x = new_id;
+       if (d->rel1.id_y == old_id) d->rel1.id_y = new_id;
+       if (d->rel2.id_x == old_id) d->rel2.id_x = new_id;
+       if (d->rel2.id_y == old_id) d->rel2.id_y = new_id;
+       if (d->text.id_source == old_id) d->text.id_source = new_id;
+       if (d->text.id_text_source == old_id) d->text.id_text_source = new_id;
+       /* ...and in all other descriptions */
+       for (ll = p->other_desc; ll; ll = ll->next)
+         {
+            d = ll->data;
+            //printf("      search in %s (%s)\n", p->name, d->state.name);
+            if (d->rel1.id_x == old_id) d->rel1.id_x = new_id;
+            if (d->rel1.id_y == old_id) d->rel1.id_y = new_id;
+            if (d->rel2.id_x == old_id) d->rel2.id_x = new_id;
+            if (d->rel2.id_y == old_id) d->rel2.id_y = new_id;
+            if (d->text.id_source == old_id) d->text.id_source = new_id;
+            if (d->text.id_text_source == old_id) d->text.id_text_source = new_id;
+         }
+     }
+
+   /*...and also in programs targets */
+   for (l = ed->collection->programs; l; l = l->next)
+     {
+       Edje_Program *epr;
+
+       epr = l->data;
+       if (epr->action != EDJE_ACTION_TYPE_STATE_SET)
+         continue;
+
+       for (ll = epr->targets; ll; ll = ll->next)
+         {
+            Edje_Program_Target *pt;
+
+            pt = ll->data;
+            if (pt->id == old_id)
+              {
+                 if (new_id == -1)
+                   epr->targets = evas_list_remove(epr->targets, pt);
+                 else
+                   pt->id = new_id;
+              }
+         }
+     }
+
+   /* Adjust table_parts */
+   if (new_id >= 0)
+     ed->table_parts[new_id] = rp;
+}
+
+static void
+_edje_parts_id_switch(Edje *ed, Edje_Real_Part *rp1, Edje_Real_Part *rp2)
+{
+   /* This function switch the id of two parts.
+    * All the depedency will be updated too.
+    * Also the table_parts is updated,
+    * The parts list isn't touched
+    */
+   int id1;
+   int id2;
+   Evas_List *l, *ll;
+
+   printf("SWITCH ID OF PART %d AND %d\n", rp1->part->id, rp2->part->id);
+
+   if (!ed || !rp1 || !rp2) return;
+   if (rp1 == rp2) return;
+
+   id1 = rp1->part->id;
+   id2 = rp2->part->id;
+
+   /* Switch ids */
+   rp1->part->id = id2;
+   rp2->part->id = id1;
+
+   /* adjust table_parts */
+   ed->table_parts[id1] = rp2;
+   ed->table_parts[id2] = rp1;
+
+   // Fix all the dependecies in all parts...
+   for (l = ed->collection->parts; l; l = l->next)
+     {
+       Edje_Part *p;
+       Evas_List *ll;
+       Edje_Part_Description *d;
+
+       p = l->data;
+       //printf("   search id: %d in %s\n", old_id, p->name);
+       if (p->clip_to_id == id1) p->clip_to_id = id2;
+       else if (p->clip_to_id == id2) p->clip_to_id = id1;
+       if (p->dragable.confine_id == id1) p->dragable.confine_id = id2;
+       else if (p->dragable.confine_id == id2) p->dragable.confine_id = id1;
+
+       // ...in default description
+       d = p->default_desc;
+       // printf("      search in %s (%s)\n", p->name, d->state.name);
+       if (d->rel1.id_x == id1) d->rel1.id_x = id2;
+       else if (d->rel1.id_x == id2) d->rel1.id_x = id1;
+       if (d->rel1.id_y == id1) d->rel1.id_y = id2;
+       else if (d->rel1.id_y == id2) d->rel1.id_y = id1;
+       if (d->rel2.id_x == id1) d->rel2.id_x = id2;
+       else if (d->rel2.id_x == id2) d->rel2.id_x = id1;
+       if (d->rel2.id_y == id1) d->rel2.id_y = id2;
+       else if (d->rel2.id_y == id2) d->rel2.id_y = id1;
+       if (d->text.id_source == id1) d->text.id_source = id2;
+       else if (d->text.id_source == id2) d->text.id_source = id1;
+       if (d->text.id_text_source == id1) d->text.id_text_source = id2;
+       else if (d->text.id_text_source == id2) d->text.id_text_source = id2;
+       // ...and in all other descriptions
+       for (ll = p->other_desc; ll; ll = ll->next)
+         {
+            d = ll->data;
+            //printf("      search in %s (%s)\n", p->name, d->state.name);
+            if (d->rel1.id_x == id1) d->rel1.id_x = id2;
+            else if (d->rel1.id_x == id2) d->rel1.id_x = id1;
+            if (d->rel1.id_y == id1) d->rel1.id_y = id2;
+            else if (d->rel1.id_y == id2) d->rel1.id_y = id1;
+            if (d->rel2.id_x == id1) d->rel2.id_x = id2;
+            else if (d->rel2.id_x == id2) d->rel2.id_x = id1;
+            if (d->rel2.id_y == id1) d->rel2.id_y = id2;
+            else if (d->rel2.id_y == id2) d->rel2.id_y = id1;
+            if (d->text.id_source == id1) d->text.id_source = id2;
+            else if (d->text.id_source == id2) d->text.id_source = id1;
+            if (d->text.id_text_source == id1) d->text.id_text_source = id2;
+            else if (d->text.id_text_source == id2) d->text.id_text_source = id2;
+         }
+     }
+   //...and also in programs targets
+   for (l = ed->collection->programs; l; l = l->next)
+     {
+       Edje_Program *epr;
+
+       epr = l->data;
+       if (epr->action != EDJE_ACTION_TYPE_STATE_SET)
+         continue;
+
+       for (ll = epr->targets; ll; ll = ll->next)
+         {
+            Edje_Program_Target *pt;
+
+            pt = ll->data;
+            if (pt->id == id1) pt->id = id2;
+            else if (pt->id == id2) pt->id = id1;
+         }
+     }
+   //TODO Real part dependencies are ok?
+}
+
+static void
+_edje_fix_parts_id(Edje *ed)
+{
+   /* We use this to clear the id hole leaved when a part is removed.
+    * After the execution of this function all parts will have a right
+    * (uniqe & ordered) id. The table_parts is also updated.
+    */
+   Evas_List *l;
+   int correct_id;
+   int count;
+
+   printf("FIXING PARTS ID \n");
+
+   //TODO order the list first to be more robust
+
+   /* Give a correct id to all the parts */
+   correct_id = 0;
+   for (l = ed->collection->parts; l; l = l->next)
+     {
+       Edje_Part *p;
+
+       p = l->data;
+       //printf(" [%d]Checking part: %s id: %d\n", correct_id, p->name, p->id);
+       if (p->id != correct_id)
+         _edje_part_id_set(ed, ed->table_parts[p->id], correct_id);
+
+       correct_id++;
+     }
+
+   /* If we have removed some parts realloc table_parts */
+   count = evas_list_count(ed->collection->parts);
+   if (count != ed->table_parts_size)
+     {
+       ed->table_parts = realloc(ed->table_parts, SZ(Edje_Real_Part *) * count);
+       ed->table_parts_size = count;
+     }
+
+   //printf("\n");
+}
+
+static void
+_edje_if_string_free(Edje *ed, const char *str)
+{
+   Eet_Dictionary *dict;
+
+   if (!ed || !str) return;
+
+   dict = eet_dictionary_get(ed->file->ef);
+   if (eet_dictionary_string_check(dict, str)) return;
+   evas_stringshare_del(str);
+   str = NULL;
+}
+
+Edje_Spectrum_Directory_Entry *
+_edje_edit_spectrum_entry_get(Edje *ed, const char* spectra)
+{
+   Edje_Spectrum_Directory_Entry *s;
+   Evas_List *l;
+
+   if (!ed->file || !spectra || !ed->file->spectrum_dir)
+      return NULL;
+
+   for (l = ed->file->spectrum_dir->entries; l; l = l->next)
+     {
+       Edje_Spectrum_Directory_Entry *s;
+
+       s = l->data;
+       if (!strcmp(s->entry, spectra))
+          return s;
+     }
+
+   return NULL;
+}
+
+Edje_Spectrum_Directory_Entry *
+_edje_edit_spectrum_entry_get_by_id(Edje *ed, int spectra_id)
+{
+   Evas_List *l;
+
+   if (!ed->file || !ed->file->spectrum_dir)
+      return NULL;
+
+   for (l = ed->file->spectrum_dir->entries; l; l = l->next)
+     {
+       Edje_Spectrum_Directory_Entry *s;
+
+       s = l->data;
+       if (s->id == spectra_id)
+          return s;
+     }
+
+   return NULL;
+}
+
+/*****************/
+/*  GENERAL API  */
+/*****************/
+
+EAPI void
+edje_edit_string_list_free(Evas_List *lst)
+{
+   //printf("FREE LIST: \n");
+   while (lst)
+     {
+       if (lst->data) evas_stringshare_del(lst->data);
+       //printf("FREE: %s\n", lst->data);
+       lst = evas_list_remove(lst, lst->data);
+     }
+}
+
+EAPI void
+edje_edit_string_free(const char *str)
+{
+   if (str) evas_stringshare_del(str);
+}
+
+/****************/
+/*  GROUPS API  */
+/****************/
+
+EAPI unsigned char
+edje_edit_group_add(Evas_Object *obj, const char *name)
+{
+   Edje_Part_Collection_Directory_Entry *de;
+   Edje_Part_Collection *pc;
+   Evas_List *l;
+   int id;
+   int search;
+   //Code *cd;
+
+   GET_ED_OR_RETURN(0);
+
+   printf("ADD GROUP: %s \n", name);
+
+   /* check if a group with the same name already exists */
+   for (l = ed->file->collection_dir->entries; l; l = l->next)
+     {
+       Edje_Part_Collection_Directory_Entry *d = l->data;
+       if (!strcmp(d->entry, name))
+         return 0;
+     }
+
+   /* Create structs */
+   de = mem_alloc(SZ(Edje_Part_Collection_Directory_Entry));
+   if (!de) return 0;
+
+   pc = mem_alloc(SZ(Edje_Part_Collection));
+   if (!pc)
+     {
+       free(de);
+       return 0;
+     }
+
+   /* Search first free id */
+   id = 0;
+   search = 0;
+   while (!id)
+     {
+       unsigned char found = 0;
+
+       for (l = ed->file->collection_dir->entries; l; l = l->next)
+         {
+            Edje_Part_Collection_Directory_Entry *d = l->data;
+
+            // printf("search if %d is free [id %d]\n", search, d->id);
+            if (search == d->id)
+              {
+                 found = 1;
+                 break;
+              }
+         }
+       if (!found)
+         id = search;
+       else
+         search++;
+     }
+
+   /* Init Edje_Part_Collection_Directory_Entry */
+   printf(" new id: %d\n", id);
+   de->id = id;
+   de->entry = mem_strdup(name);
+   ed->file->collection_dir->entries = evas_list_append(ed->file->collection_dir->entries, de);
+
+   /* Init Edje_Part_Collection */
+   pc->id = id;
+   pc->references = 1;  //TODO i'm not shure about this (maybe set to 0 ?)
+   pc->programs = NULL;
+   pc->parts = NULL;
+   pc->data = NULL;
+   pc->script = NULL;
+   pc->part = evas_stringshare_add(name);
+
+   //cd = mem_alloc(SZ(Code));
+   //codes = evas_list_append(codes, cd);
+
+   ed->file->collection_hash = evas_hash_add(ed->file->collection_hash, name, pc);
+
+   return 1;
+}
+
+
+EAPI unsigned char
+edje_edit_group_del(Evas_Object *obj)
+{
+   char buf[32];
+   Evas_List *l;
+   int i;
+   Edje_Part_Collection *g;
+   Eet_File *eetf;
+
+   GET_ED_OR_RETURN(0);
+
+   g = ed->collection;
+   printf("REMOVE GROUP: %s [id: %d]\n", g->part, g->id);
+
+   /* Don't remove the last group */
+   if (evas_list_count(ed->file->collection_dir->entries) < 2)
+     return 0;
+
+   /* Remove collection/id from eet file */
+   eetf = eet_open(ed->file->path, EET_FILE_MODE_READ_WRITE);
+   if (!eetf)
+     {
+       fprintf(stderr, "Edje_Edit: Error. unable to open \"%s\" "
+               "for writing output\n", ed->file->path);
+       return 0;
+     }
+   snprintf(buf, SZ(buf), "collections/%d", g->id);
+   eet_delete(eetf, buf);
+   eet_close(eetf);
+
+   /* Remove all Edje_Real_Parts */
+   for (i = 0; i < ed->table_parts_size; i++)
+     _edje_real_part_free(ed->table_parts[i]);
+   ed->table_parts_size = 0;
+   free(ed->table_parts);
+   ed->table_parts = NULL;
+
+   /* Free Group */
+   _edje_collection_free(ed->file, g);
+
+   /* Update collection_dir */
+   for (l = ed->file->collection_dir->entries; l; l = l->next)
+     {
+       Edje_Part_Collection_Directory_Entry *e;
+
+       e = l->data;
+       printf("  id: %d  entry: %s\n", e->id, e->entry);
+       if (e->id == g->id)
+         {
+            ed->file->collection_dir->entries =
+               evas_list_remove_list(ed->file->collection_dir->entries, l);
+            //         free(e->entry);  This should be right but cause a segv
+            free(e);
+            e = NULL;
+            break;
+         }
+     }
+
+   ed->collection = NULL;
+
+   if (ed->table_programs_size > 0)
+     {
+       free(ed->table_programs);
+       ed->table_programs = NULL;
+       ed->table_programs_size = 0;
+     }
+
+   return 1;
+}
+
+EAPI unsigned char
+edje_edit_group_exist(Evas_Object *obj, const char *group)
+{
+   Evas_List *l;
+
+   GET_ED_OR_RETURN(0);
+
+   for (l = ed->file->collection_dir->entries; l; l = l->next)
+     {
+       Edje_Part_Collection_Directory_Entry *e;
+
+       e = l->data;
+       if (e->entry && !strcmp(e->entry, group))
+         return 1;
+     }
+   return 0;
+}
+
+EAPI unsigned char
+edje_edit_group_name_set(Evas_Object *obj, const char *new_name)
+{
+   Evas_List *l;
+   Edje_Part_Collection *pc;
+
+   GET_ED_OR_RETURN(0);
+
+   if (!new_name) return 0;
+   if (edje_edit_group_exist(obj, new_name)) return 0;
+
+   pc = ed->collection;
+
+   printf("Set name of current group: %s [id: %d][new name: %s]\n",
+        pc->part, pc->id, new_name);
+
+   //if (pc->part && ed->file->free_strings) evas_stringshare_del(pc->part); TODO FIXME
+   pc->part = evas_stringshare_add(new_name);
+
+   for (l = ed->file->collection_dir->entries; l; l = l->next)
+     {
+       Edje_Part_Collection_Directory_Entry *pce = l->data;
+
+       if (pc->id == pce->id)
+         {
+            ed->file->collection_hash = evas_hash_del(ed->file->collection_hash,
+                                                      pce->entry, NULL);
+            ed->file->collection_hash = evas_hash_add(ed->file->collection_hash,
+                                                      new_name, pc);
+
+            //if (pce->entry &&  //TODO Also this cause segv
+            //    !eet_dictionary_string_check(eet_dictionary_get(ed->file->ef), pce->entry))
+            //   evas_stringshare_del(pce->entry);
+            pce->entry = evas_stringshare_add(new_name);
+
+            return 1;
+         }
+     }
+   return 0;
+}
+
+EAPI int
+edje_edit_group_min_w_get(Evas_Object *obj)
+{
+   printf("Get min_w of group\n");
+   GET_ED_OR_RETURN(-1);
+   if (!ed->collection) return -1;
+   return ed->collection->prop.min.w;
+}
+
+EAPI void
+edje_edit_group_min_w_set(Evas_Object *obj, int w)
+{
+   printf("Set min_w of group [new w: %d]\n", w);
+   GET_ED_OR_RETURN();
+   ed->collection->prop.min.w = w;
+}
+
+EAPI int
+edje_edit_group_min_h_get(Evas_Object *obj)
+{
+   printf("Get min_h of group\n");
+   GET_ED_OR_RETURN(-1);
+   if (!ed->collection) return -1;
+   return ed->collection->prop.min.h;
+}
+
+EAPI void
+edje_edit_group_min_h_set(Evas_Object *obj, int h)
+{
+   printf("Set min_h of group [new h: %d]\n", h);
+   GET_ED_OR_RETURN();
+   ed->collection->prop.min.h = h;
+}
+
+EAPI int
+edje_edit_group_max_w_get(Evas_Object *obj)
+{
+   printf("Get max_w of group\n");
+   GET_ED_OR_RETURN(-1);
+   if (!ed->collection) return -1;
+   return ed->collection->prop.max.w;
+}
+
+EAPI void
+edje_edit_group_max_w_set(Evas_Object *obj, int w)
+{
+   printf("Set max_w of group: [new w: %d]\n", w);
+   GET_ED_OR_RETURN();
+   ed->collection->prop.max.w = w;
+}
+
+EAPI int
+edje_edit_group_max_h_get(Evas_Object *obj)
+{
+   printf("Get max_h of group\n");
+   GET_ED_OR_RETURN(-1);
+   if (!ed->collection) return -1;
+   return ed->collection->prop.max.h;
+}
+
+EAPI void
+edje_edit_group_max_h_set(Evas_Object *obj, int h)
+{
+   printf("Set max_h of group: [new h: %d]\n", h);
+   GET_ED_OR_RETURN();
+   ed->collection->prop.max.h = h;
+}
+
+/***************/
+/*  PARTS API  */
+/***************/
+
+EAPI Evas_List *
+edje_edit_parts_list_get(Evas_Object *obj)
+{
+   Evas_List *parts;
+   int i;
+
+   GET_ED_OR_RETURN(NULL);
+
+   //printf("EE: Found %d parts\n", ed->table_parts_size);
+
+   parts = NULL;
+   for (i = 0; i < ed->table_parts_size; i++)
+     {
+       Edje_Real_Part *rp;
+
+       rp = ed->table_parts[i];
+       parts = evas_list_append(parts, evas_stringshare_add(rp->part->name));
+     }
+
+   return parts;
+}
+
+EAPI unsigned char
+edje_edit_part_name_set(Evas_Object *obj, const char* part, const char* new_name)
+{
+   GET_RP_OR_RETURN(0);
+
+   if (!new_name) return 0;
+   if (_edje_real_part_get(ed, new_name)) return 0;
+
+   printf("Set name of part: %s [new name: %s]\n", part, new_name);
+
+   _edje_if_string_free(ed, rp->part->name);
+   rp->part->name = (char *)evas_stringshare_add(new_name);
+
+   return 1;
+}
+
+EAPI unsigned char
+edje_edit_part_add(Evas_Object *obj, const char* name, unsigned char type)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+   Edje_Real_Part *rp;
+
+   GET_ED_OR_RETURN(0);
+
+   printf("ADD PART: %s [type: %d]\n", name, type);
+
+   /* Check if part already exists */
+   if (_edje_real_part_get(ed, name))
+     return FALSE;
+
+   /* Alloc Edje_Part or return */
+   ep = mem_alloc(sizeof(Edje_Part));
+   if (!ep) return FALSE;
+
+   /* Alloc Edje_Real_Part or return */
+   rp = mem_alloc(sizeof(Edje_Real_Part));
+   if (!rp)
+     {
+       free(ep);
+       return FALSE;
+     }
+
+   /* Init Edje_Part */
+   pc = ed->collection;
+   pc->parts = evas_list_append(pc->parts, ep);
+
+   ep->id = evas_list_count(pc->parts) - 1;
+   ep->type = type;
+   ep->name = evas_stringshare_add(name);
+   ep->mouse_events = 1;
+   ep->repeat_events = 0;
+   ep->ignore_flags = EVAS_EVENT_FLAG_NONE;
+   ep->pointer_mode = EVAS_OBJECT_POINTER_MODE_AUTOGRAB;
+   ep->precise_is_inside = 0;
+   ep->use_alternate_font_metrics = 0;
+   ep->clip_to_id = -1;
+   ep->dragable.confine_id = -1;
+   ep->dragable.events_id = -1;
+
+   ep->default_desc = NULL;
+   ep->other_desc = NULL;
+
+   /* Init Edje_Real_Part */
+   rp->edje = ed;
+   _edje_ref(rp->edje);
+   rp->part = ep;
+
+   if (ep->type == EDJE_PART_TYPE_RECTANGLE)
+     rp->object = evas_object_rectangle_add(ed->evas);
+   else if (ep->type == EDJE_PART_TYPE_IMAGE)
+     rp->object = evas_object_image_add(ed->evas);
+   else if (ep->type == EDJE_PART_TYPE_TEXT)
+     {
+       _edje_text_part_on_add(ed, rp);
+       rp->object = evas_object_text_add(ed->evas);
+       evas_object_text_font_source_set(rp->object, ed->path);
+     }
+   else if (ep->type == EDJE_PART_TYPE_SWALLOW ||
+           ep->type == EDJE_PART_TYPE_GROUP)
+     {
+       rp->object = evas_object_rectangle_add(ed->evas);
+       evas_object_color_set(rp->object, 0, 0, 0, 0);
+       evas_object_pass_events_set(rp->object, 1);
+       evas_object_pointer_mode_set(rp->object, EVAS_OBJECT_POINTER_MODE_NOGRAB);
+     }
+   else if (ep->type == EDJE_PART_TYPE_TEXTBLOCK)
+     rp->object = evas_object_textblock_add(ed->evas);
+   else if (ep->type == EDJE_PART_TYPE_GRADIENT)
+     rp->object = evas_object_gradient_add(ed->evas);
+   else
+     printf("EDJE ERROR: wrong part type %i!\n", ep->type);
+   if (rp->object)
+     {
+       evas_object_smart_member_add(rp->object, ed->obj);
+       evas_object_layer_set(rp->object, evas_object_layer_get(ed->obj));
+       if (ep->type != EDJE_PART_TYPE_SWALLOW && ep->type != EDJE_PART_TYPE_GROUP)
+         {
+            if (ep->mouse_events)
+              {
+                 _edje_callbacks_add(rp->object, ed, rp);
+                 if (ep->repeat_events)
+                   evas_object_repeat_events_set(rp->object, 1);
+
+                 if (ep->pointer_mode != EVAS_OBJECT_POINTER_MODE_AUTOGRAB)
+                   evas_object_pointer_mode_set(rp->object, ep->pointer_mode);
+              }
+            else
+              {
+                 evas_object_pass_events_set(rp->object, 1);
+                 evas_object_pointer_mode_set(rp->object,
+                                              EVAS_OBJECT_POINTER_MODE_NOGRAB);
+              }
+            if (ep->precise_is_inside)
+              evas_object_precise_is_inside_set(rp->object, 1);
+         }
+       evas_object_clip_set(rp->object, ed->clipper);
+     }
+   rp->drag.step.x = ep->dragable.step_x;
+   rp->drag.step.y = ep->dragable.step_y;
+   rp->gradient_id = -1;
+
+
+   /* Update table_parts */
+   ed->table_parts_size++;
+   ed->table_parts = realloc(ed->table_parts,
+                            sizeof(Edje_Real_Part *) * ed->table_parts_size);
+
+   ed->table_parts[ep->id % ed->table_parts_size] = rp;
+
+   /* Create default description */
+   edje_edit_state_add(obj, name, "default");
+
+   rp->param1.description = ep->default_desc;
+   rp->chosen_description = rp->param1.description;
+
+   edje_object_calc_force(obj);
+
+   return TRUE;
+}
+
+EAPI unsigned char
+edje_edit_part_del(Evas_Object *obj, const char* part)
+{
+   Edje_Part *ep;
+   Edje_Part_Collection *pc;
+   int id;
+
+   GET_RP_OR_RETURN(0);
+
+   printf("REMOVE PART: %s\n", part);
+
+   ep = rp->part;
+   id = ep->id;
+
+   if (ed->table_parts_size <= 1) return FALSE; //don't remove the last part
+
+   /* Unlik Edje_Real_Parts that link to the removed one */
+   int i;
+   for (i = 0; i < ed->table_parts_size; i++)
+     {
+       Edje_Real_Part *real;
+
+       if (i == id) continue; //don't check the deleted id
+       real = ed->table_parts[i % ed->table_parts_size];
+
+       if (real->text.source == rp) real->text.source = NULL;
+       if (real->text.text_source == rp) real->text.text_source = NULL;
+
+       if (real->param1.rel1_to_x == rp) real->param1.rel1_to_x = NULL;
+       if (real->param1.rel1_to_y == rp) real->param1.rel1_to_y = NULL;
+       if (real->param1.rel2_to_x == rp) real->param1.rel2_to_x = NULL;
+       if (real->param1.rel2_to_y == rp) real->param1.rel2_to_y = NULL;
+
+       if (real->param2.rel1_to_x == rp) real->param2.rel1_to_x = NULL;
+       if (real->param2.rel1_to_y == rp) real->param2.rel1_to_y = NULL;
+       if (real->param2.rel2_to_x == rp) real->param2.rel2_to_x = NULL;
+       if (real->param2.rel2_to_y == rp) real->param2.rel2_to_y = NULL;
+
+       if (real->custom.rel1_to_x == rp) real->custom.rel1_to_x = NULL;
+       if (real->custom.rel1_to_y == rp) real->custom.rel1_to_y = NULL;
+       if (real->custom.rel2_to_x == rp) real->custom.rel2_to_x = NULL;
+       if (real->custom.rel2_to_y == rp) real->custom.rel2_to_y = NULL;
+
+       if (real->clip_to == rp)
+         {
+            evas_object_clip_set(real->object, ed->clipper);
+            real->clip_to = NULL;
+         }
+       //TODO confine ??
+     }
+
+   /* Unlink all the parts and descriptions that refer to id */
+   _edje_part_id_set(ed, rp, -1);
+
+   /* Remove part from parts list */
+   pc = ed->collection;
+   pc->parts = evas_list_remove(pc->parts, ep);
+   _edje_fix_parts_id(ed);
+
+   /* Free Edje_Part and all descriptions */
+   _edje_if_string_free(ed, ep->name);
+   if (ep->default_desc)
+     {
+       _edje_collection_free_part_description_free(ep->default_desc, 0);
+       ep->default_desc = NULL;
+     }
+   while (ep->other_desc)
+     {
+       Edje_Part_Description *desc;
+
+       desc = ep->other_desc->data;
+       ep->other_desc = evas_list_remove(ep->other_desc, desc);
+       _edje_collection_free_part_description_free(desc, 0);
+     }
+   free(ep);
+
+   /* Free Edje_Real_Part */
+   _edje_real_part_free(rp);
+
+
+   edje_object_calc_force(obj);
+   return TRUE;
+}
+
+EAPI unsigned char
+edje_edit_part_exist(Evas_Object *obj, const char *part)
+{
+   GET_RP_OR_RETURN(0);
+   return 1;
+}
+
+EAPI unsigned char
+edje_edit_part_restack_below(Evas_Object *obj, const char* part)
+{
+   Edje_Part_Collection *group;
+   Edje_Real_Part *prev;
+
+   GET_RP_OR_RETURN(0);
+
+   printf("RESTACK PART: %s BELOW\n", part);
+
+   if (rp->part->id < 1) return 0;
+   group = ed->collection;
+
+   /* update parts list */
+   prev = ed->table_parts[(rp->part->id - 1) % ed->table_parts_size];
+   group->parts = evas_list_remove(group->parts, rp->part);
+   group->parts = evas_list_prepend_relative(group->parts, rp->part, prev->part);
+
+   _edje_parts_id_switch(ed, rp, prev);
+
+   evas_object_stack_below(rp->object, prev->object);
+
+   return 1;
+}
+
+EAPI unsigned char
+edje_edit_part_restack_above(Evas_Object *obj, const char* part)
+{
+   Edje_Part_Collection *group;
+   Edje_Real_Part *next;
+
+   GET_RP_OR_RETURN(0);
+
+   printf("RESTACK PART: %s ABOVE\n", part);
+
+   if (rp->part->id >= ed->table_parts_size - 1) return 0;
+
+   group = ed->collection;
+
+   /* update parts list */
+   next = ed->table_parts[(rp->part->id + 1) % ed->table_parts_size];
+   group->parts = evas_list_remove(group->parts, rp->part);
+   group->parts = evas_list_append_relative(group->parts, rp->part, next->part);
+
+   /* update ids */
+   _edje_parts_id_switch(ed, rp, next);
+
+   evas_object_stack_above(rp->object, next->object);
+
+   return 1;
+}
+
+EAPI unsigned char
+edje_edit_part_type_get(Evas_Object *obj, const char *part)
+{
+   GET_RP_OR_RETURN(0);
+
+   return rp->part->type;
+}
+
+EAPI const char *
+edje_edit_part_selected_state_get(Evas_Object *obj, const char *part)
+{
+   char name[PATH_MAX];
+
+   GET_RP_OR_RETURN(NULL);
+
+   if (!rp->chosen_description)
+     return "default 0.00";
+
+   snprintf(name, PATH_MAX, "%s %.2f",
+            rp->chosen_description->state.name,
+            rp->chosen_description->state.value);
+
+   return evas_stringshare_add(name);
+}
+
+EAPI unsigned char
+edje_edit_part_selected_state_set(Evas_Object *obj, const char *part, const char *state)
+{
+   Edje_Part_Description *pd;
+
+   GET_RP_OR_RETURN(0);
+
+   pd = _edje_part_description_find_byname(ed, part, state);
+   if (!pd) return 0;
+
+   printf("EDJE: Set state: %s\n", pd->state.name);
+   _edje_part_description_apply(ed, rp, pd->state.name, pd->state.value, NULL, 0); //WHAT IS NULL , 0
+
+   edje_object_calc_force(obj);
+   return 1;
+}
+
+EAPI const char *
+edje_edit_part_clip_to_get(Evas_Object *obj, const char *part)
+{
+   Edje_Real_Part *clip = NULL;
+
+   GET_RP_OR_RETURN(NULL);
+
+   printf("Get clip_to for part: %s [to_id: %d]\n", part, rp->part->clip_to_id);
+   if (rp->part->clip_to_id < 0) return NULL;
+
+   clip = ed->table_parts[rp->part->clip_to_id % ed->table_parts_size];
+   if (!clip || !clip->part || !clip->part->name) return NULL;
+
+   return evas_stringshare_add(clip->part->name);
+}
+
+EAPI unsigned char
+edje_edit_part_clip_to_set(Evas_Object *obj, const char *part, const char *clip_to)
+{
+   Edje_Real_Part *clip;
+
+   GET_RP_OR_RETURN(0);
+
+   /* unset clipping */
+   if (!clip_to)
+     {
+       printf("UnSet clip_to for part: %s\n", part);
+
+       if (rp->clip_to->object)
+         {
+            evas_object_pointer_mode_set(rp->clip_to->object,
+                                         EVAS_OBJECT_POINTER_MODE_AUTOGRAB);
+            evas_object_clip_unset(rp->object);
+         }
+
+       evas_object_clip_set(rp->object, ed->clipper);
+
+
+       rp->part->clip_to_id = -1;
+       rp->clip_to = NULL;
+
+       edje_object_calc_force(obj);
+
+       return 1;
+     }
+
+   /* set clipping */
+   printf("Set clip_to for part: %s [to: %s]\n", part, clip_to);
+   clip = _edje_real_part_get(ed, clip_to);
+   if (!clip || !clip->part) return 0;
+   rp->part->clip_to_id = clip->part->id;
+   rp->clip_to = clip;
+
+   evas_object_pass_events_set(rp->clip_to->object, 1);
+   evas_object_pointer_mode_set(rp->clip_to->object, EVAS_OBJECT_POINTER_MODE_NOGRAB);
+   evas_object_clip_set(rp->object, rp->clip_to->object);
+
+   edje_object_calc_force(obj);
+
+   return 1;
+}
+
+EAPI unsigned char
+edje_edit_part_mouse_events_get(Evas_Object *obj, const char *part)
+{
+   GET_RP_OR_RETURN(0);
+   //printf("Get mouse_events for part: %s [%d]\n", part, rp->part->mouse_events);
+   return rp->part->mouse_events;
+}
+
+EAPI void
+edje_edit_part_mouse_events_set(Evas_Object *obj, const char *part, unsigned char mouse_events)
+{
+   GET_RP_OR_RETURN();
+
+   if (!rp->object) return;
+
+   printf("Set mouse_events for part: %s [%d]\n", part, mouse_events);
+
+   rp->part->mouse_events = mouse_events ? 1 : 0;
+
+   if (mouse_events)
+     {
+       evas_object_pass_events_set(rp->object, 0);
+       _edje_callbacks_add(rp->object, ed, rp);
+     }
+   else
+     {
+       evas_object_pass_events_set(rp->object, 1);
+       _edje_callbacks_del(rp->object);
+     }
+}
+
+EAPI unsigned char
+edje_edit_part_repeat_events_get(Evas_Object *obj, const char *part)
+{
+   GET_RP_OR_RETURN(0);
+
+   //printf("Get repeat_events for part: %s [%d]\n", part, rp->part->repeat_events);
+   return rp->part->repeat_events;
+}
+
+EAPI void
+edje_edit_part_repeat_events_set(Evas_Object *obj, const char *part, unsigned char repeat_events)
+{
+   GET_RP_OR_RETURN();
+
+   if (!rp->object) return;
+
+   printf("Set repeat_events for part: %s [%d]\n", part, repeat_events);
+
+   rp->part->repeat_events = repeat_events ? 1 : 0;
+
+   if (repeat_events)
+     evas_object_repeat_events_set(rp->object, 1);
+   else
+     evas_object_repeat_events_set(rp->object, 0);
+}
+
+EAPI Evas_Event_Flags
+edje_edit_part_ignore_flags_get(Evas_Object *obj, const char *part)
+{
+   GET_RP_OR_RETURN(0);
+
+   return rp->part->ignore_flags;
+}
+
+EAPI void
+edje_edit_part_ignore_flags_set(Evas_Object *obj, const char *part, Evas_Event_Flags ignore_flags)
+{
+   GET_RP_OR_RETURN();
+
+   if (!rp->object) return;
+   printf("Set ignore_flags for part: %s [%#x]\n", part, ignore_flags);
+
+   rp->part->ignore_flags = ignore_flags;
+}
+
+EAPI const char *
+edje_edit_part_source_get(Evas_Object *obj, const char *part)
+{
+   //Edje_Real_Part *clip = NULL;
+
+   GET_RP_OR_RETURN(NULL);
+
+   printf("Get source for part: %s\n", part);
+   if (!rp->part->source) return NULL;
+
+   return evas_stringshare_add(rp->part->source);
+}
+
+EAPI unsigned char
+edje_edit_part_source_set(Evas_Object *obj, const char *part, const char *source)
+{
+   GET_RP_OR_RETURN(0);
+
+   printf("Set source for part: %s [source: %s]\n", part, source);
+
+   _edje_if_string_free(ed, rp->part->source);
+
+   if (source)
+     rp->part->source = evas_stringshare_add(source);
+
+   return 1;
+}
+
+/*********************/
+/*  PART STATES API  */
+/*********************/
+EAPI Evas_List *
+edje_edit_part_states_list_get(Evas_Object *obj, const char *part)
+{
+   char state_name[PATH_MAX];
+   Evas_List *states;
+   Evas_List *l;
+   Edje_Part_Description *state;
+
+   GET_RP_OR_RETURN(NULL);
+
+   //Is there a better place to put this? maybe edje_edit_init() ?
+   setlocale(LC_NUMERIC, "C");
+
+   states = NULL;
+
+   //append default state
+   state = rp->part->default_desc;
+   snprintf(state_name, PATH_MAX,
+            "%s %.2f", state->state.name, state->state.value);
+   states = evas_list_append(states, evas_stringshare_add(state_name));
+   //printf("NEW STATE def: %s\n", state->state.name);
+
+   //append other states
+   for (l = rp->part->other_desc; l; l = l->next)
+     {
+       state = l->data;
+       snprintf(state_name, sizeof(state_name),
+                "%s %.2f", state->state.name, state->state.value);
+       states = evas_list_append(states, evas_stringshare_add(state_name));
+       //printf("NEW STATE: %s\n", state_name);
+     }
+   return states;
+}
+
+EAPI int
+edje_edit_state_name_set(Evas_Object *obj, const char *part, const char *state, const char *new_name)//state and new_name include the value in the string (ex. "default 0.00")
+{
+   char *delim;
+   double value;
+   int part_id;
+   int i;
+
+   GET_PD_OR_RETURN(0);
+   printf("Set name of state: %s in part: %s [new name: %s]\n",
+          part, state, new_name);
+
+   if (!new_name) return 0;
+
+   /* split name from value */
+   delim = strrchr(new_name, (int)' ');
+   if (!delim) return 0;
+   if (sscanf(delim, "%lf", &value) != 1) return 0;
+   delim[0] = '\0';
+
+   /* update programs */
+   /* update the 'state' field in all programs. update only if program has
+      a single target */
+   part_id = _edje_part_id_find(ed, part);
+   for (i = 0; i < ed->table_programs_size; i++)
+     {
+       Edje_Program *epr = ed->table_programs[i];
+
+       if (evas_list_count(epr->targets) == 1)
+         {
+            Edje_Program_Target *t = epr->targets->data;
+
+            if (t->id == part_id &&
+                !strcmp(epr->state, pd->state.name) &&
+                pd->state.value == epr->value)
+              {
+                 _edje_if_string_free(ed, epr->state);
+                 epr->state = evas_stringshare_add(new_name);
+                 epr->value = value;
+              }
+         }
+     }
+
+   /* set name */
+   _edje_if_string_free(ed, pd->state.name);
+   pd->state.name = (char *)evas_stringshare_add(new_name);
+   /* set value */
+   pd->state.value = value;
+
+   delim[0] = ' ';
+   printf("## SET OK %s %.2f\n", pd->state.name, pd->state.value);
+
+   return 1;
+}
+
+EAPI void
+edje_edit_state_del(Evas_Object *obj, const char *part, const char *state)
+{
+   Edje_Part_Description *pd;
+
+   GET_RP_OR_RETURN();
+
+   printf("REMOVE STATE: %s IN PART: %s\n", state, part);
+
+   pd = _edje_part_description_find_byname(ed, part, state);
+   if (!pd) return;
+
+   rp->part->other_desc = evas_list_remove(rp->part->other_desc, pd);
+
+   _edje_collection_free_part_description_free(pd, 0);
+}
+
+EAPI void
+edje_edit_state_add(Evas_Object *obj, const char *part, const char *name)
+{
+   Edje_Part_Description *pd;
+
+   GET_RP_OR_RETURN();
+
+   printf("ADD STATE: %s TO PART: %s\n", name , part);
+
+   pd = mem_alloc(sizeof(Edje_Part_Description));
+
+   if (!rp->part->default_desc)
+     rp->part->default_desc = pd;
+   else
+     rp->part->other_desc = evas_list_append(rp->part->other_desc, pd);
+
+   pd->state.name = evas_stringshare_add(name);
+   pd->state.value = 0.0;
+   pd->visible = 1;
+   pd->align.x = 0.5;
+   pd->align.y = 0.5;
+   pd->min.w = 0;
+   pd->min.h = 0;
+   pd->fixed.w = 0;
+   pd->fixed.h = 0;
+   pd->max.w = -1;
+   pd->max.h = -1;
+   pd->rel1.relative_x = 0.0;
+   pd->rel1.relative_y = 0.0;
+   pd->rel1.offset_x = 0;
+   pd->rel1.offset_y = 0;
+   pd->rel1.id_x = -1;
+   pd->rel1.id_y = -1;
+   pd->rel2.relative_x = 1.0;
+   pd->rel2.relative_y = 1.0;
+   pd->rel2.offset_x = -1;
+   pd->rel2.offset_y = -1;
+   pd->rel2.id_x = -1;
+   pd->rel2.id_y = -1;
+   pd->image.id = -1;
+   pd->fill.smooth = 1;
+   pd->fill.pos_rel_x = 0.0;
+   pd->fill.pos_abs_x = 0;
+   pd->fill.rel_x = 1.0;
+   pd->fill.abs_x = 0;
+   pd->fill.pos_rel_y = 0.0;
+   pd->fill.pos_abs_y = 0;
+   pd->fill.rel_y = 1.0;
+   pd->fill.abs_y = 0;
+   pd->fill.angle = 0;
+   pd->fill.spread = 0;
+   pd->fill.type = EDJE_FILL_TYPE_SCALE;
+   pd->color_class = NULL;
+   pd->color.r = 255;
+   pd->color.g = 255;
+   pd->color.b = 255;
+   pd->color.a = 255;
+   pd->color2.r = 0;
+   pd->color2.g = 0;
+   pd->color2.b = 0;
+   pd->color2.a = 255;
+   pd->color3.r = 0;
+   pd->color3.g = 0;
+   pd->color3.b = 0;
+   pd->color3.a = 128;
+   pd->text.align.x = 0.5;
+   pd->text.align.y = 0.5;
+   pd->text.id_source = -1;
+   pd->text.id_text_source = -1;
+   pd->gradient.rel1.relative_x = 0;
+   pd->gradient.rel1.relative_y = 0;
+   pd->gradient.rel1.offset_x = 0;
+   pd->gradient.rel1.offset_y = 0;
+   pd->gradient.rel2.relative_x = 1;
+   pd->gradient.rel2.relative_y = 1;
+   pd->gradient.rel2.offset_x = -1;
+   pd->gradient.rel2.offset_y = -1;
+   pd->gradient.use_rel = 1;
+}
+
+EAPI unsigned char
+edje_edit_state_exist(Evas_Object *obj, const char *part, const char *state)
+{
+   GET_PD_OR_RETURN(0);
+   return 1;
+}
+
+//relative
+EAPI double
+edje_edit_state_rel1_relative_x_get(Evas_Object *obj, const char *part, const char *state)
+{
+   GET_PD_OR_RETURN(0);
+   //printf("Get rel1 rel of part: %s state: %s [%f]\n", part, state, pd->rel1.relative_x);
+   return pd->rel1.relative_x;
+}
+
+EAPI double
+edje_edit_state_rel1_relative_y_get(Evas_Object *obj, const char *part, const char *state)
+{
+   GET_PD_OR_RETURN(0);
+   //printf("Get rel1 rel of part: %s state: %s\n", part, state);
+   return pd->rel1.relative_y;
+}
+
+EAPI double
+edje_edit_state_rel2_relative_x_get(Evas_Object *obj, const char *part, const char *state)
+{
+   GET_PD_OR_RETURN(0);
+   //printf("Get rel2 rel of part: %s state: %s\n", part, state);
+   return pd->rel2.relative_x;
+}
+
+EAPI double
+edje_edit_state_rel2_relative_y_get(Evas_Object *obj, const char *part, const char *state)
+{
+   GET_PD_OR_RETURN(0);
+   //printf("Get rel2 rel of part: %s state: %s\n", part, state);
+   return pd->rel2.relative_y;
+}
+
+EAPI void
+edje_edit_state_rel1_relative_x_set(Evas_Object *obj, const char *part, const char *state, double x)
+{
+   GET_PD_OR_RETURN();
+   //printf("Set rel1x of part: %s state: %s to: %f\n", part, state, x);
+   //TODO check boudaries
+   pd->rel1.relative_x = x;
+   edje_object_calc_force(obj);
+}
+
+EAPI void
+edje_edit_state_rel1_relative_y_set(Evas_Object *obj, const char *part, const char *state, double y)
+{
+   GET_PD_OR_RETURN();
+   //printf("Set rel1y of part: %s state: %s to: %f\n", part, state, y);
+   //TODO check boudaries
+   pd->rel1.relative_y = y;
+   edje_object_calc_force(obj);
+}
+
+EAPI void
+edje_edit_state_rel2_relative_x_set(Evas_Object *obj, const char *part, const char *state, double x)
+{
+   GET_PD_OR_RETURN();
+   //printf("Set rel2x of part: %s state: %s to: %f\n", part, state, x);
+   //TODO check boudaries
+   pd->rel2.relative_x = x;
+   edje_object_calc_force(obj);
+}
+
+EAPI void
+edje_edit_state_rel2_relative_y_set(Evas_Object *obj, const char *part, const char *state, double y)
+{
+   GET_PD_OR_RETURN();
+   //printf("Set rel2y of part: %s state: %s to: %f\n", part, state, y);
+   pd = _edje_part_description_find_byname(ed, part, state);
+   //TODO check boudaries
+   pd->rel2.relative_y = y;
+   edje_object_calc_force(obj);
+}
+
+//offset
+EAPI int
+edje_edit_state_rel1_offset_x_get(Evas_Object *obj, const char *part, const char *state)
+{
+   GET_PD_OR_RETURN(0);
+   //printf("Get rel1 offset of part: %s state: %s\n", part, state);
+   return pd->rel1.offset_x;
+}
+
+EAPI int
+edje_edit_state_rel1_offset_y_get(Evas_Object *obj, const char *part, const char *state)
+{
+   GET_PD_OR_RETURN(0);
+   //printf("Get rel1 offset of part: %s state: %s\n", part, state);
+   return pd->rel1.offset_y;
+}
+
+EAPI int
+edje_edit_state_rel2_offset_x_get(Evas_Object *obj, const char *part, const char *state)
+{
+   GET_PD_OR_RETURN(0);
+   //printf("Get rel2 offset of part: %s state: %s\n", part, state);
+   return pd->rel2.offset_x;
+}
+
+EAPI int
+edje_edit_state_rel2_offset_y_get(Evas_Object *obj, const char *part, const char *state)
+{
+   GET_PD_OR_RETURN(0);
+   //printf("Get rel2 offset of part: %s state: %s\n", part, state);
+   return pd->rel2.offset_y;
+}
+
+EAPI void
+edje_edit_state_rel1_offset_x_set(Evas_Object *obj, const char *part, const char *state, double x)
+{
+   GET_PD_OR_RETURN();
+   printf("Set rel1x offset of part: %s state: %s to: %f\n", part, state, x);
+   //TODO check boudaries
+   pd->rel1.offset_x = x;
+   edje_object_calc_force(obj);
+}
+
+EAPI void
+edje_edit_state_rel1_offset_y_set(Evas_Object *obj, const char *part, const char *state, double y)
+{
+   GET_PD_OR_RETURN();
+   printf("Set rel1y offset of part: %s state: %s to: %f\n", part, state, y);
+   //TODO check boudaries
+   pd->rel1.offset_y = y;
+   edje_object_calc_force(obj);
+}
+
+EAPI void
+edje_edit_state_rel2_offset_x_set(Evas_Object *obj, const char *part, const char *state, double x)
+{
+   GET_PD_OR_RETURN();
+   printf("Set rel2x offset of part: %s state: %s to: %f\n", part, state, x);
+   //TODO check boudaries
+   pd->rel2.offset_x = x;
+   edje_object_calc_force(obj);
+}
+
+EAPI void
+edje_edit_state_rel2_offset_y_set(Evas_Object *obj, const char *part, const char *state, double y)
+{
+   GET_PD_OR_RETURN();
+   printf("Set rel2y offset of part: %s state: %s to: %f\n", part, state, y);
+   //TODO check boudaries
+   pd->rel2.offset_y = y;
+   edje_object_calc_force(obj);
+}
+
+//relative to
+EAPI const char *
+edje_edit_state_rel1_to_x_get(Evas_Object *obj, const char *part, const char *state)
+{
+   Edje_Real_Part *rel;
+
+   GET_PD_OR_RETURN(NULL);
+
+   //printf("Get rel1x TO of part: %s state: %s\n", part, state);
+
+   if (pd->rel1.id_x == -1) return NULL;
+
+   rel = ed->table_parts[pd->rel1.id_x % ed->table_parts_size];
+
+   if (rel->part->name)
+     return evas_stringshare_add(rel->part->name);
+   else
+     return NULL;
+}
+
+EAPI const char *
+edje_edit_state_rel1_to_y_get(Evas_Object *obj, const char *part, const char *state)
+{
+   Edje_Real_Part *rel;
+
+   GET_PD_OR_RETURN(NULL);
+
+   //printf("Get rel1y TO of part: %s state: %s\n", part, state);
+
+   if (pd->rel1.id_y == -1) return NULL;
+
+   rel = ed->table_parts[pd->rel1.id_y % ed->table_parts_size];
+
+   if (rel->part->name)
+     return evas_stringshare_add(rel->part->name);
+   else
+     return NULL;
+}
+
+EAPI const char *
+edje_edit_state_rel2_to_x_get(Evas_Object *obj, const char *part, const char *state)
+{
+   Edje_Real_Part *rel;
+
+   GET_PD_OR_RETURN(NULL);
+
+   //printf("Get rel2x TO of part: %s state: %s\n", part, state);
+
+   if (pd->rel2.id_x == -1) return NULL;
+
+   rel = ed->table_parts[pd->rel2.id_x % ed->table_parts_size];
+
+   if (rel->part->name)
+     return evas_stringshare_add(rel->part->name);
+   else
+     return NULL;
+}
+
+EAPI const char *
+edje_edit_state_rel2_to_y_get(Evas_Object *obj, const char *part, const char *state)
+{
+   Edje_Real_Part *rel;
+
+   GET_PD_OR_RETURN(NULL);
+
+   //printf("Get rel2y TO of part: %s state: %s\n", part, state);
+
+   if (pd->rel2.id_y == -1) return NULL;
+
+   rel = ed->table_parts[pd->rel2.id_y % ed->table_parts_size];
+
+   if (rel->part->name)
+     return evas_stringshare_add(rel->part->name);
+   else
+     return NULL;
+}
+
+EAPI void
+//note after this call edje_edit_part_selected_state_set() to update !! need to fix this
+edje_edit_state_rel1_to_x_set(Evas_Object *obj, const char *part, const char *state, const char *rel_to)
+{
+   Edje_Real_Part *relp;
+
+   GET_PD_OR_RETURN();
+
+   printf("Set rel1 to x on state: %s (to part: )\n", state);
+
+   if (rel_to)
+     {
+       relp = _edje_real_part_get(ed, rel_to);
+       if (!relp) return;
+       pd->rel1.id_x = relp->part->id;
+     }
+   else
+     pd->rel1.id_x = -1;
+
+   //_edje_part_description_apply(ed, rp, pd->state.name, pd->state.value, "state", 0.1); //Why segfault??
+   // edje_object_calc_force(obj);//don't work for redraw
+}
+
+EAPI void
+//note after this call edje_edit_part_selected_state_set() to update !! need to fix this
+edje_edit_state_rel1_to_y_set(Evas_Object *obj, const char *part, const char *state, const char *rel_to)
+{
+   Edje_Real_Part *relp;
+
+   GET_PD_OR_RETURN();
+
+   //printf("Set rel1 to y on state: %s (to part: %s)\n", state, rel_to);
+
+   if (rel_to)
+     {
+       relp = _edje_real_part_get(ed, rel_to);
+       if (!relp) return;
+       pd->rel1.id_y = relp->part->id;
+     }
+   else
+     pd->rel1.id_y = -1;
+
+   //_edje_part_description_apply(ed, rp, pd->state.name, pd->state.value, "state", 0.1); //Why segfault??
+   // edje_object_calc_force(obj);//don't work for redraw
+}
+
+EAPI void
+//note after this call edje_edit_part_selected_state_set() to update !! need to fix this
+edje_edit_state_rel2_to_x_set(Evas_Object *obj, const char *part, const char *state, const char *rel_to)
+{
+   Edje_Real_Part *relp;
+
+   GET_PD_OR_RETURN();
+
+   printf("Set rel2 to x on state: %s (to part: )\n", state);
+
+   if (rel_to)
+     {
+       relp = _edje_real_part_get(ed, rel_to);
+       if (!relp) return;
+       pd->rel2.id_x = relp->part->id;
+     }
+   else
+     pd->rel2.id_x = -1;
+
+   //_edje_part_description_apply(ed, rp, pd->state.name, pd->state.value, "state", 0.1); //Why segfault??
+   // edje_object_calc_force(obj);//don't work for redraw
+}
+
+EAPI void
+//note after this call edje_edit_part_selected_state_set() to update !! need to fix this
+edje_edit_state_rel2_to_y_set(Evas_Object *obj, const char *part, const char *state, const char *rel_to)
+{
+   Edje_Real_Part *relp;
+
+   GET_PD_OR_RETURN();
+
+   //printf("Set rel2 to y on state: %s (to part: %s)\n", state, rel_to);
+
+   if (rel_to)
+     {
+       relp = _edje_real_part_get(ed, rel_to);
+       if (!relp) return;
+       pd->rel2.id_y = relp->part->id;
+     }
+   else
+      pd->rel2.id_y = -1;
+
+   //_edje_part_description_apply(ed, rp, pd->state.name, pd->state.value, "state", 0.1); //Why segfault??
+   // edje_object_calc_force(obj);//don't work for redraw
+}
+
+//colors
+EAPI void
+edje_edit_state_color_get(Evas_Object *obj, const char *part, const char *state, int *r, int *g, int *b, int *a)
+{
+   GET_PD_OR_RETURN();
+
+   //printf("GET COLOR of state '%s'\n", state);
+
+   if (r) *r = pd->color.r;
+   if (g) *g = pd->color.g;
+   if (b) *b = pd->color.b;
+   if (a) *a = pd->color.a;
+}
+
+EAPI void
+edje_edit_state_color2_get(Evas_Object *obj, const char *part, const char *state, int *r, int *g, int *b, int *a)
+{
+   GET_PD_OR_RETURN();
+
+   //printf("GET COLOR2 of state '%s'\n", state);
+
+   if (r) *r = pd->color2.r;
+   if (g) *g = pd->color2.g;
+   if (b) *b = pd->color2.b;
+   if (a) *a = pd->color2.a;
+}
+
+EAPI void
+edje_edit_state_color3_get(Evas_Object *obj, const char *part, const char *state, int *r, int *g, int *b, int *a)
+{
+   GET_PD_OR_RETURN();
+
+   //printf("GET COLOR3 of state '%s'\n", state);
+
+   if (r) *r = pd->color3.r;
+   if (g) *g = pd->color3.g;
+   if (b) *b = pd->color3.b;
+   if (a) *a = pd->color3.a;
+}
+
+EAPI void
+edje_edit_state_color_set(Evas_Object *obj, const char *part, const char *state, int r, int g, int b, int a)
+{
+   GET_PD_OR_RETURN();
+
+   //printf("SET COLOR of state '%s'\n", state);
+
+   if (r > -1 && r < 256) pd->color.r = r;
+   if (g > -1 && g < 256) pd->color.g = g;
+   if (b > -1 && b < 256) pd->color.b = b;
+   if (a > -1 && a < 256) pd->color.a = a;
+
+   edje_object_calc_force(obj);
+}
+
+EAPI void
+edje_edit_state_color2_set(Evas_Object *obj, const char *part, const char *state, int r, int g, int b, int a)
+{
+   GET_PD_OR_RETURN();
+
+   //printf("SET COLOR2 of state '%s'\n", state);
+
+   if (r > -1 && r < 256) pd->color2.r = r;
+   if (g > -1 && g < 256) pd->color2.g = g;
+   if (b > -1 && b < 256) pd->color2.b = b;
+   if (a > -1 && a < 256) pd->color2.a = a;
+
+   edje_object_calc_force(obj);
+}
+
+EAPI void
+edje_edit_state_color3_set(Evas_Object *obj, const char *part, const char *state, int r, int g, int b, int a)
+{
+   GET_PD_OR_RETURN();
+
+   //printf("SET COLOR3 of state '%s'\n", state);
+
+   if (r > -1 && r < 256) pd->color3.r = r;
+   if (g > -1 && g < 256) pd->color3.g = g;
+   if (b > -1 && b < 256) pd->color3.b = b;
+   if (a > -1 && a < 256) pd->color3.a = a;
+
+   edje_object_calc_force(obj);
+}
+
+//align
+EAPI double
+edje_edit_state_align_x_get(Evas_Object *obj, const char *part, const char *state)
+{
+   GET_PD_OR_RETURN(0);
+
+   //printf("GET ALIGN_X of state '%s' [%f]\n", state, pd->align.x);
+
+   return pd->align.x;
+}
+
+EAPI double
+edje_edit_state_align_y_get(Evas_Object *obj, const char *part, const char *state)
+{
+   GET_PD_OR_RETURN(0);
+
+   //printf("GET ALIGN_Y of state '%s' [%f]\n", state, pd->align.y);
+
+   return pd->align.y;
+}
+
+EAPI void
+edje_edit_state_align_x_set(Evas_Object *obj, const char *part, const char *state, double align)
+{
+   GET_PD_OR_RETURN();
+   printf("SET ALIGN_X of state '%s' [to: %f]\n", state, align);
+   pd->align.x = align;
+}
+
+EAPI void
+edje_edit_state_align_y_set(Evas_Object *obj, const char *part, const char *state, double align)
+{
+   GET_PD_OR_RETURN();
+
+   printf("SET ALIGN_Y of state '%s' [to: %f]\n", state, align);
+   pd->align.y = align;
+}
+
+//min & max
+EAPI int
+edje_edit_state_min_w_get(Evas_Object *obj, const char *part, const char *state)
+{
+   GET_PD_OR_RETURN(0);
+
+   printf("GET MIN_W of state '%s' [%d]\n", state, pd->min.w);
+   return pd->min.w;
+}
+
+EAPI void
+edje_edit_state_min_w_set(Evas_Object *obj, const char *part, const char *state, int min_w)
+{
+   GET_PD_OR_RETURN();
+
+   printf("SET MIN_W of state '%s' [to: %d]\n", state, min_w);
+   pd->min.w = min_w;
+}
+
+EAPI int
+edje_edit_state_min_h_get(Evas_Object *obj, const char *part, const char *state)
+{
+   GET_PD_OR_RETURN(0);
+
+   printf("GET MIN_H of state '%s' [%d]\n", state, pd->min.h);
+   return pd->min.h;
+}
+
+EAPI void
+edje_edit_state_min_h_set(Evas_Object *obj, const char *part, const char *state, int min_h)
+{
+   GET_PD_OR_RETURN();
+
+   printf("SET MIN_H of state '%s' [to: %d]\n", state, min_h);
+   pd->min.h = min_h;
+}
+
+EAPI int
+edje_edit_state_max_w_get(Evas_Object *obj, const char *part, const char *state)
+{
+   GET_PD_OR_RETURN(0);
+
+   printf("GET MAX_W of state '%s' [%d]\n", state, pd->max.w);
+   return pd->max.w;
+}
+
+EAPI void
+edje_edit_state_max_w_set(Evas_Object *obj, const char *part, const char *state, int max_w)
+{
+   GET_PD_OR_RETURN();
+
+   printf("SET MAX_W of state '%s' [to: %d]\n", state, max_w);
+   pd->max.w = max_w;
+}
+
+EAPI int
+edje_edit_state_max_h_get(Evas_Object *obj, const char *part, const char *state)
+{
+   GET_PD_OR_RETURN(0);
+
+   printf("GET MAX_H of state '%s' [%d]\n", state, pd->max.h);
+   return pd->max.h;
+}
+
+EAPI void
+edje_edit_state_max_h_set(Evas_Object *obj, const char *part, const char *state, int max_h)
+{
+   GET_PD_OR_RETURN();
+
+   printf("SET MAX_H of state '%s' [to: %d]\n", state, max_h);
+   pd->max.h = max_h;
+}
+
+//aspect
+EAPI double
+edje_edit_state_aspect_min_get(Evas_Object *obj, const char *part, const char *state)
+{
+   GET_PD_OR_RETURN(0);
+
+   printf("GET ASPECT_MIN of state '%s' [%f]\n", state, pd->aspect.min);
+   return pd->aspect.min;
+}
+
+EAPI double
+edje_edit_state_aspect_max_get(Evas_Object *obj, const char *part, const char *state)
+{
+   GET_PD_OR_RETURN(0);
+
+   printf("GET ASPECT_MAX of state '%s' [%f]\n", state, pd->aspect.max);
+   return pd->aspect.max;
+}
+
+EAPI void
+edje_edit_state_aspect_min_set(Evas_Object *obj, const char *part, const char *state, double aspect)
+{
+   GET_PD_OR_RETURN();
+
+   printf("SET ASPECT_MIN of state '%s' [to: %f]\n", state, aspect);
+   pd->aspect.min = aspect;
+}
+
+EAPI void
+edje_edit_state_aspect_max_set(Evas_Object *obj, const char *part, const char *state, double aspect)
+{
+   GET_PD_OR_RETURN();
+
+   printf("SET ASPECT_MAX of state '%s' [to: %f]\n", state, aspect);
+   pd->aspect.max = aspect;
+}
+
+EAPI unsigned char
+edje_edit_state_aspect_pref_get(Evas_Object *obj, const char *part, const char *state)
+{
+   GET_PD_OR_RETURN(0);
+
+   printf("GET ASPECT_PREF of state '%s' [%d]\n", state, pd->aspect.prefer);
+   return pd->aspect.prefer;
+}
+
+EAPI void
+edje_edit_state_aspect_pref_set(Evas_Object *obj, const char *part, const char *state, unsigned char pref)
+{
+   GET_PD_OR_RETURN();
+
+   printf("SET ASPECT_PREF of state '%s' [to: %d]\n", state, pref);
+   pd->aspect.prefer = pref;
+}
+
+//fill
+EAPI double
+edje_edit_state_fill_origin_relative_x_get(Evas_Object *obj, const char *part, const char *state)
+{
+   GET_PD_OR_RETURN(0);
+   //printf("Get state fill origin of part: %s state: %s\n", part, state);
+   return pd->fill.pos_rel_x;
+}
+
+EAPI double
+edje_edit_state_fill_origin_relative_y_get(Evas_Object *obj, const char *part, const char *state)
+{
+   GET_PD_OR_RETURN(0);
+   //printf("Get state fill origin of part: %s state: %s\n", part, state);
+   return pd->fill.pos_rel_y;
+}
+
+EAPI int
+edje_edit_state_fill_origin_offset_x_get(Evas_Object *obj, const char *part, const char *state)
+{
+   GET_PD_OR_RETURN(0);
+   //printf("Get state fill origin offset of part: %s state: %s\n", part, state);
+   return pd->fill.pos_abs_x;
+}
+
+EAPI int
+edje_edit_state_fill_origin_offset_y_get(Evas_Object *obj, const char *part, const char *state)
+{
+   GET_PD_OR_RETURN(0);
+   //printf("Get state fill origin offset of part: %s state: %s\n", part, state);
+   return pd->fill.pos_abs_y;
+}
+
+
+EAPI void
+edje_edit_state_fill_origin_relative_x_set(Evas_Object *obj, const char *part, const char *state, double x)
+{
+   GET_PD_OR_RETURN();
+   printf("Set state fill origin of part: %s state: %s to: %f\n", part, state, x);
+   pd->fill.pos_rel_x = x;
+   edje_object_calc_force(obj);
+}
+
+EAPI void
+edje_edit_state_fill_origin_relative_y_set(Evas_Object *obj, const char *part, const char *state, double y)
+{
+   GET_PD_OR_RETURN();
+   printf("Set state fill origin of part: %s state: %s to: %f\n", part, state, y);
+   pd->fill.pos_rel_y = y;
+   edje_object_calc_force(obj);
+}
+
+EAPI void
+edje_edit_state_fill_origin_offset_x_set(Evas_Object *obj, const char *part, const char *state, double x)
+{
+   GET_PD_OR_RETURN();
+   printf("Set state fill origin offset x of part: %s state: %s to: %f\n", part, state, x);
+   pd->fill.pos_abs_x = x;
+   edje_object_calc_force(obj);
+}
+
+EAPI void
+edje_edit_state_fill_origin_offset_y_set(Evas_Object *obj, const char *part, const char *state, double y)
+{
+   GET_PD_OR_RETURN();
+   printf("Set state fill origin offset y of part: %s state: %s to: %f\n", part, state, y);
+   pd->fill.pos_abs_y = y;
+   edje_object_calc_force(obj);
+}
+
+EAPI double
+edje_edit_state_fill_size_relative_x_get(Evas_Object *obj, const char *part, const char *state)
+{
+   GET_PD_OR_RETURN(0.0);
+   //printf("Get state fill size of part: %s state: %s\n", part, state);
+   return pd->fill.rel_x;
+}
+
+EAPI double
+edje_edit_state_fill_size_relative_y_get(Evas_Object *obj, const char *part, const char *state)
+{
+   GET_PD_OR_RETURN(0.0);
+   //printf("Get state fill size of part: %s state: %s\n", part, state);
+   return pd->fill.rel_y;
+}
+
+EAPI int
+edje_edit_state_fill_size_offset_x_get(Evas_Object *obj, const char *part, const char *state)
+{
+   GET_PD_OR_RETURN(0);
+   //printf("Get state fill size offset of part: %s state: %s\n", part, state);
+   return pd->fill.abs_x;
+}
+
+EAPI int
+edje_edit_state_fill_size_offset_y_get(Evas_Object *obj, const char *part, const char *state)
+{
+   GET_PD_OR_RETURN(0);
+   //printf("Get state fill size offset of part: %s state: %s\n", part, state);
+   return pd->fill.abs_y;
+}
+
+EAPI void
+edje_edit_state_fill_size_relative_x_set(Evas_Object *obj, const char *part, const char *state, double x)
+{
+   GET_PD_OR_RETURN();
+   printf("Set state fill size of part: %s state: %s to: %f\n", part, state, x);
+   pd->fill.rel_x = x;
+   edje_object_calc_force(obj);
+}
+
+EAPI void
+edje_edit_state_fill_size_relative_y_set(Evas_Object *obj, const char *part, const char *state, double y)
+{
+   GET_PD_OR_RETURN();
+   printf("Set state fill size of part: %s state: %s to: %f\n", part, state, y);
+   pd->fill.rel_y = y;
+   edje_object_calc_force(obj);
+}
+
+EAPI void
+edje_edit_state_fill_size_offset_x_set(Evas_Object *obj, const char *part, const char *state, double x)
+{
+   GET_PD_OR_RETURN();
+   printf("Set state fill size offset x of part: %s state: %s to: %f\n", part, state, x);
+   pd->fill.abs_x = x;
+   edje_object_calc_force(obj);
+}
+
+EAPI void
+edje_edit_state_fill_size_offset_y_set(Evas_Object *obj, const char *part, const char *state, double y)
+{
+   GET_PD_OR_RETURN();
+   printf("Set state fill size offset y of part: %s state: %s to: %f\n", part, state, y);
+   pd->fill.abs_y = y;
+   edje_object_calc_force(obj);
+}
+
+
+/**************/
+/*  TEXT API */
+/**************/
+
+EAPI const char *
+edje_edit_state_text_get(Evas_Object *obj, const char *part, const char *state)
+{
+   GET_PD_OR_RETURN(NULL);
+
+   //printf("GET TEXT of state: %s\n", state);
+
+   if (pd->text.text)
+     return evas_stringshare_add(pd->text.text);
+
+   return NULL;
+}
+
+EAPI void
+edje_edit_state_text_set(Evas_Object *obj, const char *part, const char *state, const char *text)
+{
+   GET_PD_OR_RETURN();
+
+   //printf("SET TEXT of state: %s\n", state);
+
+   if (!text) return;
+
+   _edje_if_string_free(ed, pd->text.text);
+   pd->text.text = (char *)evas_stringshare_add(text);
+
+   edje_object_calc_force(obj);
+}
+
+EAPI int
+edje_edit_state_text_size_get(Evas_Object *obj, const char *part, const char *state)
+{
+   GET_PD_OR_RETURN(-1);
+
+   //printf("GET TEXT_SIZE of state: %s [%d]\n", state, pd->text.size);
+   return pd->text.size;
+}
+
+EAPI void
+edje_edit_state_text_size_set(Evas_Object *obj, const char *part, const char *state, int size)
+{
+   GET_PD_OR_RETURN();
+
+   //printf("SET TEXT_SIZE of state: %s [%d]\n", state, size);
+
+   if (size < 0) return;
+
+   pd->text.size = size;
+
+   edje_object_calc_force(obj);
+}
+
+EAPI double
+edje_edit_state_text_align_x_get(Evas_Object *obj, const char *part, const char *state)
+{
+   GET_PD_OR_RETURN(0);
+
+   //printf("GET TEXT_ALIGN_X of state: %s [%f]\n", state, pd->text.align.x);
+   return pd->text.align.x;
+}
+
+EAPI void
+edje_edit_state_text_align_x_set(Evas_Object *obj, const char *part, const char *state, double align)
+{
+   GET_PD_OR_RETURN();
+
+   //printf("SET TEXT_ALIGN_X of state: %s [%f]\n", state, align);
+
+   pd->text.align.x = align;
+   edje_object_calc_force(obj);
+}
+
+EAPI double
+edje_edit_state_text_align_y_get(Evas_Object *obj, const char *part, const char *state)
+{
+   GET_PD_OR_RETURN(0.0);
+
+   //printf("GET TEXT_ALIGN_Y of state: %s [%f]\n", state, pd->text.align.x);
+   return pd->text.align.y;
+}
+
+EAPI void
+edje_edit_state_text_align_y_set(Evas_Object *obj, const char *part, const char *state, double align)
+{
+   GET_PD_OR_RETURN();
+
+   //printf("SET TEXT_ALIGN_Y of state: %s [%f]\n", state, align);
+
+   pd->text.align.y = align;
+   edje_object_calc_force(obj);
+}
+
+EAPI Evas_List *
+edje_edit_fonts_list_get(Evas_Object *obj)
+{
+   Edje_Font_Directory_Entry *f;
+   Evas_List *fonts = NULL;
+   Evas_List *l;
+
+   GET_ED_OR_RETURN(NULL);
+
+   if (!ed->file) return NULL;
+   if (!ed->file->font_dir) return NULL;
+
+   printf("GET FONT LIST for %s\n", ed->file->path);
+
+   for (l = ed->file->font_dir->entries; l; l = l->next)
+     {
+       f = l->data;
+       fonts = evas_list_append(fonts, evas_stringshare_add(f->entry));
+       printf("   Font: %s (%s) \n", f->entry, f->path);
+     }
+
+   return fonts;
+}
+
+EAPI unsigned char
+edje_edit_font_add(Evas_Object *obj, const char* path)
+{
+   char buf[PATH_MAX];
+   Font *fn;
+   Edje_Font_Directory_Entry *fnt;
+   Eet_File *eetf;
+   struct stat st;
+   char *name;
+   FILE *f;
+   void *fdata = NULL;
+   int fsize = 0;
+
+   GET_ED_OR_RETURN(0);
+
+   printf("ADD FONT: %s\n", path);
+
+   if (!path) return 0;
+   if (stat(path, &st) || !S_ISREG(st.st_mode)) return 0;
+   if (!ed->file) return 0;
+   if (!ed->path) return 0;
+
+
+   /* Create Font_Directory if not exist */
+   if (!ed->file->font_dir)
+     ed->file->font_dir = mem_alloc(sizeof(Edje_Font_Directory));
+
+   /* Create Font */
+   fn = mem_alloc(sizeof(Font));
+   if (!fn) return 0;
+
+   if ((name = strrchr(path, '/'))) name ++;
+   else name = (char *)path;
+
+   fn->file = mem_strdup(name);
+   fn->name = mem_strdup(name);
+
+   /*{
+      Evas_List *l;
+
+      for (l = fonts; l; l = l->next)
+      {
+         Font *lfn;
+
+         lfn = l->data;
+         if (!strcmp(lfn->name, fn->name))
+         {
+            free(fn->file);
+            free(fn->name);
+            free(fn);
+            return;
+         }
+      }
+   }
+   */
+
+   /* Read font data from file */
+   f = fopen(path, "rb");
+   if (f)
+     {
+       long pos;
+
+       fseek(f, 0, SEEK_END);
+       pos = ftell(f);
+       rewind(f);
+       fdata = malloc(pos);
+       if (fdata)
+         {
+            if (fread(fdata, pos, 1, f) != 1)
+              {
+                 fprintf(stderr, "Edje_Edit: Error. unable to read all of font file \"%s\"\n",
+                         path);
+                 return 0;
+              }
+            fsize = pos;
+         }
+       fclose(f);
+     }
+   /* Write font to edje file */
+   snprintf(buf, sizeof(buf), "fonts/%s", fn->name);
+
+   if (fdata)
+     {
+       /* open the eet file */
+       eetf = eet_open(ed->path, EET_FILE_MODE_READ_WRITE);
+       if (!eetf)
+         {
+            fprintf(stderr,
+                    "Edje_Edit: Error. unable to open \"%s\" for writing output\n",
+                    ed->path);
+            return 0;
+         }
+
+       if (eet_write(eetf, buf, fdata, fsize, 1) <= 0)
+         {
+            fprintf(stderr, "Edje_Edit: Error. unable to write font part \"%s\" as \"%s\" part entry\n",
+                    path, buf);
+            eet_close(eetf);
+            free(fdata);
+            return 0;
+         }
+
+       eet_close(eetf);
+       free(fdata);
+     }
+
+   /* Create Edje_Font_Directory_Entry */
+   if (ed->file->font_dir)
+     {
+       fnt = mem_alloc(sizeof(Edje_Font_Directory_Entry));
+       fnt->entry = mem_strdup(fn->name);
+       fnt->path = mem_strdup(buf);
+
+       ed->file->font_dir->entries = evas_list_append(ed->file->font_dir->entries, fnt);
+       ed->file->font_hash = evas_hash_direct_add(ed->file->font_hash, fnt->entry, fnt);
+     }
+
+   return 1;
+}
+
+EAPI const char *
+edje_edit_state_font_get(Evas_Object *obj, const char *part, const char *state)
+{
+   GET_PD_OR_RETURN(NULL);
+
+   printf("GET FONT of state: %s [%s]\n", state, pd->text.font);
+   if (!pd->text.font) return NULL;
+   return evas_stringshare_add(pd->text.font);
+}
+
+EAPI void
+edje_edit_state_font_set(Evas_Object *obj, const char *part, const char *state, const char *font)
+{
+   GET_PD_OR_RETURN();
+
+   printf("SET FONT of state: %s [%s]\n", state, font);
+
+   _edje_if_string_free(ed, pd->text.font);
+   pd->text.font = (char *)evas_stringshare_add(font);
+
+   edje_object_calc_force(obj);
+}
+
+EAPI unsigned char
+edje_edit_part_effect_get(Evas_Object *obj, const char *part)
+{
+   GET_RP_OR_RETURN(0);
+
+   printf("GET EFFECT of part: %s\n", part);
+   return rp->part->effect;
+}
+
+EAPI void
+edje_edit_part_effect_set(Evas_Object *obj, const char *part, unsigned char effect)
+{
+   GET_RP_OR_RETURN();
+
+   printf("SET EFFECT of part: %s [%d]\n", part, effect);
+   rp->part->effect = effect;
+
+   edje_object_calc_force(obj);
+}
+
+/****************/
+/*  IMAGES API  */
+/****************/
+
+EAPI Evas_List *
+edje_edit_images_list_get(Evas_Object *obj)
+{
+   Edje_Image_Directory_Entry *i;
+   Evas_List *images = NULL;
+   Evas_List *l;
+
+   GET_ED_OR_RETURN(NULL);
+
+   if (!ed->file) return NULL;
+   if (!ed->file->image_dir) return NULL;
+
+   printf("GET IMAGES LIST for %s\n", ed->file->path);
+
+   for (l = ed->file->image_dir->entries; l; l = l->next)
+     {
+       i = l->data;
+       images = evas_list_append(images, evas_stringshare_add(i->entry));
+       //printf("   Image: %s (type: %d param: %d id: %d) \n",
+       //       i->entry, i->source_type, i->source_param, i->id);
+     }
+
+   return images;
+}
+
+EAPI unsigned char
+edje_edit_image_add(Evas_Object *obj, const char* path)
+{
+   Evas_List *l;
+   Edje_Image_Directory_Entry *de;
+   int free_id = 0;
+   char *name;
+
+   GET_ED_OR_RETURN(0);
+
+   if (!path) return 0;
+   if (!ed->file) return 0;
+   if (!ed->path) return 0;
+
+   /* Create Image_Directory if not exist */
+   if (!ed->file->image_dir)
+     ed->file->image_dir = mem_alloc(sizeof(Edje_Image_Directory));
+
+   /* Loop trough image directory to find if image exist */
+   printf("Add Image '%s' (total %d)\n", path,
+          evas_list_count(ed->file->image_dir->entries));
+   for (l = ed->file->image_dir->entries; l; l = l->next)
+     {
+       Edje_Image_Directory_Entry *i;
+
+       i = l->data;
+       if (!i) return 0;
+       if (i->id >= free_id) free_id = i->id + 1; /*TODO search for free (hole) id*/
+       printf("IMG: %s [%d]\n", i->entry, i->id);
+     }
+   printf("FREE ID: %d\n", free_id);
+
+   /* Import image */
+   if (!_edje_import_image_file(ed, path, free_id))
+      return 0;
+
+   /* Create Image Entry */
+   de = mem_alloc(sizeof(Edje_Image_Directory_Entry));
+   if ((name = strrchr(path, '/'))) name++;
+   else name = (char *)path;
+   de->entry = mem_strdup(name);
+   de->id = free_id;
+   de->source_type = 1;
+   de->source_param = 1;
+
+   /* Add image to Image Directory */
+   ed->file->image_dir->entries =
+        evas_list_append(ed->file->image_dir->entries, de);
+
+   return 1;
+}
+
+EAPI int
+edje_edit_image_id_get(Evas_Object *obj, const char *image_name)
+{
+   return _edje_image_id_find(obj, image_name);
+}
+
+EAPI int 
+edje_edit_image_compression_type_get(Evas_Object *obj, const char *image)
+{
+   Edje_Image_Directory_Entry *i = NULL;
+   Evas_List *l;
+
+   GET_ED_OR_RETURN(-1);
+
+   if (!ed->file) return -1;
+   if (!ed->file->image_dir) return -1;
+
+   for (l = ed->file->image_dir->entries; l; l = l->next)
+     {
+       i = l->data;
+       if (strcmp(i->entry, image) == 0)
+         break;
+       i = NULL;
+     }
+
+   if (!i) return -1;
+
+   switch(i->source_type)
+     {
+       case EDJE_IMAGE_SOURCE_TYPE_INLINE_PERFECT:
+               if (i->source_param == 0) // RAW
+                 return EDJE_EDIT_IMAGE_COMP_RAW;
+               else // COMP
+                 return EDJE_EDIT_IMAGE_COMP_COMP;
+               break;
+       case EDJE_IMAGE_SOURCE_TYPE_INLINE_LOSSY: // LOSSY
+               return EDJE_EDIT_IMAGE_COMP_LOSSY;
+               break;
+       case EDJE_IMAGE_SOURCE_TYPE_EXTERNAL: // USER
+               return EDJE_EDIT_IMAGE_COMP_USER;
+               break;
+     }
+
+   return -1;
+}
+
+EAPI int
+edje_edit_image_compression_rate_get(Evas_Object *obj, const char *image)
+{
+   Evas_List *l;
+   Edje_Image_Directory_Entry *i;
+
+   GET_ED_OR_RETURN(-1);
+
+   // Gets the Image Entry
+   for (l = ed->file->image_dir->entries; l; l = l->next)
+     {
+       i = l->data;
+       if (strcmp(i->entry, image) == 0) break;
+       i = NULL;
+     }
+
+   if (!i) return -1;
+   if (i->source_type != EDJE_IMAGE_SOURCE_TYPE_INLINE_LOSSY) return -2;
+
+   return i->source_param;
+}
+
+EAPI const char *
+edje_edit_state_image_get(Evas_Object *obj, const char *part, const char *state)
+{
+   char *image;
+
+   GET_PD_OR_RETURN(NULL);
+
+   image = (char *)_edje_image_name_find(obj, pd->image.id);
+   if (!image) return NULL;
+
+   //printf("GET IMAGE for %s [%s]\n", state, image);
+   return evas_stringshare_add(image);
+}
+
+EAPI void
+edje_edit_state_image_set(Evas_Object *obj, const char *part, const char *state, const char *image)
+{
+   int id;
+
+   GET_PD_OR_RETURN();
+
+   if (!image) return;
+
+   id = _edje_image_id_find(obj, image);
+   printf("SET IMAGE for %s [%s]\n", state, image);
+
+   if (id > -1) pd->image.id = id;
+
+   edje_object_calc_force(obj);
+}
+
+EAPI Evas_List *
+edje_edit_state_tweens_list_get(Evas_Object *obj, const char *part, const char *state)
+{
+   Edje_Part_Image_Id *i;
+   Evas_List *tweens = NULL, *l;
+   const char *name;
+
+   GET_PD_OR_RETURN(NULL);
+
+   //printf("GET TWEEN LIST for %s\n", state);
+
+   for (l = pd->image.tween_list; l; l = l->next)
+     {
+       i = l->data;
+       name = _edje_image_name_find(obj, i->id);
+       //printf("   t: %s\n", name);
+       tweens = evas_list_append(tweens, evas_stringshare_add(name));
+     }
+
+   return tweens;
+}
+
+EAPI unsigned char
+edje_edit_state_tween_add(Evas_Object *obj, const char *part, const char *state, const char *tween)
+{
+   Edje_Part_Image_Id *i;
+   int id;
+
+   GET_PD_OR_RETURN(0);
+
+   id = _edje_image_id_find(obj, tween);
+   if (id < 0) return 0;
+
+   /* alloc Edje_Part_Image_Id */
+   i = mem_alloc(SZ(Edje_Part_Image_Id));
+   if (!i) return 0;
+   i->id = id;
+
+   /* add to tween list */
+   pd->image.tween_list = evas_list_append(pd->image.tween_list, i);
+
+   return 1;
+}
+
+EAPI unsigned char
+edje_edit_state_tween_del(Evas_Object *obj, const char *part, const char *state, const char *tween)
+{
+   Evas_List *l;
+   int id;
+
+   GET_PD_OR_RETURN(0);
+
+   if (!pd->image.tween_list) return 0;
+
+   id = _edje_image_id_find(obj, tween);
+   if (id < 0) return 0;
+
+   for (l = pd->image.tween_list; l; l = l->next)
+     {
+       Edje_Part_Image_Id *i;
+
+       i = l->data;
+       if (i->id == id)
+         {
+            pd->image.tween_list = evas_list_remove_list(pd->image.tween_list, l);
+            return 1;
+         }
+     }
+   return 0;
+}
+
+EAPI void
+edje_edit_state_image_border_get(Evas_Object *obj, const char *part, const char *state, int *l, int *r, int *t, int *b)
+{
+   GET_PD_OR_RETURN();
+
+   //printf("GET IMAGE_BORDER of state '%s'\n", state);
+
+   if (l) *l = pd->border.l;
+   if (r) *r = pd->border.r;
+   if (t) *t = pd->border.t;
+   if (b) *b = pd->border.b;
+}
+
+EAPI void
+edje_edit_state_image_border_set(Evas_Object *obj, const char *part, const char *state, int l, int r, int t, int b)
+{
+   GET_PD_OR_RETURN();
+
+   //printf("SET IMAGE_BORDER of state '%s'\n", state);
+
+   if (l > -1) pd->border.l = l;
+   if (r > -1) pd->border.r = r;
+   if (t > -1) pd->border.t = t;
+   if (b > -1) pd->border.b = b;
+
+   edje_object_calc_force(obj);
+}
+
+/******************/
+/*  SPECTRUM API  */
+/******************/
+
+EAPI Evas_List *
+edje_edit_spectrum_list_get(Evas_Object *obj)
+{
+   Edje_Spectrum_Directory_Entry *s;
+   Evas_List *spectrum = NULL;
+   Evas_List *l;
+
+   GET_ED_OR_RETURN(NULL);
+
+   if (!ed->file) return NULL;
+   if (!ed->file->spectrum_dir) return NULL;
+
+   //printf("GET SPECTRUM LIST for %s\n", ed->file->path);
+
+   for (l = ed->file->spectrum_dir->entries; l; l = l->next)
+     {
+       s = l->data;
+       //printf("SPECTRUM: %s [id: %d]\n", s->entry, s->id);
+       spectrum = evas_list_append(spectrum, evas_stringshare_add(s->entry));
+     }
+
+   return spectrum;
+}
+
+
+EAPI unsigned char
+edje_edit_spectra_add(Evas_Object *obj, const char* name)
+{
+   int id;
+   GET_ED_OR_RETURN(0);
+
+   printf("SPECTRA ADD [new name:%s]\n", name);
+
+   Edje_Spectrum_Directory_Entry *s;
+   Evas_List *l;
+
+   if (!ed->file) return 0;
+
+   if (_edje_edit_spectrum_entry_get(ed, name)) return 0;
+
+   if (!ed->file->spectrum_dir)
+     ed->file->spectrum_dir = mem_alloc(SZ(Edje_Spectrum_Directory));
+
+   s = mem_alloc(SZ(Edje_Spectrum_Directory_Entry));
+   ed->file->spectrum_dir->entries = evas_list_append(ed->file->spectrum_dir->entries, s);
+   s->id = evas_list_count(ed->file->spectrum_dir->entries) - 1; //TODO Search for id holes
+   s->entry = (char*)evas_stringshare_add(name);
+   s->filename = NULL;
+   s->color_list = NULL;
+
+   return 1;
+}
+
+EAPI unsigned char
+edje_edit_spectra_del(Evas_Object *obj, const char* spectra)
+{
+   Edje_Spectrum_Directory_Entry *s;
+
+   GET_ED_OR_RETURN(0);
+
+   s = _edje_edit_spectrum_entry_get(ed, spectra);
+   if (!s) return 0;
+
+   printf("SPECTRA DEL %s\n", spectra);
+
+   ed->file->spectrum_dir->entries = evas_list_remove(ed->file->spectrum_dir->entries, s);
+   _edje_if_string_free(ed, s->entry);
+   _edje_if_string_free(ed, s->filename);
+   while (s->color_list)
+     {
+        Edje_Spectrum_Color *color;
+        color = s->color_list->data;
+        free(color);
+        s->color_list = evas_list_remove_list(s->color_list, s->color_list);
+     }
+   free(s);
+
+   return 1;
+}
+
+EAPI unsigned char
+edje_edit_spectra_name_set(Evas_Object *obj, const char* spectra, const char* name)
+{
+   Edje_Spectrum_Directory_Entry *s;
+
+   GET_ED_OR_RETURN(0);
+
+   printf("SET SPECTRA NAME for spectra: %s [new name:%s]\n", spectra, name);
+
+   s = _edje_edit_spectrum_entry_get(ed, spectra);
+   if (!s) return 0;
+
+   _edje_if_string_free(ed, s->entry);
+   s->entry = (char*)evas_stringshare_add(name);
+
+   return 1;
+}
+
+EAPI int
+edje_edit_spectra_stop_num_get(Evas_Object *obj, const char* spectra)
+{
+   Edje_Spectrum_Directory_Entry *s;
+
+   GET_ED_OR_RETURN(0);
+
+   //printf("GET SPECTRA STOP NUM for spectra: %s\n", spectra);
+
+   s = _edje_edit_spectrum_entry_get(ed, spectra);
+   if (!s) return 0;
+
+   return evas_list_count(s->color_list);
+}
+
+EAPI unsigned char
+edje_edit_spectra_stop_num_set(Evas_Object *obj, const char* spectra, int num)
+{
+   Edje_Spectrum_Directory_Entry *s;
+   Edje_Spectrum_Color *color;
+   GET_ED_OR_RETURN(0);
+
+   printf("SET SPECTRA STOP NUM for spectra: %s\n", spectra);
+
+   s = _edje_edit_spectrum_entry_get(ed, spectra);
+   if (!s) return 0;
+
+   if (num == evas_list_count(s->color_list)) return 1;
+
+   //destroy all colors
+   while (s->color_list)
+     {
+        color = s->color_list->data;
+        free(color);
+        s->color_list = evas_list_remove_list(s->color_list, s->color_list);
+     }
+
+   //... and recreate (TODO we should optimize this function)
+   while (num)
+     {
+        color = mem_alloc(SZ(Edje_Spectrum_Color));
+        s->color_list = evas_list_append(s->color_list, color);
+        color->r = 255;
+        color->g = 255;
+        color->b = 255;
+        color->a = 255;
+        color->d = 10;
+        num--;
+     }
+
+   return 1;
+}
+
+EAPI unsigned char
+edje_edit_spectra_stop_color_get(Evas_Object *obj, const char* spectra, int stop_number, int *r, int *g, int *b, int *a, int *d)
+{
+   Edje_Spectrum_Directory_Entry *s;
+   Edje_Spectrum_Color *color;
+   GET_ED_OR_RETURN(0);
+
+   s = _edje_edit_spectrum_entry_get(ed, spectra);
+   if (!s) return 0;
+   //printf("GET SPECTRA STOP COLOR for spectra: %s stopn: %d\n", spectra, stop_number);
+
+   color = evas_list_nth(s->color_list, stop_number);
+   if (!color) return 0;
+   if (r) *r = color->r;
+   if (g) *g = color->g;
+   if (b) *b = color->b;
+   if (a) *a = color->a;
+   if (d) *d = color->d;
+
+   return 1;
+}
+
+EAPI unsigned char
+edje_edit_spectra_stop_color_set(Evas_Object *obj, const char* spectra, int stop_number, int r, int g, int b, int a, int d)
+{
+   Edje_Spectrum_Directory_Entry *s;
+   Edje_Spectrum_Color *color;
+   GET_ED_OR_RETURN(0);
+
+   s = _edje_edit_spectrum_entry_get(ed, spectra);
+   if (!s) return 0;
+   printf("SET SPECTRA STOP COLOR for spectra: %s stopn: %d\n", spectra, stop_number);
+
+   color = evas_list_nth(s->color_list, stop_number);
+   if (!color) return 0;
+   color->r = r;
+   color->g = g;
+   color->b = b;
+   color->a = a;
+   color->d = d;
+
+   edje_object_calc_force(obj);
+
+   return 1;
+}
+
+
+/******************/
+/*  GRADIENT API  */
+/******************/
+
+EAPI const char *
+edje_edit_state_gradient_type_get(Evas_Object *obj, const char *part, const char *state)
+{
+   GET_PD_OR_RETURN(NULL);
+
+   if (!pd->gradient.type)
+      return NULL;
+
+//   printf("GET GRADIENT TYPE for part: %s state: %s [%s]\n", part, state, pd->gradient.type);
+
+   return evas_stringshare_add(pd->gradient.type);
+}
+
+EAPI unsigned char
+edje_edit_state_gradient_type_set(Evas_Object *obj, const char *part, const char *state, const char *type)
+{
+   GET_PD_OR_RETURN(0);
+   if (!type) return 0;
+
+//   printf("SET GRADIENT TYPE for part: %s state: %s TO: %s\n", part, state, type);
+
+   _edje_if_string_free(ed, pd->gradient.type);
+   pd->gradient.type = (char *)evas_stringshare_add(type);
+   edje_object_calc_force(obj);
+   return 1;
+}
+
+
+EAPI unsigned char
+edje_edit_state_gradient_use_fill_get(Evas_Object *obj, const char *part, const char *state)
+{
+   GET_PD_OR_RETURN(-1);
+
+   if (!pd->gradient.type)
+      return -1;
+
+   if (!strcmp(pd->gradient.type, "linear"))
+      return 0;
+   return 1;
+}
+
+EAPI const char *
+edje_edit_state_gradient_spectra_get(Evas_Object *obj, const char *part, const char *state)
+{
+   Edje_Spectrum_Directory_Entry *s;
+
+   GET_PD_OR_RETURN(0);
+
+   //printf("GET GRADIENT SPECTRA for part: %s state: %s\n", part, state);
+   s = _edje_edit_spectrum_entry_get_by_id(ed, pd->gradient.id);
+   if (!s) return 0;
+
+   return evas_stringshare_add(s->entry);
+}
+
+EAPI unsigned char
+edje_edit_state_gradient_spectra_set(Evas_Object *obj, const char *part, const char *state, const char* spectra)
+{
+   Edje_Spectrum_Directory_Entry *s;
+
+   GET_PD_OR_RETURN(0);
+
+   printf("SET GRADIENT SPECTRA for part: %s state: %s [%s]\n", part, state, spectra);
+
+   s = _edje_edit_spectrum_entry_get(ed, spectra);
+   if (!s) return 0;
+
+   pd->gradient.id = s->id;
+   edje_object_calc_force(obj);
+
+   return 1;
+}
+
+EAPI double
+edje_edit_state_gradient_rel1_relative_x_get(Evas_Object *obj, const char *part, const char *state)
+{
+   GET_PD_OR_RETURN(0);
+   //printf("GET GRADIENT REL1 RELX for part: %s state: %s [%f]\n", part, state, pd->gradient.rel1.relative_x);
+
+   return pd->gradient.rel1.relative_x;
+}
+
+EAPI double
+edje_edit_state_gradient_rel1_relative_y_get(Evas_Object *obj, const char *part, const char *state)
+{
+   GET_PD_OR_RETURN(0);
+   //printf("GET GRADIENT REL1 RELY for part: %s state: %s [%f]\n", part, state, pd->gradient.rel1.relative_y);
+
+   return pd->gradient.rel1.relative_y;
+}
+
+EAPI double
+edje_edit_state_gradient_rel2_relative_x_get(Evas_Object *obj, const char *part, const char *state)
+{
+   GET_PD_OR_RETURN(0);
+   //printf("GET GRADIENT REL2 RELX for part: %s state: %s [%f]\n", part, state, pd->gradient.rel2.relative_x);
+
+   return pd->gradient.rel2.relative_x;
+}
+
+EAPI double
+edje_edit_state_gradient_rel2_relative_y_get(Evas_Object *obj, const char *part, const char *state)
+{
+   GET_PD_OR_RETURN(0);
+   //printf("GET GRADIENT REL2 RELY for part: %s state: %s [%f]\n", part, state, pd->gradient.rel2.relative_y);
+
+   return pd->gradient.rel2.relative_y;
+}
+
+EAPI unsigned char
+edje_edit_state_gradient_rel1_relative_x_set(Evas_Object *obj, const char *part, const char *state, double val)
+{
+   GET_PD_OR_RETURN(0);
+   //printf("SET GRADIENT REL1 RELX for part: %s state: %s [TO %f]\n", part, state, val);
+
+   pd->gradient.rel1.relative_x = val;
+   edje_object_calc_force(obj);
+   return 1;
+}
+
+EAPI unsigned char
+edje_edit_state_gradient_rel1_relative_y_set(Evas_Object *obj, const char *part, const char *state, double val)
+{
+   GET_PD_OR_RETURN(0);
+   printf("SET GRADIENT REL1 RELY for part: %s state: %s [TO %f]\n", part, state, val);
+
+   pd->gradient.rel1.relative_y = val;
+   edje_object_calc_force(obj);
+   return 1;
+}
+
+EAPI unsigned char
+edje_edit_state_gradient_rel2_relative_x_set(Evas_Object *obj, const char *part, const char *state, double val)
+{
+   GET_PD_OR_RETURN(0);
+   printf("SET GRADIENT REL2 RELX for part: %s state: %s [TO %f]\n", part, state, val);
+
+   pd->gradient.rel2.relative_x = val;
+   edje_object_calc_force(obj);
+   return 1;
+}
+
+EAPI unsigned char
+edje_edit_state_gradient_rel2_relative_y_set(Evas_Object *obj, const char *part, const char *state, double val)
+{
+   GET_PD_OR_RETURN(0);
+   printf("SET GRADIENT REL2 RELY for part: %s state: %s [TO %f]\n", part, state, val);
+
+   pd->gradient.rel2.relative_y = val;
+   edje_object_calc_force(obj);
+   return 1;
+}
+
+EAPI int
+edje_edit_state_gradient_rel1_offset_x_get(Evas_Object *obj, const char *part, const char *state)
+{
+   GET_PD_OR_RETURN(0);
+   //printf("GET GRADIENT REL1 OFFSETX for part: %s state: %s [%f]\n", part, state, pd->gradient.rel1.offset_x);
+   return pd->gradient.rel1.offset_x;
+}
+
+EAPI int
+edje_edit_state_gradient_rel1_offset_y_get(Evas_Object *obj, const char *part, const char *state)
+{
+   GET_PD_OR_RETURN(0);
+   //printf("GET GRADIENT REL1 OFFSETY for part: %s state: %s [%f]\n", part, state, pd->gradient.rel1.offset_y);
+   return pd->gradient.rel1.offset_y;
+}
+
+EAPI int
+edje_edit_state_gradient_rel2_offset_x_get(Evas_Object *obj, const char *part, const char *state)
+{
+   GET_PD_OR_RETURN(0);
+   //printf("GET GRADIENT REL2 OFFSETX for part: %s state: %s [%f]\n", part, state, pd->gradient.rel2.offset_x);
+   return pd->gradient.rel2.offset_x;
+}
+
+EAPI int
+edje_edit_state_gradient_rel2_offset_y_get(Evas_Object *obj, const char *part, const char *state)
+{
+   GET_PD_OR_RETURN(0);
+   //printf("GET GRADIENT REL2 OFFSETY for part: %s state: %s [%f]\n", part, state, pd->gradient.rel2.offset_y);
+   return pd->gradient.rel2.offset_y;
+}
+
+EAPI unsigned char
+edje_edit_state_gradient_rel1_offset_x_set(Evas_Object *obj, const char *part, const char *state, int val)
+{
+   GET_PD_OR_RETURN(0);
+   printf("SET GRADIENT REL1 OFFSETX for part: %s state: %s [TO %d]\n", part, state, val);
+
+   pd->gradient.rel1.offset_x = val;
+   edje_object_calc_force(obj);
+   return 1;
+}
+
+EAPI unsigned char
+edje_edit_state_gradient_rel1_offset_y_set(Evas_Object *obj, const char *part, const char *state, int val)
+{
+   GET_PD_OR_RETURN(0);
+   printf("SET GRADIENT REL1 OFFSETY for part: %s state: %s [TO %d]\n", part, state, val);
+
+   pd->gradient.rel1.offset_y = val;
+   edje_object_calc_force(obj);
+   return 1;
+}
+
+EAPI unsigned char
+edje_edit_state_gradient_rel2_offset_x_set(Evas_Object *obj, const char *part, const char *state, int val)
+{
+   GET_PD_OR_RETURN(0);
+   printf("SET GRADIENT REL2 OFFSETX for part: %s state: %s [TO %d]\n", part, state, val);
+
+   pd->gradient.rel2.offset_x = val;
+   edje_object_calc_force(obj);
+   return 1;
+}
+
+EAPI unsigned char
+edje_edit_state_gradient_rel2_offset_y_set(Evas_Object *obj, const char *part, const char *state, int val)
+{
+   GET_PD_OR_RETURN(0);
+   printf("SET GRADIENT REL2 OFFSETY for part: %s state: %s [TO %d]\n", part, state, val);
+
+   pd->gradient.rel2.offset_y = val;
+   edje_object_calc_force(obj);
+   return 1;
+}
+
+/******************/
+/*  PROGRAMS API  */
+/******************/
+Edje_Program *
+_edje_program_get_byname(Evas_Object *obj, const char *prog_name)
+{
+   Edje_Program *epr;
+   int i;
+
+   GET_ED_OR_RETURN(NULL);
+
+   if (!prog_name) return NULL;
+
+   for (i = 0; i < ed->table_programs_size; i++)
+     {
+       epr = ed->table_programs[i];
+       if (strcmp(epr->name, prog_name) == 0)
+         return epr;
+     }
+   return NULL;
+}
+
+EAPI Evas_List *
+edje_edit_programs_list_get(Evas_Object *obj)
+{
+   Evas_List *progs = NULL;
+   int i;
+
+   GET_ED_OR_RETURN(NULL);
+
+   //printf("EE: Found %d programs\n", ed->table_programs_size);
+
+   for (i = 0; i < ed->table_programs_size; i++)
+     {
+       Edje_Program *epr;
+
+       epr = ed->table_programs[i];
+       progs = evas_list_append(progs, evas_stringshare_add(epr->name));
+     }
+
+   return progs;
+}
+
+EAPI unsigned char
+edje_edit_program_add(Evas_Object *obj, const char *name)
+{
+   Edje_Program *epr;
+   Edje_Part_Collection *pc;
+
+   GET_ED_OR_RETURN(0);
+
+   printf("ADD PROGRAM [new name: %s]\n", name);
+
+   //Check if program already exists
+   if (_edje_program_get_byname(obj, name))
+     return 0;
+
+   //Alloc Edje_Program or return
+   epr = mem_alloc(SZ(Edje_Program));
+   if (!epr) return 0;
+
+   //Add program to group
+   pc = ed->collection;
+   pc->programs = evas_list_append(pc->programs, epr);
+
+   //Init Edje_Program
+   epr->id = evas_list_count(pc->programs) - 1;
+   epr->name = evas_stringshare_add(name);
+   epr->signal = NULL;
+   epr->source = NULL;
+   epr->in.from = 0.0;
+   epr->in.range = 0.0;
+   epr->action = 0;
+   epr->state = NULL;
+   epr->value = 0.0;
+   epr->state2 = NULL;
+   epr->value2 = 0.0;
+   epr->tween.mode = 1;
+   epr->tween.time = 0.0;
+   epr->targets = NULL;
+   epr->after = NULL;
+
+
+   //Update table_programs
+   ed->table_programs_size++;
+   ed->table_programs = realloc(ed->table_programs,
+                                sizeof(Edje_Program *) * ed->table_programs_size);
+   ed->table_programs[epr->id % ed->table_programs_size] = epr;
+
+   //Update patterns
+   if (ed->patterns.programs.signals_patterns)
+     {
+       edje_match_patterns_free(ed->patterns.programs.signals_patterns);
+       edje_match_patterns_free(ed->patterns.programs.sources_patterns);
+     }
+   ed->patterns.programs.signals_patterns = edje_match_programs_signal_init(ed->collection->programs);
+   ed->patterns.programs.sources_patterns = edje_match_programs_source_init(ed->collection->programs);
+
+   return 1;
+}
+
+EAPI unsigned char
+edje_edit_program_del(Evas_Object *obj, const char *prog)
+{
+   Evas_List *l;
+   Edje_Part_Collection *pc;
+   int id, i;
+   int old_id;
+
+   GET_ED_OR_RETURN(0);
+   GET_EPR_OR_RETURN(0);
+
+   printf("DEL PROGRAM: %s\n", prog);
+
+   //Remove program from programs list
+   id = epr->id;
+   pc = ed->collection;
+   pc->programs = evas_list_remove(pc->programs, epr);
+
+   //Free Edje_Program
+   _edje_if_string_free(ed, epr->name);
+   _edje_if_string_free(ed, epr->signal);
+   _edje_if_string_free(ed, epr->source);
+   _edje_if_string_free(ed, epr->state);
+   _edje_if_string_free(ed, epr->state2);
+
+   while (epr->targets)
+     {
+       Edje_Program_Target *prt;
+
+       prt = epr->targets->data;
+       epr->targets = evas_list_remove_list(epr->targets, epr->targets);
+       free(prt);
+     }
+   while (epr->after)
+     {
+       Edje_Program_After *pa;
+
+       pa = epr->after->data;
+       epr->after = evas_list_remove_list(epr->after, epr->after);
+       free(pa);
+     }
+   free(epr);
+
+
+   //Update programs table
+   //We move the last program in place of the deleted one
+   //and realloc the table without the last element.
+   ed->table_programs[id % ed->table_programs_size] = ed->table_programs[ed->table_programs_size-1];
+   ed->table_programs_size--;
+   ed->table_programs = realloc(ed->table_programs,
+                             sizeof(Edje_Program *) * ed->table_programs_size);
+
+   //Update the id of the moved program
+   if (id < ed->table_programs_size)
+     {
+       Edje_Program *p;
+
+       p = ed->table_programs[id % ed->table_programs_size];
+       printf("UPDATE: %s(id:%d) with new id: %d\n",
+              p->name, p->id, id);
+       old_id = p->id;
+       p->id = id;
+     }
+   else
+     old_id = -1;
+
+   //We also update all other programs that point to old_id and id
+   for (i = 0; i < ed->table_programs_size; i++)
+     {
+       Edje_Program *p;
+
+       p = ed->table_programs[i];
+       // printf("Check dependencies on %s\n", p->name);
+       /* check in afters */
+       l = p->after;
+       while (l)
+         {
+            Edje_Program_After *pa;
+
+            pa = l->data;
+            if (pa->id == old_id)
+              {
+                 //    printf("   dep on after old_id\n");
+                 pa->id = id;
+              }
+            else if (pa->id == id)
+              {
+                 //  printf("   dep on after id\n");
+                 p->after = evas_list_remove(p->after, pa);
+              }
+
+            if (l) l = l->next;
+         }
+       /* check in targets */
+       if (p->action == EDJE_ACTION_TYPE_ACTION_STOP)
+         {
+            l = p->targets;
+            while (l)
+              {
+                 Edje_Program_Target *pt;
+
+                 pt = l->data;
+                 if (pt->id == old_id)
+                   {
+                      // printf("   dep on target old_id\n");
+                      pt->id = id;
+                   }
+                 else if (pt->id == id)
+                   {
+                      // printf("   dep on target id\n");
+                      p->targets = evas_list_remove(p->targets, pt);
+                   }
+                 if (l) l = l->next;
+              }
+         }
+     }
+
+   return 1;
+}
+
+EAPI unsigned char
+edje_edit_program_exist(Evas_Object *obj, const char *prog)
+{
+   GET_EPR_OR_RETURN(0);
+
+   return 1;
+}
+
+EAPI unsigned char
+edje_edit_program_run(Evas_Object *obj, const char *prog)
+{
+   GET_ED_OR_RETURN(0);
+   GET_EPR_OR_RETURN(0);
+
+   _edje_program_run(ed, epr, 0, "", "");
+   return 1;
+}
+
+EAPI unsigned char
+edje_edit_program_name_set(Evas_Object *obj, const char *prog, const char* new_name)
+{
+   GET_ED_OR_RETURN(0);
+   GET_EPR_OR_RETURN(0);
+
+   if (!new_name) return 0;
+
+   if (_edje_program_get_byname(obj, new_name)) return 0;
+
+   printf("SET NAME for program: %s [new name: %s]\n", prog, new_name);
+
+   _edje_if_string_free(ed, epr->name);
+   epr->name = evas_stringshare_add(new_name);
+
+   return 1;
+}
+
+EAPI const char *
+edje_edit_program_source_get(Evas_Object *obj, const char *prog)
+{
+   GET_EPR_OR_RETURN(NULL);
+
+   if (!epr->source) return NULL;
+   //printf("GET SOURCE for program: %s [%s]\n", prog, epr->source);
+   return evas_stringshare_add(epr->source);
+}
+
+EAPI unsigned char
+edje_edit_program_source_set(Evas_Object *obj, const char *prog, const char *source)
+{
+   GET_ED_OR_RETURN(0);
+   GET_EPR_OR_RETURN(0);
+
+   if (!source) return 0;
+
+   printf("SET SOURCE for program: %s [%s]\n", prog, source);
+
+   _edje_if_string_free(ed, epr->source);
+   epr->source = evas_stringshare_add(source);
+
+   //Update patterns
+   if (ed->patterns.programs.sources_patterns)
+      edje_match_patterns_free(ed->patterns.programs.sources_patterns);
+   ed->patterns.programs.sources_patterns = edje_match_programs_source_init(ed->collection->programs);
+
+   return 1;
+}
+
+EAPI const char *
+edje_edit_program_signal_get(Evas_Object *obj, const char *prog)
+{
+   GET_EPR_OR_RETURN(NULL);
+
+   if (!epr->signal) return NULL;
+   //printf("GET SIGNAL for program: %s [%s]\n", prog, epr->signal);
+   return evas_stringshare_add(epr->signal);
+}
+
+EAPI unsigned char
+edje_edit_program_signal_set(Evas_Object *obj, const char *prog, const char *signal)
+{
+   GET_ED_OR_RETURN(0);
+   GET_EPR_OR_RETURN(0);
+
+   if (!signal) return 0;
+
+   printf("SET SIGNAL for program: %s [%s]\n", prog, signal);
+
+   _edje_if_string_free(ed, epr->signal);
+   epr->signal = evas_stringshare_add(signal);
+
+   //Update patterns
+   if (ed->patterns.programs.signals_patterns)
+      edje_match_patterns_free(ed->patterns.programs.signals_patterns);
+   ed->patterns.programs.signals_patterns = edje_match_programs_signal_init(ed->collection->programs);
+
+   return 1;
+}
+
+EAPI const char *
+edje_edit_program_state_get(Evas_Object *obj, const char *prog)
+{
+   GET_EPR_OR_RETURN(NULL);
+
+   if (!epr->state) return NULL;
+   //printf("GET STATE for program: %s [%s %.2f]\n", prog, epr->state, epr->value);
+   return evas_stringshare_add(epr->state);
+}
+
+EAPI unsigned char
+edje_edit_program_state_set(Evas_Object *obj, const char *prog, const char *state)
+{
+   GET_ED_OR_RETURN(0);
+   GET_EPR_OR_RETURN(0);
+
+   printf("SET STATE for program: %s\n", prog);
+
+   _edje_if_string_free(ed, epr->state);
+   epr->state = evas_stringshare_add(state);
+
+   return 1;
+}
+
+EAPI const char *
+edje_edit_program_state2_get(Evas_Object *obj, const char *prog)
+{
+   GET_EPR_OR_RETURN(NULL);
+
+   if (!epr->state2) return NULL;
+   //printf("GET STATE2 for program: %s [%s %.2f]\n", prog, epr->state2, epr->value2);
+   return evas_stringshare_add(epr->state2);
+}
+
+EAPI unsigned char
+edje_edit_program_state2_set(Evas_Object *obj, const char *prog, const char *state2)
+{
+   GET_ED_OR_RETURN(0);
+   GET_EPR_OR_RETURN(0);
+
+   printf("SET STATE2 for program: %s\n", prog);
+
+   _edje_if_string_free(ed, epr->state2);
+   epr->state2 = evas_stringshare_add(state2);
+
+   return 1;
+}
+
+EAPI double
+edje_edit_program_value_get(Evas_Object *obj, const char *prog)
+{
+   GET_EPR_OR_RETURN(-1);
+
+   //printf("GET VALUE for program: %s [%s %.2f]\n", prog, epr->state, epr->value);
+   return epr->value;
+}
+
+EAPI unsigned char
+edje_edit_program_value_set(Evas_Object *obj, const char *prog, double value)
+{
+   GET_EPR_OR_RETURN(0);
+
+   //printf("SET VALUE for program: %s [%.2f]\n", prog, value);
+   epr->value = value;
+   return 1;
+}
+
+EAPI double
+edje_edit_program_value2_get(Evas_Object *obj, const char *prog)
+{
+   GET_EPR_OR_RETURN(-1);
+
+   //printf("GET VALUE2 for program: %s [%s %.2f]\n", prog, epr->state2, epr->value2);
+   return epr->value2;
+}
+
+EAPI unsigned char
+edje_edit_program_value2_set(Evas_Object *obj, const char *prog, double value)
+{
+   GET_EPR_OR_RETURN(0);
+
+   //printf("SET VALUE for program: %s [%.2f]\n", prog, value);
+   epr->value2 = value;
+   return 1;
+}
+
+EAPI double
+edje_edit_program_in_from_get(Evas_Object *obj, const char *prog)
+{
+   GET_EPR_OR_RETURN(0);
+
+   //printf("GET IN.FROM for program: %s [%f]\n", prog, epr->in.from);
+   return epr->in.from;
+}
+
+EAPI unsigned char
+edje_edit_program_in_from_set(Evas_Object *obj, const char *prog, double seconds)
+{
+   GET_EPR_OR_RETURN(0);
+
+   //printf("SET IN.FROM for program: %s [%f]\n", prog, epr->in.from);
+   epr->in.from = seconds;
+   return 1;
+}
+
+EAPI double
+edje_edit_program_in_range_get(Evas_Object *obj, const char *prog)
+{
+   GET_EPR_OR_RETURN(0);
+
+   //printf("GET IN.RANGE for program: %s [%f]\n", prog, epr->in.range);
+   return epr->in.range;
+}
+
+EAPI unsigned char
+edje_edit_program_in_range_set(Evas_Object *obj, const char *prog, double seconds)
+{
+   GET_EPR_OR_RETURN(0);
+
+   //printf("SET IN.RANGE for program: %s [%f]\n", prog, epr->in.range);
+   epr->in.range = seconds;
+   return 1;
+}
+
+EAPI int
+edje_edit_program_transition_get(Evas_Object *obj, const char *prog)
+{
+   GET_EPR_OR_RETURN(-1);
+
+   //printf("GET TRANSITION for program: %s [%d]\n", prog, epr->tween.mode);
+   return epr->tween.mode;
+}
+
+EAPI unsigned char
+edje_edit_program_transition_set(Evas_Object *obj, const char *prog, int transition)
+{
+   GET_EPR_OR_RETURN(0);
+
+   //printf("GET TRANSITION for program: %s [%d]\n", prog, epr->tween.mode);
+   epr->tween.mode = transition;
+   return 1;
+}
+
+EAPI double
+edje_edit_program_transition_time_get(Evas_Object *obj, const char *prog)
+{
+   GET_EPR_OR_RETURN(-1);
+
+   //printf("GET TRANSITION_TIME for program: %s [%.4f]\n", prog, epr->tween.time);
+   return epr->tween.time;
+}
+
+EAPI unsigned char
+edje_edit_program_transition_time_set(Evas_Object *obj, const char *prog, double seconds)
+{
+   GET_EPR_OR_RETURN(0);
+
+   //printf("GET TRANSITION_TIME for program: %s [%.4f]\n", prog, epr->tween.time);
+   epr->tween.time = seconds;
+   return 1;
+}
+
+EAPI int
+edje_edit_program_action_get(Evas_Object *obj, const char *prog)
+{
+   GET_EPR_OR_RETURN(-1);
+
+   //printf("GET ACTION for program: %s [%d]\n", prog, epr->action);
+   return epr->action;
+}
+
+EAPI unsigned char
+edje_edit_program_action_set(Evas_Object *obj, const char *prog, int action)
+{
+   GET_EPR_OR_RETURN(0);
+
+   //printf("SET ACTION for program: %s [%d]\n", prog, action);
+   if (action >= EDJE_ACTION_TYPE_LAST) return 0;
+
+   epr->action = action;
+   return 1;
+}
+
+EAPI Evas_List *
+edje_edit_program_targets_get(Evas_Object *obj, const char *prog)
+{
+   Evas_List *l, *targets = NULL;
+
+   GET_ED_OR_RETURN(NULL);
+   GET_EPR_OR_RETURN(NULL);
+
+   //printf("GET TARGETS for program: %s [count: %d]\n", prog, evas_list_count(epr->targets));
+
+   for (l = epr->targets; l; l = l->next)
+     {
+       Edje_Program_Target *t;
+
+       t = l->data;
+
+       if (epr->action == EDJE_ACTION_TYPE_STATE_SET)
+         {
+            /* the target is a part */
+            Edje_Real_Part *p = NULL;
+
+            p = ed->table_parts[t->id % ed->table_parts_size];
+            if (p && p->part && p->part->name)
+              targets = evas_list_append(targets,
+                    evas_stringshare_add(p->part->name));
+         }
+       else if (epr->action == EDJE_ACTION_TYPE_ACTION_STOP)
+         {
+            /* the target is a program */
+            Edje_Program *p;
+
+            p = ed->table_programs[t->id % ed->table_programs_size];
+            if (p && p->name)
+              targets = evas_list_append(targets,
+                    evas_stringshare_add(p->name));
+         }
+     }
+   return targets;
+}
+
+EAPI unsigned char
+edje_edit_program_targets_clear(Evas_Object *obj, const char *prog)
+{
+   GET_EPR_OR_RETURN(0);
+
+   while (epr->targets)
+     {
+       Edje_Program_Target *prt;
+
+       prt = epr->targets->data;
+       epr->targets = evas_list_remove_list(epr->targets, epr->targets);
+       free(prt);
+     }
+
+   return 1;
+}
+
+EAPI unsigned char
+edje_edit_program_target_add(Evas_Object *obj, const char *prog, const char *target)
+{
+   int id;
+   Edje_Program_Target *t;
+
+   GET_ED_OR_RETURN(0);
+   GET_EPR_OR_RETURN(0);
+
+   if (epr->action == EDJE_ACTION_TYPE_STATE_SET)
+     {
+       /* the target is a part */
+       Edje_Real_Part *rp;
+
+       rp = _edje_real_part_get(ed, target);
+       if (!rp) return 0;
+       id = rp->part->id;
+     }
+   else if (epr->action == EDJE_ACTION_TYPE_ACTION_STOP)
+     {
+       /* the target is a program */
+       Edje_Program *tar;
+
+       tar = _edje_program_get_byname(obj, target);
+       if (!tar) return 0;
+       id = tar->id;
+     }
+   else
+     return 0;
+
+   t = mem_alloc(SZ(Edje_Program_Target));
+   if (!t) return 0;
+
+   t->id = id;
+   epr->targets = evas_list_append(epr->targets, t);
+
+   return 1;
+}
+
+EAPI Evas_List *
+edje_edit_program_afters_get(Evas_Object *obj, const char *prog)
+{
+   Evas_List *l, *afters = NULL;
+
+   GET_ED_OR_RETURN(NULL);
+   GET_EPR_OR_RETURN(NULL);
+
+  // printf("GET AFTERS for program: %s [count: %d]\n", prog, evas_list_count(epr->after));
+
+   for (l = epr->after; l; l = l->next)
+     {
+       Edje_Program_After *a;
+       Edje_Program *p = NULL;
+
+       a = l->data;
+       p = ed->table_programs[a->id % ed->table_programs_size];
+       if (p && p->name)
+         {
+            printf("   a: %d name: %s\n", a->id, p->name);
+            afters = evas_list_append(afters, evas_stringshare_add(p->name));
+         }
+     }
+   return afters;
+}
+
+EAPI unsigned char
+edje_edit_program_afters_clear(Evas_Object *obj, const char *prog)
+{
+   GET_EPR_OR_RETURN(0);
+
+   while (epr->after)
+     {
+       Edje_Program_After *pa;
+
+       pa = epr->after->data;
+       epr->after = evas_list_remove_list(epr->after, epr->after);
+       free(pa);
+     }
+
+   return 1;
+}
+
+EAPI unsigned char
+edje_edit_program_after_add(Evas_Object *obj, const char *prog, const char *after)
+{
+   Edje_Program *af;
+   Edje_Program_After *a;
+
+   GET_EPR_OR_RETURN(0);
+
+   af = _edje_program_get_byname(obj, after);
+   if (!af) return 0;
+
+   a = mem_alloc(SZ(Edje_Program_After));
+   if (!a) return 0;
+
+   a->id = af->id;
+
+   epr->after = evas_list_append(epr->after, a);
+
+   return 1;
+}
+
+/*************************/
+/*  EMBRYO SCRIPTS  API  */
+/*************************/
+
+EAPI const char *
+edje_edit_script_get(Evas_Object *obj)
+{
+   Embryo_Program   *script = NULL;
+
+   GET_ED_OR_RETURN(NULL);
+
+   if (!ed->collection) return NULL;
+   if (!ed->collection->script) return NULL;
+
+   script = ed->collection->script;
+
+   printf("Get Script [%p] %d\n", script, embryo_program_recursion_get(script));
+
+   return "Not yet complete...";
+}
+
+#define I0 ""
+#define I1 "   "
+#define I2 "      "
+#define I3 "         "
+#define I4 "            "
+#define I5 "               "
+#define I6 "                  "
+
+static char *types[] = {"NONE", "RECT", "TEXT", "IMAGE", "SWALLOW", "TEXTBLOCK", "GRADIENT", "GROUP"};
+
+static void
+_edje_generate_source_of_part(Evas_Object *obj, const char *part, FILE *f)
+{
+   fprintf(f, I3"part {\n");
+   fprintf(f, I4"name: \"%s\";\n", part);
+   fprintf(f, I4"type: %s;\n", types[edje_edit_part_type_get(obj, part)]);
+   if (!edje_edit_part_mouse_events_get(obj, part))
+      fprintf(f, I4"mouse_events: 0;\n");
+   if (edje_edit_part_repeat_events_get(obj, part))
+      fprintf(f, I4"repeat_events: 1;\n");
+   
+   //...and so on...
+   
+   fprintf(f, I3"}\n");//part
+}
+
+static void
+_edje_generate_source_of_group(Edje *ed, const char *group, FILE *f)
+{
+   Evas_Object *obj;
+   Evas_List *l, *ll;
+   int w, h;
+   
+   obj = edje_object_add(ed->evas);
+   if (!edje_object_file_set(obj, ed->file->path, group)) return;
+      
+   fprintf(f, I1"group {\n");
+   fprintf(f, I2"name: \"%s\";\n", group);
+   //TODO Support alias:
+   if ((w = edje_edit_group_min_w_get(obj)) || (h = edje_edit_group_min_h_get(obj)))
+      fprintf(f, I2"min: %d %d;\n", w, h);
+   if ((w = edje_edit_group_max_w_get(obj)) || (h = edje_edit_group_max_h_get(obj)))
+      fprintf(f, I2"max: %d %d;\n", w, h);
+   //TODO Support data
+   //TODO Support script
+   fprintf(f, I2"parts {\n");
+   ll = edje_edit_parts_list_get(obj);
+   for (l = ll; l; l = l->next)
+     {
+        _edje_generate_source_of_part(obj, (char*)l->data, f);
+     }
+   edje_edit_string_list_free(ll);
+   fprintf(f, I2"}\n");//parts
+   //TODO programs like parts
+   
+   fprintf(f, "   }\n");//group
+   
+   
+   //TODO Free the Evas_Object *obj
+}
+
+static void
+_edje_generate_source(Evas_Object *obj)
+{
+   printf("\n****** GENERATE EDC SOURCE *********\n");
+   char tmpn[PATH_MAX];
+   int fd;
+   FILE *f;
+   long sz;
+   SrcFile *sf;
+   SrcFile_List *sfl;
+   Evas_List *l, *ll;
+
+   GET_ED_OR_RETURN();
+   
+   /* Open a temp file */
+   //TODO this will not work on windows
+   strcpy(tmpn, "/tmp/edje_edit.edc-tmp-XXXXXX");
+   if (!(fd = mkstemp(tmpn))) return;
+   printf("*** tmp file: %s\n", tmpn);
+   if (!(f = fopen(tmpn, "w"))) return;
+
+   /* Write edc into file */
+   //TODO Probably we need to save the file before generation
+   
+   /* Images */
+   if (ll = edje_edit_images_list_get(obj))
+     {
+       fprintf(f, I0"images {\n");
+       for (l = ll; l; l = l->next)
+         {
+               char *entry = l->data;  // Name
+               int comp = edje_edit_image_compression_type_get(obj, entry);
+               if (comp < 0) continue;
+
+               fprintf(f, I1"image: \"%s\" ", entry);
+
+               if (comp == EDJE_EDIT_IMAGE_COMP_LOSSY)
+                 fprintf(f, "LOSSY %d;\n",
+                         edje_edit_image_compression_rate_get(obj, entry));
+               else if (comp == EDJE_EDIT_IMAGE_COMP_RAW)
+                 fprintf(f, "RAW;\n");
+               else if (comp == EDJE_EDIT_IMAGE_COMP_USER)
+                 fprintf(f, "USER;\n");
+               else fprintf(f, "COMP;\n");
+         }
+       fprintf(f, I0"}\n\n");
+       evas_list_free(ll);
+     }
+
+   /* Fonts */
+   if (ll = edje_edit_fonts_list_get(obj))
+     {
+       fprintf(f, I0"fonts {\n");
+
+       for (l = ll; l; l = l->next)
+         {
+               char *entry = l->data;
+               // TODO Finish me
+               fprintf(f, I1"font: \"FIXME\" \"%s\";\n", entry);
+         }
+       fprintf(f, I0"}\n\n");
+       evas_list_free(ll); 
+     }
+
+   /* Data */
+   //TODO Support data
+   
+   /* Color Classes */
+   //TODO Support color classes
+   
+   /* Spectra */
+   //TODO Support spectra
+   
+   /* Styles */
+   //TODO Support styles
+   
+   /* Collections */
+   
+   fprintf(f, "collections {\n");
+   ll = edje_file_collection_list(ed->file->path);
+   for (l = ll; l; l = l->next)
+     {
+        _edje_generate_source_of_group(ed, (char*)l->data, f);
+        
+     }
+   fprintf(f, "}\n\n");
+   edje_file_collection_list_free(ll);
+   
+   fclose(f);
+
+   sfl = mem_alloc(SZ(SrcFile_List));
+   sfl->list = NULL;
+
+   /* reopen the temp file and get the contents */
+   f = fopen(tmpn, "rb");
+   if (!f) return;
+
+   fseek(f, 0, SEEK_END);
+   sz = ftell(f);
+   fseek(f, 0, SEEK_SET);
+   sf = mem_alloc(SZ(SrcFile));
+   sf->name = mem_strdup("edje_source.edc");
+   sf->file = mem_alloc(sz + 1);
+   fread(sf->file, sz, 1, f);
+   sf->file[sz] = '\0';
+   fseek(f, 0, SEEK_SET);
+   fclose(f);
+
+   printf("\n\n================= EDC START HERE =========================\n%s\n"
+          "================= EDC END HERE ===========================\n"
+          "generated file: %s\n"
+          "==========================================================\n",
+          sf->file, tmpn);
+   
+   sfl->list = evas_list_append(sfl->list, sf);
+
+   /* Write the source to the edje file */
+   //~ eetf = eet_open(ed->file->path, EET_FILE_MODE_READ_WRITE);
+   //~ if (!eetf) return;
+   //~ if (!_srcfile_list_edd)
+      //~ source_edd();
+
+   //~ eet_data_write(eetf, _srcfile_list_edd, "edje_sources", &sfl, 1);
+
+   //~ eet_close(eetf);
+}
+
+#define ABORT_WRITE2(eet_file) \
+   eet_close(eet_file); \
+   return 0;
+
+EAPI int
+edje_edit_save(Evas_Object *obj)
+{
+   char buf[256];
+   Edje_File *ef;
+   Eet_File *eetf;
+   int bytes;
+   char *progname = "Edje_Edit";
+
+   GET_ED_OR_RETURN(0);
+
+   ef = ed->file;
+   if (!ef) return 0;
+
+   printf("***********  Saving file ******************\n");
+   printf("** path: %s\n", ef->path);
+
+   eetf = eet_open(ef->path, EET_FILE_MODE_READ_WRITE);
+   if (!eetf)
+     {
+       fprintf(stderr, "%s: Error. unable to open \"%s\" for writing output\n",
+               progname, ef->path);
+       return 0;
+     }
+
+   printf("** Writing Edje_File* ed->file\n");
+   bytes = eet_data_write(eetf, _edje_edd_edje_file, "edje_file", ef, 1);
+   if (bytes <= 0)
+     {
+       fprintf(stderr, "%s: Error. unable to write \"edje_file\" "
+               "entry to \"%s\" \n", progname, ef->path);
+       ABORT_WRITE2(eetf);
+     }
+
+   if (ed->collection)
+     {
+       printf("** Writing Edje_Part_Collection* ed->collection "
+              "[id: %d]\n", ed->collection->id);
+
+       snprintf(buf, sizeof(buf), "collections/%i", ed->collection->id);
+
+       bytes = eet_data_write(eetf, _edje_edd_edje_part_collection,
+                              buf, ed->collection, 1);
+       if (bytes <= 0)
+         {
+            fprintf(stderr, "%s: Error. unable to write \"%s\" part entry to %s \n",
+                    progname, buf, ef->path);
+            ABORT_WRITE2(eetf);
+         }
+     }
+
+   eet_close(eetf);
+   printf("***********  Saving DONE ******************\n");
+   return 1;
+}
+
+EAPI void
+edje_edit_print_internal_status(Evas_Object *obj)
+{
+   Evas_List *l;
+
+   GET_ED_OR_RETURN();
+
+   _edje_generate_source(obj);
+   return;
+   
+   printf("\n****** CHECKIN' INTERNAL STRUCTS STATUS *********\n");
+
+   printf("*** Edje\n");
+   printf("    path: '%s'\n", ed->path);
+   printf("    group: '%s'\n", ed->group);
+   printf("    parent: '%s'\n", ed->parent);
+
+   printf("\n*** Parts [table:%d list:%d]\n", ed->table_parts_size,
+          evas_list_count(ed->collection->parts));
+   for (l = ed->collection->parts; l; l = l->next)
+     {
+       Edje_Part *p;
+       Edje_Real_Part *rp;
+
+       p = l->data;
+       rp = ed->table_parts[p->id % ed->table_parts_size];
+       printf("    [%d]%s ", p->id, p->name);
+       if (p == rp->part)
+         printf(" OK!\n");
+       else
+         printf(" WRONG (table[%id]->name = '%s')\n", p->id, rp->part->name);
+     }
+
+   printf("\n*** Programs [table:%d list:%d]\n", ed->table_programs_size,
+          evas_list_count(ed->collection->programs));
+   for (l = ed->collection->programs; l; l = l->next)
+     {
+       Edje_Program *epr;
+       Edje_Program *epr2;
+
+       epr = l->data;
+       epr2 = ed->table_programs[epr->id % ed->table_programs_size];
+       printf("     [%d]%s ", epr->id, epr->name);
+       if (epr == epr2)
+         printf(" OK!\n");
+       else
+         printf(" WRONG (table[%id]->name = '%s')\n", epr->id, epr2->name);
+     }
+
+   printf("\n");
+
+   printf("******************  END  ************************\n\n");
+}
diff --git a/src/lib/edje_embryo.c b/src/lib/edje_embryo.c
new file mode 100644 (file)
index 0000000..9acee50
--- /dev/null
@@ -0,0 +1,2355 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#include "edje_private.h"
+
+/*
+ * ALREADY EXPORTED BY EMBRYO:
+ *
+ * enum Float_Round_Method {
+ *    ROUND, FLOOR, CEIL, TOZERO
+ * };
+ * enum Float_Angle_Mode {
+ *    RADIAN, DEGREES, GRADES
+ * };
+ *
+ * numargs();
+ * getarg(arg, index=0);
+ * setarg(arg, index=0, value);
+ *
+ * Float:atof(string[]);
+ * Float:fract(Float:value);
+ *       round(Float:value, Float_Round_Method:method=ROUND);
+ * Float:sqrt(Float:value);
+ * Float:pow(Float:value, Float:exponent);
+ * Float:log(Float:value, Float:base=10.0);
+ * Float:sin(Float:value, Float_Angle_Mode:mode=RADIAN);
+ * Float:cos(Float:value, Float_Angle_Mode:mode=RADIAN);
+ * Float:tan(Float:value, Float_Angle_Mode:mode=RADIAN);
+ * Float:abs(Float:value);
+ *       atoi(str[]);
+ *       fnmatch(glob[], str[]);
+ *       strcmp(str1[], str2[]);
+ *       strncmp(str1[], str2[]);
+ *       strcpy(dst[], src[]);
+ *       strncpy(dst[], src[], n);
+ *       strlen(str[]);
+ *       strcat(dst[], src[]);
+ *       strncat(dst[], src[], n);
+ *       strprep(dst[], src[]);
+ *       strnprep(dst[], src[], n);
+ *       strcut(dst[], str[], n, n2);
+ *       snprintf(dst[], dstn, fmt[], ...);
+ *       strstr(str[], ndl[]);
+ *       strchr(str[], ch[]);
+ *       strrchr(str[], ch[]);
+ *       rand();
+ * Float:randf();
+ * Float:seconds();
+ *       date(&year, &month, &day, &yearday, &weekday, &hr, &min, &Float:sec);
+ *
+ */
+
+/* EDJE...
+ *
+ * implemented so far as examples:
+ *
+ * enum Msg_Type {
+ *    MSG_NONE, MSG_STRING, MSG_INT, MSG_FLOAT, MSG_STRING_SET, MSG_INT_SET,
+ *    MSG_FLOAT_SET, MSG_STRING_INT, MSG_INT_FLOAT, MSG_STRING_INT_SET,
+ *    MSG_INT_FLOAT_SET
+ * };
+ *
+ * get_int(id)
+ * set_int(id, v)
+ * Float:get_float (id)
+ * set_float(id, Float:v)
+ * get_strlen(id)
+ * get_str(id, dst[], maxlen)
+ * set_str(id, str[])
+ * timer(Float:in, fname[], val)
+ * cancel_timer(id)
+ * anim(Float:len, fname[], val)
+ * cancel_anim(id)
+ * emit(sig[], src[])
+ * set_state(part_id, state[], Float:state_val)
+ * set_tween_state(part_id, Float:tween, state1[], Float:state1_val, state2[], Float:state2_val)
+ * run_program(program_id)
+ * Direction:get_drag_dir(part_id)
+ * get_drag(part_id, &Float:dx, &Float:&dy)
+ * set_drag(part_id, Float:dx, Float:dy)
+ * get_drag_size(part_id, &Float:dx, &Float:&dy)
+ * set_drag_size(part_id, Float:dx, Float:dy)
+ * set_text(part_id, str[])
+ * get_text(part_id, dst[], maxlen)
+ * get_min_size(w, h)
+ * get_max_size(w, h)
+ * set_color_class(class[], r, g, b, a)
+ * get_color_class(class[], &r, &g, &b, &a)
+ * set_text_class(class[], font[], Float:size)
+ * get_text_class(class[], font[], &Float:size)
+ * get_drag_step(part_id, &Float:dx, &Float:&dy)
+ * set_drag_step(part_id, Float:dx, Float:dy)
+ * get_drag_page(part_id, &Float:dx, &Float:&dy)
+ * set_drag_page(part_id, Float:dx, Float:dy)
+ * get_geometry(part_id, &Float:x, &Float:y, &Float:w, &Float:h)
+ * get_mouse(&x, &y)
+ * stop_program(program_id)
+ * stop_programs_on(part_id)
+ * set_min_size(w, h)
+ * set_max_size(w, h)
+ * send_message(Msg_Type:type, id, ...)
+ *
+ * count(id)
+ * remove(id, n)
+ *
+ * append_int(id, v)
+ * prepend_int(id, v)
+ * insert_int(id, n, v)
+ * replace_int(id, n, v)
+ * fetch_int(id, n)
+ *
+ * append_str(id, str[])
+ * prepend_str(id, str[])
+ * insert_str(id, n, str[])
+ * replace_str(id, n, str[])
+ * fetch_str(id, n, dst[], maxlen)
+ *
+ * append_float(id, Float:v)
+ * prepend_float(id, Float:v)
+ * insert_float(id, n, Float:v)
+ * replace_float(id, n, Float:v)
+ * Float:fetch_float(id, n)
+ *
+ * custom_state(part_id, state[], Float:state_val = 0.0)
+ * set_state_val(part_id, State_Param:param, ...)
+ * get_state_val(part_id, State_Param:param, ...)
+ *
+ * Supported parameters:
+ * align[Float:x, Float:y]
+ * min[w, h]
+ * max[w, h]
+ * step[x,y]
+ * aspect[Float:min, Float:max]
+ * color[r,g,b,a]
+ * color2[r,g,b,a]
+ * color3[r,g,b,a]
+ * aspect_preference
+ * rel1[relx,rely]
+ * rel1[part_id,part_id]
+ * rel1[offx,offy]
+ * rel2[relx,relyr]
+ * rel2[part_id,part_id]
+ * rel2[offx,offy]
+ * image[image_id] <- all images have an Id not name in the edje
+ * border[l,r,t,b]
+ * fill[smooth]
+ * fill[pos_relx,pos_rely,pos_offx,pos_offy]
+ * fill[sz_relx,sz_rely,sz_offx,sz_offy]
+ * color_class
+ * text[text]
+ * text[text_class]
+ * text[font]
+ * text[size]
+ * text[style]
+ * text[fit_x,fit_y]
+ * text[min_x,min_y]
+ * text[align_x,align_y]
+ * visible
+ *
+ * ** part_id and program_id need to be able to be "found" from strings
+ *
+ * get_drag_count(part_id, &Float:dx, &Float:&dy)
+ * set_drag_count(part_id, Float:dx, Float:dy)
+ * set_drag_confine(part_id, confine_part_id)
+ * get_size(&w, &h);
+ * resize_request(w, h)
+ * get_mouse_buttons()
+ * //set_type(part_id, Type:type)
+ * //set_effect(part_id, Effect:fx)
+ * set_mouse_events(part_id, ev)
+ * get_mouse_events(part_id)
+ * set_repeat_events(part_id, rep)
+ * get_repeat_events(part_id)
+ * set_clip(part_id, clip_part_id)
+ * get_clip(part_id)
+ *
+ * part_swallow(part_id, group_name)
+ *
+ * ADD/DEL CUSTOM OBJECTS UNDER SOLE EMBRYO SCRIPT CONTROL
+ *
+ */
+
+/* get_int(id) */
+static Embryo_Cell
+_edje_embryo_fn_get_int(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed;
+
+   CHKPARAM(1);
+   ed = embryo_program_data_get(ep);
+   return (Embryo_Cell)_edje_var_int_get(ed, (int)params[1]);
+}
+
+/* set_int(id, v) */
+static Embryo_Cell
+_edje_embryo_fn_set_int(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed;
+
+   CHKPARAM(2);
+   ed = embryo_program_data_get(ep);
+   _edje_var_int_set(ed, (int)params[1], (int)params[2]);
+   return 0;
+}
+
+/* get_float(id) */
+static Embryo_Cell
+_edje_embryo_fn_get_float(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed;
+   float v;
+
+   CHKPARAM(1);
+   ed = embryo_program_data_get(ep);
+   v = (float)_edje_var_float_get(ed, params[1]);
+   return EMBRYO_FLOAT_TO_CELL(v);
+}
+
+/* set_float(id, v) */
+static Embryo_Cell
+_edje_embryo_fn_set_float(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed;
+   float v;
+
+   CHKPARAM(2);
+   ed = embryo_program_data_get(ep);
+   v = EMBRYO_CELL_TO_FLOAT(params[2]);
+   _edje_var_float_set(ed, (int)params[1], (double)v);
+   return 0;
+}
+
+/* get_str(id, dst[], maxlen) */
+static Embryo_Cell
+_edje_embryo_fn_get_str(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed;
+   char *s;
+
+   CHKPARAM(3);
+   if (params[3] < 1) return 0;
+   ed = embryo_program_data_get(ep);
+   s = (char *)_edje_var_str_get(ed, (int)params[1]);
+   if (s)
+     {
+       if (strlen(s) < params[3])
+         {
+            SETSTR(s, params[2]);
+         }
+       else
+         {
+            char *ss;
+
+            ss = alloca(strlen(s) + 1);
+            strcpy(ss, s);
+            ss[params[3] - 1] = 0;
+            SETSTR(ss, params[2]);
+         }
+     }
+   else
+     {
+       SETSTR("", params[2]);
+     }
+   return 0;
+}
+
+/* get_strlen(id) */
+static Embryo_Cell
+_edje_embryo_fn_get_strlen(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed;
+   char *s;
+
+   CHKPARAM(1);
+   ed = embryo_program_data_get(ep);
+   s = (char *)_edje_var_str_get(ed, (int)params[1]);
+   if (s)
+     {
+       return strlen(s);
+     }
+   return 0;
+}
+
+/* set_str(id, str[]) */
+static Embryo_Cell
+_edje_embryo_fn_set_str(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed;
+   char *s;
+
+   CHKPARAM(2);
+   ed = embryo_program_data_get(ep);
+   GETSTR(s, params[2]);
+   if (s)
+     {
+       _edje_var_str_set(ed, (int)params[1], s);
+     }
+   return 0;
+}
+
+/* count(id) */
+static Embryo_Cell
+_edje_embryo_fn_count(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed = embryo_program_data_get(ep);
+
+   CHKPARAM(1);
+
+   return (Embryo_Cell)_edje_var_list_count_get(ed, (int) params[1]);
+}
+
+/* remove(id, n) */
+static Embryo_Cell
+_edje_embryo_fn_remove(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed = embryo_program_data_get(ep);
+
+   CHKPARAM(2);
+
+   _edje_var_list_remove_nth(ed, (int) params[1], (int) params[2]);
+
+   return 0;
+}
+
+/* append_int(id, var) */
+static Embryo_Cell
+_edje_embryo_fn_append_int(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed = embryo_program_data_get(ep);
+
+   CHKPARAM(2);
+
+   _edje_var_list_int_append(ed, (int) params[1], (int) params[2]);
+
+   return 0;
+}
+
+/* prepend_int(id, var) */
+static Embryo_Cell
+_edje_embryo_fn_prepend_int(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed = embryo_program_data_get(ep);
+
+   CHKPARAM(2);
+
+   _edje_var_list_int_prepend(ed, (int) params[1], (int) params[2]);
+
+   return 0;
+}
+
+/* insert_int(id, pos, var) */
+static Embryo_Cell
+_edje_embryo_fn_insert_int(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed = embryo_program_data_get(ep);
+
+   CHKPARAM(3);
+
+   _edje_var_list_int_insert(ed, (int) params[1], (int) params[2],
+                             (int) params[3]);
+
+   return 0;
+}
+
+/* replace_int(id, pos, var) */
+static Embryo_Cell
+_edje_embryo_fn_replace_int(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed = embryo_program_data_get(ep);
+
+   CHKPARAM(3);
+
+   _edje_var_list_nth_int_set(ed, (int) params[1], (int) params[2],
+                              (int) params[3]);
+
+   return 0;
+}
+
+/* fetch_int(id, pos) */
+static Embryo_Cell
+_edje_embryo_fn_fetch_int(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed = embryo_program_data_get(ep);
+
+   CHKPARAM(2);
+
+   return _edje_var_list_nth_int_get(ed, (int) params[1],
+                                     (int) params[2]);
+}
+
+/* append_str(id, str[]) */
+static Embryo_Cell
+_edje_embryo_fn_append_str(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed = embryo_program_data_get(ep);
+   char *s;
+
+   CHKPARAM(2);
+
+   GETSTR(s, params[2]);
+   if (s)
+     _edje_var_list_str_append(ed, (int) params[1], s);
+
+   return 0;
+}
+
+/* prepend_str(id, str[]) */
+static Embryo_Cell
+_edje_embryo_fn_prepend_str(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed = embryo_program_data_get(ep);
+   char *s;
+
+   CHKPARAM(2);
+
+   GETSTR(s, params[2]);
+   if (s)
+     _edje_var_list_str_prepend(ed, (int) params[1], s);
+
+   return 0;
+}
+
+/* insert_str(id, pos, str[]) */
+static Embryo_Cell
+_edje_embryo_fn_insert_str(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed = embryo_program_data_get(ep);
+   char *s;
+
+   CHKPARAM(3);
+
+   GETSTR(s, params[3]);
+   if (s)
+     _edje_var_list_str_insert(ed, (int) params[1], (int) params[2], s);
+
+   return 0;
+}
+
+/* replace_str(id, pos, str[]) */
+static Embryo_Cell
+_edje_embryo_fn_replace_str(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed = embryo_program_data_get(ep);
+   char *s;
+
+   CHKPARAM(3);
+
+   GETSTR(s, params[3]);
+   if (s)
+       _edje_var_list_nth_str_set(ed, (int) params[1], (int) params[2], s);
+
+   return 0;
+}
+
+
+/* fetch_str(id, pos, dst[], maxlen) */
+static Embryo_Cell
+_edje_embryo_fn_fetch_str(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed = embryo_program_data_get(ep);
+   char *s;
+
+   CHKPARAM(4);
+
+   s = (char *) _edje_var_list_nth_str_get(ed, (int) params[1],
+                                           (int) params[2]);
+   if (s)
+     {
+       if (strlen(s) < params[4])
+         {
+            SETSTR(s, params[3]);
+         }
+       else
+         {
+            char *ss;
+
+            ss = alloca(strlen(s) + 1);
+            strcpy(ss, s);
+            ss[params[4] - 1] = 0;
+            SETSTR(ss, params[3]);
+         }
+     }
+   else
+     {
+       SETSTR("", params[3]);
+     }
+
+   return 0;
+}
+
+/* append_float(id, Float:f) */
+static Embryo_Cell
+_edje_embryo_fn_append_float(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed = embryo_program_data_get(ep);
+   float f;
+
+   CHKPARAM(2);
+
+   f = EMBRYO_CELL_TO_FLOAT(params[2]);
+   _edje_var_list_float_append(ed, (int) params[1], f);
+
+   return 0;
+}
+
+/* prepend_float(id, Float:f) */
+static Embryo_Cell
+_edje_embryo_fn_prepend_float(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed = embryo_program_data_get(ep);
+   float f;
+
+   CHKPARAM(2);
+
+   f = EMBRYO_CELL_TO_FLOAT(params[2]);
+   _edje_var_list_float_prepend(ed, (int) params[1], f);
+
+   return 0;
+}
+
+/* insert_float(id, pos, Float:f) */
+static Embryo_Cell
+_edje_embryo_fn_insert_float(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed = embryo_program_data_get(ep);
+   float f;
+
+   CHKPARAM(3);
+
+   f = EMBRYO_CELL_TO_FLOAT(params[3]);
+   _edje_var_list_float_insert(ed, (int) params[1], (int) params[2], f);
+
+   return 0;
+}
+
+/* replace_float(id, pos, Float:f) */
+static Embryo_Cell
+_edje_embryo_fn_replace_float(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed = embryo_program_data_get(ep);
+
+   CHKPARAM(3);
+
+   _edje_var_list_nth_float_set(ed, (int) params[1], (int) params[2],
+                               EMBRYO_CELL_TO_FLOAT(params[3]));
+
+   return 0;
+}
+
+/* Float:fetch_float(id, pos) */
+static Embryo_Cell
+_edje_embryo_fn_fetch_float(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed = embryo_program_data_get(ep);
+   float f;
+
+   CHKPARAM(2);
+
+   f = _edje_var_list_nth_float_get(ed, (int) params[1], (int) params[2]);
+
+   return EMBRYO_FLOAT_TO_CELL(f);
+}
+
+/* timer(Float:in, fname[], val) */
+static Embryo_Cell
+_edje_embryo_fn_timer(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed;
+   char *fname = NULL;
+   float f;
+   double in;
+   int val;
+
+   CHKPARAM(3);
+   ed = embryo_program_data_get(ep);
+   GETSTR(fname, params[2]);
+   if ((!fname)) return 0;
+   f = EMBRYO_CELL_TO_FLOAT(params[1]);
+   in = (double)f;
+   val = params[3];
+   return _edje_var_timer_add(ed, in, fname, val);
+}
+
+/* cancel_timer(id) */
+static Embryo_Cell
+_edje_embryo_fn_cancel_timer(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed;
+   int id;
+
+   CHKPARAM(1);
+   ed = embryo_program_data_get(ep);
+   id = params[1];
+   if (id <= 0) return 0;
+   _edje_var_timer_del(ed, id);
+   return 0;
+}
+
+/* anim(Float:len, fname[], val) */
+static Embryo_Cell
+_edje_embryo_fn_anim(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed;
+   char *fname = NULL;
+   float f;
+   double len;
+   int val;
+
+   CHKPARAM(3);
+   ed = embryo_program_data_get(ep);
+   GETSTR(fname, params[2]);
+   if ((!fname)) return 0;
+   f = EMBRYO_CELL_TO_FLOAT(params[1]);
+   len = (double)f;
+   val = params[3];
+   return _edje_var_anim_add(ed, len, fname, val);
+}
+
+/* cancel_anim(id) */
+static Embryo_Cell
+_edje_embryo_fn_cancel_anim(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed;
+   int id;
+
+   CHKPARAM(1);
+   ed = embryo_program_data_get(ep);
+   id = params[1];
+   if (id <= 0) return 0;
+   _edje_var_anim_del(ed, id);
+   return 0;
+}
+
+/* set_min_size(Float:w, Float:h) */
+static Embryo_Cell
+_edje_embryo_fn_set_min_size(Embryo_Program *ep, Embryo_Cell *params)
+{
+    Edje *ed;
+   float f = 0.0;
+   double w = 0.0, h = 0.0;
+
+   CHKPARAM(2);
+   ed = embryo_program_data_get(ep);
+   f = EMBRYO_CELL_TO_FLOAT(params[1]);
+   w = (double)f;
+   f = EMBRYO_CELL_TO_FLOAT(params[2]);
+   h = (double)f;
+
+   if (w < 0.0) w = 0.0;
+   if (h < 0.0) h = 0.0;
+   ed->collection->prop.min.w = w;
+   ed->collection->prop.min.h = h;
+   ed->dirty = 1;
+   _edje_recalc(ed);
+   return 0;
+}
+
+/* set_max_size(Float:w, Float:h) */
+static Embryo_Cell
+_edje_embryo_fn_set_max_size(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed;
+   float f = 0.0;
+   double w = 0.0, h = 0.0;
+
+   CHKPARAM(2);
+   ed = embryo_program_data_get(ep);
+   f = EMBRYO_CELL_TO_FLOAT(params[1]);
+   w = (double)f;
+   f = EMBRYO_CELL_TO_FLOAT(params[2]);
+   h = (double)f;
+
+   if (w < 0.0) w = 0.0;
+   if (h < 0.0) h = 0.0;
+   ed->collection->prop.max.w = w;
+   ed->collection->prop.max.h = h;
+   ed->dirty = 1;
+   _edje_recalc(ed);
+
+   return 0;
+}
+
+/* stop_program(program_id) */
+static Embryo_Cell
+_edje_embryo_fn_stop_program(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed;
+   int program_id = 0;
+   Edje_Running_Program *runp;
+   Evas_List *l;
+
+   CHKPARAM(1);
+   ed = embryo_program_data_get(ep);
+   program_id = params[1];
+   if (program_id < 0) return 0;
+
+   ed->walking_actions = 1;
+
+   for (l = ed->actions; l; l = l->next)
+     {
+       runp = l->data;
+       if (program_id == runp->program->id)
+         _edje_program_end(ed, runp);
+     }
+
+   ed->walking_actions = 0;
+
+   return 0;
+}
+
+/* stop_programs_on(part_id) */
+static Embryo_Cell
+_edje_embryo_fn_stop_programs_on(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed;
+
+   int part_id = 0;
+   Edje_Real_Part *rp;
+
+   CHKPARAM(1);
+   ed = embryo_program_data_get(ep);
+   part_id = params[1];
+   if (part_id < 0) return 0;
+   rp = ed->table_parts[part_id % ed->table_parts_size];
+   if (rp)
+     {
+       /* there is only ever 1 program acting on a part at any time */
+       if (rp->program) _edje_program_end(ed, rp->program);
+     }
+   return 0;
+}
+
+/* get_mouse(&x, &y) */
+static Embryo_Cell
+_edje_embryo_fn_get_mouse(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed;
+   Evas_Coord x = 0, y = 0;
+
+   CHKPARAM(2);
+   ed = embryo_program_data_get(ep);
+   evas_pointer_canvas_xy_get(ed->evas, &x, &y);
+   x -= ed->x;
+   y -= ed->y;
+   SETINT((int)x, params[1]);
+   SETINT((int)y, params[2]);
+   return 0;
+}
+
+/* get_mouse_buttons() */
+static Embryo_Cell
+_edje_embryo_fn_get_mouse_buttons(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed;
+
+   CHKPARAM(0);
+   ed = embryo_program_data_get(ep);
+   return evas_pointer_button_down_mask_get(ed->evas);
+}
+
+/* emit(sig[], src[]) */
+static Embryo_Cell
+_edje_embryo_fn_emit(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed;
+   char *sig = NULL, *src = NULL;
+
+   CHKPARAM(2);
+   ed = embryo_program_data_get(ep);
+   GETSTR(sig, params[1]);
+   GETSTR(src, params[2]);
+   if ((!sig) || (!src)) return 0;
+   _edje_emit(ed, sig, src);
+   return 0;
+}
+
+/* set_state(part_id, state[], Float:state_val) */
+static Embryo_Cell
+_edje_embryo_fn_set_state(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed;
+   char *state = NULL;
+   int part_id = 0;
+   float f = 0.0;
+   double value = 0.0;
+   Edje_Real_Part *rp;
+
+   CHKPARAM(3);
+   ed = embryo_program_data_get(ep);
+   GETSTR(state, params[2]);
+   if ((!state)) return 0;
+   part_id = params[1];
+   if (part_id < 0) return 0;
+   f = EMBRYO_CELL_TO_FLOAT(params[3]);
+   value = (double)f;
+   rp = ed->table_parts[part_id % ed->table_parts_size];
+   if (rp)
+     {
+       if (rp->program) _edje_program_end(ed, rp->program);
+       _edje_part_description_apply(ed, rp, state, value, NULL, 0.0);
+       _edje_part_pos_set(ed, rp, EDJE_TWEEN_MODE_LINEAR, 0.0);
+       _edje_recalc(ed);
+     }
+   return 0;
+}
+
+/* get_state(part_id, dst[], maxlen, &Float:val) */
+static Embryo_Cell
+_edje_embryo_fn_get_state(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed;
+   int part_id = 0;
+   Edje_Real_Part *rp;
+   const char *s;
+
+   CHKPARAM(4);
+   ed = embryo_program_data_get(ep);
+   part_id = params[1];
+   if (part_id < 0) return 0;
+   rp = ed->table_parts[part_id % ed->table_parts_size];
+   if (rp->chosen_description)
+     {
+       SETFLOAT(rp->chosen_description->state.value, params[4]);
+       s = rp->chosen_description->state.name;
+       if (s)
+         {
+            if (strlen(s) < params[3])
+              {
+                 SETSTR(s, params[2]);
+              }
+            else
+              {
+                 char *ss;
+
+                 ss = alloca(strlen(s) + 1);
+                 strcpy(ss, s);
+                 ss[params[3] - 1] = 0;
+                 SETSTR(ss, params[2]);
+              }
+         }
+       else
+         {
+            SETSTR("", params[2]);
+         }
+     }
+   else
+     {
+       SETFLOAT(0.0, params[4]);
+       SETSTR("", params[2]);
+     }
+   return 0;
+}
+
+/* set_tween_state(part_id, Float:tween, state1[], Float:state1_val, state2[], Float:state2_val) */
+static Embryo_Cell
+_edje_embryo_fn_set_tween_state(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed;
+   char *state1 = NULL, *state2 = NULL;
+   int part_id = 0;
+   float f = 0.0;
+   double tween = 0.0, value1 = 0.0, value2 = 0.0;
+   Edje_Real_Part *rp;
+
+   CHKPARAM(6);
+   ed = embryo_program_data_get(ep);
+   GETSTR(state1, params[3]);
+   GETSTR(state2, params[5]);
+   if ((!state1) || (!state2)) return 0;
+   part_id = params[1];
+   if (part_id < 0) return 0;
+   f = EMBRYO_CELL_TO_FLOAT(params[2]);
+   tween = (double)f;
+   f = EMBRYO_CELL_TO_FLOAT(params[4]);
+   value1 = (double)f;
+   f = EMBRYO_CELL_TO_FLOAT(params[6]);
+   value2 = (double)f;
+   rp = ed->table_parts[part_id % ed->table_parts_size];
+   if (rp)
+     {
+       if (rp->program) _edje_program_end(ed, rp->program);
+       _edje_part_description_apply(ed, rp, state1, value1, state2, value2);
+       _edje_part_pos_set(ed, rp, EDJE_TWEEN_MODE_LINEAR, tween);
+     }
+   return 0;
+}
+
+/* run_program(program_id) */
+static Embryo_Cell
+_edje_embryo_fn_run_program(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed;
+   int program_id = 0;
+   Edje_Program *pr;
+
+   CHKPARAM(1);
+   ed = embryo_program_data_get(ep);
+   program_id = params[1];
+   if (program_id < 0) return 0;
+   pr = ed->table_programs[program_id % ed->table_programs_size];
+   if (pr)
+     {
+       _edje_program_run(ed, pr, 0, "", "");
+     }
+   return 0;
+}
+
+/* get_drag_dir(part_id) */
+static Embryo_Cell
+_edje_embryo_fn_get_drag_dir(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed;
+   int part_id = 0;
+   Edje_Real_Part *rp;
+
+   CHKPARAM(1);
+   ed = embryo_program_data_get(ep);
+   part_id = params[1];
+   if (part_id < 0) return 0;
+   rp = ed->table_parts[part_id % ed->table_parts_size];
+   return edje_object_part_drag_dir_get(ed->obj, rp->part->name);
+}
+
+/* get_drag(part_id, &Float:dx, &Float:dy) */
+static Embryo_Cell
+_edje_embryo_fn_get_drag(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed;
+   int part_id = 0;
+   Edje_Real_Part *rp;
+   double dx = 0.0, dy = 0.0;
+
+   CHKPARAM(3);
+   ed = embryo_program_data_get(ep);
+   part_id = params[1];
+   if (part_id < 0) return 0;
+   rp = ed->table_parts[part_id % ed->table_parts_size];
+   edje_object_part_drag_value_get(ed->obj, rp->part->name, &dx, &dy);
+   SETFLOAT(dx, params[2]);
+   SETFLOAT(dy, params[3]);
+
+   return 0;
+}
+
+/* set_drag(part_id, Float:dx, Float:dy) */
+static Embryo_Cell
+_edje_embryo_fn_set_drag(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed;
+   int part_id = 0;
+   Edje_Real_Part *rp;
+
+   CHKPARAM(3);
+   ed = embryo_program_data_get(ep);
+   part_id = params[1];
+   if (part_id < 0) return 0;
+   rp = ed->table_parts[part_id % ed->table_parts_size];
+   edje_object_part_drag_value_set(ed->obj, rp->part->name,
+                                  (double)EMBRYO_CELL_TO_FLOAT(params[2]),
+                                  (double)EMBRYO_CELL_TO_FLOAT(params[3]));
+   return(0);
+}
+
+/* get_drag_size(part_id, &Float:dx, &Float:dy) */
+static Embryo_Cell
+_edje_embryo_fn_get_drag_size(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed;
+   int part_id = 0;
+   Edje_Real_Part *rp;
+   double dx = 0.0, dy = 0.0;
+
+   CHKPARAM(3);
+   ed = embryo_program_data_get(ep);
+   part_id = params[1];
+   if (part_id < 0) return 0;
+   rp = ed->table_parts[part_id % ed->table_parts_size];
+   edje_object_part_drag_size_get(ed->obj, rp->part->name, &dx, &dy);
+   SETFLOAT(dx, params[2]);
+   SETFLOAT(dy, params[3]);
+
+   return 0;
+}
+
+/* set_drag_size(part_id, Float:dx, Float:dy) */
+static Embryo_Cell
+_edje_embryo_fn_set_drag_size(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed;
+   int part_id = 0;
+   Edje_Real_Part *rp;
+
+   CHKPARAM(3);
+   ed = embryo_program_data_get(ep);
+   part_id = params[1];
+   if (part_id < 0) return 0;
+   rp = ed->table_parts[part_id % ed->table_parts_size];
+   edje_object_part_drag_size_set(ed->obj, rp->part->name,
+                                  (double)EMBRYO_CELL_TO_FLOAT(params[2]),
+                                  (double)EMBRYO_CELL_TO_FLOAT(params[3]));
+   return(0);
+}
+
+/* set_text(part_id, str[]) */
+static Embryo_Cell
+_edje_embryo_fn_set_text(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed;
+   int part_id = 0;
+   Edje_Real_Part *rp;
+   char *s;
+
+   CHKPARAM(2);
+   ed = embryo_program_data_get(ep);
+   part_id = params[1];
+   if (part_id < 0) return 0;
+   rp = ed->table_parts[part_id % ed->table_parts_size];
+   GETSTR(s, params[2]);
+   if (s){
+     edje_object_part_text_set(ed->obj, rp->part->name, s);
+   }
+   return(0);
+}
+
+/* get_text(part_id, dst[], maxlen) */
+static Embryo_Cell
+_edje_embryo_fn_get_text(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed;
+   int part_id = 0;
+   Edje_Real_Part *rp;
+   char *s;
+
+   CHKPARAM(3);
+   ed = embryo_program_data_get(ep);
+   part_id = params[1];
+   if (part_id < 0) return 0;
+   rp = ed->table_parts[part_id % ed->table_parts_size];
+   s = (char *)edje_object_part_text_get(ed->obj, rp->part->name);
+   if (s)
+     {
+       if (strlen(s) < params[3])
+         {
+            SETSTR(s, params[2]);
+         }
+       else
+         {
+            char *ss;
+
+            ss = alloca(strlen(s) + 1);
+            strcpy(ss, s);
+            ss[params[3] - 1] = 0;
+            SETSTR(ss, params[2]);
+         }
+     }
+   else
+     {
+       SETSTR("", params[2]);
+     }
+   return 0;
+}
+
+/* get_min_size(&w, &h) */
+static Embryo_Cell
+_edje_embryo_fn_get_min_size(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed;
+   Evas_Coord w = 0, h = 0;
+
+   CHKPARAM(2);
+   ed = embryo_program_data_get(ep);
+   edje_object_size_min_get(ed->obj, &w, &h);
+   SETINT(w, params[1]);
+   SETINT(h, params[2]);
+   return 0;
+}
+
+/* get_max_size(&w, &h) */
+static Embryo_Cell
+_edje_embryo_fn_get_max_size(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed;
+   Evas_Coord w = 0, h = 0;
+
+   CHKPARAM(2);
+   ed = embryo_program_data_get(ep);
+   edje_object_size_max_get(ed->obj, &w, &h);
+   SETINT(w, params[1]);
+   SETINT(h, params[2]);
+   return 0;
+
+}
+
+/* get_color_class(class[], &r, &g, &b, &a) */
+static Embryo_Cell
+_edje_embryo_fn_get_color_class(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed;
+   Edje_Color_Class *c_class;
+   char *class;
+
+   CHKPARAM(5);
+   ed = embryo_program_data_get(ep);
+   GETSTR(class, params[1]);
+   if (!class) return 0;
+   c_class = _edje_color_class_find(ed, class);
+   if (c_class == NULL) return 0;
+   SETINT(c_class->r, params[2]);
+   SETINT(c_class->g, params[3]);
+   SETINT(c_class->b, params[4]);
+   SETINT(c_class->a, params[5]);
+   return 0;
+}
+
+/* set_color_class(class[], r, g, b, a) */
+static Embryo_Cell
+_edje_embryo_fn_set_color_class(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed;
+   char *class;
+
+   CHKPARAM(5);
+   ed = embryo_program_data_get(ep);
+   GETSTR(class, params[1]);
+   if (!class) return 0;
+   edje_object_color_class_set(ed->obj, class, params[2], params[3], params[4], params[5],
+                              params[2], params[3], params[4], params[5],
+                              params[2], params[3], params[4], params[5]);
+   return 0;
+}
+
+/* set_text_class(class[], font[], Float:size) */
+static Embryo_Cell
+_edje_embryo_fn_set_text_class(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed;
+   char *class, *font;
+   Evas_Font_Size fsize;
+
+   CHKPARAM(3);
+   ed = embryo_program_data_get(ep);
+   GETSTR(class, params[1]);
+   GETSTR(font, params[2]);
+   if( !class || !font ) return 0;
+   fsize = (Evas_Font_Size) EMBRYO_CELL_TO_FLOAT(params[3]);
+   edje_object_text_class_set(ed->obj, class, font, fsize);
+   return 0;
+}
+
+/* get_text_class(class[], font[], &Float:size) */
+static Embryo_Cell
+_edje_embryo_fn_get_text_class(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed;
+   char *class;
+   Edje_Text_Class *t_class;
+
+   CHKPARAM(3);
+   ed = embryo_program_data_get(ep);
+   GETSTR(class, params[1]);
+   if (!class) return 0;
+   t_class = _edje_text_class_find(ed, class);
+   if (t_class == NULL) return 0;
+   SETSTR((char *)t_class->font, params[2]);
+   SETFLOAT(t_class->size, params[3]);
+   return 0;
+}
+
+/* get_drag_step(part_id, &Float:dx, &Float:&dy) */
+static Embryo_Cell
+_edje_embryo_fn_get_drag_step(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed;
+   int part_id = 0;
+   Edje_Real_Part *rp;
+   double dx = 0.0, dy = 0.0;
+
+   CHKPARAM(3);
+   ed = embryo_program_data_get(ep);
+   part_id = params[1];
+   if (part_id < 0) return 0;
+   rp = ed->table_parts[part_id % ed->table_parts_size];
+   edje_object_part_drag_step_get(ed->obj, rp->part->name, &dx, &dy);
+   SETFLOAT(dx, params[2]);
+   SETFLOAT(dy, params[3]);
+
+   return 0;
+}
+
+/* set_drag_step(part_id, Float:dx, Float:dy) */
+static Embryo_Cell
+_edje_embryo_fn_set_drag_step(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed;
+   int part_id = 0;
+   Edje_Real_Part *rp;
+
+   CHKPARAM(3);
+   ed = embryo_program_data_get(ep);
+   part_id = params[1];
+   if (part_id < 0) return 0;
+   rp = ed->table_parts[part_id % ed->table_parts_size];
+   edje_object_part_drag_step_set(ed->obj, rp->part->name,
+                                 (double)EMBRYO_CELL_TO_FLOAT(params[2]),
+                                 (double)EMBRYO_CELL_TO_FLOAT(params[3]));
+   return(0);
+}
+
+/* get_drag_page(part_id, &Float:dx, &Float:&dy) */
+static Embryo_Cell
+_edje_embryo_fn_get_drag_page(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed;
+   int part_id = 0;
+   Edje_Real_Part *rp;
+   double dx = 0.0, dy = 0.0;
+
+   CHKPARAM(3);
+   ed = embryo_program_data_get(ep);
+   part_id = params[1];
+   if (part_id < 0) return 0;
+   rp = ed->table_parts[part_id % ed->table_parts_size];
+   edje_object_part_drag_page_get(ed->obj, rp->part->name, &dx, &dy);
+   SETFLOAT(dx, params[2]);
+   SETFLOAT(dy, params[3]);
+
+   return 0;
+}
+
+/* get_geometry(pard_id, &x, &y, &w, &h) */
+static Embryo_Cell
+_edje_embryo_fn_get_geometry(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed;
+   int part_id = 0;
+   Edje_Real_Part *rp;
+   Evas_Coord x = 0.0, y = 0.0, w = 0.0, h = 0.0;
+
+   CHKPARAM(5);
+   ed = embryo_program_data_get(ep);
+   part_id = params[1];
+   if (part_id < 0) return 0;
+   rp = ed->table_parts[part_id % ed->table_parts_size];
+   edje_object_part_geometry_get(ed->obj, rp->part->name, &x, &y, &w, &h);
+   SETINT(x, params[2]);
+   SETINT(y, params[3]);
+   SETINT(w, params[4]);
+   SETINT(h, params[5]);
+
+   return 0;
+}
+
+/* set_drag_page(part_id, Float:dx, Float:dy) */
+static Embryo_Cell
+_edje_embryo_fn_set_drag_page(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed;
+   int part_id = 0;
+   Edje_Real_Part *rp;
+
+   CHKPARAM(3);
+   ed = embryo_program_data_get(ep);
+   part_id = params[1];
+   if (part_id < 0) return 0;
+   rp = ed->table_parts[part_id % ed->table_parts_size];
+   edje_object_part_drag_page_set(ed->obj, rp->part->name,
+                                 (double)EMBRYO_CELL_TO_FLOAT(params[2]),
+                                 (double)EMBRYO_CELL_TO_FLOAT(params[3]));
+   return(0);
+}
+
+/* send_message(id, Msg_Type:type, ...); */
+static Embryo_Cell
+_edje_embryo_fn_send_message(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed;
+   Edje_Message_Type type;
+   int id, i, n;
+   Embryo_Cell *ptr;
+
+   if (params[0] < (sizeof(Embryo_Cell) * (2))) return 0;
+   ed = embryo_program_data_get(ep);
+   type = params[1];
+   id = params[2];
+   switch (type)
+     {
+      case EDJE_MESSAGE_NONE:
+       _edje_message_send(ed, EDJE_QUEUE_APP, type, id, NULL);
+       break;
+      case EDJE_MESSAGE_SIGNAL:
+       break;
+      case EDJE_MESSAGE_STRING:
+         {
+            Embryo_Cell *cptr;
+
+            cptr = embryo_data_address_get(ep, params[3]);
+            if (cptr)
+              {
+                 Edje_Message_String *emsg;
+                 int l;
+                 char *s;
+
+                 l = embryo_data_string_length_get(ep, cptr);
+                 s = alloca(l + 1);
+                 embryo_data_string_get(ep, cptr, s);
+                 emsg = alloca(sizeof(Edje_Message_String));
+                 emsg->str = s;
+                 _edje_message_send(ed, EDJE_QUEUE_APP, type, id, emsg);
+              }
+         }
+       break;
+      case EDJE_MESSAGE_INT:
+         {
+            Edje_Message_Int *emsg;
+
+            emsg = alloca(sizeof(Edje_Message_Int));
+            ptr = embryo_data_address_get(ep, params[3]);
+            emsg->val = (int)*ptr;
+            _edje_message_send(ed, EDJE_QUEUE_APP, type, id, emsg);
+         }
+       break;
+      case EDJE_MESSAGE_FLOAT:
+         {
+            Edje_Message_Float *emsg;
+            float f;
+
+            emsg = alloca(sizeof(Edje_Message_Float));
+            ptr = embryo_data_address_get(ep, params[3]);
+            f = EMBRYO_CELL_TO_FLOAT(*ptr);
+            emsg->val = (double)f;
+            _edje_message_send(ed, EDJE_QUEUE_APP, type, id, emsg);
+         }
+       break;
+      case EDJE_MESSAGE_STRING_SET:
+         {
+            Edje_Message_String_Set *emsg;
+
+            n = (params[0] / sizeof(Embryo_Cell)) + 1;
+            emsg = alloca(sizeof(Edje_Message_String_Set) + ((n - 3 - 1) * sizeof(char *)));
+            emsg->count = n - 3;
+            for (i = 3; i < n; i++)
+              {
+                 Embryo_Cell *cptr;
+
+                 cptr = embryo_data_address_get(ep, params[i]);
+                 if (cptr)
+                   {
+                      int l;
+                      char *s;
+
+                      l = embryo_data_string_length_get(ep, cptr);
+                      s = alloca(l + 1);
+                      embryo_data_string_get(ep, cptr, s);
+                      emsg->str[i - 3] = s;
+                   }
+              }
+            _edje_message_send(ed, EDJE_QUEUE_APP, type, id, emsg);
+         }
+       break;
+      case EDJE_MESSAGE_INT_SET:
+         {
+            Edje_Message_Int_Set *emsg;
+
+            n = (params[0] / sizeof(Embryo_Cell)) + 1;
+            emsg = alloca(sizeof(Edje_Message_Int_Set) + ((n - 3 - 1) * sizeof(int)));
+            emsg->count = n - 3;
+            for (i = 3; i < n; i++)
+              {
+                 ptr = embryo_data_address_get(ep, params[i]);
+                 emsg->val[i - 3] = (int)*ptr;
+              }
+            _edje_message_send(ed, EDJE_QUEUE_APP, type, id, emsg);
+         }
+       break;
+      case EDJE_MESSAGE_FLOAT_SET:
+         {
+            Edje_Message_Float_Set *emsg;
+
+            n = (params[0] / sizeof(Embryo_Cell)) + 1;
+            emsg = alloca(sizeof(Edje_Message_Float_Set) + ((n - 3 - 1) * sizeof(double)));
+            emsg->count = n - 3;
+            for (i = 3; i < n; i++)
+              {
+                 float f;
+
+                 ptr = embryo_data_address_get(ep, params[i]);
+                 f = EMBRYO_CELL_TO_FLOAT(*ptr);
+                 emsg->val[i - 3] = (double)f;
+              }
+            _edje_message_send(ed, EDJE_QUEUE_APP, type, id, emsg);
+         }
+       break;
+      case EDJE_MESSAGE_STRING_INT:
+         {
+            Edje_Message_String_Int *emsg;
+            Embryo_Cell *cptr;
+
+            cptr = embryo_data_address_get(ep, params[3]);
+            if (cptr)
+              {
+                 int l;
+                 char *s;
+
+                 l = embryo_data_string_length_get(ep, cptr);
+                 s = alloca(l + 1);
+                 embryo_data_string_get(ep, cptr, s);
+                 emsg = alloca(sizeof(Edje_Message_String_Int));
+                 emsg->str = s;
+                 ptr = embryo_data_address_get(ep, params[4]);
+                 emsg->val = (int)*ptr;
+                 _edje_message_send(ed, EDJE_QUEUE_APP, type, id, emsg);
+              }
+         }
+       break;
+      case EDJE_MESSAGE_STRING_FLOAT:
+         {
+            Edje_Message_String_Float *emsg;
+            Embryo_Cell *cptr;
+
+            cptr = embryo_data_address_get(ep, params[3]);
+            if (cptr)
+              {
+                 int l;
+                 char *s;
+                 float f;
+
+                 l = embryo_data_string_length_get(ep, cptr);
+                 s = alloca(l + 1);
+                 embryo_data_string_get(ep, cptr, s);
+                 emsg = alloca(sizeof(Edje_Message_String_Float));
+                 emsg->str = s;
+                 ptr = embryo_data_address_get(ep, params[4]);
+                 f = EMBRYO_CELL_TO_FLOAT(*ptr);
+                 emsg->val = (double)f;
+                 _edje_message_send(ed, EDJE_QUEUE_APP, type, id, emsg);
+              }
+         }
+       break;
+      case EDJE_MESSAGE_STRING_INT_SET:
+         {
+            Edje_Message_String_Int_Set *emsg;
+            Embryo_Cell *cptr;
+
+            cptr = embryo_data_address_get(ep, params[3]);
+            if (cptr)
+              {
+                 int l;
+                 char *s;
+
+                 l = embryo_data_string_length_get(ep, cptr);
+                 s = alloca(l + 1);
+                 embryo_data_string_get(ep, cptr, s);
+                 n = (params[0] / sizeof(Embryo_Cell)) + 1;
+                 emsg = alloca(sizeof(Edje_Message_String_Int_Set) + ((n - 4 - 1) * sizeof(int)));
+                 emsg->str = s;
+                 emsg->count = n - 4;
+                 for (i = 4; i < n; i++)
+                   {
+                      ptr = embryo_data_address_get(ep, params[i]);
+                      emsg->val[i - 4] = (int)*ptr;
+                   }
+                 _edje_message_send(ed, EDJE_QUEUE_APP, type, id, emsg);
+              }
+         }
+       break;
+      case EDJE_MESSAGE_STRING_FLOAT_SET:
+         {
+            Edje_Message_String_Float_Set *emsg;
+            Embryo_Cell *cptr;
+
+            cptr = embryo_data_address_get(ep, params[3]);
+            if (cptr)
+              {
+                 int l;
+                 char *s;
+
+                 l = embryo_data_string_length_get(ep, cptr);
+                 s = alloca(l + 1);
+                 embryo_data_string_get(ep, cptr, s);
+                 n = (params[0] / sizeof(Embryo_Cell)) + 1;
+                 emsg = alloca(sizeof(Edje_Message_String_Float_Set) + ((n - 4 - 1) * sizeof(double)));
+                 emsg->str = s;
+                 emsg->count = n - 4;
+                 for (i = 4; i < n; i++)
+                   {
+                      float f;
+
+                      ptr = embryo_data_address_get(ep, params[i]);
+                      f = EMBRYO_CELL_TO_FLOAT(*ptr);
+                      emsg->val[i - 4] = (double)f;
+                   }
+                 _edje_message_send(ed, EDJE_QUEUE_APP, type, id, emsg);
+              }
+         }
+       break;
+      default:
+       break;
+     }
+   return(0);
+}
+
+/* custom_state(part_id, state[], Float:state_val = 0.0) */
+static Embryo_Cell
+_edje_embryo_fn_custom_state(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed = embryo_program_data_get(ep);
+   Edje_Real_Part *rp;
+   Edje_Part_Description *parent, *d;
+   Evas_List *l;
+   char *name;
+   float val;
+
+   CHKPARAM(3);
+
+   if (params[1] < 0)
+     return 0;
+
+   if (!(rp = ed->table_parts[params[1] % ed->table_parts_size]))
+     return 0;
+
+   /* check whether this part already has a "custom" state */
+   if (rp->custom.description)
+     return 0;
+
+   GETSTR(name, params[2]);
+   if (!name)
+     return 0;
+
+   val = EMBRYO_CELL_TO_FLOAT(params[3]);
+
+   if (!(parent = _edje_part_description_find(ed, rp, name, val)))
+     return 0;
+
+   /* now create the custom state */
+   if (!(d = calloc(1, sizeof(Edje_Part_Description))))
+     return 0;
+
+   *d = *parent;
+
+   d->state.name = (char *)evas_stringshare_add("custom");
+   d->state.value = 0.0;
+
+   /* make sure all the allocated memory is getting copied,
+    * not just referenced
+    */
+   d->image.tween_list = NULL;
+
+   for (l = parent->image.tween_list; l; l = l->next)
+     {
+       Edje_Part_Image_Id *iid = l->data, *iid_new;
+
+       iid_new = calloc(1, sizeof(Edje_Part_Image_Id));
+       iid_new->id = iid->id;
+
+       d->image.tween_list = evas_list_append(d->image.tween_list, iid_new);
+     }
+
+#define DUP(x) x ? (char *)evas_stringshare_add(x) : NULL
+   d->color_class = DUP(d->color_class);
+   d->text.text = DUP(d->text.text);
+   d->text.text_class = DUP(d->text.text_class);
+   d->text.font = DUP(d->text.font);
+   d->text.style = DUP(d->text.style);
+#undef DUP
+
+   rp->custom.description = d;
+
+   return 0;
+}
+
+/* set_state_val(part_id, State_Param:p, ...) */
+static Embryo_Cell
+_edje_embryo_fn_set_state_val(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed = embryo_program_data_get(ep);
+   Edje_Real_Part *rp;
+   char *s;
+
+   /* we need at least 3 arguments */
+   if (params[0] < (sizeof(Embryo_Cell) * 3))
+     return 0;
+
+   if (params[1] < 0)
+     return 0;
+
+   if (!(rp = ed->table_parts[params[1] % ed->table_parts_size]))
+     return 0;
+
+   /* check whether this part has a "custom" state */
+   if (!rp->custom.description)
+     return 0;
+
+   switch (params[2])
+     {
+      case EDJE_STATE_PARAM_ALIGNMENT:
+        CHKPARAM(4);
+
+        GETFLOAT(rp->custom.description->align.x, params[3]);
+        GETFLOAT(rp->custom.description->align.y, params[4]);
+
+        break;
+      case EDJE_STATE_PARAM_MIN:
+        CHKPARAM(4);
+
+        GETINT(rp->custom.description->min.w, params[3]);
+        GETINT(rp->custom.description->min.h, params[4]);
+
+        break;
+      case EDJE_STATE_PARAM_MAX:
+        CHKPARAM(4);
+
+        GETINT(rp->custom.description->max.w, params[3]);
+        GETINT(rp->custom.description->max.h, params[4]);
+
+        break;
+      case EDJE_STATE_PARAM_STEP:
+        CHKPARAM(4);
+
+        GETINT(rp->custom.description->step.x, params[3]);
+        GETINT(rp->custom.description->step.y, params[4]);
+
+        break;
+      case EDJE_STATE_PARAM_ASPECT:
+        CHKPARAM(4);
+
+        GETFLOAT(rp->custom.description->aspect.min, params[3]);
+        GETFLOAT(rp->custom.description->aspect.max, params[4]);
+
+        break;
+      case EDJE_STATE_PARAM_ASPECT_PREF:
+        CHKPARAM(3);
+
+        GETINT(rp->custom.description->aspect.prefer, params[3]);
+
+        break;
+      case EDJE_STATE_PARAM_COLOR:
+        CHKPARAM(6);
+
+        GETINT(rp->custom.description->color.r, params[3]);
+        GETINT(rp->custom.description->color.g, params[4]);
+        GETINT(rp->custom.description->color.b, params[5]);
+        GETINT(rp->custom.description->color.a, params[6]);
+
+        break;
+      case EDJE_STATE_PARAM_COLOR2:
+        CHKPARAM(6);
+
+        GETINT(rp->custom.description->color2.r, params[3]);
+        GETINT(rp->custom.description->color2.g, params[4]);
+        GETINT(rp->custom.description->color2.b, params[5]);
+        GETINT(rp->custom.description->color2.a, params[6]);
+
+        break;
+      case EDJE_STATE_PARAM_COLOR3:
+        CHKPARAM(6);
+
+        GETINT(rp->custom.description->color3.r, params[3]);
+        GETINT(rp->custom.description->color3.g, params[4]);
+        GETINT(rp->custom.description->color3.b, params[5]);
+        GETINT(rp->custom.description->color3.a, params[6]);
+
+        break;
+      case EDJE_STATE_PARAM_COLOR_CLASS:
+        CHKPARAM(3);
+
+        GETSTR(s, params[3]);
+        GETSTREVAS(s, rp->custom.description->color_class);
+
+        break;
+      case EDJE_STATE_PARAM_REL1:
+        CHKPARAM(4);
+
+        GETFLOAT(rp->custom.description->rel1.relative_x, params[3]);
+        GETFLOAT(rp->custom.description->rel1.relative_y, params[4]);
+
+        break;
+      case EDJE_STATE_PARAM_REL1_TO:
+        CHKPARAM(4);
+
+        GETINT(rp->custom.description->rel1.id_x, params[3]);
+        GETINT(rp->custom.description->rel1.id_y, params[4]);
+
+        if (rp->param1.description->rel1.id_x >= 0)
+          rp->param1.rel1_to_x = ed->table_parts[rp->param1.description->rel1.id_x % ed->table_parts_size];
+        if (rp->param1.description->rel1.id_y >= 0)
+          rp->param1.rel1_to_y = ed->table_parts[rp->param1.description->rel1.id_y % ed->table_parts_size];
+
+        break;
+      case EDJE_STATE_PARAM_REL1_OFFSET:
+        CHKPARAM(4);
+
+        GETINT(rp->custom.description->rel1.offset_x, params[3]);
+        GETINT(rp->custom.description->rel1.offset_y, params[4]);
+
+        break;
+      case EDJE_STATE_PARAM_REL2:
+        CHKPARAM(4);
+
+        GETFLOAT(rp->custom.description->rel2.relative_x, params[3]);
+        GETFLOAT(rp->custom.description->rel2.relative_y, params[4]);
+
+        break;
+      case EDJE_STATE_PARAM_REL2_TO:
+        CHKPARAM(4);
+
+        GETINT(rp->custom.description->rel2.id_x, params[3]);
+        GETINT(rp->custom.description->rel2.id_y, params[4]);
+
+        if (rp->param1.description->rel2.id_x >= 0)
+          rp->param1.rel2_to_x = ed->table_parts[rp->param1.description->rel2.id_x % ed->table_parts_size];
+        if (rp->param1.description->rel2.id_y >= 0)
+          rp->param1.rel2_to_y = ed->table_parts[rp->param1.description->rel2.id_y % ed->table_parts_size];
+
+        break;
+      case EDJE_STATE_PARAM_REL2_OFFSET:
+        CHKPARAM(4);
+
+        GETINT(rp->custom.description->rel2.offset_x, params[3]);
+        GETINT(rp->custom.description->rel2.offset_y, params[4]);
+
+        break;
+      case EDJE_STATE_PARAM_IMAGE:
+        if ( (rp->part->type != EDJE_PART_TYPE_IMAGE) ) return 0;
+        CHKPARAM(3);
+
+        GETINT(rp->custom.description->image.id, params[3]);
+
+        break;
+      case EDJE_STATE_PARAM_BORDER:
+        if ( (rp->part->type != EDJE_PART_TYPE_IMAGE) ) return 0;
+        CHKPARAM(6);
+
+        GETINT(rp->custom.description->border.l, params[3]);
+        GETINT(rp->custom.description->border.r, params[4]);
+        GETINT(rp->custom.description->border.t, params[5]);
+        GETINT(rp->custom.description->border.b, params[6]);
+
+        break;
+      case EDJE_STATE_PARAM_FILL_SMOOTH:
+        if ( (rp->part->type != EDJE_PART_TYPE_IMAGE) ) return 0;
+        CHKPARAM(3);
+
+        GETINT(rp->custom.description->fill.smooth, params[3]);
+
+        break;
+      case EDJE_STATE_PARAM_FILL_POS:
+        if ( (rp->part->type != EDJE_PART_TYPE_IMAGE) ) return 0;
+        CHKPARAM(6);
+
+        GETFLOAT(rp->custom.description->fill.pos_rel_x, params[3]);
+        GETFLOAT(rp->custom.description->fill.pos_rel_y, params[4]);
+        GETINT(rp->custom.description->fill.pos_abs_x, params[5]);
+        GETINT(rp->custom.description->fill.pos_abs_y, params[6]);
+
+        break;
+      case EDJE_STATE_PARAM_FILL_SIZE:
+        if ( (rp->part->type != EDJE_PART_TYPE_IMAGE) ) return 0;
+        CHKPARAM(6);
+
+        GETFLOAT(rp->custom.description->fill.rel_x, params[3]);
+        GETFLOAT(rp->custom.description->fill.rel_y, params[4]);
+        GETINT(rp->custom.description->fill.abs_x, params[5]);
+        GETINT(rp->custom.description->fill.abs_y, params[6]);
+
+        break;
+      case EDJE_STATE_PARAM_TEXT:
+        if ( (rp->part->type != EDJE_PART_TYPE_TEXT) && \
+             (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK))
+          return 0;
+        CHKPARAM(3);
+
+        GETSTR(s, params[3]);
+        GETSTREVAS(s, rp->custom.description->text.text);
+
+        break;
+      case EDJE_STATE_PARAM_TEXT_CLASS:
+        if ( (rp->part->type != EDJE_PART_TYPE_TEXT) && \
+              (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK))
+          return 0;
+        CHKPARAM(3);
+
+        GETSTR(s, params[3]);
+        GETSTREVAS(s, rp->custom.description->text.text_class);
+
+        break;
+      case EDJE_STATE_PARAM_TEXT_FONT:
+        if ((rp->part->type != EDJE_PART_TYPE_TEXT)) return 0;
+        CHKPARAM(3);
+
+        GETSTR(s, params[3]);
+        GETSTREVAS(s, rp->custom.description->text.font);
+
+        break;
+      case EDJE_STATE_PARAM_TEXT_STYLE:
+        if ((rp->part->type != EDJE_PART_TYPE_TEXTBLOCK)) return 0;
+        CHKPARAM(3);
+
+        GETSTR(s, params[3]);
+        GETSTREVAS(s, rp->custom.description->text.style);
+
+        break;
+      case EDJE_STATE_PARAM_TEXT_SIZE:
+        if ((rp->part->type != EDJE_PART_TYPE_TEXT)) return 0;
+        CHKPARAM(3);
+
+        GETINT(rp->custom.description->text.size, params[3]);
+
+        break;
+      case EDJE_STATE_PARAM_TEXT_FIT:
+        if ((rp->part->type != EDJE_PART_TYPE_TEXT)) return 0;
+        CHKPARAM(4);
+
+        GETINT(rp->custom.description->text.fit_x, params[3]);
+        GETINT(rp->custom.description->text.fit_y, params[4]);
+
+        break;
+      case EDJE_STATE_PARAM_TEXT_MIN:
+        if ( (rp->part->type != EDJE_PART_TYPE_TEXT) && \
+              (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK))
+          return 0;
+        CHKPARAM(4);
+
+        GETINT(rp->custom.description->text.min_x, params[3]);
+        GETINT(rp->custom.description->text.min_y, params[4]);
+
+        break;
+      case EDJE_STATE_PARAM_TEXT_MAX:
+        if ( (rp->part->type != EDJE_PART_TYPE_TEXT) && \
+              (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK))
+          return 0;
+        CHKPARAM(4);
+
+        GETINT(rp->custom.description->text.max_x, params[3]);
+        GETINT(rp->custom.description->text.max_y, params[4]);
+
+        break;
+      case EDJE_STATE_PARAM_TEXT_ALIGN:
+        if ((rp->part->type != EDJE_PART_TYPE_TEXT)) return 0;
+        CHKPARAM(4);
+
+        GETFLOAT(rp->custom.description->text.align.x, params[3]);
+        GETFLOAT(rp->custom.description->text.align.y, params[4]);
+
+        break;
+      case EDJE_STATE_PARAM_VISIBLE:
+        CHKPARAM(3);
+
+        GETINT(rp->custom.description->visible, params[3]);
+
+        break;
+      default:
+        break;
+     }
+
+   ed->dirty=1;
+   return 0;
+}
+
+/* get_state_val(part_id, State_Param:p, ...) */
+static Embryo_Cell
+_edje_embryo_fn_get_state_val(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed = embryo_program_data_get(ep);
+   Edje_Real_Part *rp;
+   char *s;
+
+   /* we need at least 3 arguments */
+   if (params[0] < (sizeof(Embryo_Cell) * 3))
+     return 0;
+
+   if (params[1] < 0)
+     return 0;
+
+   if (!(rp = ed->table_parts[params[1] % ed->table_parts_size]))
+     return 0;
+
+   /* check whether this part has a "custom" state */
+   if (!rp->custom.description)
+     return 0;
+
+   switch (params[2])
+     {
+      case EDJE_STATE_PARAM_ALIGNMENT:
+        CHKPARAM(4);
+
+        SETFLOAT(rp->custom.description->align.x, params[3]);
+        SETFLOAT(rp->custom.description->align.y, params[4]);
+
+        break;
+      case EDJE_STATE_PARAM_MIN:
+        CHKPARAM(4);
+
+        SETINT(rp->custom.description->min.w, params[3]);
+        SETINT(rp->custom.description->min.h, params[4]);
+
+        break;
+      case EDJE_STATE_PARAM_MAX:
+        CHKPARAM(4);
+
+        SETINT(rp->custom.description->max.w, params[3]);
+        SETINT(rp->custom.description->max.h, params[4]);
+
+        break;
+      case EDJE_STATE_PARAM_STEP:
+        CHKPARAM(4);
+
+        SETINT(rp->custom.description->step.x, params[3]);
+        SETINT(rp->custom.description->step.y, params[4]);
+
+        break;
+      case EDJE_STATE_PARAM_ASPECT:
+        CHKPARAM(4);
+
+        SETFLOAT(rp->custom.description->aspect.min, params[3]);
+        SETFLOAT(rp->custom.description->aspect.max, params[4]);
+
+        break;
+      case EDJE_STATE_PARAM_ASPECT_PREF:
+        CHKPARAM(3);
+
+        SETINT(rp->custom.description->aspect.prefer, params[3]);
+
+        break;
+      case EDJE_STATE_PARAM_COLOR:
+        CHKPARAM(6);
+
+        SETINT(rp->custom.description->color.r, params[3]);
+        SETINT(rp->custom.description->color.g, params[4]);
+        SETINT(rp->custom.description->color.b, params[5]);
+        SETINT(rp->custom.description->color.a, params[6]);
+
+        break;
+      case EDJE_STATE_PARAM_COLOR2:
+        CHKPARAM(6);
+
+        SETINT(rp->custom.description->color2.r, params[3]);
+        SETINT(rp->custom.description->color2.g, params[4]);
+        SETINT(rp->custom.description->color2.b, params[5]);
+        SETINT(rp->custom.description->color2.a, params[6]);
+
+        break;
+      case EDJE_STATE_PARAM_COLOR3:
+        CHKPARAM(6);
+
+        SETINT(rp->custom.description->color3.r, params[3]);
+        SETINT(rp->custom.description->color3.g, params[4]);
+        SETINT(rp->custom.description->color3.b, params[5]);
+        SETINT(rp->custom.description->color3.a, params[6]);
+
+        break;
+      case EDJE_STATE_PARAM_COLOR_CLASS:
+        CHKPARAM(4);
+
+        s = rp->custom.description->color_class;
+        SETSTRALLOCATE(s);
+
+        break;
+      case EDJE_STATE_PARAM_REL1:
+        CHKPARAM(4);
+
+        SETFLOAT(rp->custom.description->rel1.relative_x, params[3]);
+        SETFLOAT(rp->custom.description->rel1.relative_y, params[4]);
+
+        break;
+      case EDJE_STATE_PARAM_REL1_TO:
+        CHKPARAM(4);
+
+        SETINT(rp->custom.description->rel1.id_x, params[3]);
+        SETINT(rp->custom.description->rel1.id_y, params[4]);
+
+        break;
+      case EDJE_STATE_PARAM_REL1_OFFSET:
+        CHKPARAM(4);
+
+        SETINT(rp->custom.description->rel1.offset_x, params[3]);
+        SETINT(rp->custom.description->rel1.offset_y, params[4]);
+
+        break;
+      case EDJE_STATE_PARAM_REL2:
+        CHKPARAM(4);
+
+        SETFLOAT(rp->custom.description->rel2.relative_x, params[3]);
+        SETFLOAT(rp->custom.description->rel2.relative_y, params[4]);
+
+        break;
+      case EDJE_STATE_PARAM_REL2_TO:
+        CHKPARAM(4);
+
+        SETINT(rp->custom.description->rel2.id_x, params[3]);
+        SETINT(rp->custom.description->rel2.id_y, params[4]);
+
+        break;
+      case EDJE_STATE_PARAM_REL2_OFFSET:
+        CHKPARAM(4);
+
+        SETINT(rp->custom.description->rel2.offset_x, params[3]);
+        SETINT(rp->custom.description->rel2.offset_y, params[4]);
+
+        break;
+      case EDJE_STATE_PARAM_IMAGE:
+        if ( (rp->part->type != EDJE_PART_TYPE_IMAGE) ) return 0;
+        CHKPARAM(3);
+
+        SETINT(rp->custom.description->image.id, params[3]);
+
+        break;
+      case EDJE_STATE_PARAM_BORDER:
+        if ( (rp->part->type != EDJE_PART_TYPE_IMAGE) ) return 0;
+        CHKPARAM(6);
+
+        SETINT(rp->custom.description->border.l, params[3]);
+        SETINT(rp->custom.description->border.r, params[4]);
+        SETINT(rp->custom.description->border.t, params[5]);
+        SETINT(rp->custom.description->border.b, params[6]);
+
+        break;
+      case EDJE_STATE_PARAM_FILL_SMOOTH:
+        if ( (rp->part->type != EDJE_PART_TYPE_IMAGE) ) return 0;
+        CHKPARAM(3);
+
+        SETINT(rp->custom.description->fill.smooth, params[3]);
+
+        break;
+      case EDJE_STATE_PARAM_FILL_POS:
+        if ( (rp->part->type != EDJE_PART_TYPE_IMAGE) ) return 0;
+        CHKPARAM(6);
+
+        SETFLOAT(rp->custom.description->fill.pos_rel_x, params[3]);
+        SETFLOAT(rp->custom.description->fill.pos_rel_y, params[4]);
+        SETINT(rp->custom.description->fill.pos_abs_x, params[5]);
+        SETINT(rp->custom.description->fill.pos_abs_y, params[6]);
+
+        break;
+      case EDJE_STATE_PARAM_FILL_SIZE:
+        if ( (rp->part->type != EDJE_PART_TYPE_IMAGE) ) return 0;
+        CHKPARAM(6);
+
+        SETFLOAT(rp->custom.description->fill.rel_x, params[3]);
+        SETFLOAT(rp->custom.description->fill.rel_y, params[4]);
+        SETINT(rp->custom.description->fill.abs_x, params[5]);
+        SETINT(rp->custom.description->fill.abs_y, params[6]);
+
+        break;
+      case EDJE_STATE_PARAM_TEXT:
+        if ( (rp->part->type != EDJE_PART_TYPE_TEXT) && \
+              (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK))
+          return 0;
+        CHKPARAM(4);
+
+        s = rp->custom.description->text.text;
+        SETSTRALLOCATE(s);
+
+        break;
+      case EDJE_STATE_PARAM_TEXT_CLASS:
+        if ( (rp->part->type != EDJE_PART_TYPE_TEXT) && \
+              (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK))
+          return 0;
+        CHKPARAM(4);
+
+        s = rp->custom.description->text.text_class;
+        SETSTRALLOCATE(s);
+
+        break;
+      case EDJE_STATE_PARAM_TEXT_FONT:
+        if ((rp->part->type != EDJE_PART_TYPE_TEXT)) return 0;
+        CHKPARAM(4);
+
+        s = rp->custom.description->text.font;
+        SETSTRALLOCATE(s);
+
+        break;
+      case EDJE_STATE_PARAM_TEXT_STYLE:
+        if ((rp->part->type != EDJE_PART_TYPE_TEXTBLOCK)) return 0;
+        CHKPARAM(4);
+
+        s = rp->custom.description->text.style;
+        SETSTRALLOCATE(s);
+
+        break;
+      case EDJE_STATE_PARAM_TEXT_SIZE:
+        if ((rp->part->type != EDJE_PART_TYPE_TEXT)) return 0;
+        CHKPARAM(3);
+
+        SETINT(rp->custom.description->text.size, params[3]);
+
+        break;
+      case EDJE_STATE_PARAM_TEXT_FIT:
+        if ((rp->part->type != EDJE_PART_TYPE_TEXT)) return 0;
+        CHKPARAM(4);
+
+        SETINT(rp->custom.description->text.fit_x, params[3]);
+        SETINT(rp->custom.description->text.fit_y, params[4]);
+
+        break;
+      case EDJE_STATE_PARAM_TEXT_MIN:
+        if ( (rp->part->type != EDJE_PART_TYPE_TEXT) && \
+              (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK))
+          return 0;
+        CHKPARAM(4);
+
+        SETINT(rp->custom.description->text.min_x, params[3]);
+        SETINT(rp->custom.description->text.min_y, params[4]);
+
+        break;
+      case EDJE_STATE_PARAM_TEXT_MAX:
+        if ( (rp->part->type != EDJE_PART_TYPE_TEXT) && \
+              (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK))
+          return 0;
+        CHKPARAM(4);
+
+        SETINT(rp->custom.description->text.max_x, params[3]);
+        SETINT(rp->custom.description->text.max_y, params[4]);
+
+        break;
+      case EDJE_STATE_PARAM_TEXT_ALIGN:
+        if ((rp->part->type != EDJE_PART_TYPE_TEXT)) return 0;
+        CHKPARAM(4);
+
+        SETFLOAT(rp->custom.description->text.align.x, params[3]);
+        SETFLOAT(rp->custom.description->text.align.y, params[4]);
+
+        break;
+      case EDJE_STATE_PARAM_VISIBLE:
+        CHKPARAM(3);
+
+        SETINT(rp->custom.description->visible, params[3]);
+
+        break;
+      default:
+        break;
+     }
+
+   return 0;
+}
+
+/* part_swallow(part_id, group_name) */
+static Embryo_Cell
+_edje_embryo_fn_part_swallow(Embryo_Program *ep, Embryo_Cell *params)
+{
+   int part_id = 0;
+   char* group_name = 0;
+   Edje *ed;
+   Edje_Real_Part *rp;
+   Evas_Object *new_obj;
+   
+   CHKPARAM(2);
+
+   part_id = params[1];
+   if (part_id < 0) return 0;
+
+   GETSTR(group_name, params[2]);
+   if (!group_name) return 0;
+
+   ed = embryo_program_data_get(ep);
+
+   rp = ed->table_parts[part_id % ed->table_parts_size];
+   if (!rp) return 0;
+
+   new_obj =  edje_object_add(ed->evas);
+   if (!new_obj) return 0;
+
+   if (!edje_object_file_set(new_obj, ed->file->path, group_name)) 
+     {
+        evas_object_del(new_obj);
+        return 0;
+     }
+   edje_object_part_swallow(ed->obj, rp->part->name, new_obj);
+
+   return 0;
+}
+
+void
+_edje_embryo_script_init(Edje *ed)
+{
+   Embryo_Program *ep;
+
+   if (!ed) return;
+   if (!ed->collection) return;
+   if (!ed->collection->script) return;
+   ep = ed->collection->script;
+   embryo_program_data_set(ep, ed);
+   /* first advertise all the edje "script" calls */
+   embryo_program_native_call_add(ep, "get_int", _edje_embryo_fn_get_int);
+   embryo_program_native_call_add(ep, "set_int", _edje_embryo_fn_set_int);
+   embryo_program_native_call_add(ep, "get_float", _edje_embryo_fn_get_float);
+   embryo_program_native_call_add(ep, "set_float", _edje_embryo_fn_set_float);
+   embryo_program_native_call_add(ep, "get_str", _edje_embryo_fn_get_str);
+   embryo_program_native_call_add(ep, "get_strlen", _edje_embryo_fn_get_strlen);
+   embryo_program_native_call_add(ep, "set_str", _edje_embryo_fn_set_str);
+   embryo_program_native_call_add(ep, "count", _edje_embryo_fn_count);
+   embryo_program_native_call_add(ep, "remove", _edje_embryo_fn_remove);
+   embryo_program_native_call_add(ep, "append_int", _edje_embryo_fn_append_int);
+   embryo_program_native_call_add(ep, "prepend_int", _edje_embryo_fn_prepend_int);
+   embryo_program_native_call_add(ep, "insert_int", _edje_embryo_fn_insert_int);
+   embryo_program_native_call_add(ep, "replace_int", _edje_embryo_fn_replace_int);
+   embryo_program_native_call_add(ep, "fetch_int", _edje_embryo_fn_fetch_int);
+   embryo_program_native_call_add(ep, "append_str", _edje_embryo_fn_append_str);
+   embryo_program_native_call_add(ep, "prepend_str", _edje_embryo_fn_prepend_str);
+   embryo_program_native_call_add(ep, "insert_str", _edje_embryo_fn_insert_str);
+   embryo_program_native_call_add(ep, "replace_str", _edje_embryo_fn_replace_str);
+   embryo_program_native_call_add(ep, "fetch_str", _edje_embryo_fn_fetch_str);
+   embryo_program_native_call_add(ep, "append_float", _edje_embryo_fn_append_float);
+   embryo_program_native_call_add(ep, "prepend_float", _edje_embryo_fn_prepend_float);
+   embryo_program_native_call_add(ep, "insert_float", _edje_embryo_fn_insert_float);
+   embryo_program_native_call_add(ep, "replace_float", _edje_embryo_fn_replace_float);
+   embryo_program_native_call_add(ep, "fetch_float", _edje_embryo_fn_fetch_float);
+
+   embryo_program_native_call_add(ep, "timer", _edje_embryo_fn_timer);
+   embryo_program_native_call_add(ep, "cancel_timer", _edje_embryo_fn_cancel_timer);
+
+   embryo_program_native_call_add(ep, "anim", _edje_embryo_fn_anim);
+   embryo_program_native_call_add(ep, "cancel_anim", _edje_embryo_fn_cancel_anim);
+
+   embryo_program_native_call_add(ep, "emit", _edje_embryo_fn_emit);
+   embryo_program_native_call_add(ep, "set_state", _edje_embryo_fn_set_state);
+   embryo_program_native_call_add(ep, "get_state", _edje_embryo_fn_get_state);
+   embryo_program_native_call_add(ep, "set_tween_state", _edje_embryo_fn_set_tween_state);
+   embryo_program_native_call_add(ep, "run_program", _edje_embryo_fn_run_program);
+   embryo_program_native_call_add(ep, "get_drag_dir", _edje_embryo_fn_get_drag_dir);
+   embryo_program_native_call_add(ep, "get_drag", _edje_embryo_fn_get_drag);
+   embryo_program_native_call_add(ep, "set_drag", _edje_embryo_fn_set_drag);
+   embryo_program_native_call_add(ep, "get_drag_size", _edje_embryo_fn_get_drag_size);
+   embryo_program_native_call_add(ep, "set_drag_size", _edje_embryo_fn_set_drag_size);
+   embryo_program_native_call_add(ep, "set_text", _edje_embryo_fn_set_text);
+   embryo_program_native_call_add(ep, "get_text", _edje_embryo_fn_get_text);
+   embryo_program_native_call_add(ep, "get_min_size", _edje_embryo_fn_get_min_size);
+   embryo_program_native_call_add(ep, "get_max_size", _edje_embryo_fn_get_max_size);
+   embryo_program_native_call_add(ep, "get_color_class", _edje_embryo_fn_get_color_class);
+   embryo_program_native_call_add(ep, "set_color_class", _edje_embryo_fn_set_color_class);
+   embryo_program_native_call_add(ep, "set_text_class", _edje_embryo_fn_set_text_class);
+   embryo_program_native_call_add(ep, "get_text_class", _edje_embryo_fn_get_text_class);
+   embryo_program_native_call_add(ep, "get_drag_step", _edje_embryo_fn_get_drag_step);
+   embryo_program_native_call_add(ep, "set_drag_step", _edje_embryo_fn_set_drag_step);
+   embryo_program_native_call_add(ep, "get_drag_page", _edje_embryo_fn_get_drag_page);
+   embryo_program_native_call_add(ep, "set_drag_page", _edje_embryo_fn_set_drag_page);
+   embryo_program_native_call_add(ep, "get_mouse", _edje_embryo_fn_get_mouse);
+   embryo_program_native_call_add(ep, "get_mouse_buttons", _edje_embryo_fn_get_mouse_buttons);
+   embryo_program_native_call_add(ep, "stop_program", _edje_embryo_fn_stop_program);
+   embryo_program_native_call_add(ep, "stop_programs_on", _edje_embryo_fn_stop_programs_on);
+   embryo_program_native_call_add(ep, "set_min_size", _edje_embryo_fn_set_min_size);
+   embryo_program_native_call_add(ep, "set_max_size", _edje_embryo_fn_set_max_size);
+
+   embryo_program_native_call_add(ep, "send_message", _edje_embryo_fn_send_message);
+   embryo_program_native_call_add(ep, "get_geometry", _edje_embryo_fn_get_geometry);
+   embryo_program_native_call_add(ep, "custom_state", _edje_embryo_fn_custom_state);
+   embryo_program_native_call_add(ep, "set_state_val", _edje_embryo_fn_set_state_val);
+   embryo_program_native_call_add(ep, "get_state_val", _edje_embryo_fn_get_state_val);
+
+   embryo_program_native_call_add(ep, "part_swallow", _edje_embryo_fn_part_swallow);
+
+//   embryo_program_vm_push(ed->collection->script);
+//   _edje_embryo_globals_init(ed);
+}
+
+void
+_edje_embryo_script_shutdown(Edje *ed)
+{
+   if (!ed) return;
+   if (!ed->collection) return;
+   if (!ed->collection->script) return;
+   if (embryo_program_recursion_get(ed->collection->script) > 0) return;
+//   embryo_program_vm_pop(ed->collection->script);
+   embryo_program_free(ed->collection->script);
+   ed->collection->script = NULL;
+}
+
+void
+_edje_embryo_script_reset(Edje *ed)
+{
+   if (!ed) return;
+   if (!ed->collection) return;
+   if (!ed->collection->script) return;
+   if (embryo_program_recursion_get(ed->collection->script) > 0) return;
+   embryo_program_vm_reset(ed->collection->script);
+   _edje_embryo_globals_init(ed);
+}
+
+/* this may change in future - thus "test_run" is its name */
+void
+_edje_embryo_test_run(Edje *ed, const char *fname, const char *sig, const char *src)
+{
+   Embryo_Function fn;
+
+   if (!ed) return;
+   if (!ed->collection) return;
+   if (!ed->collection->script) return;
+   embryo_program_vm_push(ed->collection->script);
+   _edje_embryo_globals_init(ed);
+
+   //   _edje_embryo_script_reset(ed);
+   fn = embryo_program_function_find(ed->collection->script, (char *)fname);
+   if (fn != EMBRYO_FUNCTION_NONE)
+     {
+       void *pdata;
+       int ret;
+
+       embryo_parameter_string_push(ed->collection->script, (char *)sig);
+       embryo_parameter_string_push(ed->collection->script, (char *)src);
+       pdata = embryo_program_data_get(ed->collection->script);
+       embryo_program_data_set(ed->collection->script, ed);
+       /* 5 million instructions is an arbitary number. on my p4-2.6 here */
+       /* IF embryo is ONLY runing embryo stuff and NO native calls thats */
+       /* about 0.016 seconds, and longer on slower cpu's. if a simple */
+       /* embryo script snippet hasn't managed to do its work in 5 MILLION */
+       /* embryo virtual machine instructions - something is wrong, or */
+       /* embryo is simply being mis-used. Embryo is meant to be minimal */
+       /* logic enhancment - not entire applications. this cycle count */
+       /* does NOT include time spent in native function calls, that the */
+       /* script may call to do the REAL work, so in terms of time this */
+       /* will likely end up being much longer than 0.016 seconds - more */
+       /* like 0.03 - 0.05 seconds or even more */
+       embryo_program_max_cycle_run_set(ed->collection->script, 5000000);
+       ret = embryo_program_run(ed->collection->script, fn);
+       if (ret == EMBRYO_PROGRAM_FAIL)
+         {
+            printf("EDJE:        ERROR with embryo script.\n"
+                   "ENTRY POINT: %s\n"
+                   "ERROR:       %s\n",
+                   fname,
+                   embryo_error_string_get(embryo_program_error_get(ed->collection->script)));
+         }
+       else if (ret == EMBRYO_PROGRAM_TOOLONG)
+         {
+            printf("EDJE:        ERROR with embryo script.\n"
+                   "ENTRY POINT: %s\n"
+                   "ERROR:       Script exceeded maximum allowed cycle count of %i\n",
+                   fname,
+                   embryo_program_max_cycle_run_get(ed->collection->script));
+         }
+       embryo_program_data_set(ed->collection->script, pdata);
+     }
+   embryo_program_vm_pop(ed->collection->script);
+}
+
+void
+_edje_embryo_globals_init(Edje *ed)
+{
+   int n, i;
+   Embryo_Program *ep;
+
+   ep = ed->collection->script;
+   n = embryo_program_variable_count_get(ep);
+   for (i = 0; i < n; i++)
+     {
+       Embryo_Cell cell, *cptr;
+
+       cell = embryo_program_variable_get(ep, i);
+       if (cell != EMBRYO_CELL_NONE)
+         {
+            cptr = embryo_data_address_get(ep, cell);
+            if (cptr) *cptr = EDJE_VAR_MAGIC_BASE + i;
+         }
+     }
+}
diff --git a/src/lib/edje_load.c b/src/lib/edje_load.c
new file mode 100644 (file)
index 0000000..aac4c7f
--- /dev/null
@@ -0,0 +1,1035 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#include "edje_private.h"
+
+void _edje_collection_free_part_description_free(Edje_Part_Description *desc, unsigned int free_strings);
+static Evas_Bool _edje_file_collection_hash_foreach(const Evas_Hash *hash, const char *key, void *data, void *fdata);
+#ifdef EDJE_PROGRAM_CACHE
+static int  _edje_collection_free_prog_cache_matches_free_cb(Evas_Hash *hash, const char *key, void *data, void *fdata);
+#endif
+static int _edje_object_file_set_internal(Evas_Object *obj, const char *file, const char *group, Evas_List *group_path);
+static void _cb_signal_repeat(void *data, Evas_Object *obj, const char *signal, const char *source);
+
+static Evas_List *_edje_swallows_collect(Edje *ed);
+
+/************************** API Routines **************************/
+
+/* FIXDOC: Verify/expand doc */
+/** Sets the EET file and group to load @a obj from
+ * @param obj A valid Evas_Object handle
+ * @param file The path to the EET file
+ * @param group The group name in the Edje
+ * @return 0 on Error\n
+ * 1 on Success and sets EDJE_LOAD_ERROR_NONE
+ *
+ * Edje uses EET files, conventionally ending in .edj, to store object
+ * descriptions. A single file contains multiple named groups. This function
+ * specifies the file and group name to load @a obj from.
+ */
+EAPI int
+edje_object_file_set(Evas_Object *obj, const char *file, const char *group)
+{
+   return _edje_object_file_set_internal(obj, file, group, NULL);
+}
+
+/* FIXDOC: Verify/expand doc. */
+/** Get the file and group name that @a obj was loaded from
+ * @param obj A valid Evas_Object handle
+ * @param file A pointer to store a pointer to the filename in
+ * @param group A pointer to store a pointer to the group name in
+ *
+ * This gets the EET file location and group for the given Evas_Object.
+ * If @a obj is either not an edje file, or has not had its file/group set
+ * using edje_object_file_set(), then both @a file and @a group will be set
+ * to NULL.
+ *
+ * It is valid to pass in NULL for either @a file or @a group if you are not
+ * interested in one of the values.
+ */
+EAPI void
+edje_object_file_get(const Evas_Object *obj, const char **file, const char **group)
+{
+   Edje *ed;
+
+   ed = _edje_fetch(obj);
+   if (!ed)
+     {
+       if (file) *file = NULL;
+       if (group) *group = NULL;
+       return;
+     }
+   if (file) *file = ed->path;
+   if (group) *group = ed->group;
+}
+
+/* FIXDOC: Verify. return error? */
+/** Gets the Edje load error
+ * @param obj A valid Evas_Object handle
+ *
+ * @return The Edje load error:\n
+ * 0: No Error\n
+ * 1: Generic Error\n
+ * 2: Does not Exist\n
+ * 3: Permission Denied\n
+ * 4: Resource Allocation Failed\n
+ * 5: Corrupt File\n
+ * 6: Unknown Format\n
+ * 7: Incompatible File
+ */
+EAPI int
+edje_object_load_error_get(const Evas_Object *obj)
+{
+   Edje *ed;
+
+   ed = _edje_fetch(obj);
+   if (!ed) return EDJE_LOAD_ERROR_NONE;
+   return ed->load_error;
+}
+
+/** Get a list of groups in an edje file
+ * @param file The path to the edje file
+ *
+ * @return The Evas_List of group names (char *)
+ *
+ * Note: the list must be freed using edje_file_collection_list_free()
+ * when you are done with it.
+ */
+EAPI Evas_List *
+edje_file_collection_list(const char *file)
+{
+   Evas_List *lst = NULL;
+   Edje_File *edf;
+   int error_ret = 0;
+
+   if ((!file) || (!*file)) return NULL;
+   edf = _edje_cache_file_coll_open(file, NULL, &error_ret, NULL);
+   if (edf != NULL)
+     {
+       if (edf->collection_dir)
+         {
+            Evas_List *l;
+
+            for (l = edf->collection_dir->entries; l; l = l->next)
+              {
+                 Edje_Part_Collection_Directory_Entry *ce;
+
+                 ce = l->data;
+                 lst = evas_list_append(lst, evas_stringshare_add(ce->entry));
+              }
+         }
+       _edje_cache_file_unref(edf);
+     }
+   return lst;
+}
+
+/** Free file collection list
+ * @param lst The Evas_List of groups
+ *
+ * Frees the list returned by edje_file_collection_list().
+ */
+EAPI void
+edje_file_collection_list_free(Evas_List *lst)
+{
+   while (lst)
+     {
+       if (lst->data) evas_stringshare_del(lst->data);
+       lst = evas_list_remove(lst, lst->data);
+     }
+}
+
+/** Determine whether a group matching glob exists in an edje file.
+ * @param file The file path
+ * @param glob A glob to match on
+ *
+ * @return 1 if a match is found, 0 otherwise
+ */
+EAPI int
+edje_file_group_exists(const char *file, const char *glob)
+{
+   Edje_File *edf;
+   int error_ret = 0;
+
+   if ((!file) || (!*file)) return 0;
+   edf = _edje_cache_file_coll_open(file, NULL, &error_ret, NULL);
+   if (edf != NULL)
+     {
+       if (edf->collection_dir)
+         {
+             Edje_Patterns *patterns;
+
+             patterns =
+               edje_match_collection_dir_init(edf->collection_dir->entries);
+             if (edje_match_collection_dir_exec(patterns, glob))
+               {
+                  edje_match_patterns_free(patterns);
+                  return 1;
+               }
+             edje_match_patterns_free(patterns);
+         }
+       _edje_cache_file_unref(edf);
+     }
+   return 0;
+}
+
+
+/** Get data from the file level data block of an edje file
+ * @param file The path to the .edj file
+ * @param key The data key
+ * @return The string value of the data
+ *
+ * If an edje file is built from the following edc:
+ *
+ * data {
+ *   item: "key1" "value1";
+ *   item: "key2" "value2";
+ * }
+ * collections { ... }
+ *
+ * Then, edje_file_data_get("key1") will return "value1"
+ */
+EAPI char *
+edje_file_data_get(const char *file, const char *key)
+{
+   Edje_File *edf;
+   char *str = NULL;
+   int error_ret = 0;
+
+   if (key)
+     {
+       edf = _edje_cache_file_coll_open(file, NULL, &error_ret, NULL);
+       if ((edf != NULL) && (edf->data_cache != NULL))
+         {
+            str = evas_hash_find(edf->data_cache, key);
+            if (str) str = strdup(str);
+            _edje_cache_file_unref(edf);
+         }
+     }
+   return str;
+}
+
+static void
+_edje_programs_patterns_clean(Edje *ed)
+{
+   _edje_signals_sources_patterns_clean(&ed->patterns.programs);
+}
+
+static void
+_edje_programs_patterns_init(Edje *ed)
+{
+   Edje_Signals_Sources_Patterns *ssp = &ed->patterns.programs;
+   Evas_List *programs = ed->collection->programs;
+
+   if (ssp->signals_patterns)
+     return;
+
+   ssp->signals_patterns = edje_match_programs_signal_init(programs);
+   ssp->sources_patterns = edje_match_programs_source_init(programs);
+}
+
+static int
+_edje_object_file_set_internal(Evas_Object *obj, const char *file, const char *group, Evas_List *group_path)
+{
+   Edje *ed;
+   int n;
+   Evas_List *parts = NULL;
+   Evas_List *old_swallows;
+   int group_path_started = 0;
+
+   ed = _edje_fetch(obj);
+   if (!ed) return 0;
+   if (!file) file = "";
+   if (!group) group = "";
+   if (((ed->path) && (!strcmp(file, ed->path))) &&
+       (ed->group) && (!strcmp(group, ed->group)))
+     return 1;
+
+   old_swallows = _edje_swallows_collect(ed);
+
+   if (_edje_script_only(ed)) _edje_script_only_shutdown(ed);
+   _edje_file_del(ed);
+
+   if (ed->path) evas_stringshare_del(ed->path);
+   if (ed->group) evas_stringshare_del(ed->group);
+   ed->path = evas_stringshare_add(file);
+   ed->group = evas_stringshare_add(group);
+
+   ed->load_error = EDJE_LOAD_ERROR_NONE;
+  _edje_file_add(ed);
+
+   _edje_textblock_styles_add(ed);
+   _edje_textblock_style_all_update(ed);
+
+   if (ed->collection)
+     {
+       if (ed->collection->script_only)
+         {
+            ed->load_error = EDJE_LOAD_ERROR_NONE;
+            _edje_script_only_init(ed);
+         }
+       else
+         {
+            Evas_List *l;
+            int i;
+            int errors = 0;
+
+            /* colorclass stuff */
+            for (l = ed->collection->parts; (l && ! errors); l = l->next)
+              {
+                 Edje_Part *ep;
+                 Evas_List *hist = NULL;
+                 
+                 /* Register any color classes in this parts descriptions. */
+                 ep = l->data;
+                 if ((ep->default_desc) && (ep->default_desc->color_class))
+                   _edje_color_class_member_add(ed, ep->default_desc->color_class);
+                 for (hist = ep->other_desc; hist; hist = hist->next)
+                   {
+                      Edje_Part_Description *desc;
+                      
+                      desc = hist->data;
+                      if (desc->color_class)
+                        _edje_color_class_member_add(ed, desc->color_class);
+                   }
+              }
+            /* build real parts */
+            for (n = 0, l = ed->collection->parts; l; l = l->next, n++)
+              {
+                 Edje_Part *ep;
+                 Edje_Real_Part *rp;
+                 
+                 ep = l->data;
+                 rp = calloc(1, sizeof(Edje_Real_Part));
+                 if (!rp)
+                   {
+                      ed->load_error = EDJE_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
+                      return 0;
+                   }
+                 rp->edje = ed;
+                 _edje_ref(rp->edje);
+                 rp->part = ep;
+                 parts = evas_list_append(parts, rp);
+                 rp->param1.description = ep->default_desc;
+                 rp->chosen_description = rp->param1.description;
+                 if (!rp->param1.description)
+                   printf("EDJE ERROR: no default part description!\n");
+                 if (ep->type == EDJE_PART_TYPE_RECTANGLE)
+                   rp->object = evas_object_rectangle_add(ed->evas);
+                 else if (ep->type == EDJE_PART_TYPE_IMAGE)
+                   rp->object = evas_object_image_add(ed->evas);
+                 else if (ep->type == EDJE_PART_TYPE_TEXT)
+                   {
+                      _edje_text_part_on_add(ed, rp);
+                      rp->object = evas_object_text_add(ed->evas);
+                      evas_object_text_font_source_set(rp->object, ed->path);
+                   }
+                 else if (ep->type == EDJE_PART_TYPE_SWALLOW || ep->type == EDJE_PART_TYPE_GROUP)
+                   {
+                      rp->object = evas_object_rectangle_add(ed->evas);
+                      evas_object_color_set(rp->object, 0, 0, 0, 0);
+                      evas_object_pass_events_set(rp->object, 1);
+                      evas_object_pointer_mode_set(rp->object, EVAS_OBJECT_POINTER_MODE_NOGRAB);
+                   }
+                 else if (ep->type == EDJE_PART_TYPE_TEXTBLOCK)
+                   rp->object = evas_object_textblock_add(ed->evas);
+                 else if (ep->type == EDJE_PART_TYPE_GRADIENT)
+                   rp->object = evas_object_gradient_add(ed->evas);
+                 else
+                   printf("EDJE ERROR: wrong part type %i!\n", ep->type);
+                 if (rp->object)
+                   {
+                      evas_object_smart_member_add(rp->object, ed->obj);
+//                    evas_object_layer_set(rp->object, evas_object_layer_get(ed->obj));
+                      if (ep->type != EDJE_PART_TYPE_SWALLOW && ep->type != EDJE_PART_TYPE_GROUP)
+                        {
+                           if (ep->mouse_events)
+                             {
+                                _edje_callbacks_add(rp->object, ed, rp);
+                                if (ep->repeat_events)
+                                  evas_object_repeat_events_set(rp->object, 1);
+                                
+                                if (ep->pointer_mode != EVAS_OBJECT_POINTER_MODE_AUTOGRAB)
+                                  evas_object_pointer_mode_set(rp->object, ep->pointer_mode);
+                             }
+                           else
+                             {
+                                evas_object_pass_events_set(rp->object, 1);
+                                evas_object_pointer_mode_set(rp->object, EVAS_OBJECT_POINTER_MODE_NOGRAB);
+                             }
+                           if (ep->precise_is_inside)
+                             evas_object_precise_is_inside_set(rp->object, 1);
+                        }
+                      if (rp->part->clip_to_id < 0)
+                        evas_object_clip_set(rp->object, ed->clipper);
+                   }
+                 rp->drag.step.x = ep->dragable.step_x;
+                 rp->drag.step.y = ep->dragable.step_y;
+                 rp->gradient_id = -1;
+              }
+            if (n > 0)
+              {
+                 Edje_Real_Part *rp;
+                 ed->table_parts = malloc(sizeof(Edje_Real_Part *) * n);
+                 ed->table_parts_size = n;
+                 /* FIXME: check malloc return */
+                 n = 0;
+                 for (l = parts; l; l = l->next)
+                   {
+                      rp = l->data;
+                      ed->table_parts[n] = rp;
+                      n++;
+                   }
+                 evas_list_free(parts);
+                 for (i = 0; i < ed->table_parts_size; i++)
+                   {
+                      rp = ed->table_parts[i];
+                      if (rp->param1.description->rel1.id_x >= 0)
+                        rp->param1.rel1_to_x = ed->table_parts[rp->param1.description->rel1.id_x % ed->table_parts_size];
+                      if (rp->param1.description->rel1.id_y >= 0)
+                        rp->param1.rel1_to_y = ed->table_parts[rp->param1.description->rel1.id_y % ed->table_parts_size];
+                      if (rp->param1.description->rel2.id_x >= 0)
+                        rp->param1.rel2_to_x = ed->table_parts[rp->param1.description->rel2.id_x % ed->table_parts_size];
+                      if (rp->param1.description->rel2.id_y >= 0)
+                        rp->param1.rel2_to_y = ed->table_parts[rp->param1.description->rel2.id_y % ed->table_parts_size];
+                      _edje_text_part_on_add_clippers(ed, rp);
+                      if (rp->part->clip_to_id >= 0)
+                        {
+                           rp->clip_to = ed->table_parts[rp->part->clip_to_id % ed->table_parts_size];
+                           if (rp->clip_to)
+                             {
+                                evas_object_pass_events_set(rp->clip_to->object, 1);
+                                evas_object_pointer_mode_set(rp->clip_to->object, EVAS_OBJECT_POINTER_MODE_NOGRAB);
+                                evas_object_clip_set(rp->object, rp->clip_to->object);
+                             }
+                        }
+                      if (rp->part->dragable.confine_id >= 0)
+                        rp->confine_to = ed->table_parts[rp->part->dragable.confine_id % ed->table_parts_size];
+                      
+                      /* replay events for dragable */
+                      if (rp->part->dragable.events_id >= 0)
+                        {
+                           rp->events_to =
+                             ed->table_parts[rp->part->dragable.events_id % ed->table_parts_size];
+                           /* events_to may be used only with dragable */
+                           if (!rp->events_to->part->dragable.x &&
+                               !rp->events_to->part->dragable.y)
+                             rp->events_to = NULL;
+                        }
+                      
+                      rp->swallow_params.min.w = 0;
+                      rp->swallow_params.min.w = 0;
+                      rp->swallow_params.max.w = -1;
+                      rp->swallow_params.max.h = -1;
+                      
+                      if (ed->file->feature_ver < 1)
+                        {
+                           rp->param1.description->text.id_source = -1;
+                           rp->param1.description->text.id_text_source = -1;
+                        }
+                      if (rp->param1.description->text.id_source >= 0)
+                        rp->text.source = ed->table_parts[rp->param1.description->text.id_source % ed->table_parts_size];
+                      if (rp->param1.description->text.id_text_source >= 0)
+                        rp->text.text_source = ed->table_parts[rp->param1.description->text.id_text_source % ed->table_parts_size];
+                   }
+              }
+            
+            _edje_programs_patterns_init(ed);
+            
+            n = evas_list_count(ed->collection->programs);
+            if (n > 0)
+              {
+                 /* FIXME: keeping a table AND a list is just bad - nuke list */
+                 ed->table_programs = malloc(sizeof(Edje_Program *) * n);
+                 ed->table_programs_size = n;
+                 /* FIXME: check malloc return */
+                 n = 0;
+                 for (l = ed->collection->programs; l; l = l->next)
+                   {
+                      Edje_Program *pr;
+                      
+                      pr = l->data;
+                      ed->table_programs[n] = pr;
+                      n++;
+                   }
+              }
+            _edje_ref(ed);
+            _edje_block(ed);
+            _edje_freeze(ed);
+            if (ed->collection->script) _edje_embryo_script_init(ed);
+            _edje_var_init(ed);
+            for (i = 0; i < ed->table_parts_size; i++)
+              {
+                 Edje_Real_Part *rp;
+                 
+                 rp = ed->table_parts[i];
+                 evas_object_show(rp->object);
+                 if (_edje_block_break(ed)) break;
+                 if (rp->part->dragable.x < 0) rp->drag.val.x = 1.0;
+                 if (rp->part->dragable.y < 0) rp->drag.val.x = 1.0;
+                 _edje_dragable_pos_set(ed, rp, rp->drag.val.x, rp->drag.val.y);
+              }
+            ed->dirty = 1;
+            if ((evas_object_clipees_get(ed->clipper)) &&
+                (evas_object_visible_get(obj)))
+              evas_object_show(ed->clipper);
+            
+            /* instantiate 'internal swallows' */
+            for (i = 0; i < ed->table_parts_size; i++)
+              {
+                 Edje_Real_Part *rp;
+                 
+                 rp = ed->table_parts[i];
+                 if (rp->part->type != EDJE_PART_TYPE_GROUP) continue;
+                 if (rp->part->source)
+                   {
+                      Evas_List *l;
+                      Evas_Object *child_obj;
+                      Edje *child_ed;
+                      const char *group_path_entry = evas_stringshare_add(rp->part->source);
+                      if (!group_path)
+                        {
+                           group_path = evas_list_append(NULL, evas_stringshare_add(group));
+                           group_path_started = 1;
+                        }
+                      /* make sure that this group isn't already in the tree of parents */
+                      for (l = group_path; l; l = l->next)
+                        {
+                           if (l->data == group_path_entry)
+                             {
+                                _edje_thaw(ed);
+                                _edje_unblock(ed);
+                                _edje_unref(ed);
+                                _edje_file_del(ed);
+                                evas_stringshare_del(group_path_entry);
+                                if (group_path_started)
+                                  {
+                                     evas_stringshare_del(group_path->data);
+                                     evas_list_free(group_path);
+                                  }
+                                ed->load_error = EDJE_LOAD_ERROR_RECURSIVE_REFERENCE;
+                                return 0;
+                             }
+                        }
+                      
+                      child_obj = edje_object_add(ed->evas);
+                      group_path = evas_list_append(group_path, group_path_entry);
+                      if (!_edje_object_file_set_internal(child_obj, file, rp->part->source, group_path))
+                        {
+                           _edje_thaw(ed);
+                           _edje_unblock(ed);
+                           _edje_unref(ed);
+                           _edje_file_del(ed);
+                           
+                           if (group_path_started)
+                             {
+                                while (group_path)
+                                  {
+                                     evas_stringshare_del(group_path->data);
+                                     group_path = evas_list_remove_list(group_path, group_path);
+                                  }
+                             }
+                           ed->load_error = edje_object_load_error_get(child_obj);
+                           return 0;
+                        }
+                      child_ed = _edje_fetch(child_obj);
+                      child_ed->parent = evas_stringshare_add(rp->part->name);
+                      
+                      group_path = evas_list_remove(group_path, group_path_entry);
+                      evas_stringshare_del(group_path_entry);
+                      
+                      edje_object_signal_callback_add(child_obj, "*", "*", _cb_signal_repeat, obj);
+                      _edje_real_part_swallow(rp, child_obj);
+                   }
+              }
+            
+            if (group_path_started)
+              {
+                 while (group_path)
+                   {
+                      evas_stringshare_del(group_path->data);
+                      group_path = evas_list_remove_list(group_path, group_path);
+                   }
+              }
+            
+            /* reswallow any swallows that existed before setting the file */
+            if (old_swallows)
+              {
+                 while (old_swallows)
+                   {
+                      const char *name;
+                      Evas_Object *swallow;
+                      
+                      name = old_swallows->data;
+                      old_swallows = evas_list_remove_list(old_swallows, old_swallows);
+                      
+                      swallow = old_swallows->data;
+                      old_swallows = evas_list_remove_list(old_swallows, old_swallows);
+                      
+                      edje_object_part_swallow(obj, name, swallow);
+                      evas_stringshare_del(name);
+                   }
+              }
+            
+            _edje_recalc(ed);
+            _edje_thaw(ed);
+            _edje_unblock(ed);
+            _edje_unref(ed);
+            ed->load_error = EDJE_LOAD_ERROR_NONE;
+            _edje_emit(ed, "load", NULL);
+         }
+       return 1;
+     }
+   else
+     return 0;
+   ed->load_error = EDJE_LOAD_ERROR_NONE;
+   return 1;
+}
+
+void
+_edje_file_add(Edje *ed)
+{
+   if (_edje_edd_edje_file == NULL) return;
+   ed->file = _edje_cache_file_coll_open(ed->path, ed->group,
+                                        &(ed->load_error),
+                                        &(ed->collection));
+
+   if (!ed->collection)
+     {
+       if (ed->file)
+         {
+            _edje_cache_file_unref(ed->file);
+            ed->file = NULL;
+         }
+     }
+}
+
+static Evas_List *
+_edje_swallows_collect(Edje *ed)
+{
+   Evas_List *swallows = NULL;
+   int i;
+
+   if (!ed->file || !ed->table_parts) return NULL;
+   for (i = 0; i < ed->table_parts_size; i++)
+     {
+       Edje_Real_Part *rp;
+
+       rp = ed->table_parts[i];
+       if (rp->part->type != EDJE_PART_TYPE_SWALLOW || !rp->swallowed_object) continue;
+       swallows = evas_list_append(swallows, evas_stringshare_add(rp->part->name));
+       swallows = evas_list_append(swallows, rp->swallowed_object);
+     }
+   return swallows;
+}
+
+void
+_edje_file_del(Edje *ed)
+{
+   _edje_message_del(ed);
+   _edje_block_violate(ed);
+   _edje_var_shutdown(ed);
+   _edje_programs_patterns_clean(ed);
+
+   if (!((ed->file) && (ed->collection))) return;
+   if ((ed->file) && (ed->collection))
+     {
+       Evas_List *l;
+
+       _edje_textblock_styles_del(ed);
+       for (l = ed->collection->parts; l; l = l->next)
+         {
+            Edje_Part *ep;
+
+            ep = l->data;
+            _edje_text_part_on_del(ed, ep);
+            _edje_color_class_on_del(ed, ep);
+         }
+       _edje_cache_coll_unref(ed->file, ed->collection);
+       ed->collection = NULL;
+     }
+   if (ed->table_parts)
+     {
+       int i;
+       for (i = 0; i < ed->table_parts_size; i++)
+         {
+            Edje_Real_Part *rp;
+
+            rp = ed->table_parts[i];
+            if (rp->object)
+              {
+                 _edje_text_real_part_on_del(ed, rp);
+                 _edje_callbacks_del(rp->object);
+                 evas_object_del(rp->object);
+              }
+            if (rp->swallowed_object)
+              {
+                 evas_object_smart_member_del(rp->swallowed_object);
+                 evas_object_event_callback_del(rp->swallowed_object,
+                                                EVAS_CALLBACK_FREE,
+                                                _edje_object_part_swallow_free_cb);
+                 evas_object_clip_unset(rp->swallowed_object);
+                 evas_object_data_del(rp->swallowed_object, "\377 edje.swallowing_part");
+                 if (rp->part->mouse_events)
+                    _edje_callbacks_del(rp->swallowed_object);
+
+                  /* Objects swallowed by the app do not get deleted,
+                   but those internally swallowed (GROUP type) do. */
+                 if (rp->part->type == EDJE_PART_TYPE_GROUP)
+                   evas_object_del(rp->swallowed_object);
+
+                 rp->swallowed_object = NULL;
+              }
+            if (rp->text.text) evas_stringshare_del(rp->text.text);
+            if (rp->text.font) evas_stringshare_del(rp->text.font);
+            if (rp->text.cache.in_str) evas_stringshare_del(rp->text.cache.in_str);
+            if (rp->text.cache.out_str) evas_stringshare_del(rp->text.cache.out_str);
+
+            if (rp->custom.description)
+              _edje_collection_free_part_description_free(rp->custom.description, ed->file->free_strings);
+
+            _edje_unref(rp->edje);
+            free(rp);
+         }
+     }
+   if (ed->file)
+     {
+       _edje_cache_file_unref(ed->file);
+       ed->file = NULL;
+     }
+   if (ed->actions)
+     {
+       while (ed->actions)
+         {
+            Edje_Running_Program *runp;
+
+            _edje_anim_count--;
+            runp = ed->actions->data;
+            ed->actions = evas_list_remove(ed->actions, runp);
+            free(runp);
+         }
+     }
+   _edje_animators = evas_list_remove(_edje_animators, ed);
+   if (ed->pending_actions)
+     {
+       while (ed->pending_actions)
+         {
+            Edje_Pending_Program *pp;
+
+            pp = ed->pending_actions->data;
+            ed->pending_actions = evas_list_remove(ed->pending_actions, pp);
+            ecore_timer_del(pp->timer);
+            free(pp);
+         }
+     }
+   if (ed->table_parts) free(ed->table_parts);
+   ed->table_parts = NULL;
+   ed->table_parts_size = 0;
+   if (ed->table_programs) free(ed->table_programs);
+   ed->table_programs = NULL;
+   ed->table_programs_size = 0;
+}
+/**
+ * Used to free the cached data values that are stored in the data_cache
+ * hash table.
+ */
+static Evas_Bool data_cache_free(const Evas_Hash *hash, const char *key, void *data, void *fdata)
+{
+   Edje_File    *edf;
+
+   edf = fdata;
+   if (edf->free_strings) evas_stringshare_del(data);
+   return 1;
+}
+
+void
+_edje_file_free(Edje_File *edf)
+{
+   if (edf->font_dir)
+     {
+       while (edf->font_dir->entries)
+         {
+            Edje_Font_Directory_Entry *fe;
+
+            fe = edf->font_dir->entries->data;
+            edf->font_dir->entries =
+              evas_list_remove_list(edf->font_dir->entries, edf->font_dir->entries);
+            edf->font_hash = evas_hash_del(edf->font_hash, fe->entry, edf);
+            if (edf->free_strings && fe->path) evas_stringshare_del(fe->path);
+            free(fe);
+         }
+       free(edf->font_dir);
+     }
+   if (edf->image_dir)
+     {
+       while (edf->image_dir->entries)
+         {
+            Edje_Image_Directory_Entry *ie;
+
+            ie = edf->image_dir->entries->data;
+            edf->image_dir->entries =
+              evas_list_remove_list(edf->image_dir->entries, edf->image_dir->entries);
+            if (edf->free_strings && ie->entry) evas_stringshare_del(ie->entry);
+            free(ie);
+         }
+       free(edf->image_dir);
+     }
+   if (edf->collection_dir)
+     {
+       while (edf->collection_dir->entries)
+         {
+            Edje_Part_Collection_Directory_Entry *ce;
+
+            ce = edf->collection_dir->entries->data;
+            edf->collection_dir->entries =
+              evas_list_remove_list(edf->collection_dir->entries, edf->collection_dir->entries);
+            if (edf->free_strings && ce->entry) evas_stringshare_del(ce->entry);
+            free(ce);
+         }
+       free(edf->collection_dir);
+     }
+   if (edf->spectrum_dir)
+     {
+       while (edf->spectrum_dir->entries)
+         {
+            Edje_Spectrum_Directory_Entry *se;
+
+            se = edf->spectrum_dir->entries->data;
+            edf->spectrum_dir->entries =
+              evas_list_remove_list(edf->spectrum_dir->entries, edf->spectrum_dir->entries);
+            while (se->color_list)
+              {
+                 free(se->color_list->data);
+                 se->color_list =
+                    evas_list_remove_list(se->color_list, se->color_list);
+              }
+             if (edf->free_strings)
+               {
+                  if (se->entry) evas_stringshare_del(se->entry);
+                  if (se->filename) evas_stringshare_del(se->filename);
+               }
+            free(se);
+         }
+       free(edf->spectrum_dir);
+     }
+   while (edf->data)
+     {
+       Edje_Data *edt;
+
+       edt = edf->data->data;
+       edf->data = evas_list_remove(edf->data, edt);
+        if (edf->free_strings)
+          {
+             if (edt->key) evas_stringshare_del(edt->key);
+             if (edt->value) evas_stringshare_del(edt->value);
+          }
+       free(edt);
+     }
+   if (edf->data_cache)
+     {
+       evas_hash_foreach(edf->data_cache, data_cache_free, edf);
+       evas_hash_free(edf->data_cache);
+       edf->data_cache = NULL;
+     }
+
+   while (edf->color_classes)
+     {
+       Edje_Color_Class *ecc;
+
+       ecc = edf->color_classes->data;
+       edf->color_classes =
+          evas_list_remove_list(edf->color_classes, edf->color_classes);
+       if (edf->free_strings && ecc->name) evas_stringshare_del(ecc->name);
+       free(ecc);
+     }
+
+   /* FIXME: free collection_hash and collection_cache */
+   if (edf->collection_hash)
+     {
+       printf("EDJE ERROR:\n"
+              "\n"
+              "Naughty Programmer - spank spank!\n"
+              "\n"
+              "This program as probably called edje_shutdown() with active Edje objects\n"
+              "still around.\n This can cause problems as both Evas and Edje retain\n"
+              "references to the objects. you should shut down all canvases and objects\n"
+              "before calling edje_shutdown().\n"
+              "The following errors are the edje object files and parts that are still\n"
+              "hanging around, with their reference counts\n");
+       evas_hash_foreach(edf->collection_hash,
+                          _edje_file_collection_hash_foreach, edf);
+       evas_hash_free(edf->collection_hash);
+     }
+   if (edf->path) evas_stringshare_del(edf->path);
+   if (edf->free_strings && edf->compiler) evas_stringshare_del(edf->compiler);
+   if (edf->collection_cache) _edje_cache_coll_flush(edf);
+   _edje_textblock_style_cleanup(edf);
+   if (edf->ef) eet_close(edf->ef);
+   free(edf);
+}
+
+void
+_edje_collection_free(Edje_File *edf, Edje_Part_Collection *ec)
+{
+   while (ec->programs)
+     {
+       Edje_Program *pr;
+
+       pr = ec->programs->data;
+       ec->programs = evas_list_remove_list(ec->programs, ec->programs);
+        if (edf->free_strings)
+          {
+             if (pr->name) evas_stringshare_del(pr->name);
+             if (pr->signal) evas_stringshare_del(pr->signal);
+             if (pr->source) evas_stringshare_del(pr->source);
+             if (pr->state) evas_stringshare_del(pr->state);
+             if (pr->state2) evas_stringshare_del(pr->state2);
+          }
+       while (pr->targets)
+         {
+            Edje_Program_Target *prt;
+
+            prt = pr->targets->data;
+            pr->targets = evas_list_remove_list(pr->targets, pr->targets);
+            free(prt);
+         }
+       while (pr->after)
+         {
+            Edje_Program_After *pa;
+
+            pa = pr->after->data;
+            pr->after = evas_list_remove_list(pr->after, pr->after);
+            free(pa);
+         }
+       free(pr);
+     }
+   while (ec->parts)
+     {
+       Edje_Part *ep;
+
+       ep = ec->parts->data;
+       ec->parts = evas_list_remove(ec->parts, ep);
+       if (edf->free_strings && ep->name) evas_stringshare_del(ep->name);
+       if (ep->default_desc)
+         {
+            _edje_collection_free_part_description_free(ep->default_desc, edf->free_strings);
+            ep->default_desc = NULL;
+         }
+       while (ep->other_desc)
+         {
+            Edje_Part_Description *desc;
+
+            desc = ep->other_desc->data;
+            ep->other_desc = evas_list_remove(ep->other_desc, desc);
+            _edje_collection_free_part_description_free(desc, edf->free_strings);
+         }
+       free(ep);
+     }
+   if (ec->data)
+     {
+       while (ec->data)
+         {
+            Edje_Data *edt;
+
+            edt = ec->data->data;
+            ec->data = evas_list_remove(ec->data, edt);
+             if (edf->free_strings)
+               {
+                  if (edt->key) evas_stringshare_del(edt->key);
+                  if (edt->value) evas_stringshare_del(edt->value);
+               }
+            free(edt);
+         }
+     }
+   if (edf->free_strings && ec->part) evas_stringshare_del(ec->part);
+#ifdef EDJE_PROGRAM_CACHE
+   if (ec->prog_cache.no_matches) evas_hash_free(ec->prog_cache.no_matches);
+   if (ec->prog_cache.matches)
+     {
+       evas_hash_foreach(ec->prog_cache.matches,
+                         _edje_collection_free_prog_cache_matches_free_cb,
+                         NULL);
+       evas_hash_free(ec->prog_cache.matches);
+     }
+#endif
+   if (ec->script) embryo_program_free(ec->script);
+   free(ec);
+}
+
+void
+_edje_collection_free_part_description_free(Edje_Part_Description *desc, unsigned int free_strings)
+{
+   while (desc->image.tween_list)
+     {
+       Edje_Part_Image_Id *pi;
+
+       pi = desc->image.tween_list->data;
+       desc->image.tween_list = evas_list_remove(desc->image.tween_list, pi);
+       free(pi);
+     }
+   if (free_strings)
+     {
+       if (desc->color_class)     evas_stringshare_del(desc->color_class);
+       if (desc->text.text)       evas_stringshare_del(desc->text.text);
+       if (desc->text.text_class) evas_stringshare_del(desc->text.text_class);
+       if (desc->text.style)      evas_stringshare_del(desc->text.style);
+       if (desc->text.font)       evas_stringshare_del(desc->text.font);
+       if (desc->gradient.type)   evas_stringshare_del(desc->gradient.type);
+       if (desc->gradient.params) evas_stringshare_del(desc->gradient.params);
+     }
+   free(desc);
+}
+
+static Evas_Bool
+_edje_file_collection_hash_foreach(const Evas_Hash *hash, const char *key, void *data, void *fdata)
+{
+   Edje_File *edf;
+   Edje_Part_Collection *coll;
+
+   edf = fdata;
+   coll = data;
+   printf("EEK: EDJE FILE: \"%s\" ref(%i) PART: \"%s\" ref(%i) \n",
+         edf->path, edf->references,
+         coll->part, coll->references);
+   _edje_collection_free(edf, coll);
+
+   return 1;
+}
+
+#ifdef EDJE_PROGRAM_CACHE
+static int
+_edje_collection_free_prog_cache_matches_free_cb(const Evas_Hash *hash, const char *key, void *data, void *fdata)
+{
+   evas_list_free((Evas_List *)data);
+   return 1;
+   hash = NULL;
+   fdata = NULL;
+}
+#endif
+
+static void
+_cb_signal_repeat(void *data, Evas_Object *obj, const char *signal, const char *source)
+{
+   Evas_Object *parent;
+   Edje                *ed;
+   char                 new_src[4096]; /* XXX is this max reasonable? */
+   int          length_parent = 0;
+   int          length_source;
+
+   parent = data;
+   ed = _edje_fetch(obj);
+   if (!ed) return;
+   /* Replace snprint("%s%c%s") == memcpy + *new_src + memcat */
+   if (ed->parent)
+     length_parent = strlen(ed->parent);
+   length_source = strlen(source);
+   if (length_source + length_parent + 2 > sizeof(new_src))
+     return ;
+
+   if (ed->parent)
+     memcpy(new_src, ed->parent, length_parent);
+   new_src[length_parent] = EDJE_PART_PATH_SEPARATOR;
+   memcpy(new_src + length_parent + 1, source, length_source + 1);
+
+   edje_object_signal_emit(parent, signal, new_src);
+}
diff --git a/src/lib/edje_main.c b/src/lib/edje_main.c
new file mode 100644 (file)
index 0000000..a46c7bb
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#include "edje_private.h"
+
+static int initted = 0;
+
+/************************** API Routines **************************/
+
+/** Initialize the EDJE library.
+ *
+ * @return The new init count.
+ */
+EAPI int
+edje_init(void)
+{
+   initted++;
+   if (initted == 1)
+     {
+        ecore_job_init();
+       srand(time(NULL));
+       _edje_edd_setup();
+       _edje_text_init();
+       embryo_init();
+     }
+   _edje_message_init();
+   return initted;
+}
+
+/** Shutdown the EDJE library.
+ *
+ * @return The new init count.
+ */
+EAPI int
+edje_shutdown(void)
+{
+   initted--;
+   if (initted > 0) return initted;
+
+   if (_edje_timer)
+     ecore_animator_del(_edje_timer);
+   _edje_timer = NULL;
+
+   _edje_file_cache_shutdown();
+   _edje_message_shutdown();
+   _edje_edd_free();
+   _edje_color_class_members_free();
+   _edje_color_class_hash_free();
+   _edje_text_class_members_free();
+   _edje_text_class_hash_free();
+   embryo_shutdown();
+   ecore_job_shutdown();
+
+   return 0;
+}
+
+/* Private Routines */
+
+Edje *
+_edje_add(Evas_Object *obj)
+{
+   Edje *ed;
+
+   ed = calloc(1, sizeof(Edje));
+   if (!ed) return NULL;
+   ed->evas = evas_object_evas_get(obj);
+   ed->clipper = evas_object_rectangle_add(ed->evas);
+   evas_object_smart_member_add(ed->clipper, obj);
+   evas_object_color_set(ed->clipper, 255, 255, 255, 255);
+   evas_object_move(ed->clipper, -10000, -10000);
+   evas_object_resize(ed->clipper, 20000, 20000);
+   evas_object_pass_events_set(ed->clipper, 1);
+   ed->have_objects = 1;
+   ed->references = 1;
+   return ed;
+}
+
+void
+_edje_del(Edje *ed)
+{
+   if (ed->processing_messages)
+     {
+       ed->delete_me = 1;
+       return;
+     }
+   _edje_message_del(ed);
+   _edje_callbacks_patterns_clean(ed);
+   _edje_file_del(ed);
+   if (ed->path) evas_stringshare_del(ed->path);
+   if (ed->group) evas_stringshare_del(ed->group);
+   if (ed->parent) evas_stringshare_del(ed->parent);
+   ed->path = NULL;
+   ed->group = NULL;
+   if ((ed->actions) || (ed->pending_actions))
+     {
+       _edje_animators = evas_list_remove(_edje_animators, ed);
+     }
+   while (ed->actions)
+     {
+       Edje_Running_Program *runp;
+
+       runp = ed->actions->data;
+       ed->actions = evas_list_remove(ed->actions, runp);
+       free(runp);
+     }
+   while (ed->pending_actions)
+     {
+       Edje_Pending_Program *pp;
+
+       pp = ed->pending_actions->data;
+       ed->pending_actions = evas_list_remove(ed->pending_actions, pp);
+       free(pp);
+     }
+   while (ed->callbacks)
+     {
+       Edje_Signal_Callback *escb;
+
+       escb = ed->callbacks->data;
+       ed->callbacks = evas_list_remove(ed->callbacks, escb);
+       if (escb->signal) evas_stringshare_del(escb->signal);
+       if (escb->source) evas_stringshare_del(escb->source);
+       free(escb);
+     }
+   while (ed->color_classes)
+     {
+       Edje_Color_Class *cc;
+
+       cc = ed->color_classes->data;
+       ed->color_classes = evas_list_remove(ed->color_classes, cc);
+       if (cc->name) evas_stringshare_del(cc->name);
+       free(cc);
+     }
+   while (ed->text_classes)
+     {
+       Edje_Text_Class *tc;
+
+       tc = ed->text_classes->data;
+       ed->text_classes = evas_list_remove(ed->text_classes, tc);
+       if (tc->name) evas_stringshare_del(tc->name);
+       if (tc->font) evas_stringshare_del(tc->font);
+       free(tc);
+     }
+   free(ed);
+}
+
+void
+_edje_clean_objects(Edje *ed)
+{
+   evas_object_del(ed->clipper);
+   ed->evas = NULL;
+   ed->obj = NULL;
+   ed->clipper = NULL;
+}
+
+void
+_edje_ref(Edje *ed)
+{
+   if (ed->references <= 0) return;
+   ed->references++;
+}
+
+void
+_edje_unref(Edje *ed)
+{
+   ed->references--;
+   if (ed->references == 0) _edje_del(ed);
+}
diff --git a/src/lib/edje_match.c b/src/lib/edje_match.c
new file mode 100644 (file)
index 0000000..2fa8dda
--- /dev/null
@@ -0,0 +1,557 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#include "edje_private.h"
+
+/* States manipulations. */
+
+typedef struct _Edje_State      Edje_State;
+struct _Edje_State
+{
+  size_t        idx;
+  size_t        pos;
+};
+
+struct _Edje_States
+{
+  size_t         size;
+  Edje_State    *states;
+  _Bool         *has;
+};
+
+static void
+_edje_match_states_free(Edje_States      *states,
+                        size_t            states_size)
+{
+   (void) states_size;
+   free(states);
+}
+
+#define ALIGN(Size)                             \
+  {                                             \
+     Size--;                                    \
+     Size |= sizeof (void*) - 1;                \
+     Size++;                                    \
+  };
+
+static int
+_edje_match_states_alloc(Edje_Patterns *ppat, int n)
+{
+   Edje_States *l;
+
+   const size_t patterns_size = ppat->patterns_size;
+   const size_t patterns_max_length = ppat->max_length;
+
+   const size_t array_len = (patterns_max_length + 1) * patterns_size;
+
+   size_t       states_size;
+   size_t       has_size;
+   size_t       states_has_size;
+   size_t       struct_size;
+
+   unsigned char        *states;
+   unsigned char        *has;
+
+   size_t        i;
+
+   states_size = sizeof (*l->states) * array_len;
+   ALIGN(states_size);
+
+   has_size = sizeof (*l->has) * array_len;
+   ALIGN(has_size);
+
+   states_has_size = states_size + has_size;
+
+   struct_size = sizeof (*l);
+   ALIGN(struct_size);
+   struct_size += states_has_size;
+
+   l = calloc(1, n * struct_size);
+   if (!l) return 0;
+
+   ppat->states = l;
+   states = (unsigned char *) (l + n);
+   has = states + states_size;
+
+   for (i = 0; i < n; ++i)
+     {
+        l[i].states = (Edje_State *) states;
+        l[i].has = (_Bool *) has;
+        states += states_has_size;
+        has += states_has_size;
+     }
+
+   return 1;
+}
+
+static void
+_edje_match_states_insert(Edje_States    *list,
+                          size_t          patterns_max_length,
+                          size_t          idx,
+                          size_t          pos)
+{
+   size_t i;
+
+   i = (idx * (patterns_max_length + 1)) + pos;
+   
+   if (list->size > i)
+     {
+       if (list->has[i]) return;
+     }
+   list->has[i] = 1;
+   
+   i = list->size;
+   list->states[i].idx = idx;
+   list->states[i].pos = pos;
+   list->has[i] = 0;
+   list->size++;
+}
+
+static void
+_edje_match_states_clear(Edje_States     *list,
+                         size_t           patterns_size,
+                         size_t           patterns_max_length)
+{
+   list->size = 0;
+}
+
+/* Token manipulation. */
+
+enum status
+{
+   patterns_not_found          = 0,
+   patterns_found              = 1,
+   patterns_syntax_error       = 2
+};
+
+static size_t
+_edje_match_patterns_exec_class_token(enum status      *status,
+                                      const char       *cl_tok,
+                                      char              c)
+{
+  if (! *cl_tok)
+    {
+      *status = patterns_syntax_error;
+      return 0;
+    }
+  else if (cl_tok[1] == '-' && cl_tok[2] != ']')
+    {
+      if (*cl_tok <= c && c <= cl_tok[2])
+       *status = patterns_found;
+      return 3;
+    }
+  else
+    {
+      if (c == *cl_tok)
+       *status = patterns_found;
+      return 1;
+    }
+}
+
+static Edje_Match_Error
+_edje_match_patterns_exec_class_complement(const char *cl_tok, size_t *ret)
+{
+  switch (*cl_tok)
+    {
+     case 0:
+        return EDJE_MATCH_SYNTAX_ERROR;
+
+     case '!':
+        *ret = 1;
+        return EDJE_MATCH_OK;
+
+    default:
+       *ret = 0;
+       return EDJE_MATCH_OK;
+    }
+}
+
+static Edje_Match_Error
+_edje_match_patterns_exec_class(const char     *cl,
+                                char            c,
+                                size_t          *ret)
+{
+   enum status status = patterns_not_found;
+   int         pos = 1;
+   size_t       neg;
+
+   if (_edje_match_patterns_exec_class_complement(cl + 1, &neg) != EDJE_MATCH_OK)
+     return EDJE_MATCH_SYNTAX_ERROR;
+
+   pos += neg;
+
+   do
+     pos += _edje_match_patterns_exec_class_token(&status, cl + pos, c);
+   while (cl[pos] && cl[pos] != ']');
+
+   if (status == patterns_syntax_error || ! cl[pos])
+     return EDJE_MATCH_SYNTAX_ERROR;
+
+   if (status == patterns_found)
+     *ret = neg ? 0 : pos + 1;
+   else
+     *ret = neg ? pos + 1 : 0;
+
+   return EDJE_MATCH_OK;
+}
+
+static Edje_Match_Error
+_edje_match_patterns_exec_token(const char     *tok,
+                                char            c,
+                                size_t          *ret)
+{
+  switch (*tok)
+    {
+    case '\\':
+      if (tok[1])
+        {
+           *ret = tok[1] == c ? 2 : 0;
+           return EDJE_MATCH_OK;
+        }
+      return EDJE_MATCH_SYNTAX_ERROR;
+
+    case '?':
+      *ret = 1;
+      return EDJE_MATCH_OK;
+
+    case '[':
+       return _edje_match_patterns_exec_class(tok, c, ret);
+
+    default:
+       *ret = *tok == c ? 1 : 0;
+       return EDJE_MATCH_OK;
+    }
+}
+
+static void
+_edje_match_patterns_exec_init_states(Edje_States       *states,
+                                      size_t            patterns_size,
+                                      size_t             patterns_max_length)
+{
+   size_t       i;
+
+   states->size = patterns_size;
+
+   for (i = 0; i < patterns_size; ++i)
+     {
+        states->states[i].idx = i;
+        states->states[i].pos = 0;
+        states->has[i * (patterns_max_length + 1)] = 1;
+     }
+}
+
+/* Exported function. */
+
+#define EDJE_MATCH_INIT(Func, Type, Source, Show)               \
+  Edje_Patterns*                                                \
+  Func(Evas_List *lst)                                          \
+  {                                                             \
+     Edje_Patterns      *r;                                     \
+     size_t              i;                                     \
+                                                                \
+     if (!lst || evas_list_count(lst) <= 0)                     \
+       return NULL;                                             \
+                                                                \
+     r = malloc(sizeof (Edje_Patterns) +                        \
+                evas_list_count(lst)                            \
+                * sizeof (*r->finals)                           \
+                * sizeof(*r->patterns));                        \
+     if (!r) return NULL;                                       \
+                                                                \
+     r->patterns_size = evas_list_count(lst);                   \
+     r->max_length = 0;                                         \
+     r->patterns = (const char **) r->finals + r->patterns_size + 1;    \
+                                                                \
+     for (i = 0; lst; ++i)                                      \
+       {                                                        \
+          const char    *str;                                   \
+          Type          *data;                                  \
+          size_t         j;                                     \
+                                                                \
+          data = evas_list_data(lst);                           \
+          if (!data)                                            \
+            {                                                   \
+               free(r);                                         \
+               return NULL;                                     \
+            }                                                   \
+                                                                \
+          str = data->Source;                                   \
+          if (!str) str = "";                                   \
+          r->patterns[i] = str;                                 \
+                                                                \
+          if (Show)                                             \
+            fprintf(stderr, "%i [%s]\n", i, str);               \
+                                                                \
+          r->finals[i] = 0;                                     \
+          for (j = 0; str[j]; ++j)                              \
+            if (str[j] != '*')                                  \
+              r->finals[i] = j + 1;                             \
+                                                                \
+          if (j > r->max_length)                                \
+            r->max_length = j;                                  \
+                                                                \
+          lst = evas_list_next(lst);                            \
+       }                                                        \
+                                                                \
+     if (!_edje_match_states_alloc(r, 2))                       \
+       {                                                        \
+          free(r);                                              \
+          return NULL;                                          \
+       }                                                        \
+                                                                \
+     return r;                                                  \
+  }
+
+EDJE_MATCH_INIT(edje_match_collection_dir_init,
+                Edje_Part_Collection_Directory_Entry,
+                entry, 0);
+EDJE_MATCH_INIT(edje_match_programs_signal_init,
+                Edje_Program,
+                signal, 0);
+EDJE_MATCH_INIT(edje_match_programs_source_init,
+                Edje_Program,
+                source, 0);
+EDJE_MATCH_INIT(edje_match_callback_signal_init,
+                Edje_Signal_Callback,
+                signal, 0);
+EDJE_MATCH_INIT(edje_match_callback_source_init,
+                Edje_Signal_Callback,
+                source, 0);
+
+static int
+_edje_match_collection_dir_exec_finals(const size_t      *finals,
+                                       const Edje_States *states)
+{
+   size_t       i;
+
+   for (i = 0; i < states->size; ++i)
+     if (states->states[i].pos >= finals[states->states[i].idx])
+       return 1;
+   return 0;
+}
+
+static int
+edje_match_programs_exec_check_finals(const size_t      *signal_finals,
+                                      const size_t      *source_finals,
+                                      const Edje_States *signal_states,
+                                      const Edje_States *source_states,
+                                      Evas_List         *programs,
+                                      int (*func)(Edje_Program *pr, void *data),
+                                      void              *data)
+{
+   size_t       i;
+   size_t       j;
+
+   for (i = 0; i < signal_states->size; ++i)
+     if (signal_states->states[i].pos >= signal_finals[signal_states->states[i].idx])
+       for (j = 0; j < source_states->size; ++j)
+         if (signal_states->states[i].idx == source_states->states[j].idx
+             && source_states->states[j].pos >= source_finals[source_states->states[j].idx])
+           {
+              Edje_Program  *pr;
+
+              pr = evas_list_nth(programs, signal_states->states[i].idx);
+              if (pr)
+                {
+                   if (func(pr, data))
+                     return 0;
+                }
+       }
+
+   return 1;
+}
+
+static int
+edje_match_callback_exec_check_finals(const size_t      *signal_finals,
+                                      const size_t      *source_finals,
+                                      const Edje_States *signal_states,
+                                      const Edje_States *source_states,
+                                      const char        *signal,
+                                      const char        *source,
+                                      Evas_List         *callbacks,
+                                      Edje              *ed)
+{
+   size_t       i;
+   size_t       j;
+   int          r = 1;
+
+   for (i = 0; i < signal_states->size; ++i)
+     if (signal_states->states[i].pos >= signal_finals[signal_states->states[i].idx])
+       for (j = 0; j < source_states->size; ++j)
+         if (signal_states->states[i].idx == source_states->states[j].idx
+             && source_states->states[j].pos >= source_finals[source_states->states[j].idx])
+           {
+              Edje_Signal_Callback      *escb;
+
+              escb = evas_list_nth(callbacks, signal_states->states[i].idx);
+              if (escb)
+                {
+                   if ((!escb->just_added)
+                       && (!escb->delete_me))
+                     {
+                        escb->func(escb->data, ed->obj, signal, source);
+                        r = 2;
+                     }
+                   if (_edje_block_break(ed))
+                     return 0;
+                }
+       }
+
+   return r;
+}
+
+
+static Edje_States*
+_edje_match_fn(const Edje_Patterns      *ppat,
+               const char               *string,
+               Edje_States              *states)
+{
+   Edje_States  *new_states = states + 1;
+   const char   *c;
+
+   for (c = string; *c && states->size; ++c)
+     {
+        size_t  i;
+
+        _edje_match_states_clear(new_states, ppat->patterns_size, ppat->max_length);
+
+        for (i = 0; i < states->size; ++i)
+          {
+             const size_t       idx = states->states[i].idx;
+             const size_t       pos = states->states[i].pos;
+
+             if (!ppat->patterns[idx][pos])
+               continue;
+             else if (ppat->patterns[idx][pos] == '*')
+               {
+                  _edje_match_states_insert(states, ppat->max_length, idx, pos + 1);
+                  _edje_match_states_insert(new_states, ppat->max_length, idx, pos);
+               }
+             else
+               {
+                  size_t        m;
+
+                  if (_edje_match_patterns_exec_token(ppat->patterns[idx] + pos,
+                                                      *c,
+                                                      &m) != EDJE_MATCH_OK)
+                    return NULL;
+
+                  if (m)
+                    _edje_match_states_insert(new_states, ppat->max_length, idx, pos + m);
+               }
+          }
+        {
+           Edje_States  *tmp = states;
+
+           states = new_states;
+           new_states = tmp;
+        }
+     }
+
+   return states;
+}
+
+int
+edje_match_collection_dir_exec(const Edje_Patterns      *ppat,
+                               const char               *string)
+{
+   Edje_States  *result;
+   int           r = 0;
+
+   _edje_match_patterns_exec_init_states(ppat->states, ppat->patterns_size, ppat->max_length);
+
+   result = _edje_match_fn(ppat, string, ppat->states);
+
+   if (result)
+     r = _edje_match_collection_dir_exec_finals(ppat->finals, result);
+
+   return r;
+}
+
+int
+edje_match_programs_exec(const Edje_Patterns    *ppat_signal,
+                         const Edje_Patterns    *ppat_source,
+                         const char             *signal,
+                         const char             *source,
+                         Evas_List              *programs,
+                         int (*func)(Edje_Program *pr, void *data),
+                         void                   *data)
+{
+   Edje_States  *signal_result;
+   Edje_States  *source_result;
+   int           r = 0;
+
+   _edje_match_patterns_exec_init_states(ppat_signal->states,
+                                         ppat_signal->patterns_size,
+                                         ppat_signal->max_length);
+   _edje_match_patterns_exec_init_states(ppat_source->states,
+                                         ppat_source->patterns_size,
+                                         ppat_source->max_length);
+
+   signal_result = _edje_match_fn(ppat_signal, signal, ppat_signal->states);
+   source_result = _edje_match_fn(ppat_source, source, ppat_source->states);
+
+   if (signal_result && source_result)
+     r = edje_match_programs_exec_check_finals(ppat_signal->finals,
+                                               ppat_source->finals,
+                                               signal_result,
+                                               source_result,
+                                               programs,
+                                               func,
+                                               data);
+   return r;
+}
+
+int
+edje_match_callback_exec(const Edje_Patterns    *ppat_signal,
+                         const Edje_Patterns    *ppat_source,
+                         const char             *signal,
+                         const char             *source,
+                         Evas_List              *callbacks,
+                         Edje                   *ed)
+{
+   Edje_States  *signal_result;
+   Edje_States  *source_result;
+   int           r = 0;
+
+   _edje_match_patterns_exec_init_states(ppat_signal->states,
+                                         ppat_signal->patterns_size,
+                                         ppat_signal->max_length);
+   _edje_match_patterns_exec_init_states(ppat_source->states,
+                                         ppat_source->patterns_size,
+                                         ppat_source->max_length);
+
+   signal_result = _edje_match_fn(ppat_signal, signal, ppat_signal->states);
+   source_result = _edje_match_fn(ppat_source, source, ppat_source->states);
+
+   if (signal_result && source_result)
+     r = edje_match_callback_exec_check_finals(ppat_signal->finals,
+                                               ppat_source->finals,
+                                               signal_result,
+                                               source_result,
+                                               signal,
+                                               source,
+                                               callbacks,
+                                               ed);
+   return r;
+}
+
+void
+edje_match_patterns_free(Edje_Patterns *ppat)
+{
+   _edje_match_states_free(ppat->states, 2);
+   free(ppat);
+}
+
+void
+_edje_signals_sources_patterns_clean(Edje_Signals_Sources_Patterns *ssp)
+{
+   if (!ssp->signals_patterns)
+     return;
+
+   edje_match_patterns_free(ssp->signals_patterns);
+   edje_match_patterns_free(ssp->sources_patterns);
+   ssp->signals_patterns = NULL;
+   ssp->sources_patterns = NULL;
+}
diff --git a/src/lib/edje_message_queue.c b/src/lib/edje_message_queue.c
new file mode 100644 (file)
index 0000000..1be342e
--- /dev/null
@@ -0,0 +1,707 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#include "edje_private.h"
+
+static Ecore_Job *job = NULL;
+static Ecore_Timer *job_loss_timer = NULL;
+
+static Evas_List *msgq = NULL;
+static Evas_List *tmp_msgq = NULL;
+
+EAPI void
+edje_object_message_send(Evas_Object *obj, Edje_Message_Type type, int id, void *msg)
+{
+   Edje *ed;
+   int i;
+
+   ed = _edje_fetch(obj);
+   if (!ed) return;
+   _edje_message_send(ed, EDJE_QUEUE_SCRIPT, type, id, msg);
+
+   for (i = 0; i < ed->table_parts_size; i++)
+     {
+       Edje_Real_Part *rp = ed->table_parts[i];
+       if ((rp->part->type == EDJE_PART_TYPE_GROUP) && (rp->swallowed_object))
+         edje_object_message_send(rp->swallowed_object, type, id, msg);
+     }
+}
+
+EAPI void
+edje_object_message_handler_set(Evas_Object *obj, void (*func) (void *data, Evas_Object *obj, Edje_Message_Type type, int id, void *msg), void *data)
+{
+   Edje *ed;
+
+   ed = _edje_fetch(obj);
+   if (!ed) return;
+   _edje_message_cb_set(ed, func, data);
+}
+
+EAPI void
+edje_object_message_signal_process(Evas_Object *obj)
+{
+   Evas_List *l, *tmpq = NULL;
+   Edje *ed;
+
+   ed = _edje_fetch(obj);
+   if (!ed) return;
+
+   for (l = msgq; l; l = l->next)
+     {
+       Edje_Message *em;
+
+       em = l->data;
+       if (em->edje == ed)
+         tmpq = evas_list_append(tmpq, em);
+     }
+   /* now remove them from the old queue */
+   for (l = tmpq; l; l = l->next)
+     msgq = evas_list_remove(msgq, l->data);
+   /* a temporary message queue */
+   if (tmp_msgq)
+     {
+       while (tmpq)
+         {
+            tmp_msgq = evas_list_append(tmp_msgq, tmpq->data);
+            tmpq = evas_list_remove_list(tmpq, tmpq);
+         }
+     }
+   else
+     {
+       tmp_msgq = tmpq;
+       tmpq = NULL;
+     }
+
+   while (tmp_msgq)
+     {
+       Edje_Message *em;
+
+       em = tmp_msgq->data;
+       tmp_msgq = evas_list_remove_list(tmp_msgq, tmp_msgq);
+       em->edje->message.num--;
+       _edje_message_process(em);
+       _edje_message_free(em);
+     }
+}
+
+EAPI void
+edje_message_signal_process(void)
+{
+   _edje_message_queue_process();
+}
+
+static int
+_edje_dummy_timer(void *data)
+{
+   return 0;
+}
+
+static void
+_edje_job(void *data)
+{
+   if (job_loss_timer)
+     {
+       ecore_timer_del(job_loss_timer);
+       job_loss_timer = NULL;
+     }
+   _edje_message_queue_process();
+   job = NULL;
+}
+
+static int
+_edje_job_loss_timer(void *data)
+{
+   job_loss_timer = NULL;
+   if (job) job = NULL;
+   return 0;
+}
+
+void
+_edje_message_init(void)
+{
+}
+
+void
+_edje_message_shutdown(void)
+{
+   _edje_message_queue_clear();
+   if (job_loss_timer)
+     ecore_timer_del(job_loss_timer);
+   job = NULL;
+   job_loss_timer = NULL;
+}
+
+void
+_edje_message_cb_set(Edje *ed, void (*func) (void *data, Evas_Object *obj, Edje_Message_Type type, int id, void *msg), void *data)
+{
+   ed->message.func = func;
+   ed->message.data = data;
+}
+
+Edje_Message *
+_edje_message_new(Edje *ed, Edje_Queue queue, Edje_Message_Type type, int id)
+{
+   Edje_Message *em;
+
+   em = calloc(1, sizeof(Edje_Message));
+   if (!em) return NULL;
+   em->edje = ed;
+   em->queue = queue;
+   em->type = type;
+   em->id = id;
+   em->edje->message.num++;
+   return em;
+}
+
+void
+_edje_message_free(Edje_Message *em)
+{
+   if (em->msg)
+     {
+       int i;
+
+       switch (em->type)
+         {
+          case EDJE_MESSAGE_STRING:
+              {
+                 Edje_Message_String *emsg;
+
+                 emsg = (Edje_Message_String *)em->msg;
+                 free(emsg->str);
+                 free(emsg);
+              }
+            break;
+          case EDJE_MESSAGE_INT:
+              {
+                 Edje_Message_Int *emsg;
+
+                 emsg = (Edje_Message_Int *)em->msg;
+                 free(emsg);
+              }
+            break;
+          case EDJE_MESSAGE_FLOAT:
+              {
+                 Edje_Message_Float *emsg;
+
+                 emsg = (Edje_Message_Float *)em->msg;
+                 free(emsg);
+              }
+            break;
+          case EDJE_MESSAGE_INT_SET:
+              {
+                 Edje_Message_Int_Set *emsg;
+
+                 emsg = (Edje_Message_Int_Set *)em->msg;
+                 free(emsg);
+              }
+            break;
+          case EDJE_MESSAGE_FLOAT_SET:
+              {
+                 Edje_Message_Float_Set *emsg;
+
+                 emsg = (Edje_Message_Float_Set *)em->msg;
+                 free(emsg);
+              }
+            break;
+          case EDJE_MESSAGE_STRING_FLOAT:
+              {
+                 Edje_Message_String_Float *emsg;
+
+                 emsg = (Edje_Message_String_Float *)em->msg;
+                 free(emsg->str);
+                 free(emsg);
+              }
+            break;
+          case EDJE_MESSAGE_STRING_INT:
+              {
+                 Edje_Message_String_Int *emsg;
+
+                 emsg = (Edje_Message_String_Int *)em->msg;
+                 free(emsg->str);
+                 free(emsg);
+              }
+            break;
+          case EDJE_MESSAGE_STRING_FLOAT_SET:
+              {
+                 Edje_Message_String_Float_Set *emsg;
+
+                 emsg = (Edje_Message_String_Float_Set *)em->msg;
+                 free(emsg->str);
+                 free(emsg);
+              }
+            break;
+          case EDJE_MESSAGE_STRING_INT_SET:
+              {
+                 Edje_Message_String_Int_Set *emsg;
+
+                 emsg = (Edje_Message_String_Int_Set *)em->msg;
+                 free(emsg->str);
+                 free(emsg);
+              }
+            break;
+          case EDJE_MESSAGE_SIGNAL:
+              {
+                 Edje_Message_Signal *emsg;
+
+                 emsg = (Edje_Message_Signal *)em->msg;
+                 if (emsg->sig) evas_stringshare_del(emsg->sig);
+                 if (emsg->src) evas_stringshare_del(emsg->src);
+                 free(emsg);
+              }
+            break;
+          case EDJE_MESSAGE_STRING_SET:
+              {
+                 Edje_Message_String_Set *emsg;
+
+                 emsg = (Edje_Message_String_Set *)em->msg;
+                 for (i = 0; i < emsg->count; i++)
+                   free(emsg->str[i]);
+                 free(emsg);
+              }
+            break;
+          case EDJE_MESSAGE_NONE:
+          default:
+            break;
+         }
+     }
+   free(em);
+}
+
+void
+_edje_message_send(Edje *ed, Edje_Queue queue, Edje_Message_Type type, int id, void *emsg)
+{
+   /* FIXME: check all malloc & strdup fails and gracefully unroll and exit */
+   Edje_Message *em;
+   int i;
+   unsigned char *msg = NULL;
+
+   if (!job)
+     {
+       job = ecore_job_add(_edje_job, NULL);
+       if (job_loss_timer) ecore_timer_del(job_loss_timer);
+       job_loss_timer = ecore_timer_add(0.05, _edje_job_loss_timer, NULL);
+     }
+   em = _edje_message_new(ed, queue, type, id);
+   if (!em) return;
+   switch (em->type)
+     {
+      case EDJE_MESSAGE_NONE:
+       break;
+      case EDJE_MESSAGE_SIGNAL:
+         {
+            Edje_Message_Signal *emsg2, *emsg3;
+
+            emsg2 = (Edje_Message_Signal *)emsg;
+            emsg3 = calloc(1, sizeof(Edje_Message_Signal));
+            if (emsg2->sig) emsg3->sig = evas_stringshare_add(emsg2->sig);
+            if (emsg2->src) emsg3->src = evas_stringshare_add(emsg2->src);
+            msg = (unsigned char *)emsg3;
+         }
+       break;
+      case EDJE_MESSAGE_STRING:
+         {
+            Edje_Message_String *emsg2, *emsg3;
+
+            emsg2 = (Edje_Message_String *)emsg;
+            emsg3 = malloc(sizeof(Edje_Message_String));
+            emsg3->str = strdup(emsg2->str);
+            msg = (unsigned char *)emsg3;
+         }
+       break;
+      case EDJE_MESSAGE_INT:
+         {
+            Edje_Message_Int *emsg2, *emsg3;
+
+            emsg2 = (Edje_Message_Int *)emsg;
+            emsg3 = malloc(sizeof(Edje_Message_Int));
+            emsg3->val = emsg2->val;
+            msg = (unsigned char *)emsg3;
+         }
+       break;
+      case EDJE_MESSAGE_FLOAT:
+         {
+            Edje_Message_Float *emsg2, *emsg3;
+
+            emsg2 = (Edje_Message_Float *)emsg;
+            emsg3 = malloc(sizeof(Edje_Message_Float));
+            emsg3->val = emsg2->val;
+            msg = (unsigned char *)emsg3;
+         }
+       break;
+      case EDJE_MESSAGE_STRING_SET:
+         {
+            Edje_Message_String_Set *emsg2, *emsg3;
+
+            emsg2 = (Edje_Message_String_Set *)emsg;
+            emsg3 = malloc(sizeof(Edje_Message_String_Set) + ((emsg2->count - 1) * sizeof(char *)));
+            emsg3->count = emsg2->count;
+            for (i = 0; i < emsg3->count; i++)
+              emsg3->str[i] = strdup(emsg2->str[i]);
+            msg = (unsigned char *)emsg3;
+         }
+       break;
+      case EDJE_MESSAGE_INT_SET:
+         {
+            Edje_Message_Int_Set *emsg2, *emsg3;
+
+            emsg2 = (Edje_Message_Int_Set *)emsg;
+            emsg3 = malloc(sizeof(Edje_Message_Int_Set) + ((emsg2->count - 1) * sizeof(int)));
+            emsg3->count = emsg2->count;
+            for (i = 0; i < emsg3->count; i++)
+              emsg3->val[i] = emsg2->val[i];
+            msg = (unsigned char *)emsg3;
+         }
+       break;
+      case EDJE_MESSAGE_FLOAT_SET:
+         {
+            Edje_Message_Float_Set *emsg2, *emsg3;
+
+            emsg2 = (Edje_Message_Float_Set *)emsg;
+            emsg3 = malloc(sizeof(Edje_Message_Float_Set) + ((emsg2->count - 1) * sizeof(double)));
+            emsg3->count = emsg2->count;
+            for (i = 0; i < emsg3->count; i++)
+              emsg3->val[i] = emsg2->val[i];
+            msg = (unsigned char *)emsg3;
+         }
+       break;
+      case EDJE_MESSAGE_STRING_INT:
+         {
+            Edje_Message_String_Int *emsg2, *emsg3;
+
+            emsg2 = (Edje_Message_String_Int *)emsg;
+            emsg3 = malloc(sizeof(Edje_Message_String_Int));
+            emsg3->str = strdup(emsg2->str);
+            emsg3->val = emsg2->val;
+            msg = (unsigned char *)emsg3;
+         }
+       break;
+      case EDJE_MESSAGE_STRING_FLOAT:
+         {
+            Edje_Message_String_Float *emsg2, *emsg3;
+
+            emsg2 = (Edje_Message_String_Float *)emsg;
+            emsg3 = malloc(sizeof(Edje_Message_String_Float));
+            emsg3->str = strdup(emsg2->str);
+            emsg3->val = emsg2->val;
+            msg = (unsigned char *)emsg3;
+         }
+       break;
+      case EDJE_MESSAGE_STRING_INT_SET:
+         {
+            Edje_Message_String_Int_Set *emsg2, *emsg3;
+
+            emsg2 = (Edje_Message_String_Int_Set *)emsg;
+            emsg3 = malloc(sizeof(Edje_Message_String_Int_Set) + ((emsg2->count - 1) * sizeof(int)));
+            emsg3->str = strdup(emsg2->str);
+            emsg3->count = emsg2->count;
+            for (i = 0; i < emsg3->count; i++)
+              emsg3->val[i] = emsg2->val[i];
+            msg = (unsigned char *)emsg3;
+         }
+       break;
+      case EDJE_MESSAGE_STRING_FLOAT_SET:
+         {
+            Edje_Message_String_Float_Set *emsg2, *emsg3;
+
+            emsg2 = (Edje_Message_String_Float_Set *)emsg;
+            emsg3 = malloc(sizeof(Edje_Message_String_Float_Set) + ((emsg2->count - 1) * sizeof(double)));
+            emsg3->str = strdup(emsg2->str);
+            emsg3->count = emsg2->count;
+            for (i = 0; i < emsg3->count; i++)
+              emsg3->val[i] = emsg2->val[i];
+            msg = (unsigned char *)emsg3;
+         }
+       break;
+      default:
+       break;
+     }
+
+   em->msg = msg;
+   msgq = evas_list_append(msgq, em);
+}
+
+void
+_edje_message_parameters_push(Edje_Message *em)
+{
+   int i;
+   
+   /* these params ALWAYS go on */
+   /* first param is the message type - always */
+   embryo_parameter_cell_push(em->edje->collection->script,
+                             (Embryo_Cell)em->type);
+   /* 2nd param is the integer of the event id - always there */
+   embryo_parameter_cell_push(em->edje->collection->script,
+                             (Embryo_Cell)em->id);
+   /* the rest is varags of whatever is in the msg */
+   switch (em->type)
+     {
+      case EDJE_MESSAGE_NONE:
+       break;
+      case EDJE_MESSAGE_STRING:
+       embryo_parameter_string_push(em->edje->collection->script,
+                                    ((Edje_Message_String *)em->msg)->str);
+       break;
+      case EDJE_MESSAGE_INT:
+         {
+            Embryo_Cell v;
+
+            v = (Embryo_Cell)((Edje_Message_Int *)em->msg)->val;
+            embryo_parameter_cell_array_push(em->edje->collection->script, &v, 1);
+         }
+       break;
+      case EDJE_MESSAGE_FLOAT:
+         {
+            Embryo_Cell v;
+            float fv;
+
+            fv = ((Edje_Message_Float *)em->msg)->val;
+            v = EMBRYO_FLOAT_TO_CELL(fv);
+            embryo_parameter_cell_array_push(em->edje->collection->script, &v, 1);
+         }
+       break;
+      case EDJE_MESSAGE_STRING_SET:
+       for (i = 0; i < ((Edje_Message_String_Set *)em->msg)->count; i++)
+         embryo_parameter_string_push(em->edje->collection->script,
+                                      ((Edje_Message_String_Set *)em->msg)->str[i]);
+       break;
+      case EDJE_MESSAGE_INT_SET:
+       for (i = 0; i < ((Edje_Message_Int_Set *)em->msg)->count; i++)
+         {
+            Embryo_Cell v;
+
+            v = (Embryo_Cell)((Edje_Message_Int_Set *)em->msg)->val[i];
+            embryo_parameter_cell_array_push(em->edje->collection->script, &v, 1);
+         }
+       break;
+      case EDJE_MESSAGE_FLOAT_SET:
+       for (i = 0; i < ((Edje_Message_Float_Set *)em->msg)->count; i++)
+         {
+            Embryo_Cell v;
+            float fv;
+
+            fv = ((Edje_Message_Float_Set *)em->msg)->val[i];
+            v = EMBRYO_FLOAT_TO_CELL(fv);
+            embryo_parameter_cell_array_push(em->edje->collection->script, &v, 1);
+         }
+       break;
+      case EDJE_MESSAGE_STRING_INT:
+       embryo_parameter_string_push(em->edje->collection->script,
+                                    ((Edje_Message_String_Int *)em->msg)->str);
+         {
+            Embryo_Cell v;
+
+            v = (Embryo_Cell)((Edje_Message_String_Int *)em->msg)->val;
+            embryo_parameter_cell_array_push(em->edje->collection->script, &v, 1);
+         }
+       break;
+      case EDJE_MESSAGE_STRING_FLOAT:
+       embryo_parameter_string_push(em->edje->collection->script,
+                                    ((Edje_Message_String_Float *)em->msg)->str);
+         {
+            Embryo_Cell v;
+            float fv;
+
+            fv = ((Edje_Message_String_Float *)em->msg)->val;
+            v = EMBRYO_FLOAT_TO_CELL(fv);
+            embryo_parameter_cell_array_push(em->edje->collection->script, &v, 1);
+         }
+       break;
+      case EDJE_MESSAGE_STRING_INT_SET:
+       embryo_parameter_string_push(em->edje->collection->script,
+                                    ((Edje_Message_String_Int_Set *)em->msg)->str);
+       for (i = 0; i < ((Edje_Message_String_Int_Set *)em->msg)->count; i++)
+         {
+            Embryo_Cell v;
+
+            v = (Embryo_Cell)((Edje_Message_String_Int_Set *)em->msg)->val[i];
+            embryo_parameter_cell_array_push(em->edje->collection->script, &v, 1);
+         }
+       break;
+      case EDJE_MESSAGE_STRING_FLOAT_SET:
+       embryo_parameter_string_push(em->edje->collection->script,
+                                    ((Edje_Message_String_Float_Set *)em->msg)->str);
+       for (i = 0; i < ((Edje_Message_String_Float_Set *)em->msg)->count; i++)
+         {
+            Embryo_Cell v;
+            float fv;
+
+            fv = ((Edje_Message_String_Float_Set *)em->msg)->val[i];
+            v = EMBRYO_FLOAT_TO_CELL(fv);
+            embryo_parameter_cell_array_push(em->edje->collection->script, &v, 1);
+         }
+       break;
+      default:
+       break;
+     }
+}
+
+void
+_edje_message_process(Edje_Message *em)
+{
+   Embryo_Function fn;
+   void *pdata;
+
+   /* signals are only handled one way */
+   if (em->type == EDJE_MESSAGE_SIGNAL)
+     {
+       _edje_emit_handle(em->edje,
+                         ((Edje_Message_Signal *)em->msg)->sig,
+                         ((Edje_Message_Signal *)em->msg)->src);
+       return;
+     }
+   /* if this has been queued up for the app then just call the callback */
+   if (em->queue == EDJE_QUEUE_APP)
+     {
+       if (em->edje->message.func)
+         em->edje->message.func(em->edje->message.data, em->edje->obj,
+                                em->type, em->id, em->msg);
+       return;
+     }
+   /* now this message is destined for the script message handler fn */
+   if (!((em->edje->collection) && (em->edje->collection->script))) return;
+   if (_edje_script_only(em->edje))
+     {
+       _edje_script_only_message(em->edje, em);
+       return;
+     }
+   fn = embryo_program_function_find(em->edje->collection->script, "message");
+   if (fn == EMBRYO_FUNCTION_NONE) return;
+   /* reset the engine */
+   _edje_embryo_script_reset(em->edje);
+   
+   _edje_message_parameters_push(em);
+   
+   embryo_program_vm_push(em->edje->collection->script);
+   _edje_embryo_globals_init(em->edje);
+   pdata = embryo_program_data_get(em->edje->collection->script);
+   embryo_program_data_set(em->edje->collection->script, em->edje);
+   embryo_program_max_cycle_run_set(em->edje->collection->script, 5000000);
+   embryo_program_run(em->edje->collection->script, fn);
+   embryo_program_data_set(em->edje->collection->script, pdata);
+   embryo_program_vm_pop(em->edje->collection->script);
+}
+
+void
+_edje_message_queue_process(void)
+{
+   int i;
+
+   if (msgq == NULL) return;
+
+   /* allow the message queue to feed itself up to 8 times before forcing */
+   /* us to go back to normal processing and let a 0 timeout deal with it */
+   for (i = 0; (i < 8) && (msgq); i++)
+     {
+       /* a temporary message queue */
+       if (tmp_msgq)
+         {
+            while (msgq)
+              {
+                 tmp_msgq = evas_list_append(tmp_msgq, msgq->data);
+                 msgq = evas_list_remove_list(msgq, msgq);
+              }
+         }
+       else
+         {
+            tmp_msgq = msgq;
+            msgq = NULL;
+         }
+
+       while (tmp_msgq)
+         {
+            Edje_Message *em;
+            Edje *ed;
+
+            em = tmp_msgq->data;
+            ed = em->edje;
+            tmp_msgq = evas_list_remove_list(tmp_msgq, tmp_msgq);
+            em->edje->message.num--;
+            if (!ed->delete_me)
+              {
+                 ed->processing_messages++;
+                 _edje_message_process(em);
+                 _edje_message_free(em);
+                 ed->processing_messages--;
+              }
+            else
+              _edje_message_free(em);
+            if (ed->processing_messages == 0)
+              {
+                 if (ed->delete_me) _edje_del(ed);
+              }
+         }
+     }
+
+   /* if the message queue filled again set a timer to expire in 0.0 sec */
+   /* to get the idle enterer to be run again */
+   if (msgq)
+     {
+       ecore_timer_add(0.0, _edje_dummy_timer, NULL);
+     }
+}
+
+void
+_edje_message_queue_clear(void)
+{
+   while (msgq)
+     {
+       Edje_Message *em;
+
+       em = msgq->data;
+       msgq = evas_list_remove_list(msgq, msgq);
+       em->edje->message.num--;
+       _edje_message_free(em);
+     }
+   while (tmp_msgq)
+     {
+       Edje_Message *em;
+
+       em = tmp_msgq->data;
+       tmp_msgq = evas_list_remove_list(tmp_msgq, tmp_msgq);
+       em->edje->message.num--;
+       _edje_message_free(em);
+     }
+}
+
+void
+_edje_message_del(Edje *ed)
+{
+   Evas_List *l;
+
+   if (ed->message.num <= 0) return;
+   /* delete any messages on the main queue for this edje object */
+   for (l = msgq; l; )
+     {
+       Edje_Message *em;
+       Evas_List *lp;
+
+       em = l->data;
+       lp = l;
+       l = l->next;
+       if (em->edje == ed)
+         {
+            msgq = evas_list_remove_list(msgq, lp);
+            em->edje->message.num--;
+            _edje_message_free(em);
+         }
+       if (ed->message.num <= 0) return;
+     }
+   /* delete any on the processing queue */
+   for (l = tmp_msgq; l; )
+     {
+       Edje_Message *em;
+       Evas_List *lp;
+
+       em = l->data;
+       lp = l;
+       l = l->next;
+       if (em->edje == ed)
+         {
+            tmp_msgq = evas_list_remove_list(tmp_msgq, lp);
+            em->edje->message.num--;
+            _edje_message_free(em);
+         }
+       if (ed->message.num <= 0) return;
+     }
+}
diff --git a/src/lib/edje_misc.c b/src/lib/edje_misc.c
new file mode 100644 (file)
index 0000000..32a4dd1
--- /dev/null
@@ -0,0 +1 @@
+#include "edje_private.h"
diff --git a/src/lib/edje_private.h b/src/lib/edje_private.h
new file mode 100644 (file)
index 0000000..4bc95cc
--- /dev/null
@@ -0,0 +1,1223 @@
+#ifndef _EDJE_PRIVATE_H
+#define _EDJE_PRIVATE_H
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <string.h>
+#include <limits.h>
+#include <math.h>
+#include <time.h>
+#include <assert.h>
+#include <locale.h>
+#include <errno.h>
+
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+#ifdef HAVE_ALLOCA_H
+# include <alloca.h>
+#elif defined __GNUC__
+# define alloca __builtin_alloca
+#elif defined _AIX
+# define alloca __alloca
+#elif defined _MSC_VER
+# include <malloc.h>
+# define alloca _alloca
+#else
+# include <stddef.h>
+# ifdef  __cplusplus
+extern "C"
+# endif
+void *alloca (size_t);
+#endif
+
+#ifdef HAVE_EVIL
+# include <Evil.h>
+#endif
+
+#include <Evas.h>
+#include <Ecore.h>
+#include <Ecore_Str.h>
+#include <Ecore_Job.h>
+#include <Eet.h>
+#include <Embryo.h>
+
+#include "Edje.h"
+#include "Edje_Edit.h"
+
+
+#ifdef __GNUC__
+# if __GNUC__ >= 4
+// BROKEN in gcc 4 on amd64
+//#  pragma GCC visibility push(hidden)
+# endif
+#endif
+
+#ifndef ABS
+#define ABS(x) ((x) < 0 ? -(x) : (x))
+#endif
+
+#ifndef CLAMP
+#define CLAMP(x, min, max) (((x) > (max)) ? (max) : (((x) < (min)) ? (min) : (x)))
+#endif
+
+#ifndef MIN
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#endif
+
+/* increment this when the EET data descriptors have changed and old
+ * EETs cannot be loaded/used correctly anymore.
+ */
+#define EDJE_FILE_VERSION 2
+
+/* FIXME:
+ *
+ * More example Edje files
+ *
+ * ? programs can do multiple actions from one signal
+ * ? add containering (hbox, vbox, table, wrapping multi-line hbox & vbox)
+ * ? text entry widget (single line only)
+ * ? reduce linked list walking and list_nth calls
+ *
+ * ? recursions, unsafe callbacks outside Edje etc. with freeze, ref/unref and block/unblock and break_programs needs to be redesigned & fixed
+ * ? all unsafe calls that may result in callbacks must be marked and dealt with
+ */
+
+
+/* Cache result of program glob matches - this uses up extra ram with the gain
+ * of faster program matching if a part has LOTS of programs.
+#define EDJE_PROGRAM_CACHE
+*/
+
+struct _Edje_Position_Scale
+{
+   double x, y;
+};
+
+struct _Edje_Position
+{
+   int x, y;
+};
+
+struct _Edje_Size
+{
+   int w, h;
+};
+
+struct _Edje_Rectangle
+{
+   int x, y, w, h;
+};
+
+struct _Edje_Color
+{
+   unsigned char  r, g, b, a;
+};
+
+struct _Edje_Aspect_Prefer
+{
+   double min, max;
+   enum {
+     EDJE_ASPECT_PREFER_NONE,
+     EDJE_ASPECT_PREFER_VERTICAL,
+     EDJE_ASPECT_PREFER_HORIZONTAL,
+     EDJE_ASPECT_PREFER_BOTH
+   } prefer;
+};
+
+struct _Edje_Aspect
+{
+   int w, h;
+   Edje_Aspect_Control mode;
+};
+
+typedef struct _Edje_Position_Scale                  Edje_Alignment;
+typedef struct _Edje_Position_Scale                  Edje_Position_Scale;
+typedef struct _Edje_Position                        Edje_Position;
+typedef struct _Edje_Size                            Edje_Size;
+typedef struct _Edje_Rectangle                       Edje_Rectangle;
+typedef struct _Edje_Color                           Edje_Color;
+typedef struct _Edje_Aspect_Prefer                   Edje_Aspect_Prefer;
+typedef struct _Edje_Aspect                          Edje_Aspect;
+
+typedef struct _Edje_File                            Edje_File;
+typedef struct _Edje_Style                           Edje_Style;
+typedef struct _Edje_Style_Tag                       Edje_Style_Tag;
+typedef struct _Edje_Data                            Edje_Data;
+typedef struct _Edje_Font_Directory                  Edje_Font_Directory;
+typedef struct _Edje_Font_Directory_Entry            Edje_Font_Directory_Entry;
+typedef struct _Edje_Image_Directory                 Edje_Image_Directory;
+typedef struct _Edje_Image_Directory_Entry           Edje_Image_Directory_Entry;
+typedef struct _Edje_Spectrum_Directory              Edje_Spectrum_Directory;
+typedef struct _Edje_Spectrum_Directory_Entry        Edje_Spectrum_Directory_Entry;
+typedef struct _Edje_Program                         Edje_Program;
+typedef struct _Edje_Program_Target                  Edje_Program_Target;
+typedef struct _Edje_Program_After                   Edje_Program_After;
+typedef struct _Edje_Part_Collection_Directory       Edje_Part_Collection_Directory;
+typedef struct _Edje_Part_Collection_Directory_Entry Edje_Part_Collection_Directory_Entry;
+typedef struct _Edje_Part_Collection                 Edje_Part_Collection;
+typedef struct _Edje_Part                            Edje_Part;
+typedef struct _Edje_Part_Image_Id                   Edje_Part_Image_Id;
+typedef struct _Edje_Part_Description                Edje_Part_Description;
+typedef struct _Edje_Spectrum_Color                  Edje_Spectrum_Color;
+typedef struct _Edje_Patterns                        Edje_Patterns;
+
+#define PI 3.14159265358979323846
+
+#define EDJE_INF_MAX_W 100000
+#define EDJE_INF_MAX_H 100000
+
+#define EDJE_IMAGE_SOURCE_TYPE_NONE           0
+#define EDJE_IMAGE_SOURCE_TYPE_INLINE_PERFECT 1
+#define EDJE_IMAGE_SOURCE_TYPE_INLINE_LOSSY   2
+#define EDJE_IMAGE_SOURCE_TYPE_EXTERNAL       3
+#define EDJE_IMAGE_SOURCE_TYPE_LAST           4
+
+#define EDJE_PART_TYPE_NONE      0
+#define EDJE_PART_TYPE_RECTANGLE 1
+#define EDJE_PART_TYPE_TEXT      2
+#define EDJE_PART_TYPE_IMAGE     3
+#define EDJE_PART_TYPE_SWALLOW   4
+#define EDJE_PART_TYPE_TEXTBLOCK 5
+#define EDJE_PART_TYPE_GRADIENT  6
+#define EDJE_PART_TYPE_GROUP     7
+#define EDJE_PART_TYPE_LAST      8
+
+#define EDJE_TEXT_EFFECT_NONE                0
+#define EDJE_TEXT_EFFECT_PLAIN               1
+#define EDJE_TEXT_EFFECT_OUTLINE             2
+#define EDJE_TEXT_EFFECT_SOFT_OUTLINE        3
+#define EDJE_TEXT_EFFECT_SHADOW              4
+#define EDJE_TEXT_EFFECT_SOFT_SHADOW         5
+#define EDJE_TEXT_EFFECT_OUTLINE_SHADOW      6
+#define EDJE_TEXT_EFFECT_OUTLINE_SOFT_SHADOW 7
+#define EDJE_TEXT_EFFECT_FAR_SHADOW          8
+#define EDJE_TEXT_EFFECT_FAR_SOFT_SHADOW     9
+#define EDJE_TEXT_EFFECT_GLOW               10
+#define EDJE_TEXT_EFFECT_LAST               11
+
+#define EDJE_ACTION_TYPE_NONE          0
+#define EDJE_ACTION_TYPE_STATE_SET     1
+#define EDJE_ACTION_TYPE_ACTION_STOP   2
+#define EDJE_ACTION_TYPE_SIGNAL_EMIT   3
+#define EDJE_ACTION_TYPE_DRAG_VAL_SET  4
+#define EDJE_ACTION_TYPE_DRAG_VAL_STEP 5
+#define EDJE_ACTION_TYPE_DRAG_VAL_PAGE 6
+#define EDJE_ACTION_TYPE_SCRIPT        7
+#define EDJE_ACTION_TYPE_LAST          8
+
+#define EDJE_TWEEN_MODE_NONE       0
+#define EDJE_TWEEN_MODE_LINEAR     1
+#define EDJE_TWEEN_MODE_SINUSOIDAL 2
+#define EDJE_TWEEN_MODE_ACCELERATE 3
+#define EDJE_TWEEN_MODE_DECELERATE 4
+#define EDJE_TWEEN_MODE_LAST       5
+
+#define EDJE_VAR_NONE   0
+#define EDJE_VAR_INT    1
+#define EDJE_VAR_FLOAT  2
+#define EDJE_VAR_STRING 3
+#define EDJE_VAR_LIST   4
+#define EDJE_VAR_HASH   5
+
+#define EDJE_VAR_MAGIC_BASE 0x12fe84ba
+
+#define EDJE_STATE_PARAM_NONE         0
+#define EDJE_STATE_PARAM_ALIGNMENT    1
+#define EDJE_STATE_PARAM_MIN          2
+#define EDJE_STATE_PARAM_MAX          3
+#define EDJE_STATE_PARAM_STEP         4
+#define EDJE_STATE_PARAM_ASPECT       5
+#define EDJE_STATE_PARAM_ASPECT_PREF  6
+#define EDJE_STATE_PARAM_COLOR        7
+#define EDJE_STATE_PARAM_COLOR2       8
+#define EDJE_STATE_PARAM_COLOR3       9
+#define EDJE_STATE_PARAM_COLOR_CLASS  10
+#define EDJE_STATE_PARAM_REL1         11
+#define EDJE_STATE_PARAM_REL1_TO      12
+#define EDJE_STATE_PARAM_REL1_OFFSET  13
+#define EDJE_STATE_PARAM_REL2         14
+#define EDJE_STATE_PARAM_REL2_TO      15
+#define EDJE_STATE_PARAM_REL2_OFFSET  16
+#define EDJE_STATE_PARAM_IMAGE        17
+#define EDJE_STATE_PARAM_BORDER       18
+#define EDJE_STATE_PARAM_FILL_SMOOTH  19
+#define EDJE_STATE_PARAM_FILL_POS     20
+#define EDJE_STATE_PARAM_FILL_SIZE    21
+#define EDJE_STATE_PARAM_TEXT         22
+#define EDJE_STATE_PARAM_TEXT_CLASS   23
+#define EDJE_STATE_PARAM_TEXT_FONT    24
+#define EDJE_STATE_PARAM_TEXT_STYLE   25
+#define EDJE_STATE_PARAM_TEXT_SIZE    26
+#define EDJE_STATE_PARAM_TEXT_FIT     27
+#define EDJE_STATE_PARAM_TEXT_MIN     28
+#define EDJE_STATE_PARAM_TEXT_MAX     29
+#define EDJE_STATE_PARAM_TEXT_ALIGN   30
+#define EDJE_STATE_PARAM_VISIBLE      31
+#define EDJE_STATE_PARAM_LAST         32
+
+#define EDJE_PART_PATH_SEPARATOR ':'
+#define EDJE_PART_PATH_SEPARATOR_STRING ":"
+/*----------*/
+
+struct _Edje_File
+{
+   const char                     *path;
+
+   Edje_Font_Directory            *font_dir;
+   Edje_Image_Directory           *image_dir;
+   Edje_Spectrum_Directory        *spectrum_dir;
+   Edje_Part_Collection_Directory *collection_dir;
+   Evas_List                      *data;
+   Evas_List                      *styles;
+   Evas_List                      *color_classes;
+
+   int                             references;
+   char                           *compiler;
+   int                             version;
+   int                             feature_ver;
+
+   Evas_Hash                      *collection_hash;
+   Evas_Hash                     *font_hash;
+   Evas_List                      *collection_cache;
+   Evas_Hash                      *data_cache;
+
+   Eet_File                       *ef;
+
+   unsigned int                    free_strings : 1;
+};
+
+struct _Edje_Style
+{
+   char                           *name;
+   Evas_List                      *tags;
+   Evas_Textblock_Style           *style;
+};
+
+struct _Edje_Style_Tag
+{
+   const char                     *key;
+   const char                     *value;
+   const char                    *font;
+   double                         font_size;
+   const char                    *text_class;
+};
+
+/*----------*/
+
+struct _Edje_Data
+{
+   char *key;
+   char *value;
+};
+
+/*----------*/
+
+struct _Edje_Font_Directory
+{
+   Evas_List *entries; /* a list of Edje_Font_Directory_Entry */
+};
+
+struct _Edje_Font_Directory_Entry
+{
+   const char *entry; /* the name of the font */
+   const char *path;
+};
+
+
+/*----------*/
+
+struct _Edje_Image_Directory
+{
+   Evas_List *entries; /* a list of Edje_Image_Directory_Entry */
+};
+
+struct _Edje_Image_Directory_Entry
+{
+   char *entry; /* the nominal name of the image - if any */
+   int   source_type; /* alternate source mode. 0 = none */
+   int   source_param; /* extra params on encoding */
+   int   id; /* the id no. of the image */
+};
+
+/*----------*/
+
+struct _Edje_Spectrum_Directory
+{
+   Evas_List *entries; /* a list of Edje_Spectrum_Directory_Entry */
+};
+
+struct _Edje_Spectrum_Directory_Entry
+{
+   char      *entry;
+   /* only one of the following two should be included. filename takes precedence */
+   char      *filename; /* filename of external spectrum. */
+   Evas_List *color_list; /* list of Edje_Spectrum_Color */
+   int        id;
+};
+
+struct _Edje_Spectrum_Color
+{
+   int r, g, b, a;
+   int d;
+};
+
+
+/*----------*/
+
+struct _Edje_Program /* a conditional program to be run */
+{
+   int         id; /* id of program */
+   const char *name; /* name of the action */
+
+   const char *signal; /* if signal emission name matches the glob here... */
+   const char *source; /* if part that emitted this (name) matches this glob */
+
+   struct {
+      double   from;
+      double   range;
+   } in;
+
+   int         action; /* type - set state, stop action, set drag pos etc. */
+   const char *state; /* what state of alternates to apply, NULL = default */
+   const char *state2; /* what other state to use - for signal emit action */
+   double      value; /* value of state to apply (if multiple names match) */
+   double      value2; /* other value for drag actions */
+
+   struct {
+      int      mode; /* how to tween - linear, sinusoidal etc. */
+      double   time; /* time to graduate between current and new state */
+   } tween;
+
+   Evas_List  *targets; /* list of target parts to apply the state to */
+
+   Evas_List  *after; /* list of actions to run at the end of this, for looping */
+};
+
+struct _Edje_Program_Target /* the target of an action */
+{
+   int id; /* just the part id no, or action id no */
+};
+
+struct _Edje_Program_After /* the action to run after another action */
+{
+   int id;
+};
+
+/*----------*/
+
+struct _Edje_Part_Collection_Directory
+{
+   Evas_List *entries; /* a list of Edje_Part_Collection_Directory_Entry */
+
+   int        references;
+};
+
+struct _Edje_Part_Collection_Directory_Entry
+{
+   const char *entry; /* the nominal name of the part collection */
+   int         id; /* the id of this named part collection */
+};
+
+/*----------*/
+
+struct _Edje_Part_Collection
+{
+   Evas_List *programs; /* a list of Edje_Program */
+   Evas_List *parts; /* a list of Edje_Part */
+   Evas_List *data;
+
+   int        id; /* the collection id */
+
+   struct {
+      Edje_Size min, max;
+   } prop;
+
+   int        references;
+#ifdef EDJE_PROGRAM_CACHE
+   struct {
+      Evas_Hash                   *no_matches;
+      Evas_Hash                   *matches;
+   } prog_cache;
+#endif
+
+   Embryo_Program   *script; /* all the embryo script code for this group */
+
+   const char       *part;
+   
+   unsigned char    script_only;
+};
+
+struct _Edje_Part
+{
+   const char            *name; /* the name if any of the part */
+   Edje_Part_Description *default_desc; /* the part descriptor for default */
+   Evas_List             *other_desc; /* other possible descriptors */
+   const char            *source;
+   int                    id; /* its id number */
+   int                    clip_to_id; /* the part id to clip this one to */
+   struct {
+      int                 step_x; /* drag jumps n pixels (0 = no limit) */
+      int                 step_y; /* drag jumps n pixels (0 = no limit) */
+
+      int                 count_x; /* drag area divided by n (0 = no limit) */
+      int                 count_y; /* drag area divided by n (0 = no limit) */
+
+      int                 confine_id; /* dragging within this bit, -1 = no */
+
+      /* davinchi */
+      int                events_id; /* If it is used as scrollbar */
+
+      signed char         x; /* can u click & drag this bit in x dir */
+      signed char         y; /* can u click & drag this bit in y dir */
+   } dragable;
+   unsigned char          type; /* what type (image, rect, text) */
+   unsigned char          effect; /* 0 = plain... */
+   unsigned char          mouse_events; /* it will affect/respond to mouse events */
+   unsigned char          repeat_events; /* it will repeat events to objects below */
+   Evas_Event_Flags       ignore_flags;
+   unsigned char          precise_is_inside;
+   unsigned char          use_alternate_font_metrics;
+   char                   pointer_mode;
+};
+
+struct _Edje_Part_Image_Id
+{
+   int id;
+};
+
+struct _Edje_Part_Description
+{
+   struct {
+      double         value; /* the value of the state (for ranges) */
+      const char    *name; /* the named state if any */
+   } state;
+
+   Edje_Alignment align; /* 0 <-> 1.0 alignment within allocated space */
+
+   struct {
+      unsigned char  w, h; /* width or height is fixed in side (cannot expand with Edje object size) */
+   } fixed;
+
+   Edje_Size min, max;
+   Edje_Position step; /* size stepping by n pixels, 0 = none */
+   Edje_Aspect_Prefer aspect;
+
+   struct {
+      double         relative_x;
+      double         relative_y;
+      int            offset_x;
+      int            offset_y;
+      int            id_x; /* -1 = whole part collection, or part ID */
+      int            id_y; /* -1 = whole part collection, or part ID */
+   } rel1, rel2;
+
+   struct {
+      Evas_List     *tween_list; /* list of Edje_Part_Image_Id */
+      int            id; /* the image id to use */
+   } image;
+
+   struct {
+      char          *type; /* type of spectrum - 'linear', 'radial', etc */
+      char          *params; /* params for spectrum type */
+      int            id; /* the spectrum id to use */
+      int            use_rel; /* 1 - use rel1,rel2; 0 - use fill */
+      struct {
+         double      relative_x;
+         double      relative_y;
+         int         offset_x;
+         int         offset_y;
+      } rel1, rel2; /* linear gradient fill options */
+   } gradient;
+
+   struct {
+      int            l, r, t, b; /* border scaling on image fill */
+      unsigned char  no_fill; /* do we fill the center of the image if bordered? 1 == NO!!!! */
+   } border;
+
+   struct {
+      double         pos_rel_x; /* fill offset x relative to area */
+      double         rel_x; /* relative size compared to area */
+      double         pos_rel_y; /* fill offset y relative to area */
+      double         rel_y; /* relative size compared to area */
+      int            pos_abs_x; /* fill offset x added to fill offset */
+      int            abs_x; /* size of fill added to relative fill */
+      int            pos_abs_y; /* fill offset y added to fill offset */
+      int            abs_y; /* size of fill added to relative fill */
+      int            angle; /* angle of fill -- currently only used by grads */
+      int            spread; /* spread of fill -- currently only used by grads */
+      char           smooth; /* fill with smooth scaling or not */
+      unsigned char  type; /* fill coordinate from container (SCALE) or from source image (TILE) */
+   } fill;
+
+   char             *color_class; /* how to modify the color */
+
+   struct {
+      char          *text; /* if "" or NULL, then leave text unchanged */
+      char          *text_class; /* how to apply/modify the font */
+      char          *style; /* the text style if a textblock */
+      char          *font; /* if a specific font is asked for */
+
+      Edje_Alignment align; /* text alignment within bounds */
+
+      double         elipsis; /* 0.0 - 1.0 defining where the elipsis align */
+      int            size; /* 0 = use user set size */
+      int            id_source; /* -1 if none */
+      int            id_text_source; /* -1 if none */
+
+      unsigned char  fit_x; /* resize font size down to fit in x dir */
+      unsigned char  fit_y; /* resize font size down to fit in y dir */
+      unsigned char  min_x; /* if text size should be part min size */
+      unsigned char  min_y; /* if text size should be part min size */
+      unsigned char  max_x; /* if text size should be part max size */
+      unsigned char  max_y; /* if text size should be part max size */
+
+   } text;
+
+   Edje_Color color, color2, color3;  /* color for rect or text, shadow etc. */
+
+   unsigned char     visible; /* is it shown */
+};
+
+
+/*----------*/
+
+
+typedef struct _Edje Edje;
+typedef struct _Edje_Real_Part Edje_Real_Part;
+typedef struct _Edje_Running_Program Edje_Running_Program;
+typedef struct _Edje_Signal_Callback Edje_Signal_Callback;
+typedef struct _Edje_Calc_Params Edje_Calc_Params;
+typedef struct _Edje_Pending_Program Edje_Pending_Program;
+typedef struct _Edje_Text_Style Edje_Text_Style;
+typedef struct _Edje_Color_Class Edje_Color_Class;
+typedef struct _Edje_Text_Class Edje_Text_Class;
+typedef struct _Edje_Var Edje_Var;
+typedef struct _Edje_Var_Int Edje_Var_Int;
+typedef struct _Edje_Var_Float Edje_Var_Float;
+typedef struct _Edje_Var_String Edje_Var_String;
+typedef struct _Edje_Var_List Edje_Var_List;
+typedef struct _Edje_Var_Hash Edje_Var_Hash;
+typedef struct _Edje_Var_Animator Edje_Var_Animator;
+typedef struct _Edje_Var_Timer Edje_Var_Timer;
+typedef struct _Edje_Var_Pool Edje_Var_Pool;
+
+struct _Edje_Signals_Sources_Patterns
+{
+   Edje_Patterns *signals_patterns;
+   Edje_Patterns *sources_patterns;
+};
+
+typedef struct _Edje_Signals_Sources_Patterns Edje_Signals_Sources_Patterns;
+
+struct _Edje
+{
+   const char           *path;
+   const char           *group;
+   const char           *parent;
+
+   Evas_Coord            x, y, w, h;
+   Edje_Size             min;
+   double                paused_at;
+   Evas                 *evas; /* the Evas this Edje belongs to */
+   Evas_Object          *obj; /* the smart object */
+   Evas_Object          *clipper; /* a big rect to clip this Edje to */
+   Edje_File            *file; /* the file the data comes form */
+   Edje_Part_Collection *collection; /* the description being used */
+   Evas_List            *actions; /* currently running actions */
+   Evas_List            *callbacks;
+   Evas_List            *pending_actions;
+   Evas_List            *color_classes;
+   Evas_List            *text_classes;
+   /* variable pool for Edje Embryo scripts */
+   Edje_Var_Pool        *var_pool;
+   /* for faster lookups to avoid nth list walks */
+   Edje_Real_Part      **table_parts;
+   Edje_Program        **table_programs;
+   void                 *script_only_data;
+   int                   table_programs_size;
+   int                   table_parts_size;
+
+   struct {
+      Edje_Signals_Sources_Patterns callbacks;
+      Edje_Signals_Sources_Patterns programs;
+   } patterns;
+
+   int                   references;
+   int                   block;
+   int                   load_error;
+   int                   freeze;
+
+   struct {
+      void (*func) (void *data, Evas_Object *obj, const char *part);
+      void *data;
+   } text_change;
+
+   struct {
+      void                (*func) (void *data, Evas_Object *obj, Edje_Message_Type type, int id, void *msg);
+      void                 *data;
+      int                   num;
+   } message;
+   int                      processing_messages;
+
+   unsigned short        dirty : 1;
+   unsigned short        recalc : 1;
+   unsigned short        walking_callbacks : 1;
+   unsigned short        delete_callbacks : 1;
+   unsigned short        just_added_callbacks : 1;
+   unsigned short        have_objects : 1;
+   unsigned short        paused : 1;
+   unsigned short        no_anim : 1;
+   unsigned short        calc_only : 1;
+   unsigned short        walking_actions : 1;
+   unsigned short        block_break : 1;
+   unsigned short        delete_me : 1;
+};
+
+struct _Edje_Real_Part
+{
+   Edje                     *edje;
+   Evas_Object              *object;
+   Evas_List                *extra_objects;
+   Evas_Object              *swallowed_object;
+   Edje_Part                *part;
+   int                       x, y, w, h;
+   Edje_Rectangle            req;
+   Edje_Position             offset;
+   struct {
+      Edje_Size min, max;
+      Edje_Aspect aspect;
+   } swallow_params;
+   struct {
+      double        x, y;
+      Edje_Position_Scale val, size, step, page;
+      struct {
+        unsigned int count;
+        int  x, y;
+      } down;
+      struct {
+        int  x, y;
+      } tmp;
+      unsigned char need_reset : 1;
+   } drag;
+   struct {
+      Edje_Real_Part        *source;
+      Edje_Real_Part        *text_source;
+      const char            *text;
+      const char           *font;
+      const char           *style;
+      int                    size;
+      struct {
+        double              in_w, in_h;
+        int                 in_size;
+        const char         *in_str;
+        const char         *out_str;
+        int                 out_size;
+        double              align_x, align_y;
+        double              elipsis;
+        int                 fit_x, fit_y;
+      } cache;
+   } text;
+
+   double                    description_pos;
+   Edje_Part_Description    *chosen_description;
+   struct {
+      Edje_Part_Description *description;
+      Edje_Real_Part        *rel1_to_x;
+      Edje_Real_Part        *rel1_to_y;
+      Edje_Real_Part        *rel2_to_x;
+      Edje_Real_Part        *rel2_to_y;
+   } param1, param2, custom;
+
+   Edje_Real_Part           *confine_to;
+   Edje_Real_Part           *clip_to;
+
+   Edje_Running_Program     *program;
+   Edje_Real_Part           *events_to;
+
+   int                       clicked_button;
+   int                       gradient_id;
+
+   unsigned char             calculated;
+   unsigned char             calculating;
+
+   unsigned char             still_in   : 1;
+};
+
+struct _Edje_Running_Program
+{
+   Edje           *edje;
+   Edje_Program   *program;
+   double          start_time;
+   char            delete_me : 1;
+};
+
+struct _Edje_Signal_Callback
+{
+   const char    *signal;
+   const char    *source;
+   void (*func) (void *data, Evas_Object *o, const char *emission, const char *source);
+   void  *data;
+   unsigned char just_added : 1;
+   unsigned char delete_me : 1;
+};
+
+struct _Edje_Calc_Params
+{
+   int              x, y, w, h;
+   Edje_Rectangle   req;
+   Edje_Rectangle   req_drag;
+   struct {
+      int           x, y, w, h;
+      int           angle;
+      int           spread;
+   } fill;
+   Edje_Color color, color2, color3;
+   struct {
+      int           l, r, t, b;
+   } border;
+   struct {
+      Edje_Alignment align; /* text alignment within bounds */
+      double         elipsis;
+   } text;
+   struct {
+     int             id;
+     char           *type;
+   } gradient;
+   unsigned char    visible : 1;
+   unsigned char    smooth : 1;
+};
+
+struct _Edje_Pending_Program
+{
+   Edje         *edje;
+   Edje_Program *program;
+   Ecore_Timer  *timer;
+};
+
+struct _Edje_Text_Style
+{
+   struct {
+      unsigned char x, y;
+   } offset;
+   struct {
+      unsigned char l, r, t, b;
+   } pad;
+   int num;
+   struct {
+      unsigned char color; /* 0 = color, 1, 2 = color2, color3 */
+      signed   char x, y; /* offset */
+      unsigned char alpha;
+   } members[32];
+};
+
+struct _Edje_Color_Class
+{
+   const char    *name;
+   unsigned char  r, g, b, a;
+   unsigned char  r2, g2, b2, a2;
+   unsigned char  r3, g3, b3, a3;
+};
+
+struct _Edje_Text_Class
+{
+   const char     *name;
+   const char     *font;
+   Evas_Font_Size  size;
+};
+
+struct _Edje_Var_Int
+{
+   int      v;
+};
+
+struct _Edje_Var_Float
+{
+   double   v;
+};
+
+struct _Edje_Var_String
+{
+   char    *v;
+};
+
+struct _Edje_Var_List
+{
+   Evas_List *v;
+};
+
+struct _Edje_Var_Hash
+{
+   Evas_Hash *v;
+};
+
+struct _Edje_Var_Timer
+{
+   Edje           *edje;
+   int             id;
+   Embryo_Function func;
+   int             val;
+   Ecore_Timer    *timer;
+};
+
+struct _Edje_Var_Animator
+{
+   Edje           *edje;
+   int             id;
+   Embryo_Function func;
+   int             val;
+   double          start, len;
+   char            delete_me;
+};
+
+struct _Edje_Var_Pool
+{
+   int          id_count;
+   Evas_List   *timers;
+   Evas_List   *animators;
+   int          size;
+   Edje_Var    *vars;
+   int          walking_list;
+};
+
+struct _Edje_Var
+{
+   union {
+      Edje_Var_Int    i;
+      Edje_Var_Float  f;
+      Edje_Var_String s;
+      Edje_Var_List   l;
+      Edje_Var_Hash   h;
+   } data;
+   unsigned char type;
+};
+
+
+typedef enum _Edje_Queue
+{
+   EDJE_QUEUE_APP,
+     EDJE_QUEUE_SCRIPT
+} Edje_Queue;
+
+typedef struct _Edje_Message_Signal Edje_Message_Signal;
+typedef struct _Edje_Message        Edje_Message;
+
+struct _Edje_Message_Signal
+{
+   const char *sig;
+   const char *src;
+};
+
+struct _Edje_Message
+{
+   Edje              *edje;
+   Edje_Queue         queue;
+   Edje_Message_Type  type;
+   int                id;
+   unsigned char     *msg;
+};
+
+typedef enum _Edje_Fill
+{
+   EDJE_FILL_TYPE_SCALE = 0,
+     EDJE_FILL_TYPE_TILE
+} Edje_Fill;
+
+typedef enum _Edje_Match_Error
+{
+   EDJE_MATCH_OK,
+     EDJE_MATCH_ALLOC_ERROR,
+     EDJE_MATCH_SYNTAX_ERROR
+
+} Edje_Match_Error;
+
+typedef struct _Edje_States     Edje_States;
+struct _Edje_Patterns
+{
+   const char    **patterns;
+
+   Edje_States    *states;
+
+   size_t          patterns_size;
+   size_t          max_length;
+   size_t          finals[];
+};
+
+Edje_Patterns   *edje_match_collection_dir_init(Evas_List *lst);
+Edje_Patterns   *edje_match_programs_signal_init(Evas_List *lst);
+Edje_Patterns   *edje_match_programs_source_init(Evas_List *lst);
+Edje_Patterns   *edje_match_callback_signal_init(Evas_List *lst);
+Edje_Patterns   *edje_match_callback_source_init(Evas_List *lst);
+
+int              edje_match_collection_dir_exec(const Edje_Patterns      *ppat,
+                                               const char               *string);
+int              edje_match_programs_exec(const Edje_Patterns    *ppat_signal,
+                                         const Edje_Patterns    *ppat_source,
+                                         const char             *signal,
+                                         const char             *source,
+                                         Evas_List              *programs,
+                                         int (*func)(Edje_Program *pr, void *data),
+                                         void                   *data);
+int              edje_match_callback_exec(const Edje_Patterns    *ppat_signal,
+                                         const Edje_Patterns    *ppat_source,
+                                         const char             *signal,
+                                         const char             *source,
+                                         Evas_List              *callbacks,
+                                         Edje                   *ed);
+
+void             edje_match_patterns_free(Edje_Patterns *ppat);
+
+EAPI extern Eet_Data_Descriptor *_edje_edd_edje_file;
+EAPI extern Eet_Data_Descriptor *_edje_edd_edje_style;
+EAPI extern Eet_Data_Descriptor *_edje_edd_edje_style_tag;
+EAPI extern Eet_Data_Descriptor *_edje_edd_edje_data;
+EAPI extern Eet_Data_Descriptor *_edje_edd_edje_font_directory;
+EAPI extern Eet_Data_Descriptor *_edje_edd_edje_font_directory_entry;
+EAPI extern Eet_Data_Descriptor *_edje_edd_edje_image_directory;
+EAPI extern Eet_Data_Descriptor *_edje_edd_edje_image_directory_entry;
+EAPI extern Eet_Data_Descriptor *_edje_edd_edje_spectrum_directory;
+EAPI extern Eet_Data_Descriptor *_edje_edd_edje_spectrum_directory_entry;
+EAPI extern Eet_Data_Descriptor *_edje_edd_edje_program;
+EAPI extern Eet_Data_Descriptor *_edje_edd_edje_program_target;
+EAPI extern Eet_Data_Descriptor *_edje_edd_edje_part_collection_directory;
+EAPI extern Eet_Data_Descriptor *_edje_edd_edje_part_collection_directory_entry;
+EAPI extern Eet_Data_Descriptor *_edje_edd_edje_part_collection;
+EAPI extern Eet_Data_Descriptor *_edje_edd_edje_part;
+EAPI extern Eet_Data_Descriptor *_edje_edd_edje_part_description;
+EAPI extern Eet_Data_Descriptor *_edje_edd_edje_part_image_id;
+EAPI extern Eet_Data_Descriptor *_edje_edd_edje_spectrum_color;
+
+extern int              _edje_anim_count;
+extern Ecore_Animator  *_edje_timer;
+extern Evas_List       *_edje_animators;
+extern Evas_List       *_edje_edjes;
+
+extern char            *_edje_fontset_append;
+
+void  _edje_part_pos_set(Edje *ed, Edje_Real_Part *ep, int mode, double pos);
+Edje_Part_Description *_edje_part_description_find(Edje *ed, Edje_Real_Part *rp, const char *name, double val);
+void  _edje_part_description_apply(Edje *ed, Edje_Real_Part *ep, const char  *d1, double v1, const char *d2, double v2);
+void  _edje_recalc(Edje *ed);
+int   _edje_part_dragable_calc(Edje *ed, Edje_Real_Part *ep, double *x, double *y);
+void  _edje_dragable_pos_set(Edje *ed, Edje_Real_Part *ep, double x, double y);
+
+void  _edje_mouse_in_cb(void *data, Evas * e, Evas_Object * obj, void *event_info);
+void  _edje_mouse_out_cb(void *data, Evas * e, Evas_Object * obj, void *event_info);
+void  _edje_mouse_down_cb(void *data, Evas * e, Evas_Object * obj, void *event_info);
+void  _edje_mouse_up_cb(void *data, Evas * e, Evas_Object * obj, void *event_info);
+void  _edje_mouse_move_cb(void *data, Evas * e, Evas_Object * obj, void *event_info);
+void  _edje_mouse_wheel_cb(void *data, Evas * e, Evas_Object * obj, void *event_info);
+int   _edje_timer_cb(void *data);
+int   _edje_pending_timer_cb(void *data);
+void  _edje_callbacks_add(Evas_Object *obj, Edje *ed, Edje_Real_Part *rp);
+void  _edje_callbacks_del(Evas_Object *obj);
+
+void  _edje_edd_setup(void);
+void  _edje_edd_free(void);
+
+void  _edje_file_add(Edje *ed);
+void  _edje_file_del(Edje *ed);
+void  _edje_file_free(Edje_File *edf);
+void  _edje_file_cache_shutdown(void);
+void  _edje_collection_free(Edje_File *edf, Edje_Part_Collection *ec);
+void  _edje_collection_free_part_description_free(Edje_Part_Description *desc, unsigned int free_strings);
+
+
+Edje *_edje_add(Evas_Object *obj);
+void  _edje_del(Edje *ed);
+void  _edje_ref(Edje *ed);
+void  _edje_unref(Edje *ed);
+void  _edje_clean_objects(Edje *ed);
+void  _edje_ref(Edje *ed);
+void  _edje_unref(Edje *ed);
+
+int   _edje_program_run_iterate(Edje_Running_Program *runp, double tim);
+void  _edje_program_end(Edje *ed, Edje_Running_Program *runp);
+void  _edje_program_run(Edje *ed, Edje_Program *pr, int force, const char *ssig, const char *ssrc);
+void  _edje_emit(Edje *ed, const char *sig, const char *src);
+void  _edje_emit_handle(Edje *ed, const char *sig, const char *src);
+void  _edje_signals_sources_patterns_clean(Edje_Signals_Sources_Patterns *ssp);
+void  _edje_callbacks_patterns_clean(Edje *ed);
+
+void           _edje_text_init(void);
+void           _edje_text_part_on_add(Edje *ed, Edje_Real_Part *ep);
+void           _edje_text_part_on_add_clippers(Edje *ed, Edje_Real_Part *ep);
+void           _edje_text_part_on_del(Edje *ed, Edje_Part *ep);
+void           _edje_text_real_part_on_del(Edje *ed, Edje_Real_Part *ep);
+void           _edje_text_recalc_apply(Edje *ed, Edje_Real_Part *ep, Edje_Calc_Params *params, Edje_Part_Description *chosen_desc);
+Evas_Font_Size _edje_text_size_calc(Evas_Font_Size size, Edje_Text_Class *tc);
+const char *   _edje_text_class_font_get(Edje *ed, Edje_Part_Description *chosen_desc, int *size, char **free_later);
+
+
+Edje_Real_Part   *_edje_real_part_get(Edje *ed, const char *part);
+Edje_Real_Part   *_edje_real_part_recursive_get(Edje *ed, const char *part);
+Edje_Color_Class *_edje_color_class_find(Edje *ed, const char *color_class);
+void              _edje_color_class_member_add(Edje *ed, const char *color_class);
+void              _edje_color_class_member_del(Edje *ed, const char *color_class);
+void              _edje_color_class_on_del(Edje *ed, Edje_Part *ep);
+void              _edje_color_class_members_free(void);
+void              _edje_color_class_hash_free(void);
+
+Edje_Text_Class  *_edje_text_class_find(Edje *ed, const char *text_class);
+void              _edje_text_class_member_add(Edje *ed, const char *text_class);
+void              _edje_text_class_member_del(Edje *ed, const char *text_class);
+void              _edje_text_class_members_free(void);
+void              _edje_text_class_hash_free(void);
+
+Edje             *_edje_fetch(const Evas_Object *obj);
+int               _edje_freeze(Edje *ed);
+int               _edje_thaw(Edje *ed);
+int               _edje_block(Edje *ed);
+int               _edje_unblock(Edje *ed);
+int               _edje_block_break(Edje *ed);
+void              _edje_block_violate(Edje *ed);
+void              _edje_object_part_swallow_free_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
+void              _edje_real_part_swallow(Edje_Real_Part *rp, Evas_Object *obj_swallow);
+
+void          _edje_embryo_script_init      (Edje *ed);
+void          _edje_embryo_script_shutdown  (Edje *ed);
+void          _edje_embryo_script_reset     (Edje *ed);
+void          _edje_embryo_test_run         (Edje *ed, const char *fname, const char *sig, const char *src);
+Edje_Var     *_edje_var_new                 (void);
+void          _edje_var_free                (Edje_Var *var);
+void          _edje_var_init                (Edje *ed);
+void          _edje_var_shutdown            (Edje *ed);
+int           _edje_var_string_id_get       (Edje *ed, const char *string);
+int           _edje_var_var_int_get         (Edje *ed, Edje_Var *var);
+void          _edje_var_var_int_set         (Edje *ed, Edje_Var *var, int v);
+double        _edje_var_var_float_get       (Edje *ed, Edje_Var *var);
+void          _edje_var_var_float_set       (Edje *ed, Edje_Var *var, double v);
+const char   *_edje_var_var_str_get         (Edje *ed, Edje_Var *var);
+void          _edje_var_var_str_set         (Edje *ed, Edje_Var *var, const char *str);
+int           _edje_var_int_get             (Edje *ed, int id);
+void          _edje_var_int_set             (Edje *ed, int id, int v);
+double        _edje_var_float_get           (Edje *ed, int id);
+void          _edje_var_float_set           (Edje *ed, int id, double v);
+const char   *_edje_var_str_get             (Edje *ed, int id);
+void          _edje_var_str_set             (Edje *ed, int id, const char *str);
+
+void          _edje_var_list_var_append(Edje *ed, int id, Edje_Var *var);
+void          _edje_var_list_var_prepend(Edje *ed, int id, Edje_Var *var);
+void          _edje_var_list_var_append_relative(Edje *ed, int id, Edje_Var *var, Edje_Var *relative);
+void          _edje_var_list_var_prepend_relative(Edje *ed, int id, Edje_Var *var, Edje_Var *relative);
+Edje_Var     *_edje_var_list_nth(Edje *ed, int id, int n);
+
+int           _edje_var_list_count_get(Edje *ed, int id);
+void          _edje_var_list_remove_nth(Edje *ed, int id, int n);
+
+int           _edje_var_list_nth_int_get(Edje *ed, int id, int n);
+void          _edje_var_list_nth_int_set(Edje *ed, int id, int n, int v);
+void          _edje_var_list_int_append(Edje *ed, int id, int v);
+void          _edje_var_list_int_prepend(Edje *ed, int id, int v);
+void          _edje_var_list_int_insert(Edje *ed, int id, int n, int v);
+
+double        _edje_var_list_nth_float_get(Edje *ed, int id, int n);
+void          _edje_var_list_nth_float_set(Edje *ed, int id, int n, double v);
+void          _edje_var_list_float_append(Edje *ed, int id, double v);
+void          _edje_var_list_float_prepend(Edje *ed, int id, double v);
+void          _edje_var_list_float_insert(Edje *ed, int id, int n, double v);
+
+const char   *_edje_var_list_nth_str_get(Edje *ed, int id, int n);
+void          _edje_var_list_nth_str_set(Edje *ed, int id, int n, const char *v);
+void          _edje_var_list_str_append(Edje *ed, int id, const char *v);
+void          _edje_var_list_str_prepend(Edje *ed, int id, const char *v);
+void          _edje_var_list_str_insert(Edje *ed, int id, int n, const char *v);
+
+int           _edje_var_timer_add           (Edje *ed, double in, const char *fname, int val);
+void          _edje_var_timer_del           (Edje *ed, int id);
+
+int           _edje_var_anim_add            (Edje *ed, double len, const char *fname, int val);
+void          _edje_var_anim_del            (Edje *ed, int id);
+
+void          _edje_message_init            (void);
+void          _edje_message_shutdown        (void);
+void          _edje_message_cb_set          (Edje *ed, void (*func) (void *data, Evas_Object *obj, Edje_Message_Type type, int id, void *msg), void *data);
+Edje_Message *_edje_message_new             (Edje *ed, Edje_Queue queue, Edje_Message_Type type, int id);
+void          _edje_message_free            (Edje_Message *em);
+void          _edje_message_send            (Edje *ed, Edje_Queue queue, Edje_Message_Type type, int id, void *emsg);
+void          _edje_message_parameters_push (Edje_Message *em);
+void          _edje_message_process         (Edje_Message *em);
+void          _edje_message_queue_process   (void);
+void          _edje_message_queue_clear     (void);
+void          _edje_message_del             (Edje *ed);
+
+void _edje_textblock_styles_add(Edje *ed);
+void _edje_textblock_styles_del(Edje *ed);
+void _edje_textblock_style_all_update(Edje *ed);
+void _edje_textblock_style_parse_and_fix(Edje_File *edf);
+void _edje_textblock_style_cleanup(Edje_File *edf);
+Edje_File *_edje_cache_file_coll_open(const char *file, const char *coll, int *error_ret, Edje_Part_Collection **edc_ret);
+void _edje_cache_coll_clean(Edje_File *edf);
+void _edje_cache_coll_flush(Edje_File *edf);
+void _edje_cache_coll_unref(Edje_File *edf, Edje_Part_Collection *edc);
+void _edje_cache_file_unref(Edje_File *edf);
+
+void _edje_embryo_globals_init(Edje *ed);
+
+#define CHKPARAM(n) if (params[0] != (sizeof(Embryo_Cell) * (n))) return -1;
+#define GETSTR(str, par) { \
+   Embryo_Cell *___cptr; \
+   int ___l; \
+   str = NULL; \
+   if ((___cptr = embryo_data_address_get(ep, (par)))) { \
+      ___l = embryo_data_string_length_get(ep, ___cptr); \
+      if (((str) = alloca(___l + 1))) \
+       embryo_data_string_get(ep, ___cptr, (str)); } }
+#define GETSTREVAS(str, par) { \
+   if ((str)) { \
+      if ((par) && (!strcmp((par), (str)))) return 0; \
+      if ((par)) evas_stringshare_del((par)); \
+      (par) = (char *)evas_stringshare_add((str)); } \
+   else (par) = NULL; }
+#define GETFLOAT(val, par) { \
+   float *___cptr; \
+   if ((___cptr = (float *)embryo_data_address_get(ep, (par)))) { \
+      val = *___cptr; } }
+#define GETINT(val, par) { \
+   int *___cptr; \
+   if ((___cptr = (int *)embryo_data_address_get(ep, (par)))) { \
+      val = *___cptr; } }
+#define SETSTR(str, par) { \
+   Embryo_Cell *___cptr; \
+   if ((___cptr = embryo_data_address_get(ep, (par)))) { \
+      embryo_data_string_set(ep, str, ___cptr); } }
+#define SETSTRALLOCATE(s) { \
+   if (s) { \
+      if (strlen((s)) < params[4]) { \
+        SETSTR((s), params[3]); } \
+      else { \
+        char *ss; \
+        ss = alloca(strlen((s)) + 1); \
+        strcpy(ss, (s)); \
+        ss[params[4] - 2] = 0; \
+        SETSTR(ss, params[3]); } } \
+   else \
+     SETSTR("", params[3]); }
+#define SETFLOAT(val, par) { \
+   float *___cptr; \
+   if ((___cptr = (float *)embryo_data_address_get(ep, (par)))) { \
+      *___cptr = (float)val; } }
+#define SETINT(val, par) { \
+   int *___cptr; \
+   if ((___cptr = (int *)embryo_data_address_get(ep, (par)))) { \
+      *___cptr = (int)val; } }
+
+int _edje_script_only(Edje *ed);
+void _edje_script_only_init(Edje *ed);
+void _edje_script_only_shutdown(Edje *ed);
+void _edje_script_only_show(Edje *ed);
+void _edje_script_only_hide(Edje *ed);
+void _edje_script_only_move(Edje *ed);
+void _edje_script_only_resize(Edje *ed);
+void _edje_script_only_message(Edje *ed, Edje_Message *em);
+    
+#endif
diff --git a/src/lib/edje_program.c b/src/lib/edje_program.c
new file mode 100644 (file)
index 0000000..f3a7ad4
--- /dev/null
@@ -0,0 +1,1050 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#include "edje_private.h"
+
+static void _edje_emit_cb(Edje *ed, const char *sig, const char *src);
+
+int             _edje_anim_count = 0;
+Ecore_Animator *_edje_timer = NULL;
+Evas_List      *_edje_animators = NULL;
+
+/************************** API Routines **************************/
+
+/* FIXDOC: Expand */
+/** Set the frametime
+ * @param t The frametime
+ *
+ * Sets the global frametime in seconds, by default this is 1/30.
+ */
+EAPI void
+edje_frametime_set(double t)
+{
+   ecore_animator_frametime_set(t);
+}
+
+/* FIXDOC: Expand */
+/** Get the frametime
+ * @return The frametime
+ *
+ * Returns the frametime in seconds, by default this is 1/30.
+ */
+EAPI double
+edje_frametime_get(void)
+{
+   return ecore_animator_frametime_get();
+}
+
+/* FIXDOC: Expand */
+/** Add a callback for a signal emitted by @a obj.
+ * @param obj A valid Evas_Object handle
+ * @param emission The signal name
+ * @param source The signal source
+ * @param func The callback function to be executed when the signal is emitted
+ * @param data A pointer to data to pass in to the callback function
+ *
+ * Connects a callback function to a signal emitted by @a obj.
+ * In EDC, a program can emit a signal as follows:
+ *
+ * @code
+ * program {
+ *   name: "emit_example";
+ *   action: SIGNAL_EMIT "a_signal" "a_source";
+ * }
+ * @endcode
+ *
+ * Assuming a function with the following declaration is definded:
+ *
+ * @code
+ * void cb_signal(void *data, Evas_Object *o, const char *emission, const char *source);
+ * @endcode
+ *
+ * a callback is attached using:
+ *
+ * @code
+ * edje_object_callback_add(obj, "a_signal", "a_source", cb_signal, data);
+ * @endcode
+ *
+ * Here, @a data is an arbitrary pointer to be used as desired.
+ * Note that @a emission and @a source correspond respectively to first and
+ * second parameters to the SIGNAL_EMIT action.
+ *
+ * Internal edje signals can also be attached to, and globs can be in either
+ * the emission or source name. e.g.
+ *
+ * @code
+ * edje_object_callback_add(obj, "mouse,down,*", "button.*", NULL);
+ * @endcode
+ *
+ * Here, any mouse down events on an edje part whose name begins with
+ * "button." will trigger the callback. The actual signal and source name
+ * will be passed in to the @a emission and @a source parameters of the
+ * callback function. (e.g. "mouse,down,2" and "button.close").
+ */
+EAPI void
+edje_object_signal_callback_add(Evas_Object *obj, const char *emission, const char *source, void (*func) (void *data, Evas_Object *o, const char *emission, const char *source), void *data)
+{
+   Edje *ed;
+   Edje_Signal_Callback *escb;
+
+   if ((!emission) || (!source) || (!func)) return;
+   ed = _edje_fetch(obj);
+   if (!ed) return;
+   if (ed->delete_me) return;
+   escb = calloc(1, sizeof(Edje_Signal_Callback));
+   if ((emission) && (emission[0]))
+     escb->signal = evas_stringshare_add(emission);
+   if ((source) && (source[0]))
+     escb->source = evas_stringshare_add(source);
+   escb->func = func;
+   escb->data = data;
+   ed->callbacks = evas_list_append(ed->callbacks, escb);
+   if (ed->walking_callbacks)
+     {
+       escb->just_added = 1;
+       ed->just_added_callbacks = 1;
+     }
+   else
+     _edje_callbacks_patterns_clean(ed);
+}
+
+/** Remove a callback from an object
+ * @param obj A valid Evas_Object handle
+ * @param emission the emission string
+ * @param source the source string
+ * @param func the callback function
+ * @return the data pointer
+ *
+ * Removes a callback from an object. The parameters @a emission, @a source
+ * and @a func must match exactly those passed to a previous call to
+ * edje_object_signal_callback_add(). The data pointer that was passed to
+ * this call will be returned.
+ */
+EAPI void *
+edje_object_signal_callback_del(Evas_Object *obj, const char *emission, const char *source, void (*func) (void *data, Evas_Object *o, const char *emission, const char *source))
+{
+   Edje *ed;
+   Evas_List *l;
+
+   if ((!emission) || (!source) || (!func)) return NULL;
+   ed = _edje_fetch(obj);
+   if (!ed) return NULL;
+   if (ed->delete_me) return NULL;
+   for (l = ed->callbacks; l; l = l->next)
+     {
+       Edje_Signal_Callback *escb;
+
+       escb = l->data;
+       if ((escb->func == func) &&
+           ((!escb->signal && !emission[0]) ||
+             (escb->signal && !strcmp(escb->signal, emission))) &&
+           ((!escb->source && !source[0]) ||
+             (escb->source && !strcmp(escb->source, source))))
+         {
+            void *data;
+
+            data = escb->data;
+            if (ed->walking_callbacks)
+              {
+                 escb->delete_me = 1;
+                 ed->delete_callbacks = 1;
+              }
+            else
+              {
+                 _edje_callbacks_patterns_clean(ed);
+
+                 ed->callbacks = evas_list_remove_list(ed->callbacks, l);
+                 if (escb->signal) evas_stringshare_del(escb->signal);
+                 if (escb->source) evas_stringshare_del(escb->source);
+                 free(escb);
+              }
+            return data;
+         }
+     }
+   return NULL;
+}
+
+/* FIXDOC: Verify/Expand */
+/** Send a signal to the Edje object
+ * @param obj A vaild Evas_Object handle
+ * @param emission The signal
+ * @param source The signal source
+ *
+ * This sends a signal to the edje object.
+ *
+ * An edje program can respond to a signal by specifying matching 'signal'
+ * and 'source' fields.
+ *
+ * E.g.
+ *
+ * @code
+ * edje_object_signal_emit(obj, "a_signal", "");
+ * @endcode
+ *
+ * will trigger a program whose edc is:
+ *
+ * @code
+ * program {
+ *  name: "a_program";
+ *  signal: "a_signal";
+ *  source: "";
+ *  action: ...
+ * }
+ * @endcode
+ *
+ * FIXME should this signal be sent to children also?
+ */
+EAPI void
+edje_object_signal_emit(Evas_Object *obj, const char *emission, const char *source)
+{
+   Edje *ed;
+
+   if ((!emission) || (!source)) return;
+   ed = _edje_fetch(obj);
+   if (!ed) return;
+   if (ed->delete_me) return;
+   _edje_emit(ed, (char *)emission, (char *)source);
+}
+
+/* FIXDOC: Verify/Expand */
+/** Set the Edje to play or pause
+ * @param obj A valid Evas_Object handle
+ * @param play Play instruction (1 to play, 0 to pause)
+ *
+ * This sets the Edje to play or pause depending on the parameter.
+ * This has no effect if the Edje is already in that state.
+ */
+EAPI void
+edje_object_play_set(Evas_Object *obj, int play)
+{
+   Edje *ed;
+   double t;
+   Evas_List *l;
+   int i;
+
+   ed = _edje_fetch(obj);
+   if (!ed) return;
+   if (ed->delete_me) return;
+   if (play)
+     {
+       if (!ed->paused) return;
+       ed->paused = 0;
+       t = ecore_time_get() - ed->paused_at;
+       for (l = ed->actions; l; l = l->next)
+         {
+            Edje_Running_Program *runp;
+
+            runp = l->data;
+            runp->start_time += t;
+         }
+     }
+   else
+     {
+       if (ed->paused) return;
+       ed->paused = 1;
+       ed->paused_at = ecore_time_get();
+     }
+
+   for (i = 0; i < ed->table_parts_size; i++)
+     {
+       Edje_Real_Part *rp;
+       rp = ed->table_parts[i];
+       if (rp->part->type == EDJE_PART_TYPE_GROUP && rp->swallowed_object)
+         edje_object_play_set(rp->swallowed_object, play);
+     }
+}
+
+/* FIXDOC: Verify/Expand */
+/** Get the Edje play/pause state
+ * @param obj A valid Evas_Object handle
+ * @return 0 if Edje not connected, Edje delete_me, or Edje paused\n
+ * 1 if Edje set to play
+ */
+EAPI int
+edje_object_play_get(const Evas_Object *obj)
+{
+   Edje *ed;
+
+   ed = _edje_fetch(obj);
+   if (!ed) return 0;
+   if (ed->delete_me) return 0;
+   if (ed->paused) return 0;
+   return 1;
+}
+
+/* FIXDOC: Verify/Expand */
+/** Set Animation state
+ * @param obj A valid Evas_Object handle
+ * @param on Animation State
+ *
+ * Stop or start an Edje animation.
+ */
+EAPI void
+edje_object_animation_set(Evas_Object *obj, int on)
+{
+   Edje *ed;
+   Evas_List *l;
+   int i;
+
+   ed = _edje_fetch(obj);
+   if (!ed) return;
+   if (ed->delete_me) return;
+   _edje_block(ed);
+   ed->no_anim = !on;
+   _edje_freeze(ed);
+   if (!on)
+     {
+       Evas_List *newl = NULL;
+
+       for (l = ed->actions; l; l = l->next)
+         newl = evas_list_append(newl, l->data);
+       while (newl)
+         {
+            Edje_Running_Program *runp;
+
+            runp = newl->data;
+            newl = evas_list_remove(newl, newl->data);
+            _edje_program_run_iterate(runp, runp->start_time + runp->program->tween.time);
+            if (_edje_block_break(ed))
+              {
+                 evas_list_free(newl);
+                 goto break_prog;
+              }
+         }
+     }
+   else
+     {
+       _edje_emit(ed, "load", NULL);
+       if (evas_object_visible_get(obj))
+         {
+            evas_object_hide(obj);
+            evas_object_show(obj);
+         }
+     }
+   break_prog:
+
+   for (i = 0; i < ed->table_parts_size; i++)
+     {
+       Edje_Real_Part *rp;
+       rp = ed->table_parts[i];
+       if (rp->part->type == EDJE_PART_TYPE_GROUP && rp->swallowed_object)
+         edje_object_animation_set(rp->swallowed_object, on);
+     }
+
+   _edje_thaw(ed);
+   _edje_unblock(ed);
+}
+
+/* FIXDOC: Verify/Expand */
+/** Get the animation state
+ * @param obj A valid Evas_Object handle
+ * @return 0 on Error or if not animated\n
+ * 1 if animated
+ */
+EAPI int
+edje_object_animation_get(const Evas_Object *obj)
+{
+   Edje *ed;
+
+   ed = _edje_fetch(obj);
+   if (!ed) return 0;
+   if (ed->delete_me) return 0;
+   if (ed->no_anim) return 0;
+   return 1;
+}
+
+/* Private Routines */
+
+int
+_edje_program_run_iterate(Edje_Running_Program *runp, double tim)
+{
+   double t, total;
+   Evas_List *l;
+   Edje *ed;
+
+   ed = runp->edje;
+   if (ed->delete_me) return 0;
+   _edje_block(ed);
+   _edje_ref(ed);
+   _edje_freeze(ed);
+   t = tim - runp->start_time;
+   total = runp->program->tween.time;
+   t /= total;
+   if (t > 1.0) t = 1.0;
+   for (l = runp->program->targets; l; l = l->next)
+     {
+       Edje_Real_Part *rp;
+       Edje_Program_Target *pt;
+
+       pt = l->data;
+       if (pt->id >= 0)
+         {
+            rp = ed->table_parts[pt->id % ed->table_parts_size];
+            if (rp) _edje_part_pos_set(ed, rp,
+                                       runp->program->tween.mode, t);
+         }
+     }
+   if (t >= 1.0)
+     {
+       for (l = runp->program->targets; l; l = l->next)
+         {
+            Edje_Real_Part *rp;
+            Edje_Program_Target *pt;
+
+            pt = l->data;
+            if (pt->id >= 0)
+              {
+                 rp = ed->table_parts[pt->id % ed->table_parts_size];
+                 if (rp)
+                   {
+                      _edje_part_description_apply(ed, rp,
+                                                   runp->program->state,
+                                                   runp->program->value,
+                                                   NULL,
+                                                   0.0);
+                      _edje_part_pos_set(ed, rp,
+                                         runp->program->tween.mode, 0.0);
+                      rp->program = NULL;
+                   }
+              }
+         }
+       _edje_recalc(ed);
+       runp->delete_me = 1;
+       if (!ed->walking_actions)
+         {
+            _edje_anim_count--;
+            ed->actions = evas_list_remove(ed->actions, runp);
+            if (!ed->actions)
+              _edje_animators = evas_list_remove(_edje_animators, ed);
+         }
+       _edje_emit(ed, "program,stop", runp->program->name);
+       if (_edje_block_break(ed))
+         {
+            if (!ed->walking_actions) free(runp);
+            goto break_prog;
+         }
+       for (l = runp->program->after; l; l = l->next)
+         {
+            Edje_Program *pr;
+            Edje_Program_After *pa = l->data;
+
+            if (pa->id >= 0)
+              {
+                 pr = ed->table_programs[pa->id % ed->table_programs_size];
+                 if (pr) _edje_program_run(ed, pr, 0, "", "");
+                 if (_edje_block_break(ed))
+                   {
+                      if (!ed->walking_actions) free(runp);
+                      goto break_prog;
+                   }
+              }
+         }
+       _edje_thaw(ed);
+       _edje_unref(ed);
+       if (!ed->walking_actions) free(runp);
+       _edje_unblock(ed);
+       return  0;
+     }
+   break_prog:
+   _edje_recalc(ed);
+   _edje_thaw(ed);
+   _edje_unref(ed);
+   _edje_unblock(ed);
+   return 1;
+}
+
+void
+_edje_program_end(Edje *ed, Edje_Running_Program *runp)
+{
+   Evas_List *l;
+   const char *pname = NULL;
+   int free_runp = 0;
+
+   if (ed->delete_me) return;
+   _edje_ref(ed);
+   _edje_freeze(ed);
+   for (l = runp->program->targets; l; l = l->next)
+     {
+       Edje_Real_Part *rp;
+       Edje_Program_Target *pt;
+
+       pt = l->data;
+       if (pt->id >= 0)
+         {
+            rp = ed->table_parts[pt->id % ed->table_parts_size];
+            if (rp)
+              {
+                 _edje_part_description_apply(ed, rp,
+                                              runp->program->state,
+                                              runp->program->value,
+                                              NULL,
+                                              0.0);
+                 _edje_part_pos_set(ed, rp,
+                                    runp->program->tween.mode, 0.0);
+                 rp->program = NULL;
+              }
+         }
+     }
+   _edje_recalc(ed);
+   runp->delete_me = 1;
+   pname = runp->program->name;
+   if (!ed->walking_actions)
+     {
+       _edje_anim_count--;
+       ed->actions = evas_list_remove(ed->actions, runp);
+       free_runp = 1;
+       if (!ed->actions)
+         {
+            _edje_animators = evas_list_remove(_edje_animators, ed);
+         }
+     }
+   _edje_emit(ed, "program,stop", pname);
+   _edje_thaw(ed);
+   _edje_unref(ed);
+   if (free_runp) free(runp);
+}
+
+void
+_edje_program_run(Edje *ed, Edje_Program *pr, int force, const char *ssig, const char *ssrc)
+{
+   Evas_List *l;
+   /* limit self-feeding loops in programs to 64 levels */
+   static int recursions = 0;
+   static int recursion_limit = 0;
+
+   if (ed->delete_me) return;
+   if ((pr->in.from > 0.0) && (pr->in.range >= 0.0) && (!force))
+     {
+       Edje_Pending_Program *pp;
+       double r = 0.0;
+
+       pp = calloc(1, sizeof(Edje_Pending_Program));
+       if (!pp) return;
+       if (pr->in.range > 0.0) r = ((double)rand() / RAND_MAX);
+       pp->timer = ecore_timer_add(pr->in.from + (pr->in.range * r),
+                                   _edje_pending_timer_cb, pp);
+       if (!pp->timer)
+         {
+            free(pp);
+            return;
+         }
+       pp->edje = ed;
+       pp->program = pr;
+       ed->pending_actions = evas_list_append(ed->pending_actions, pp);
+       return;
+     }
+   if ((recursions >= 64) || (recursion_limit))
+     {
+       printf("EDJE ERROR: programs recursing up to recursion limit of %i. Disabled.\n",
+              64);
+       recursion_limit = 1;
+       return;
+     }
+   recursions++;
+   _edje_block(ed);
+   _edje_ref(ed);
+   _edje_freeze(ed);
+   if (pr->action == EDJE_ACTION_TYPE_STATE_SET)
+     {
+       if ((pr->tween.time > 0.0) && (!ed->no_anim))
+         {
+            Edje_Running_Program *runp;
+
+            runp = calloc(1, sizeof(Edje_Running_Program));
+            for (l = pr->targets; l; l = l->next)
+              {
+                 Edje_Real_Part *rp;
+                 Edje_Program_Target *pt;
+
+                 pt = l->data;
+                 if (pt->id >= 0)
+                   {
+                      rp = ed->table_parts[pt->id % ed->table_parts_size];
+                      if (rp)
+                        {
+                           if (rp->program)
+                             _edje_program_end(ed, rp->program);
+                           _edje_part_description_apply(ed, rp,
+                                                        rp->param1.description->state.name,
+                                                        rp->param1.description->state.value,
+                                                        pr->state,
+                                                        pr->value);
+                           _edje_part_pos_set(ed, rp, pr->tween.mode, 0.0);
+                           rp->program = runp;
+                        }
+                   }
+              }
+            _edje_emit(ed, "program,start", pr->name);
+            if (_edje_block_break(ed))
+              {
+                 ed->actions = evas_list_append(ed->actions, runp);
+                 goto break_prog;
+              }
+            if (!ed->actions)
+              _edje_animators = evas_list_append(_edje_animators, ed);
+            ed->actions = evas_list_append(ed->actions, runp);
+            runp->start_time = ecore_time_get();
+            runp->edje = ed;
+            runp->program = pr;
+            if (!_edje_timer)
+              _edje_timer = ecore_animator_add(_edje_timer_cb, NULL);
+            _edje_anim_count++;
+         }
+       else
+         {
+            for (l = pr->targets; l; l = l->next)
+              {
+                 Edje_Real_Part *rp;
+                 Edje_Program_Target *pt;
+
+                 pt = l->data;
+                 if (pt->id >= 0)
+                   {
+                      rp = ed->table_parts[pt->id % ed->table_parts_size];
+                      if (rp)
+                        {
+                           if (rp->program)
+                             _edje_program_end(ed, rp->program);
+                           _edje_part_description_apply(ed, rp,
+                                                        pr->state,
+                                                        pr->value,
+                                                        NULL,
+                                                        0.0);
+                           _edje_part_pos_set(ed, rp, pr->tween.mode, 0.0);
+                        }
+                   }
+              }
+            _edje_emit(ed, "program,start", pr->name);
+            if (_edje_block_break(ed)) goto break_prog;
+            _edje_emit(ed, "program,stop", pr->name);
+            if (_edje_block_break(ed)) goto break_prog;
+
+            for (l = pr->after; l; l = l->next)
+              {
+                 Edje_Program *pr2;
+                 Edje_Program_After *pa = l->data;
+
+                 if (pa->id >= 0)
+                   {
+                      pr2 = ed->table_programs[pa->id % ed->table_programs_size];
+                      if (pr2) _edje_program_run(ed, pr2, 0, "", "");
+                      if (_edje_block_break(ed)) goto break_prog;
+                   }
+              }
+            _edje_recalc(ed);
+         }
+     }
+   else if (pr->action == EDJE_ACTION_TYPE_ACTION_STOP)
+     {
+       _edje_emit(ed, "program,start", pr->name);
+       for (l = pr->targets; l; l = l->next)
+         {
+            Edje_Program_Target *pt;
+            Evas_List *ll;
+
+            pt = l->data;
+            for (ll = ed->actions; ll; ll = ll->next)
+              {
+                 Edje_Running_Program *runp;
+
+                 runp = ll->data;
+                 if (pt->id == runp->program->id)
+                   {
+                      _edje_program_end(ed, runp);
+                      goto done;
+                   }
+              }
+            for (ll = ed->pending_actions; ll; ll = ll->next)
+              {
+                 Edje_Pending_Program *pp;
+
+                 pp = ll->data;
+                 if (pt->id == pp->program->id)
+                   {
+                      ed->pending_actions = evas_list_remove(ed->pending_actions, pp);
+                      ecore_timer_del(pp->timer);
+                      free(pp);
+                      goto done;
+                   }
+              }
+            done:
+               continue;
+         }
+       _edje_emit(ed, "program,stop", pr->name);
+       if (_edje_block_break(ed)) goto break_prog;
+     }
+   else if (pr->action == EDJE_ACTION_TYPE_SIGNAL_EMIT)
+     {
+       _edje_emit(ed, "program,start", pr->name);
+       if (_edje_block_break(ed)) goto break_prog;
+       _edje_emit(ed, pr->state, pr->state2);
+       if (_edje_block_break(ed)) goto break_prog;
+       _edje_emit(ed, "program,stop", pr->name);
+       if (_edje_block_break(ed)) goto break_prog;
+     }
+   else if (pr->action == EDJE_ACTION_TYPE_DRAG_VAL_SET)
+     {
+       _edje_emit(ed, "program,start", pr->name);
+       if (_edje_block_break(ed)) goto break_prog;
+       for (l = pr->targets; l; l = l->next)
+         {
+            Edje_Real_Part *rp;
+            Edje_Program_Target *pt;
+
+            pt = l->data;
+            if (pt->id >= 0)
+              {
+                 rp = ed->table_parts[pt->id % ed->table_parts_size];
+                 if ((rp) && (rp->drag.down.count == 0))
+                   {
+                      rp->drag.val.x = pr->value;
+                      rp->drag.val.y = pr->value2;
+                      if      (rp->drag.val.x < 0.0) rp->drag.val.x = 0.0;
+                      else if (rp->drag.val.x > 1.0) rp->drag.val.x = 1.0;
+                      if      (rp->drag.val.y < 0.0) rp->drag.val.y = 0.0;
+                      else if (rp->drag.val.y > 1.0) rp->drag.val.y = 1.0;
+                      _edje_dragable_pos_set(ed, rp, rp->drag.val.x, rp->drag.val.y);
+                      _edje_emit(ed, "drag,set", rp->part->name);
+                      if (_edje_block_break(ed)) goto break_prog;
+                   }
+              }
+         }
+       _edje_emit(ed, "program,stop", pr->name);
+       if (_edje_block_break(ed)) goto break_prog;
+     }
+   else if (pr->action == EDJE_ACTION_TYPE_DRAG_VAL_STEP)
+     {
+       _edje_emit(ed, "program,start", pr->name);
+       if (_edje_block_break(ed)) goto break_prog;
+       for (l = pr->targets; l; l = l->next)
+         {
+            Edje_Real_Part *rp;
+            Edje_Program_Target *pt;
+
+            pt = l->data;
+            if (pt->id >= 0)
+              {
+                 rp = ed->table_parts[pt->id % ed->table_parts_size];
+                 if ((rp) && (rp->drag.down.count == 0))
+                   {
+                      rp->drag.val.x += pr->value * rp->drag.step.x * rp->part->dragable.x;
+                      rp->drag.val.y += pr->value2 * rp->drag.step.y * rp->part->dragable.y;
+                      if      (rp->drag.val.x < 0.0) rp->drag.val.x = 0.0;
+                      else if (rp->drag.val.x > 1.0) rp->drag.val.x = 1.0;
+                      if      (rp->drag.val.y < 0.0) rp->drag.val.y = 0.0;
+                      else if (rp->drag.val.y > 1.0) rp->drag.val.y = 1.0;
+                      _edje_dragable_pos_set(ed, rp, rp->drag.val.x, rp->drag.val.y);
+                      _edje_emit(ed, "drag,step", rp->part->name);
+                      if (_edje_block_break(ed)) goto break_prog;
+                   }
+              }
+         }
+       _edje_emit(ed, "program,stop", pr->name);
+       if (_edje_block_break(ed)) goto break_prog;
+     }
+   else if (pr->action == EDJE_ACTION_TYPE_DRAG_VAL_PAGE)
+     {
+       _edje_emit(ed, "program,start", pr->name);
+       if (_edje_block_break(ed)) goto break_prog;
+       for (l = pr->targets; l; l = l->next)
+         {
+            Edje_Real_Part *rp;
+            Edje_Program_Target *pt;
+
+            pt = l->data;
+            if (pt->id >= 0)
+              {
+                 rp = ed->table_parts[pt->id % ed->table_parts_size];
+                 if ((rp) && (rp->drag.down.count == 0))
+                   {
+                      rp->drag.val.x += pr->value * rp->drag.page.x * rp->part->dragable.x;
+                      rp->drag.val.y += pr->value2 * rp->drag.page.y * rp->part->dragable.y;
+                      if      (rp->drag.val.x < 0.0) rp->drag.val.x = 0.0;
+                      else if (rp->drag.val.x > 1.0) rp->drag.val.x = 1.0;
+                      if      (rp->drag.val.y < 0.0) rp->drag.val.y = 0.0;
+                      else if (rp->drag.val.y > 1.0) rp->drag.val.y = 1.0;
+                      _edje_dragable_pos_set(ed, rp, rp->drag.val.x, rp->drag.val.y);
+                      _edje_emit(ed, "drag,page", rp->part->name);
+                      if (_edje_block_break(ed)) goto break_prog;
+                   }
+              }
+         }
+       _edje_emit(ed, "program,stop", pr->name);
+       if (_edje_block_break(ed)) goto break_prog;
+     }
+   else if (pr->action == EDJE_ACTION_TYPE_SCRIPT)
+     {
+       char fname[128];
+
+       _edje_emit(ed, "program,start", pr->name);
+       if (_edje_block_break(ed)) goto break_prog;
+       snprintf(fname, sizeof(fname), "_p%i", pr->id);
+       _edje_embryo_test_run(ed, fname, ssig, ssrc);
+       _edje_emit(ed, "program,stop", pr->name);
+       if (_edje_block_break(ed)) goto break_prog;
+       _edje_recalc(ed);
+     }
+   else
+     {
+       _edje_emit(ed, "program,start", pr->name);
+       _edje_emit(ed, "program,stop", pr->name);
+     }
+   if (!((pr->action == EDJE_ACTION_TYPE_STATE_SET)
+        /* hmm this fucks somethgin up. must look into it later */
+        /* && (pr->tween.time > 0.0) && (!ed->no_anim))) */
+        ))
+     {
+       for (l= pr->after; l; l = l->next)
+         {
+            Edje_Program *pr2;
+            Edje_Program_After *pa = l->data;
+
+            if (pa->id >= 0)
+              {
+                 pr2 = ed->table_programs[pa->id % ed->table_programs_size];
+                 if (pr2) _edje_program_run(ed, pr2, 0, "", "");
+                 if (_edje_block_break(ed)) goto break_prog;
+              }
+         }
+     }
+   break_prog:
+   _edje_thaw(ed);
+   _edje_unref(ed);
+   recursions--;
+   if (recursions == 0) recursion_limit = 0;
+   _edje_unblock(ed);
+}
+
+void
+_edje_emit(Edje *ed, const char *sig, const char *src)
+{
+   Edje_Message_Signal emsg;
+
+   if (ed->delete_me) return;
+   emsg.sig = sig;
+   emsg.src = src;
+   _edje_message_send(ed, EDJE_QUEUE_SCRIPT, EDJE_MESSAGE_SIGNAL, 0, &emsg);
+}
+
+struct _Edje_Program_Data
+{
+#ifdef EDJE_PROGRAM_CACHE
+  Evas_List     *matches;
+  int            matched;
+#endif
+  Edje          *ed;
+  const char    *signal;
+  const char    *source;
+};
+
+static int _edje_glob_callback(Edje_Program *pr, void *dt)
+{
+   struct _Edje_Program_Data    *data = dt;
+
+#ifdef EDJE_PROGRAM_CACHE
+   data->matched++;
+#endif
+
+   _edje_program_run(data->ed, pr, 0, data->signal, data->source);
+   if (_edje_block_break(data->ed))
+     {
+#ifdef EDJE_PROGRAM_CACHE
+        evas_list_free(data->matches);
+        data->matches = NULL;
+#endif
+        return 1;
+     }
+
+#ifdef EDJE_PROGRAM_CACHE
+   data->matches = evas_list_append(data->matches, pr);
+#endif
+
+   return 0;
+}
+
+
+void
+_edje_callbacks_patterns_clean(Edje *ed)
+{
+   _edje_signals_sources_patterns_clean(&ed->patterns.callbacks);
+}
+
+static void
+_edje_callbacks_patterns_init(Edje *ed)
+{
+   Edje_Signals_Sources_Patterns *ssp = &ed->patterns.callbacks;
+
+   if (ssp->signals_patterns)
+     return;
+
+   ssp->signals_patterns = edje_match_callback_signal_init(ed->callbacks);
+   ssp->sources_patterns = edje_match_callback_source_init(ed->callbacks);
+}
+
+/* FIXME: what if we delete the evas object??? */
+void
+_edje_emit_handle(Edje *ed, const char *sig, const char *src)
+{
+   if (ed->delete_me) return;
+   if (!sig) sig = "";
+   if (!src) src = "";
+//   printf("EDJE EMIT: signal: \"%s\" source: \"%s\"\n", sig, src);
+   _edje_block(ed);
+   _edje_ref(ed);
+   _edje_freeze(ed);
+   if (ed->collection)
+     {
+       Edje_Part_Collection *ec;
+#ifdef EDJE_PROGRAM_CACHE
+       char *tmps;
+       int l1, l2;
+#endif
+       int done;
+
+       ec = ed->collection;
+#ifdef EDJE_PROGRAM_CACHE
+       l1 = strlen(sig);
+       l2 = strlen(src);
+       tmps = alloca(l1 + l2 + 2);
+       strcpy(tmps, sig);
+       tmps[l1] = '\377';
+       strcpy(&(tmps[l1 + 1]), src);
+#endif
+       done = 0;
+
+#ifdef EDJE_PROGRAM_CACHE
+         {
+            Evas_List *matches;
+
+            if (evas_hash_find(ec->prog_cache.no_matches, tmps))
+              {
+                 done = 1;
+              }
+            else if ((matches = evas_hash_find(ec->prog_cache.matches, tmps)))
+              {
+                 for (l = matches; l; l = l->next)
+                   {
+                      Edje_Program *pr;
+
+                      pr = l->data;
+                      _edje_program_run(ed, pr, 0, sig, src);
+                      if (_edje_block_break(ed))
+                        {
+                           goto break_prog;
+                        }
+                   }
+                 done = 1;
+              }
+         }
+#endif
+       if (!done)
+         {
+             struct _Edje_Program_Data  data;
+
+             data.ed = ed;
+             data.source = src;
+             data.signal = sig;
+#ifdef EDJE_PROGRAM_CACHE
+            data.matched = 0;
+            data.matches = NULL;
+#endif
+             if (ed->collection->programs)
+               {
+                  if (edje_match_programs_exec(ed->patterns.programs.signals_patterns,
+                                               ed->patterns.programs.sources_patterns,
+                                               sig,
+                                               src,
+                                               ed->collection->programs,
+                                               _edje_glob_callback,
+                                               &data) == 0)
+                    goto break_prog;
+               }
+
+#ifdef EDJE_PROGRAM_CACHE
+            if (tmps)
+              {
+                 if (matched == 0)
+                   ec->prog_cache.no_matches =
+                   evas_hash_add(ec->prog_cache.no_matches, tmps, ed);
+                 else
+                   ec->prog_cache.matches =
+                   evas_hash_add(ec->prog_cache.matches, tmps, data.matches);
+              }
+#endif
+         }
+       _edje_emit_cb(ed, sig, src);
+       if (_edje_block_break(ed))
+         {
+            goto break_prog;
+         }
+     }
+   break_prog:
+   _edje_thaw(ed);
+   _edje_unref(ed);
+   _edje_unblock(ed);
+}
+
+/* FIXME: what if we delete the evas object??? */
+static void
+_edje_emit_cb(Edje *ed, const char *sig, const char *src)
+{
+   Evas_List            *l;
+
+   if (ed->delete_me) return;
+   _edje_ref(ed);
+   _edje_freeze(ed);
+   _edje_block(ed);
+
+   if (ed->just_added_callbacks)
+     _edje_callbacks_patterns_clean(ed);
+
+   ed->walking_callbacks = 1;
+
+   if (ed->callbacks)
+     {
+        int     r;
+
+       _edje_callbacks_patterns_init(ed);
+        r = edje_match_callback_exec(ed->patterns.callbacks.signals_patterns,
+                                     ed->patterns.callbacks.sources_patterns,
+                                     sig,
+                                     src,
+                                     ed->callbacks,
+                                     ed);
+
+        if (!r)
+          goto break_prog;
+     }
+
+   ed->walking_callbacks = 0;
+   if ((ed->delete_callbacks) || (ed->just_added_callbacks))
+     {
+       ed->delete_callbacks = 0;
+       ed->just_added_callbacks = 0;
+       for (l = ed->callbacks; l;)
+         {
+            Edje_Signal_Callback *escb;
+            Evas_List *next_l;
+
+            escb = l->data;
+            next_l = l->next;
+            if (escb->just_added)
+              escb->just_added = 0;
+            if (escb->delete_me)
+              {
+                 ed->callbacks = evas_list_remove_list(ed->callbacks, l);
+                 if (escb->signal) evas_stringshare_del(escb->signal);
+                 if (escb->source) evas_stringshare_del(escb->source);
+                 free(escb);
+              }
+            l = next_l;
+         }
+
+        _edje_callbacks_patterns_clean(ed);
+     }
+   break_prog:
+   _edje_unblock(ed);
+   _edje_thaw(ed);
+   _edje_unref(ed);
+}
diff --git a/src/lib/edje_script_only.c b/src/lib/edje_script_only.c
new file mode 100644 (file)
index 0000000..0dffa7b
--- /dev/null
@@ -0,0 +1,585 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#include "edje_private.h"
+
+/*
+ * ALREADY EXPORTED BY EMBRYO:
+ *
+ * enum Float_Round_Method {
+ *    ROUND, FLOOR, CEIL, TOZERO
+ * };
+ * enum Float_Angle_Mode {
+ *    RADIAN, DEGREES, GRADES
+ * };
+ *
+ * numargs();
+ * getarg(arg, index=0);
+ * setarg(arg, index=0, value);
+ *
+ * Float:atof(string[]);
+ * Float:fract(Float:value);
+ *       round(Float:value, Float_Round_Method:method=ROUND);
+ * Float:sqrt(Float:value);
+ * Float:pow(Float:value, Float:exponent);
+ * Float:log(Float:value, Float:base=10.0);
+ * Float:sin(Float:value, Float_Angle_Mode:mode=RADIAN);
+ * Float:cos(Float:value, Float_Angle_Mode:mode=RADIAN);
+ * Float:tan(Float:value, Float_Angle_Mode:mode=RADIAN);
+ * Float:abs(Float:value);
+ *       atoi(str[]);
+ *       fnmatch(glob[], str[]);
+ *       strcmp(str1[], str2[]);
+ *       strncmp(str1[], str2[]);
+ *       strcpy(dst[], src[]);
+ *       strncpy(dst[], src[], n);
+ *       strlen(str[]);
+ *       strcat(dst[], src[]);
+ *       strncat(dst[], src[], n);
+ *       strprep(dst[], src[]);
+ *       strnprep(dst[], src[], n);
+ *       strcut(dst[], str[], n, n2);
+ *       snprintf(dst[], dstn, fmt[], ...);
+ *       strstr(str[], ndl[]);
+ *       strchr(str[], ch[]);
+ *       strrchr(str[], ch[]);
+ *       rand();
+ * Float:randf();
+ * Float:seconds();
+ *       date(&year, &month, &day, &yearday, &weekday, &hr, &min, &Float:sec);
+ *
+ */
+
+typedef struct _Sinfo Sinfo;
+
+struct _Sinfo
+{
+   struct {
+      Embryo_Function
+       obj_init, obj_shutdown, obj_show, obj_show_immediate,
+       obj_hide, obj_hide_immediate, obj_move, obj_move_immediate,
+       obj_resize, obj_resize_immediate, obj_message
+       ;
+   } fn;
+   struct {
+      Ecore_Job 
+       *show, *hide, *move, *resize
+       ;
+   } job;
+   struct {
+      int id;
+      Evas_Hash *hash; // FIXME: hash -> bad. too big. one-way lookup etc.
+   } oid;
+};
+
+static void _call_fn(Edje *ed, const char *fname, Embryo_Function fn);
+
+/* frankly - these make the code shorter to type and read - just sanity for
+ * development */
+#define IFFN(func) if (si->fn.func != EMBRYO_FUNCTION_NONE)
+#define IFNO(func) if (si->fn.func == EMBRYO_FUNCTION_NONE)
+#define CLFN(func) IFFN(func) {_call_fn(ed, #func, si->fn.func);}
+#define SI Sinfo *si; si = ed->script_only_data; if (!si) return
+#define SI_RETURN(ret) Sinfo *si; si = ed->script_only_data; if (!si) return (ret)
+#define PINT(val) embryo_parameter_cell_push(ed->collection->script, (Embryo_Cell)(val))
+#define PSTR(val) embryo_parameter_string_push(ed->collection->script, val)
+#define GTFN(func) si->fn.func = embryo_program_function_find(ed->collection->script, #func)
+#define DELJ(type) if (si->job.type) ecore_job_del(si->job.type);
+#define ADDJ(type, func) si->job.type = ecore_job_add(func, ed);
+#define ZERJ(type) si->job.type = NULL;
+#define IFNJ(type) if (!si->job.type)
+#define EXPF(func) embryo_program_native_call_add(ed->collection->script, #func, _exp_##func)
+
+typedef struct _Oid Oid;
+
+struct _Oid
+{
+   Edje *ed;
+   Evas_Object *obj;
+   Evas_Coord x, y, w, h;
+   int oid;
+};
+
+/* FIXME: using evas_hash and strings is just nasty! make a custom int hash */
+static int
+_oid_alloc(Edje *ed)
+{
+   SI_RETURN(0);
+   
+   si->oid.id++;
+   return si->oid.id;
+}
+
+static Oid *
+_oid_track(Edje *ed, Evas_Object *o)
+{
+   Oid *oi;
+   char buf[64];
+   SI_RETURN(NULL);
+   
+   oi = calloc(1, sizeof(Oid));
+   if (!oi) return NULL;
+   oi->oid = _oid_alloc(ed);
+   if (!oi->oid)
+     {
+       free(oi);
+       return NULL;
+     }
+   oi->ed = ed;
+   oi->obj = o;
+   evas_object_smart_member_add(oi->obj, oi->ed->obj);
+   evas_object_clip_set(oi->obj, oi->ed->clipper);
+   evas_object_geometry_get(oi->obj, &(oi->x), &(oi->y), &(oi->w), &(oi->h));
+   snprintf(buf, sizeof(buf), "%i", oi->oid);
+   si->oid.hash = evas_hash_add(si->oid.hash, buf, oi);
+   return oi;
+}
+
+static Oid *
+_oid_find(Edje *ed, int oid)
+{
+   char buf[64];
+   SI_RETURN(NULL);
+
+   snprintf(buf, sizeof(buf), "%i", oid);
+   return evas_hash_find(si->oid.hash, buf);
+}
+
+static void
+_oid_del(Edje *ed, int oid)
+{
+   char buf[64];
+   SI;
+
+   snprintf(buf, sizeof(buf), "%i", oid);
+   si->oid.hash = evas_hash_del(si->oid.hash, buf, NULL);
+}
+
+static void
+_oid_free(Oid *oid)
+{
+   free(oid);
+}
+
+static Evas_Bool
+_oid_freeall_cb(const Evas_Hash *hash, const char *key, void *data, void *fdata)
+{
+   Oid *oid = data;
+   evas_object_del(oid->obj);
+   free(oid);
+   return 1;
+}
+
+static void
+_oid_freeall(Edje *ed)
+{
+   SI;
+   if (!si->oid.hash) return;
+   evas_hash_foreach(si->oid.hash, _oid_freeall_cb, ed);
+   evas_hash_free(si->oid.hash);
+   si->oid.hash = NULL;
+}
+
+static Evas_Bool
+_oid_moveall_cb(const Evas_Hash *hash, const char *key, void *data, void *fdata)
+{
+   Oid *oid = data;
+   evas_object_move(oid->obj, oid->ed->x + oid->x, oid->ed->y + oid->y);
+   return 1;
+}
+
+static void
+_oid_moveall(Edje *ed)
+{
+   SI;
+   if (!si->oid.hash) return;
+   evas_hash_foreach(si->oid.hash, _oid_moveall_cb, ed);
+}
+
+/**********/
+
+static Embryo_Cell
+_exp_e_obj_del(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed = embryo_program_data_get(ep);
+   Oid *oid;
+   SI_RETURN(-1);
+
+   CHKPARAM(1);
+   if (!(oid = _oid_find(ed, params[1]))) return -1;
+   evas_object_del(oid->obj);
+   _oid_del(ed, oid->oid);
+   _oid_free(oid);
+   return 0;
+}
+    
+static Embryo_Cell
+_exp_e_obj_rect_add(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed = embryo_program_data_get(ep);
+   Evas_Object *o;
+   Oid *oid;
+   SI_RETURN(-1);
+   
+   o = evas_object_rectangle_add(evas_object_evas_get(ed->obj));
+   if (!o) return 0;
+   oid = _oid_track(ed, o);
+   if (oid) return oid->oid;
+   return 0;
+}
+    
+static Embryo_Cell
+_exp_e_obj_show(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed = embryo_program_data_get(ep);
+   Oid *oid;
+   SI_RETURN(-1);
+
+   CHKPARAM(1);
+   if (!(oid = _oid_find(ed, params[1]))) return -1;
+   evas_object_show(oid->obj);
+   return 0;
+}
+    
+static Embryo_Cell
+_exp_e_obj_hide(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed = embryo_program_data_get(ep);
+   Oid *oid;
+   SI_RETURN(-1);
+
+   CHKPARAM(1);
+   if (!(oid = _oid_find(ed, params[1]))) return -1;
+   evas_object_hide(oid->obj);
+   return 0;
+}
+    
+static Embryo_Cell
+_exp_e_obj_move(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed = embryo_program_data_get(ep);
+   Oid *oid;
+   SI_RETURN(-1);
+   
+   CHKPARAM(3);
+   if (!(oid = _oid_find(ed, params[1]))) return -1;
+   if ((oid->x == params[2]) && (oid->y == params[3])) return -1;
+   oid->x = params[2];
+   oid->y = params[3];
+   evas_object_move(oid->obj, ed->x + oid->x, ed->y + oid->y);
+   return 0;
+}
+    
+static Embryo_Cell
+_exp_e_obj_resize(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed = embryo_program_data_get(ep);
+   Oid *oid;
+   SI_RETURN(-1);
+   
+   CHKPARAM(3);
+   if (!(oid = _oid_find(ed, params[1]))) return -1;
+   if ((oid->w == params[2]) && (oid->h == params[3])) return -1;
+   oid->w = params[2];
+   oid->h = params[3];
+   evas_object_resize(oid->obj, oid->w, oid->h);
+   return 0;
+}
+    
+static Embryo_Cell
+_exp_e_obj_geometry_set(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed = embryo_program_data_get(ep);
+   Oid *oid;
+   SI_RETURN(-1);
+   
+   CHKPARAM(5);
+   if (!(oid = _oid_find(ed, params[1]))) return -1;
+   if ((oid->x == params[2]) && (oid->y == params[3]) &&
+       (oid->w == params[4]) && (oid->h == params[5])) return -1;
+   oid->x = params[2];
+   oid->y = params[3];
+   oid->w = params[4];
+   oid->h = params[5];
+   evas_object_move(oid->obj, ed->x + oid->x, ed->y + oid->y);
+   evas_object_resize(oid->obj, oid->w, oid->h);
+   return 0;
+}
+    
+static Embryo_Cell
+_exp_e_obj_geometry_get(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed = embryo_program_data_get(ep);
+   Oid *oid;
+   SI_RETURN(-1);
+   
+   CHKPARAM(5);
+   if (!(oid = _oid_find(ed, params[1]))) return -1;
+   SETINT(oid->x, params[2]);
+   SETINT(oid->y, params[3]);
+   SETINT(oid->w, params[4]);
+   SETINT(oid->h, params[5]);
+   return 0;
+}
+    
+static Embryo_Cell
+_exp_e_obj_color_set(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed = embryo_program_data_get(ep);
+   Oid *oid;
+   SI_RETURN(-1);
+
+   CHKPARAM(5);
+   if (!(oid = _oid_find(ed, params[1]))) return -1;
+   evas_object_color_set(oid->obj, params[2], params[3], params[4], params[5]);
+   return 0;
+}
+
+static Embryo_Cell
+_exp_e_obj_color_get(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed = embryo_program_data_get(ep);
+   Oid *oid;
+   int r, g, b, a;
+   SI_RETURN(-1);
+
+   CHKPARAM(5);
+   if (!(oid = _oid_find(ed, params[1]))) return -1;
+   evas_object_color_get(oid->obj, &r, &g , &b, &a);
+   SETINT(r, params[2]);
+   SETINT(g, params[3]);
+   SETINT(b, params[4]);
+   SETINT(a, params[5]);
+   return 0;
+}
+
+static Embryo_Cell
+_exp_e_signal_emit(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed = embryo_program_data_get(ep);
+   char *sig = NULL, *src = NULL;
+   SI_RETURN(-1);
+   
+   CHKPARAM(2);
+   GETSTR(sig, params[1]);
+   GETSTR(src, params[2]);
+   if ((!sig) || (!src)) return -1;
+   _edje_emit(ed, sig, src);
+   return 0;
+}
+
+/**********/
+
+int
+_edje_script_only(Edje *ed)
+{
+   if ((ed->collection) && (ed->collection->script) &&
+       (ed->collection->script_only))
+     return 1;
+   return 0;
+}
+
+void
+_edje_script_only_init(Edje *ed)
+{
+   Sinfo *si;
+   
+   si = calloc(1, sizeof(Sinfo));
+   if (!si) return;
+   ed->script_only_data = si;
+
+   embryo_program_data_set(ed->collection->script, ed);
+   
+   EXPF(e_obj_del);
+   EXPF(e_obj_rect_add);
+   EXPF(e_obj_show);
+   EXPF(e_obj_hide);
+   EXPF(e_obj_move);
+   EXPF(e_obj_resize);
+   EXPF(e_obj_geometry_set);
+   EXPF(e_obj_geometry_get);
+   EXPF(e_obj_color_set);
+   EXPF(e_obj_color_get);
+   EXPF(e_signal_emit);
+   
+   embryo_program_vm_push(ed->collection->script);
+   embryo_program_max_cycle_run_set(ed->collection->script, 5000000);
+
+   GTFN(obj_init);
+   GTFN(obj_shutdown);
+   GTFN(obj_show);
+   GTFN(obj_show_immediate);
+   GTFN(obj_hide);
+   GTFN(obj_hide_immediate);
+   GTFN(obj_move);
+   GTFN(obj_move_immediate);
+   GTFN(obj_resize);
+   GTFN(obj_resize_immediate);
+   GTFN(obj_message);
+
+   CLFN(obj_init);
+   _edje_script_only_move(ed);
+}
+
+void
+_edje_script_only_shutdown(Edje *ed)
+{
+   SI;
+
+   CLFN(obj_shutdown);
+   DELJ(show);
+   DELJ(hide);
+   DELJ(move);
+   DELJ(resize);
+   _oid_freeall(ed);
+}
+
+static void
+_show_job(void *data)
+{
+   Edje *ed = data;
+   SI;
+   
+   ZERJ(show);
+   CLFN(obj_show);
+}
+void
+_edje_script_only_show(Edje *ed)
+{
+   SI;
+   
+   IFFN(obj_show)
+     {
+       IFNJ(hide)
+         {
+            DELJ(show);
+            ADDJ(show, _show_job);
+         }
+       else
+         {
+            DELJ(hide);
+         }
+     }
+   IFNO(obj_show_immediate) return;
+   CLFN(obj_show_immediate);
+}
+
+static void
+_hide_job(void *data)
+{
+   Edje *ed = data;
+   SI;
+   
+   ZERJ(hide);
+   CLFN(obj_hide);
+}
+void
+_edje_script_only_hide(Edje *ed)
+{
+   SI;
+   
+   IFFN(obj_hide)
+     {
+       IFNJ(show)
+         {
+            DELJ(hide);
+            ADDJ(hide, _hide_job);
+         }
+       else
+         {
+            DELJ(show);
+         }
+     }
+   IFNO(obj_hide_immediate) return;
+   CLFN(obj_hide_immediate);
+}
+
+static void
+_move_job(void *data)
+{
+   Edje *ed = data;
+   SI;
+   
+   _oid_moveall(ed);
+   ZERJ(move);
+   IFNO(obj_move) return;
+   PINT(ed->x);
+   PINT(ed->y);
+   CLFN(obj_move);
+}
+void
+_edje_script_only_move(Edje *ed)
+{
+   SI;
+
+   DELJ(move);
+   ADDJ(move, _move_job);
+   IFNO(obj_move_immediate) return;
+   PINT(ed->x);
+   PINT(ed->y);
+   CLFN(obj_move_immediate);
+}
+
+static void
+_resize_job(void *data)
+{
+   Edje *ed = data;
+   SI;
+   
+   ZERJ(resize);
+   PINT(ed->w);
+   PINT(ed->h);
+   CLFN(obj_resize);
+}
+void
+_edje_script_only_resize(Edje *ed)
+{
+   SI;
+
+   IFFN(obj_resize)
+     {
+       DELJ(resize);
+       ADDJ(resize, _resize_job);
+     }
+   PINT(ed->w);
+   PINT(ed->h);
+   CLFN(obj_resize_immediate);
+}
+
+void
+_edje_script_only_message(Edje *ed, Edje_Message *em)
+{
+   SI;
+   
+   IFNO(obj_message) return;
+   _edje_message_parameters_push(em);
+   CLFN(obj_message);
+}
+
+/**************************************************/
+
+static void
+_call_fn(Edje *ed, const char *fname, Embryo_Function fn)
+{
+   int ret;
+   
+   ret = embryo_program_run(ed->collection->script, fn);
+   if (ret == EMBRYO_PROGRAM_FAIL)
+     {
+       printf("EDJE:        ERROR with embryo script.\n"
+              "ENTRY POINT: %s\n"
+              "ERROR:       %s\n",
+              fname,
+              embryo_error_string_get(embryo_program_error_get(ed->collection->script)));
+     }
+   else if (ret == EMBRYO_PROGRAM_TOOLONG)
+     {
+       printf("EDJE:        ERROR with embryo script.\n"
+              "ENTRY POINT: %s\n"
+              "ERROR:       Script exceeded maximum allowed cycle count of %i\n",
+              fname,
+              embryo_program_max_cycle_run_get(ed->collection->script));
+     }
+}
+
diff --git a/src/lib/edje_smart.c b/src/lib/edje_smart.c
new file mode 100644 (file)
index 0000000..b4f027f
--- /dev/null
@@ -0,0 +1,239 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#include "edje_private.h"
+
+static void _edje_smart_add(Evas_Object * obj);
+static void _edje_smart_del(Evas_Object * obj);
+static void _edje_smart_move(Evas_Object * obj, Evas_Coord x, Evas_Coord y);
+static void _edje_smart_resize(Evas_Object * obj, Evas_Coord w, Evas_Coord h);
+static void _edje_smart_show(Evas_Object * obj);
+static void _edje_smart_hide(Evas_Object * obj);
+static void _edje_smart_color_set(Evas_Object * obj, int r, int g, int b, int a);
+static void _edje_smart_clip_set(Evas_Object * obj, Evas_Object * clip);
+static void _edje_smart_clip_unset(Evas_Object * obj);
+
+static Evas_Smart *_edje_smart = NULL;
+
+Evas_List *_edje_edjes = NULL;
+
+/************************** API Routines **************************/
+
+/* FIXDOC: Verify/Expand */
+/** Constructs the Edje object
+ * @param evas A valid Evas handle
+ * @return The Evas_Object pointer.
+ *
+ * Creates the Edje smart object, returning the Evas_Object handle.
+ */
+EAPI Evas_Object *
+edje_object_add(Evas *evas)
+{
+   if (!_edje_smart)
+     {
+        static const Evas_Smart_Class sc =
+         {
+            "edje",
+              EVAS_SMART_CLASS_VERSION,
+              _edje_smart_add,
+              _edje_smart_del,
+              _edje_smart_move,
+              _edje_smart_resize,
+              _edje_smart_show,
+              _edje_smart_hide,
+              _edje_smart_color_set,
+              _edje_smart_clip_set,
+              _edje_smart_clip_unset,
+              NULL
+         };
+       _edje_smart = evas_smart_class_new(&sc);
+     }
+   return evas_object_smart_add(evas, _edje_smart);
+}
+
+/* Private Routines */
+static void
+_edje_smart_add(Evas_Object *obj)
+{
+   Edje *ed;
+
+   ed = _edje_add(obj);
+   if (!ed) return;
+   evas_object_smart_data_set(obj, ed);
+   evas_object_geometry_get(obj, &(ed->x), &(ed->y), &(ed->w), &(ed->h));
+   ed->obj = obj;
+   _edje_edjes = evas_list_append(_edje_edjes, obj);
+/*
+     {
+       Evas_List *l;
+
+       printf("--- EDJE DUMP [%i]\n", evas_list_count(_edje_edjes));
+       for (l = _edje_edjes; l; l = l->next)
+         {
+            ed = _edje_fetch(l->data);
+            printf("EDJE: %80s | %80s\n", ed->path, ed->part);
+         }
+       printf("--- EDJE DUMP [%i]\n", evas_list_count(_edje_edjes));
+     }
+ */
+}
+
+static void
+_edje_smart_del(Evas_Object * obj)
+{
+   Edje *ed;
+
+   ed = evas_object_smart_data_get(obj);
+   if (!ed) return;
+   _edje_block_violate(ed);
+   ed->delete_me = 1;
+   _edje_clean_objects(ed);
+   _edje_edjes = evas_list_remove(_edje_edjes, obj);
+   evas_object_smart_data_set(obj, NULL);
+   if (_edje_script_only(ed)) _edje_script_only_shutdown(ed);
+   _edje_file_del(ed);
+   _edje_unref(ed);
+}
+
+static void
+_edje_smart_move(Evas_Object * obj, Evas_Coord x, Evas_Coord y)
+{
+   Edje *ed;
+   int i;
+
+   ed = evas_object_smart_data_get(obj);
+   if (!ed) return;
+   if ((ed->x == x) && (ed->y == y)) return;
+   ed->x = x;
+   ed->y = y;
+//   evas_object_move(ed->clipper, ed->x, ed->y);
+
+   if (_edje_script_only(ed))
+     {
+       _edje_script_only_move(ed);
+       return;
+     }
+   
+   for (i = 0; i < ed->table_parts_size; i++)
+     {
+       Edje_Real_Part *ep;
+       Evas_Coord ox, oy;
+
+       ep = ed->table_parts[i];
+       evas_object_geometry_get(ep->object, &ox, &oy, NULL, NULL);
+       evas_object_move(ep->object, ed->x + ep->x + ep->offset.x, ed->y + ep->y +ep->offset.y);
+       if (ep->swallowed_object)
+         {
+            evas_object_geometry_get(ep->swallowed_object, &ox, &oy, NULL, NULL);
+            evas_object_move(ep->swallowed_object, ed->x + ep->x + ep->offset.x, ed->y + ep->y +ep->offset.y);
+         }
+       if (ep->extra_objects)
+         {
+            Evas_List *el;
+
+            for (el = ep->extra_objects; el; el = el->next)
+              {
+                 Evas_Object *o;
+                 Evas_Coord oox, ooy;
+
+                 o = el->data;
+                 evas_object_geometry_get(o, &oox, &ooy, NULL, NULL);
+                 evas_object_move(o, ed->x + ep->x + ep->offset.x + (oox - ox), ed->y + ep->y + ep->offset.y + (ooy - oy));
+              }
+         }
+     }
+//   _edje_emit(ed, "move", NULL);
+}
+
+static void
+_edje_smart_resize(Evas_Object * obj, Evas_Coord w, Evas_Coord h)
+{
+   Edje *ed;
+
+   ed = evas_object_smart_data_get(obj);
+   if (!ed) return;
+   if ((w == ed->w) && (h == ed->h)) return;
+   ed->w = w;
+   ed->h = h;
+   if (_edje_script_only(ed))
+     {
+       _edje_script_only_resize(ed);
+       return;
+     }
+//   evas_object_resize(ed->clipper, ed->w, ed->h);
+   ed->dirty = 1;
+   _edje_recalc(ed);
+   _edje_emit(ed, "resize", NULL);
+}
+
+static void
+_edje_smart_show(Evas_Object * obj)
+{
+   Edje *ed;
+
+   ed = evas_object_smart_data_get(obj);
+   if (!ed) return;
+   if (evas_object_visible_get(ed->clipper)) return;
+   if ((ed->collection) && (evas_object_clipees_get(ed->clipper)))
+     evas_object_show(ed->clipper);
+   if (_edje_script_only(ed))
+     {  
+       _edje_script_only_show(ed);
+       return;
+     }
+   _edje_emit(ed, "show", NULL);
+}
+
+static void
+_edje_smart_hide(Evas_Object * obj)
+{
+   Edje *ed;
+
+   ed = evas_object_smart_data_get(obj);
+   if (!ed) return;
+   if (!evas_object_visible_get(ed->clipper)) return;
+   if ((ed->collection) && (evas_object_clipees_get(ed->clipper)))
+     evas_object_hide(ed->clipper);
+   if (_edje_script_only(ed))
+     {  
+       _edje_script_only_hide(ed);
+       return;
+     }
+   _edje_emit(ed, "hide", NULL);
+}
+
+static void
+_edje_smart_color_set(Evas_Object * obj, int r, int g, int b, int a)
+{
+   Edje *ed;
+
+   ed = evas_object_smart_data_get(obj);
+   if (!ed) return;
+   evas_object_color_set(ed->clipper, r, g, b, a);
+//   _edje_emit(ed, "color_set", NULL);
+}
+
+static void
+_edje_smart_clip_set(Evas_Object * obj, Evas_Object * clip)
+{
+   Edje *ed;
+
+   ed = evas_object_smart_data_get(obj);
+   if (!ed) return;
+   if (evas_object_clip_get(obj) == clip) return;
+   evas_object_clip_set(ed->clipper, clip);
+//   _edje_emit(ed, "clip_set", NULL);
+}
+
+static void
+_edje_smart_clip_unset(Evas_Object * obj)
+{
+   Edje *ed;
+
+   ed = evas_object_smart_data_get(obj);
+   if (!ed) return;
+   if (!evas_object_clip_get(obj)) return;
+   evas_object_clip_unset(ed->clipper);
+//   _edje_emit(ed, "clip_unset", NULL);
+}
diff --git a/src/lib/edje_text.c b/src/lib/edje_text.c
new file mode 100644 (file)
index 0000000..1637a6a
--- /dev/null
@@ -0,0 +1,723 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#include "edje_private.h"
+
+
+/* returns with and height for this part.
+ *
+ * depending on the value of the use_alternate_font_metrics flag, it will
+ * either use evas_object_geometry_get() or the _advance_get() functions.
+ *
+ * The latter is useful if you want to make sure that width and height
+ * are the same value for the same number of characters in the text.
+ * This usually only makes sense for monospaced fonts.
+ *
+ * In future changes to this file, you probably should use this wrapper
+ * function everywhere instead of calling evas_object_geometry_get()
+ * directly.
+ */
+static inline void
+part_get_geometry(Edje_Real_Part *rp, Evas_Coord *w, Evas_Coord *h)
+{
+   if (!rp->part->use_alternate_font_metrics)
+     evas_object_geometry_get(rp->object, NULL, NULL, w, h);
+   else
+     {
+       if (w) *w = evas_object_text_horiz_advance_get(rp->object);
+       if (h) *h = evas_object_text_vert_advance_get(rp->object);
+     }
+}
+
+void
+_edje_text_init(void)
+{
+}
+
+void
+_edje_text_part_on_add(Edje *ed, Edje_Real_Part *ep)
+{
+   Evas_List *tmp;
+   Edje_Part *pt = ep->part;
+
+   if (ep->part->type != EDJE_PART_TYPE_TEXT) return;
+
+   /* if text class exists for this part, add the edje to the tc member list */
+   if ((pt->default_desc) && (pt->default_desc->text.text_class))
+     _edje_text_class_member_add(ed, pt->default_desc->text.text_class);
+
+   /* If any other classes exist add them */
+   for (tmp = pt->other_desc; tmp; tmp = tmp->next)
+     {
+        Edje_Part_Description *desc;
+
+       desc = tmp->data;
+       if ((desc) && (desc->text.text_class))
+         _edje_text_class_member_add(ed, desc->text.text_class);
+     }
+}
+
+void
+_edje_text_part_on_add_clippers(Edje *ed, Edje_Real_Part *ep)
+{
+   Evas_List *l;
+
+   for (l = ep->extra_objects; l; l = l->next)
+     {
+       Evas_Object *o;
+
+       o = l->data;
+       if (ep->part->clip_to_id >= 0)
+         {
+            ep->clip_to = ed->table_parts[ep->part->clip_to_id % ed->table_parts_size];
+            if (ep->clip_to)
+              {
+                 evas_object_pass_events_set(ep->clip_to->object, 1);
+                 evas_object_clip_set(o, ep->clip_to->object);
+              }
+         }
+     }
+}
+
+void
+_edje_text_part_on_del(Edje *ed, Edje_Part *pt)
+{
+   Evas_List *tmp;
+
+   if ((pt->default_desc) && (pt->default_desc->text.text_class))
+     _edje_text_class_member_del(ed, pt->default_desc->text.text_class);
+
+   for (tmp = pt->other_desc; tmp; tmp = tmp->next)
+     {
+        Edje_Part_Description *desc;
+
+        desc = tmp->data;
+        if (desc->text.text_class)
+          _edje_text_class_member_del(ed, desc->text.text_class);
+     }
+}
+
+void
+_edje_text_real_part_on_del(Edje *ed, Edje_Real_Part *ep)
+{
+   while (ep->extra_objects)
+     {
+       Evas_Object *o;
+
+       o = ep->extra_objects->data;
+       ep->extra_objects = evas_list_remove(ep->extra_objects, o);
+       evas_object_del(o);
+     }
+}
+
+static void
+_edje_text_fit_set(char *buf, const char *text, int c1, int c2)
+{
+   /* helper function called from _edje_text_fit_x().
+    * note that we can use strcpy()/strcat() safely, the buffer lengths
+    * are checked in the caller.
+    */
+
+   if (c1 >= 0)
+     {
+       strcpy(buf, "...");
+
+       if (c2 >= 0)
+         {
+            strncat(buf, text + c1, c2 - c1);
+            strcat(buf, "...");
+         }
+       else
+         strcat(buf, text + c1);
+     }
+   else
+     {
+       if (c2 >= 0)
+         {
+            strncpy(buf, text, c2);
+            buf[c2] = 0;
+            strcat(buf, "...");
+         }
+       else
+         strcpy(buf, text);
+     }
+}
+
+static const char *
+_edje_text_fit_x(Edje *ed, Edje_Real_Part *ep,
+                 Edje_Calc_Params *params,
+                 const char *text, const char *font, int size,
+                 Evas_Coord sw, int *free_text)
+{
+   Evas_Coord tw = 0, th = 0, p;
+   int l, r;
+   char *buf;
+   int c1 = -1, c2 = -1, loop = 0, extra;
+   size_t orig_len;
+
+   *free_text = 0;
+
+   evas_object_text_font_set(ep->object, font, size);
+   evas_object_text_text_set(ep->object, text);
+
+   part_get_geometry(ep, &tw, &th);
+   evas_object_text_style_pad_get(ep->object, &l, &r, NULL, NULL);
+
+   p = ((sw - tw) * params->text.elipsis);
+
+   /* chop chop */
+   if (tw > sw)
+     {
+       if (params->text.elipsis != 0.0)
+         c1 = evas_object_text_char_coords_get(ep->object,
+               -p + l, th / 2,
+               NULL, NULL, NULL, NULL);
+       if (params->text.elipsis != 1.0)
+         c2 = evas_object_text_char_coords_get(ep->object,
+               -p + sw - r, th / 2,
+               NULL, NULL, NULL, NULL);
+       if ((c1 < 0) && (c2 < 0))
+         {
+            c1 = 0;
+            c2 = 0;
+         }
+     }
+
+   if (!(((c1 >= 0) || (c2 >= 0)) && (tw > sw)))
+     return text;
+
+   if ((c1 == 0) && (c2 == 0))
+     return text;
+
+   orig_len = strlen(text);
+
+   /* don't overflow orig_len by adding extra
+    * FIXME: we might want to set a max string length somewhere...
+    */
+   extra = 1 + 3 + 3; /* terminator, leading and trailing ellipsis */
+   orig_len = MIN(orig_len, 8192 - extra);
+
+   if (!(buf = malloc(orig_len + extra)))
+     return text;
+
+   while (((c1 >= 0) || (c2 >= 0)) && (tw > sw))
+     {
+       loop++;
+       if (sw <= 0.0)
+         {
+            buf[0] = 0;
+            break;
+         }
+       if ((c1 >= 0) && (c2 >= 0))
+         {
+            if ((loop & 0x1))
+              {
+                 if (c1 >= 0)
+                   c1 = evas_string_char_next_get(text, c1, NULL);
+              }
+            else
+              {
+                 if (c2 >= 0)
+                   {
+                      c2 = evas_string_char_prev_get(text, c2, NULL);
+                      if (c2 < 0)
+                        {
+                           buf[0] = 0;
+                           break;
+                        }
+                   }
+              }
+         }
+       else
+         {
+            if (c1 >= 0)
+              c1 = evas_string_char_next_get(text, c1, NULL);
+            else if (c2 >= 0)
+              {
+                 c2 = evas_string_char_prev_get(text, c2, NULL);
+                 if (c2 < 0)
+                   {
+                      buf[0] = 0;
+                      break;
+                   }
+              }
+         }
+       if ((c1 >= 0) && (c2 >= 0))
+         {
+            if (c1 >= c2)
+              {
+                 buf[0] = 0;
+                 break;
+              }
+         }
+       else if ((c1 > 0 && c1 >= orig_len) || c2 == 0)
+         {
+            buf[0] = 0;
+            break;
+         }
+
+       buf[0] = 0;
+
+       _edje_text_fit_set(buf, text, c1, c2);
+
+       evas_object_text_text_set(ep->object, buf);
+       part_get_geometry(ep, &tw, &th);
+     }
+
+   *free_text = 1;
+
+   return buf;
+}
+
+static const char *
+_edje_text_font_get(const char *base, const char *new, char **free_later)
+{
+   const char *base_style, *new_style, *aux;
+   int font_len, style_len;
+
+   if (base && (!new))
+     return base;
+   else if ((!base) && new)
+     return new;
+
+   base_style = strstr(base, ":style=");
+   if (!base_style)
+     return new;
+
+   new_style = strstr(new, ":style=");
+   if (new_style)
+     return new;
+
+   font_len = strlen(new);
+   aux = strchr(base_style, ',');
+   style_len = (aux) ?  (aux - base_style) : strlen(base_style);
+
+   *free_later = malloc(font_len + style_len + 1);
+   memcpy(*free_later, new, font_len);
+   memcpy(*free_later + font_len, base_style, style_len);
+   (*free_later)[font_len + style_len] = '\0';
+
+   return *free_later;
+}
+
+const char *
+_edje_text_class_font_get(Edje *ed, Edje_Part_Description *chosen_desc, int *size, char **free_later)
+{
+   Edje_Text_Class *tc;
+   const char *text_class_name, *font;
+
+   font = chosen_desc->text.font;
+   *size = chosen_desc->text.size;
+
+   text_class_name = chosen_desc->text.text_class;
+   if ((!text_class_name) || (!text_class_name[0]))
+     return font;
+
+   tc = _edje_text_class_find(ed, text_class_name);
+   if (!tc)
+     return font;
+
+   font = _edje_text_font_get(chosen_desc->text.font, tc->font, free_later);
+   *size = _edje_text_size_calc(*size, tc);
+
+   return font;
+}
+
+void
+_edje_text_recalc_apply(Edje *ed, Edje_Real_Part *ep,
+                       Edje_Calc_Params *params,
+                       Edje_Part_Description *chosen_desc)
+{
+   const char  *text;
+   const char  *font;
+   char                *font2 = NULL;
+   char         *sfont = NULL;
+   int          size;
+   Evas_Coord   tw, th;
+   Evas_Coord   sw, sh;
+   int          inlined_font = 0, free_text = 0;
+
+
+   text = chosen_desc->text.text;
+   font = _edje_text_class_font_get(ed, chosen_desc, &size, &sfont);
+
+   if (ep->text.text) text = (char *) ep->text.text;
+   if (ep->text.font) font = ep->text.font;
+   if (ep->text.size > 0) size = ep->text.size;
+
+   if (ep->text.text_source)
+     {
+       text = ep->text.text_source->chosen_description->text.text;
+       if (ep->text.text_source->text.text) text = ep->text.text_source->text.text;
+     }
+   if (ep->text.source)
+     {
+       font = ep->text.source->chosen_description->text.font;
+       size = ep->text.source->chosen_description->text.size;
+       if (ep->text.source->text.font) font = ep->text.source->text.font;
+       if (ep->text.source->text.size > 0) size = ep->text.source->text.size;
+     }
+
+   if (!text) text = "";
+   if (!font) font = "";
+
+   /* check if the font is embedded in the .eet */
+   if (ed->file->font_hash)
+     {
+       Edje_Font_Directory_Entry *fnt = evas_hash_find(ed->file->font_hash, font);
+
+       if (fnt)
+         {
+            font = fnt->path;
+            inlined_font = 1;
+         }
+     }
+
+   if ((_edje_fontset_append) && (font))
+     {
+       font2 = malloc(strlen(font) + 1 + strlen(_edje_fontset_append) + 1);
+       if (font2)
+         {
+            strcpy(font2, font);
+            strcat(font2, ",");
+            strcat(font2, _edje_fontset_append);
+            font = font2;
+         }
+     }
+     {
+       int l, r, t, b;
+
+       evas_object_text_style_pad_get(ep->object, &l, &r, &t, &b);
+       sw = params->w;
+       sh = params->h;
+     }
+   if ((ep->text.cache.in_size == size) &&
+       (ep->text.cache.in_w == sw) &&
+       (ep->text.cache.in_h == sh) &&
+       (ep->text.cache.in_str) &&
+       (text) &&
+       (!strcmp(ep->text.cache.in_str, text)) &&
+       (ep->text.cache.align_x == params->text.align.x) &&
+       (ep->text.cache.align_y == params->text.align.y) &&
+       (ep->text.cache.elipsis == params->text.elipsis) &&
+       (ep->text.cache.fit_x == chosen_desc->text.fit_x) &&
+       (ep->text.cache.fit_y == chosen_desc->text.fit_y))
+     {
+       text = (char *)ep->text.cache.out_str;
+       size = ep->text.cache.out_size;
+
+       if (!text) text = "";
+
+       goto arrange_text;
+     }
+   if (ep->text.cache.in_str) evas_stringshare_del(ep->text.cache.in_str);
+   ep->text.cache.in_str = evas_stringshare_add(text);
+   ep->text.cache.in_size = size;
+   if (chosen_desc->text.fit_x)
+     {
+        if (inlined_font) evas_object_text_font_source_set(ep->object, ed->path);
+       else evas_object_text_font_source_set(ep->object, NULL);
+
+       evas_object_text_font_set(ep->object, font, size);
+       evas_object_text_text_set(ep->object, text);
+       part_get_geometry(ep, &tw, &th);
+       if (tw > sw)
+         {
+            int psize;
+
+            psize = size;
+            while ((tw > sw) && (size > 0) && (tw != 0))
+              {
+                 psize = size;
+                 size = (size * sw) / tw;
+                 if ((psize - size) <= 0) size = psize - 1;
+                 if (inlined_font) evas_object_text_font_source_set(ep->object, ed->path);
+                 else evas_object_text_font_source_set(ep->object, NULL);
+
+                 evas_object_text_font_set(ep->object, font, size);
+                 part_get_geometry(ep, &tw, &th);
+                 if ((size > 0) && (tw == 0)) break;
+              }
+         }
+       else if (tw < sw)
+         {
+            int psize;
+
+            psize = size;
+            while ((tw < sw) && (size > 0) && (tw != 0))
+              {
+                 psize = size;
+                 size = (size * sw) / tw;
+                 if ((psize - size) >= 0) size = psize + 1;
+                 if (inlined_font) evas_object_text_font_source_set(ep->object, ed->path);
+                 else evas_object_text_font_source_set(ep->object, NULL);
+
+                 evas_object_text_font_set(ep->object, font, size);
+                 part_get_geometry(ep, &tw, &th);
+                 if ((size > 0) && (tw == 0)) break;
+              }
+         }
+     }
+   if (chosen_desc->text.fit_y)
+     {
+       /* if we fit in the x axis, too, size already has a somewhat
+        * meaningful value, so don't overwrite it with the starting
+        * value in that case
+        */
+       if (!chosen_desc->text.fit_x) size = sh;
+
+        if (inlined_font) evas_object_text_font_source_set(ep->object, ed->path);
+       else evas_object_text_font_source_set(ep->object, NULL);
+
+       evas_object_text_font_set(ep->object, font, size);
+       evas_object_text_text_set(ep->object, text);
+       part_get_geometry(ep, &tw, &th);
+
+       /* only grow the font size if we didn't already reach the max size
+        * for the x axis
+        */
+       if (!chosen_desc->text.fit_x && th < sh)
+         {
+            int dif;
+
+            dif = (th - sh) / 4;
+            if (dif < 1) dif = 1;
+            while ((th < sh) && (sw > 0))
+              {
+                 size += dif;
+                 if (size <= 0) break;
+                 if (inlined_font) evas_object_text_font_source_set(ep->object, ed->path);
+                 else evas_object_text_font_source_set(ep->object, NULL);
+
+                 evas_object_text_font_set(ep->object, font, size);
+                 part_get_geometry(ep, &tw, &th);
+                 if ((size > 0) && (th == 0)) break;
+              }
+            size -= dif;
+         }
+       else if (th > sh)
+         {
+            int current;
+
+            evas_object_text_font_set(ep->object, font, 10);
+            part_get_geometry(ep, &tw, &th);
+
+            if (th == sh)
+              current = 10;
+            else
+              {
+                 int bottom, top;
+
+                 if (th < sh)
+                   bottom = 10;
+                 else if (th > sh)
+                   {
+                      bottom = 1;
+                      top = 10;
+                   }
+
+                 top = size;
+                 /* search one that fits (binary search) */
+                 do
+                   {
+                      current = (top + bottom) / 2;
+
+                      evas_object_text_font_set(ep->object, font, current);
+                      part_get_geometry(ep, &tw, &th);
+
+                      if      (th < sh) bottom = current + 1;
+                      else if (th > sh) top    = current - 1;
+                   } while ((bottom < top) && (th != sh));
+              }
+
+            /* search the larger one that fits (linear search) */
+            do
+              {
+                 current++;
+
+                 evas_object_text_font_set(ep->object, font, current);
+                 part_get_geometry(ep, &tw, &th);
+              } while (th <= sh);
+            size = current - 1;
+         }
+     }
+   if (size < 1) size = 1;
+
+   if (!chosen_desc->text.fit_x)
+     {
+       if (inlined_font) evas_object_text_font_source_set(ep->object, ed->path);
+       else evas_object_text_font_source_set(ep->object, NULL);
+
+       text = _edje_text_fit_x(ed, ep, params, text, font, size, sw, &free_text);
+     }
+
+   if (ep->text.cache.out_str) evas_stringshare_del(ep->text.cache.out_str);
+   ep->text.cache.out_str = evas_stringshare_add(text);
+   ep->text.cache.in_w = sw;
+   ep->text.cache.in_h = sh;
+   ep->text.cache.out_size = size;
+   ep->text.cache.align_x = params->text.align.x;
+   ep->text.cache.align_y = params->text.align.y;
+   ep->text.cache.elipsis = params->text.elipsis;
+   ep->text.cache.fit_x = chosen_desc->text.fit_x;
+   ep->text.cache.fit_y = chosen_desc->text.fit_y;
+   arrange_text:
+
+   if (inlined_font) evas_object_text_font_source_set(ep->object, ed->path);
+   else evas_object_text_font_source_set(ep->object, NULL);
+
+   evas_object_text_font_set(ep->object, font, size);
+   evas_object_text_text_set(ep->object, text);
+   part_get_geometry(ep, &tw, &th);
+   ep->offset.x = ((sw - tw) * params->text.align.x);
+   ep->offset.y = ((sh - th) * params->text.align.y);
+
+   evas_object_move(ep->object,
+                   ed->x + params->x + ep->offset.x,
+                   ed->y + params->y + ep->offset.y);
+
+   if (params->visible) evas_object_show(ep->object);
+   else evas_object_hide(ep->object);
+     {
+       Evas_Text_Style_Type style;
+
+       style = EVAS_TEXT_STYLE_PLAIN;
+
+       evas_object_color_set(ep->object,
+                             (params->color.r * params->color.a) / 255,
+                             (params->color.g * params->color.a) / 255,
+                             (params->color.b * params->color.a) / 255,
+                             params->color.a);
+
+       if ((ep->part->effect == EDJE_TEXT_EFFECT_NONE) ||
+             (ep->part->effect == EDJE_TEXT_EFFECT_PLAIN))
+         {
+            style = EVAS_TEXT_STYLE_PLAIN;
+         }
+       else if (ep->part->effect == EDJE_TEXT_EFFECT_OUTLINE)
+         {
+            style = EVAS_TEXT_STYLE_OUTLINE;
+            evas_object_text_outline_color_set(ep->object,
+                                               (params->color2.r * params->color2.a) / 255,
+                                               (params->color2.g * params->color2.a) / 255,
+                                               (params->color2.b * params->color2.a) / 255,
+                                               params->color2.a);
+         }
+       else if (ep->part->effect == EDJE_TEXT_EFFECT_SOFT_OUTLINE)
+         {
+            style = EVAS_TEXT_STYLE_SOFT_OUTLINE;
+            evas_object_text_outline_color_set(ep->object,
+                                               (params->color2.r * params->color2.a) / 255,
+                                               (params->color2.g * params->color2.a) / 255,
+                                               (params->color2.b * params->color2.a) / 255,
+                                               params->color2.a);
+         }
+       else if (ep->part->effect == EDJE_TEXT_EFFECT_SHADOW)
+         {
+            style = EVAS_TEXT_STYLE_SHADOW;
+            evas_object_text_shadow_color_set(ep->object,
+                                              (params->color3.r * params->color3.a) / 255,
+                                              (params->color3.g * params->color3.a) / 255,
+                                              (params->color3.b * params->color3.a) / 255,
+                                              params->color3.a);
+         }
+       else if (ep->part->effect == EDJE_TEXT_EFFECT_SOFT_SHADOW)
+         {
+            style = EVAS_TEXT_STYLE_SOFT_SHADOW;
+            evas_object_text_shadow_color_set(ep->object,
+                                              (params->color3.r * params->color3.a) / 255,
+                                              (params->color3.g * params->color3.a) / 255,
+                                              (params->color3.b * params->color3.a) / 255,
+                                              params->color3.a);
+         }
+       else if (ep->part->effect == EDJE_TEXT_EFFECT_OUTLINE_SHADOW)
+         {
+            style = EVAS_TEXT_STYLE_OUTLINE_SHADOW;
+            evas_object_text_outline_color_set(ep->object,
+                                               (params->color2.r * params->color2.a) / 255,
+                                               (params->color2.g * params->color2.a) / 255,
+                                               (params->color2.b * params->color2.a) / 255,
+                                               params->color2.a);
+            evas_object_text_shadow_color_set(ep->object,
+                                              (params->color3.r * params->color3.a) / 255,
+                                              (params->color3.g * params->color3.a) / 255,
+                                              (params->color3.b * params->color3.a) / 255,
+                                              params->color3.a);
+         }
+       else if (ep->part->effect == EDJE_TEXT_EFFECT_OUTLINE_SOFT_SHADOW)
+         {
+            style = EVAS_TEXT_STYLE_OUTLINE_SOFT_SHADOW;
+            evas_object_text_outline_color_set(ep->object,
+                                               (params->color2.r * params->color2.a) / 255,
+                                               (params->color2.g * params->color2.a) / 255,
+                                               (params->color2.b * params->color2.a) / 255,
+                                               params->color2.a);
+            evas_object_text_shadow_color_set(ep->object,
+                                              (params->color3.r * params->color3.a) / 255,
+                                              (params->color3.g * params->color3.a) / 255,
+                                              (params->color3.b * params->color3.a) / 255,
+                                              params->color3.a);
+         }
+       else if (ep->part->effect == EDJE_TEXT_EFFECT_FAR_SHADOW)
+         {
+            style = EVAS_TEXT_STYLE_FAR_SHADOW;
+            evas_object_text_shadow_color_set(ep->object,
+                                              (params->color3.r * params->color3.a) / 255,
+                                              (params->color3.g * params->color3.a) / 255,
+                                              (params->color3.b * params->color3.a) / 255,
+                                              params->color3.a);
+         }
+       else if (ep->part->effect == EDJE_TEXT_EFFECT_FAR_SOFT_SHADOW)
+         {
+            style = EVAS_TEXT_STYLE_FAR_SOFT_SHADOW;
+            evas_object_text_shadow_color_set(ep->object,
+                                              (params->color3.r * params->color3.a) / 255,
+                                              (params->color3.g * params->color3.a) / 255,
+                                              (params->color3.b * params->color3.a) / 255,
+                                              params->color3.a);
+         }
+       else if (ep->part->effect == EDJE_TEXT_EFFECT_GLOW)
+         {
+            style = EVAS_TEXT_STYLE_GLOW;
+            evas_object_text_glow_color_set(ep->object,
+                                               (params->color2.r * params->color2.a) / 255,
+                                               (params->color2.g * params->color2.a) / 255,
+                                               (params->color2.b * params->color2.a) / 255,
+                                               params->color2.a);
+            evas_object_text_glow2_color_set(ep->object,
+                                              (params->color3.r * params->color3.a) / 255,
+                                              (params->color3.g * params->color3.a) / 255,
+                                              (params->color3.b * params->color3.a) / 255,
+                                              params->color3.a);
+         }
+       evas_object_text_style_set(ep->object, style);
+     }
+
+   if (free_text)
+     free((char *)text);
+   if (font2)
+     free(font2);
+   if (sfont)
+     free(sfont);
+}
+
+Evas_Font_Size
+_edje_text_size_calc(Evas_Font_Size size, Edje_Text_Class *tc)
+{
+   int val;
+
+   if (tc->size == 0)
+     {
+       val = size;
+     }
+   else if (tc->size > 0.0)
+     {
+       val = tc->size;
+     }
+   else
+     {
+       val = (size * -tc->size) / 100;
+     }
+   return val;
+}
diff --git a/src/lib/edje_textblock_styles.c b/src/lib/edje_textblock_styles.c
new file mode 100644 (file)
index 0000000..3138819
--- /dev/null
@@ -0,0 +1,503 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#include "edje_private.h"
+
+static int
+_edje_font_is_embedded(Edje_File *edf, char *font)
+{
+   if (!edf->font_dir) return 0;
+   return 1;
+}
+
+/* Put a \ before and Space( ), \ or ' in a string.
+ * A newly allocated string is returned.
+ */
+static char *
+_edje_str_escape(const char *str)
+{
+   char *s2, *d;
+   const char *s;
+
+   s2 = malloc((strlen(str) * 2) + 1);
+   if (!s2) return NULL;
+   for (s = str, d = s2; *s != 0; s++, d++)
+     {
+       if ((*s == ' ') || (*s == '\\') || (*s == '\''))
+         {
+            *d = '\\';
+            d++;
+         }
+       *d = *s;
+     }
+   *d = 0;
+   return s2;
+}
+
+static void
+_edje_format_param_parse(char *item, char **key, char **val)
+{
+   char *p;
+   char *k, *v;
+
+   p = strchr(item, '=');
+   k = malloc(p - item + 1);
+   strncpy(k, item, p - item);
+   k[p - item] = 0;
+   *key = k;
+   p++;
+   v = strdup(p);
+   *val = v;
+}
+
+static char *
+_edje_format_parse(const char **s)
+{
+   char *item, *ds;
+   const char *p;
+   const char *ss;
+   const char *s1 = NULL;
+   const char *s2 = NULL;
+
+   p = *s;
+   if ((!p) || (*p == 0)) return NULL;
+   for (;;)
+     {
+       if (!s1)
+         {
+            if (*p != ' ') s1 = p;
+            if (*p == 0) break;
+         }
+       else if (!s2)
+         {
+            if ((p > *s) && (p[-1] != '\\'))
+              {
+                 if (*p == ' ') s2 = p;
+              }
+            if (*p == 0) s2 = p;
+         }
+       p++;
+       if (s1 && s2)
+         {
+            item = malloc(s2 - s1 + 1);
+            if (item)
+              {
+                 ds = item;
+                 for (ds = item, ss = s1; ss < s2; ss++, ds++)
+                   {
+                      if ((*ss == '\\') && (ss < (s2 - 1))) ss++;
+                      *ds = *ss;
+                   }
+                 *ds = 0;
+              }
+            *s = s2;
+            return item;
+         }
+     }
+   *s = p;
+   return NULL;
+}
+
+static int
+_edje_format_is_param(char *item)
+{
+   if (strchr(item, '=')) return 1;
+   return 0;
+}
+
+static char *
+_edje_strbuf_append(char *s, const char *s2, int *len, int *alloc)
+{
+   int l2;
+   int tlen;
+
+   if (!s2) return s;
+   l2 = strlen(s2);
+   tlen = *len + l2;
+   if (tlen > *alloc)
+     {
+       char *ts;
+       int talloc;
+
+       talloc = ((tlen + 31) >> 5) << 5;
+       ts = realloc(s, talloc + 1);
+       if (!ts) return s;
+       s = ts;
+       *alloc = talloc;
+     }
+   strcpy(s + *len, s2);
+   *len = tlen;
+   return s;
+}
+
+static char *
+_edje_strbuf_append_escaped(char *s, const char *unescaped_s, int *len, int *alloc)
+{
+   char *tmp;
+
+   tmp = _edje_str_escape(unescaped_s);
+   if (!tmp)
+     return s;
+
+   s = _edje_strbuf_append(s, tmp, len, alloc);
+   free(tmp);
+
+   return s;
+}
+
+static char *
+_edje_format_reparse(Edje_File *edf, const char *str, Edje_Style_Tag **tag_ret)
+{
+   char *s2;
+   char *item;
+   char *newstr = NULL;
+   const char *s;
+   int newlen = 0, newalloc = 0;
+
+   s = str;
+   while ((item = _edje_format_parse(&s)))
+     {
+       if (_edje_format_is_param(item))
+         {
+            char *key = NULL, *val = NULL;
+
+            _edje_format_param_parse(item, &key, &val);
+            if (!strcmp(key, "font_source"))
+              {
+                 /* dont allow font sources */
+              }
+            else if (!strcmp(key, "text_class"))
+              {
+                 if (tag_ret)
+                   (*tag_ret)->text_class = evas_stringshare_add(val);
+              }
+            else if (!strcmp(key, "font_size"))
+              {
+                 if (tag_ret)
+                   (*tag_ret)->font_size = atof(val);
+              }
+            else if (!strcmp(key, "font")) /* Fix fonts */
+              {
+                 if (tag_ret)
+                   {
+                      if (_edje_font_is_embedded(edf, val))
+                        {
+                           char     *tmpstr = NULL;
+                           int       tmplen = 0;
+                           int       tmpalloc = 0;
+
+                           tmpstr = _edje_strbuf_append(tmpstr, "fonts/", &tmplen, &tmpalloc);
+                           tmpstr = _edje_strbuf_append(tmpstr, val, &tmplen, &tmpalloc);
+                           (*tag_ret)->font = evas_stringshare_add(tmpstr);
+                           free(tmpstr);
+                        }
+                      else
+                        {
+                           (*tag_ret)->font = evas_stringshare_add(val);
+                        }
+                   }
+              }
+            else /* Otherwise add to tag buffer */
+              {
+                 s2 = _edje_str_escape(item);
+                 if (s2)
+                   {
+                      if (newstr) newstr = _edje_strbuf_append(newstr, " ", &newlen, &newalloc);
+                      newstr = _edje_strbuf_append(newstr, s2, &newlen, &newalloc);
+                      free(s2);
+                   }
+              }
+            free(key);
+            free(val);
+         }
+       else
+         {
+            if (newstr) newstr = _edje_strbuf_append(newstr, " ", &newlen, &newalloc);
+            newstr = _edje_strbuf_append(newstr, item, &newlen, &newalloc);
+         }
+       free(item);
+     }
+   return newstr;
+}
+
+/* Update all evas_styles which are in an edje
+ *
+ * @param ed   The edje containing styles which need to be updated
+ */
+void
+_edje_textblock_style_all_update(Edje *ed)
+{
+   Evas_List *l, *ll;
+
+   if (!ed->file) return;
+
+   for (l = ed->file->styles; l; l = l->next)
+     {
+       Edje_Style *stl;
+       Edje_Style_Tag *tag;
+       Edje_Text_Class *tc;
+       char *buf = NULL;
+       int bufalloc = 0;
+       int buflen = 0;
+       int found = 0;
+       char *fontset = NULL, *fontsource = NULL;
+
+       stl = l->data;
+       /* Make sure the style is already defined */
+       if (!stl->style) break;
+
+       /* Make sure the style contains a text_class */
+       for (ll = stl->tags; ll; ll = ll->next)
+         {
+            tag = ll->data;
+            if (tag->text_class)
+              found = 1;
+         }
+
+       /* No text classes , goto next style */
+       if (!found) continue;
+       found = 0;
+
+       if (_edje_fontset_append)
+         fontset = _edje_str_escape(_edje_fontset_append);
+       fontsource = _edje_str_escape(ed->file->path);
+
+       /* Build the style from each tag */
+       for (ll = stl->tags; ll; ll = ll->next)
+         {
+            tag = ll->data;
+            if (!tag->key) continue;
+
+            /* Add Tag Key */
+            buf = _edje_strbuf_append(buf, tag->key, &buflen, &bufalloc);
+            buf = _edje_strbuf_append(buf, "='", &buflen, &bufalloc);
+
+            /* Configure fonts from text class if it exists */
+            if ((tc = _edje_text_class_find(ed, tag->text_class)))
+              {
+                 /* Only update if not clearing, If clear leave it at zero */
+                 if (tc->font) found = 1;
+              }
+
+            /* Add and Ha`ndle tag parsed data */
+            buf = _edje_strbuf_append(buf, tag->value, &buflen, &bufalloc);
+
+            if (!strcmp(tag->key, "DEFAULT"))
+              {
+                 if (fontset)
+                   {
+                      buf = _edje_strbuf_append(buf, " ", &buflen, &bufalloc);
+                      buf = _edje_strbuf_append(buf, "font_fallbacks=", &buflen, &bufalloc);
+                      buf = _edje_strbuf_append(buf, fontset, &buflen, &bufalloc);
+                   }
+                 buf = _edje_strbuf_append(buf, " ", &buflen, &bufalloc);
+                 buf = _edje_strbuf_append(buf, "font_source=", &buflen, &bufalloc);
+                 buf = _edje_strbuf_append(buf, fontsource, &buflen, &bufalloc);
+              }
+            if (tag->font_size != 0)
+              {
+                 char font_size[32];
+
+                 if (found)
+                   snprintf(font_size, sizeof(font_size), "%f", (double) _edje_text_size_calc(tag->font_size, tc));
+                 else
+                   snprintf(font_size, sizeof(font_size), "%f", tag->font_size);
+
+                 buf = _edje_strbuf_append(buf, " ", &buflen, &bufalloc);
+                 buf = _edje_strbuf_append(buf, "font_size=", &buflen, &bufalloc);
+                 buf = _edje_strbuf_append(buf, font_size, &buflen, &bufalloc);
+              }
+            /* Add font name last to save evas from multiple loads */
+            if (tag->font)
+              {
+                 const char *f;
+
+                 buf = _edje_strbuf_append(buf, " ", &buflen, &bufalloc);
+                 buf = _edje_strbuf_append(buf, "font=", &buflen, &bufalloc);
+
+                 f = (found) ? tc->font : tag->font;
+                 buf = _edje_strbuf_append_escaped(buf, f, &buflen, &bufalloc);
+              }
+            found = 0;
+
+            buf = _edje_strbuf_append(buf, "'", &buflen, &bufalloc);
+         }
+       if (fontset) free(fontset);
+       if (fontsource) free(fontsource);
+
+       /* Configure the style */
+       evas_textblock_style_set(stl->style, buf);
+       free(buf);
+     }
+}
+
+void
+_edje_textblock_styles_add(Edje *ed)
+{
+   Evas_List *l, *ll;
+
+   if (!ed->file) return;
+
+   for (l = ed->file->styles; l; l = l->next)
+     {
+       Edje_Style *stl;
+       Edje_Style_Tag *tag;
+
+       stl = l->data;
+
+       /* Make sure the style contains the text_class */
+       for (ll = stl->tags; ll; ll = ll->next)
+         {
+            tag = ll->data;
+            if (!tag->text_class) continue;
+            _edje_text_class_member_add(ed, tag->text_class);
+         }
+     }
+}
+
+void
+_edje_textblock_styles_del(Edje *ed)
+{
+   Evas_List *l, *ll;
+
+   if (!ed->file) return;
+
+   for (l = ed->file->styles; l; l = l->next)
+     {
+       Edje_Style *stl;
+       Edje_Style_Tag *tag;
+
+       stl = l->data;
+
+       /* Make sure the style contains the text_class */
+       for (ll = stl->tags; ll; ll = ll->next)
+         {
+            tag = ll->data;
+            if (!tag->text_class) continue;
+            _edje_text_class_member_del(ed, tag->text_class);
+         }
+     }
+}
+
+/* When we get to here the edje file had been read into memory
+ * the name of the style is established as well as the name and
+ * data for the tags.  This function will create the Evas_Style
+ * object for each style. The style is composed of a base style
+ * followed by a list of tags.
+ */
+void
+_edje_textblock_style_parse_and_fix(Edje_File *edf)
+{
+   Evas_List *l, *ll;
+
+   for (l = edf->styles; l; l = l->next)
+     {
+       Edje_Style *stl;
+       Edje_Style_Tag *tag;
+       char *buf = NULL;
+       int bufalloc = 0;
+       int buflen = 0;
+       char *fontset = NULL, *fontsource = NULL, *ts;
+
+       stl = l->data;
+       if (stl->style) break;
+
+       stl->style = evas_textblock_style_new();
+       evas_textblock_style_set(stl->style, buf);
+
+       if (_edje_fontset_append)
+         fontset = _edje_str_escape(_edje_fontset_append);
+       fontsource = _edje_str_escape(edf->path);
+
+       /* Build the style from each tag */
+       for (ll = stl->tags; ll; ll = ll->next)
+         {
+            tag = ll->data;
+            if (!tag->key) continue;
+
+            /* Add Tag Key */
+            buf = _edje_strbuf_append(buf, tag->key, &buflen, &bufalloc);
+            buf = _edje_strbuf_append(buf, "='", &buflen, &bufalloc);
+
+            ts = _edje_format_reparse(edf, tag->value, &(tag));
+
+            /* Add and Handle tag parsed data */
+            if (ts)
+              {
+                 if (eet_dictionary_string_check(eet_dictionary_get(edf->ef), tag->value) == 0)
+                   evas_stringshare_del(tag->value);
+                 tag->value = evas_stringshare_add(ts);
+                 buf = _edje_strbuf_append(buf, tag->value, &buflen, &bufalloc);
+                 free(ts);
+              }
+
+            if (!strcmp(tag->key, "DEFAULT"))
+              {
+                 if (fontset)
+                   {
+                      buf = _edje_strbuf_append(buf, " ", &buflen, &bufalloc);
+                      buf = _edje_strbuf_append(buf, "font_fallbacks=", &buflen, &bufalloc);
+                      buf = _edje_strbuf_append(buf, fontset, &buflen, &bufalloc);
+                   }
+                 buf = _edje_strbuf_append(buf, " ", &buflen, &bufalloc);
+                 buf = _edje_strbuf_append(buf, "font_source=", &buflen, &bufalloc);
+                 buf = _edje_strbuf_append(buf, fontsource, &buflen, &bufalloc);
+              }
+            if (tag->font_size > 0)
+              {
+                 char font_size[32];
+
+                 snprintf(font_size, sizeof(font_size), "%f", tag->font_size);
+                 buf = _edje_strbuf_append(buf, " ", &buflen, &bufalloc);
+                 buf = _edje_strbuf_append(buf, "font_size=", &buflen, &bufalloc);
+                 buf = _edje_strbuf_append(buf, font_size, &buflen, &bufalloc);
+              }
+            /* Add font name last to save evas from multiple loads */
+            if (tag->font)
+              {
+                 buf = _edje_strbuf_append(buf, " ", &buflen, &bufalloc);
+                 buf = _edje_strbuf_append(buf, "font=", &buflen, &bufalloc);
+                 buf = _edje_strbuf_append_escaped(buf, tag->font, &buflen, &bufalloc);
+              }
+            buf = _edje_strbuf_append(buf, "'", &buflen, &bufalloc);
+         }
+       if (fontset) free(fontset);
+       if (fontsource) free(fontsource);
+
+       /* Configure the style */
+       evas_textblock_style_set(stl->style, buf);
+       free(buf);
+     }
+}
+
+void
+_edje_textblock_style_cleanup(Edje_File *edf)
+{
+   while (edf->styles)
+     {
+       Edje_Style *stl;
+
+       stl = edf->styles->data;
+       edf->styles = evas_list_remove_list(edf->styles, edf->styles);
+       while (stl->tags)
+         {
+            Edje_Style_Tag *tag;
+
+            tag = stl->tags->data;
+            stl->tags = evas_list_remove_list(stl->tags, stl->tags);
+             if (edf->free_strings)
+               {
+                  if (tag->key) evas_stringshare_del(tag->key);
+/*                FIXME: Find a proper way to handle it. */
+                  if (tag->value) evas_stringshare_del(tag->value);
+                  if (tag->text_class) evas_stringshare_del(tag->text_class);
+                  if (tag->font) evas_stringshare_del(tag->font);
+               }
+             free(tag);
+         }
+        if (edf->free_strings && stl->name) evas_stringshare_del(stl->name);
+       if (stl->style) evas_textblock_style_free(stl->style);
+       free(stl);
+     }
+}
diff --git a/src/lib/edje_util.c b/src/lib/edje_util.c
new file mode 100644 (file)
index 0000000..4d91bd6
--- /dev/null
@@ -0,0 +1,2101 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#include "edje_private.h"
+
+static Evas_Hash *_edje_color_class_hash = NULL;
+static Evas_Hash *_edje_color_class_member_hash = NULL;
+
+static Evas_Hash *_edje_text_class_hash = NULL;
+static Evas_Hash *_edje_text_class_member_hash = NULL;
+
+char *_edje_fontset_append = NULL;
+
+typedef struct _Edje_List_Foreach_Data Edje_List_Foreach_Data;
+
+struct _Edje_List_Foreach_Data
+{
+   Evas_List *list;
+};
+
+static Evas_Bool _edje_color_class_list_foreach(const Evas_Hash *hash, const char *key, void *data, void *fdata);
+static Evas_Bool _edje_text_class_list_foreach(const Evas_Hash *hash, const char *key, void *data, void *fdata);
+
+Edje_Real_Part *_edje_real_part_recursive_get_helper(Edje *ed, char **path);
+
+/************************** API Routines **************************/
+
+/* FIXDOC: These all need to be looked over, Verified/Expanded upon.  I just got lazy and stopped putting FIXDOC next to each function in this file. */
+
+/** Freeze all Edje objects in the current process.
+ *
+ * See edje_object_freeze() for more.
+ */
+EAPI void
+edje_freeze(void)
+{
+   Evas_List *l;
+
+   for (l = _edje_edjes; l; l = l->next)
+     edje_object_freeze((Evas_Object *)(l->data));
+}
+
+/** Thaw all Edje objects in the current process.
+ *
+ * See edje_object_thaw() for more.
+ */
+EAPI void
+edje_thaw(void)
+{
+   Evas_List *l;
+
+   for (l = _edje_edjes; l; l = l->next)
+     edje_object_thaw((Evas_Object *)(l->data));
+}
+
+/* FIXDOC: Expand */
+EAPI void
+edje_fontset_append_set(const char *fonts)
+{
+   if (_edje_fontset_append)
+     free(_edje_fontset_append);
+   _edje_fontset_append = fonts ? strdup(fonts) : NULL;
+}
+
+/* FIXDOC: Expand */
+EAPI const char *
+edje_fontset_append_get(void)
+{
+   return _edje_fontset_append;
+}
+
+/* FIXDOC: Verify/Expand */
+/** Get Edje object data
+ * @param obj A valid Evas_Object handle
+ * @param key The data key
+ * @return The data string
+ *
+ * This fetches data specified at the object level.
+ *
+ * In EDC this comes from a data block within the group block that @a obj
+ * was loaded from. E.g.
+ *
+ * @code
+ * collections {
+ *   group {
+ *     name: "a_group";
+ *     data {
+ *      item: "key1" "value1";
+ *      item: "key2" "value2";
+ *     }
+ *   }
+ * }
+ * @endcode
+ */
+EAPI const char *
+edje_object_data_get(const Evas_Object *obj, const char *key)
+{
+   Edje *ed;
+   Evas_List *l;
+
+   ed = _edje_fetch(obj);
+   if ((!ed) || (!key))
+     return NULL;
+   if (!ed->collection) return NULL;
+   for (l = ed->collection->data; l; l = l->next)
+     {
+       Edje_Data *di;
+
+       di = l->data;
+       if ((di->key) && (!strcmp(di->key, key)))
+         return (const char *)di->value;
+     }
+   return NULL;
+}
+
+/* FIXDOC: Verify/Expand */
+/** Freeze object
+ * @param obj A valid Evas_Object handle
+ * @return The frozen state\n
+ * 0 on Error
+ *
+ * This puts all changes on hold.  Successive freezes will nest,
+ * requiring an equal number of thaws.
+ */
+EAPI int
+edje_object_freeze(Evas_Object *obj)
+{
+   Edje *ed;
+   int i;
+
+   ed = _edje_fetch(obj);
+   if (!ed) return 0;
+   for (i = 0; i < ed->table_parts_size; i++)
+     {
+       Edje_Real_Part *rp;
+       rp = ed->table_parts[i];
+       if (rp->part->type == EDJE_PART_TYPE_GROUP && rp->swallowed_object)
+         edje_object_freeze(rp->swallowed_object);
+     }
+   return _edje_freeze(ed);
+}
+
+/** Thaw object
+ * @param obj A valid Evas_Object handle
+ * @return The frozen state\n
+ * 0 on Error
+ *
+ * This allows frozen changes to occur.
+ */
+EAPI int
+edje_object_thaw(Evas_Object *obj)
+{
+   Edje *ed;
+   int i;
+
+   ed = _edje_fetch(obj);
+   if (!ed) return 0;
+   for (i = 0; i < ed->table_parts_size; i++)
+     {
+       Edje_Real_Part *rp;
+       rp = ed->table_parts[i];
+       if (rp->part->type == EDJE_PART_TYPE_GROUP && rp->swallowed_object)
+         edje_object_thaw(rp->swallowed_object);
+     }
+   return _edje_thaw(ed);
+}
+
+/** Set Edje color class
+ * @param color_class
+ * @param r Object Red value
+ * @param g Object Green value
+ * @param b Object Blue value
+ * @param a Object Alpha value
+ * @param r2 Outline Red value
+ * @param g2 Outline Green value
+ * @param b2 Outline Blue value
+ * @param a2 Outline Alpha value
+ * @param r3 Shadow Red value
+ * @param g3 Shadow Green value
+ * @param b3 Shadow Blue value
+ * @param a3 Shadow Alpha value
+ *
+ * Sets the color values for a process level color class. This will cause all
+ * edje parts in the current process that have the specified color class to
+ * have their colors multiplied by these values. (Object level color classes
+ * set by edje_object_color_class_set() will override the values set by this
+ * function).
+ *
+ * The first color is the object, the second is the text outline, and the
+ * third is the text shadow. (Note that the second two only apply to text parts)
+ */
+EAPI void
+edje_color_class_set(const char *color_class, int r, int g, int b, int a, int r2, int g2, int b2, int a2, int r3, int g3, int b3, int a3)
+{
+   Evas_List *members;
+   Edje_Color_Class *cc;
+
+   if (!color_class) return;
+
+   cc = evas_hash_find(_edje_color_class_hash, color_class);
+   if (!cc)
+     {
+        cc = calloc(1, sizeof(Edje_Color_Class));
+       if (!cc) return;
+       cc->name = evas_stringshare_add(color_class);
+       if (!cc->name)
+         {
+            free(cc);
+            return;
+         }
+       _edje_color_class_hash =
+          evas_hash_add(_edje_color_class_hash, color_class, cc);
+       if (evas_hash_alloc_error())
+         {
+            evas_stringshare_del(cc->name);
+            free(cc);
+            return;
+         }
+
+     }
+
+   if (r < 0)   r = 0;
+   if (r > 255) r = 255;
+   if (g < 0)   g = 0;
+   if (g > 255) g = 255;
+   if (b < 0)   b = 0;
+   if (b > 255) b = 255;
+   if (a < 0)   a = 0;
+   if (a > 255) a = 255;
+   if ((cc->r == r) && (cc->g == g) &&
+       (cc->b == b) && (cc->a == a) &&
+       (cc->r2 == r2) && (cc->g2 == g2) &&
+       (cc->b2 == b2) && (cc->a2 == a2) &&
+       (cc->r3 == r3) && (cc->g3 == g3) &&
+       (cc->b3 == b3) && (cc->a3 == a3))
+     return;
+   cc->r = r;
+   cc->g = g;
+   cc->b = b;
+   cc->a = a;
+   cc->r2 = r2;
+   cc->g2 = g2;
+   cc->b2 = b2;
+   cc->a2 = a2;
+   cc->r3 = r3;
+   cc->g3 = g3;
+   cc->b3 = b3;
+   cc->a3 = a3;
+
+   members = evas_hash_find(_edje_color_class_member_hash, color_class);
+   while (members)
+     {
+       Edje *ed;
+
+       ed = members->data;
+       ed->dirty = 1;
+       _edje_recalc(ed);
+       members = members->next;
+     }
+}
+
+/**
+ * @param color_class
+ *
+ * Deletes any values at the process level for the specified color class.
+ */
+void
+edje_color_class_del(const char *color_class)
+{
+   Edje_Color_Class *cc;
+   Evas_List *members;
+
+   if (!color_class) return;
+
+   cc = evas_hash_find(_edje_color_class_hash, color_class);
+   if (!cc) return;
+
+   _edje_color_class_hash =
+     evas_hash_del(_edje_color_class_hash, color_class, cc);
+   evas_stringshare_del(cc->name);
+   free(cc);
+
+   members = evas_hash_find(_edje_color_class_member_hash, color_class);
+   while (members)
+     {
+       Edje *ed;
+
+       ed = members->data;
+       ed->dirty = 1;
+       _edje_recalc(ed);
+       members = members->next;
+     }
+}
+
+/**
+ * Lists all color classes known about by the current process.
+ *
+ * @return A list of color class names (strings). These strings and the list
+ * must be free()'d by the caller.
+ */
+Evas_List *
+edje_color_class_list(void)
+{
+   Edje_List_Foreach_Data fdata;
+
+   memset(&fdata, 0, sizeof(Edje_List_Foreach_Data));
+   evas_hash_foreach(_edje_color_class_member_hash,
+                     _edje_color_class_list_foreach, &fdata);
+
+   return fdata.list;
+}
+
+static Evas_Bool
+_edje_color_class_list_foreach(const Evas_Hash *hash, const char *key, void *data, void *fdata)
+{
+   Edje_List_Foreach_Data *fd;
+
+   fd = fdata;
+   fd->list = evas_list_append(fd->list, strdup(key));
+   return 1;
+}
+
+/** Sets the object color class
+ * @param obj A valid Evas_Object handle
+ * @param color_class
+ * @param r Object Red value
+ * @param g Object Green value
+ * @param b Object Blue value
+ * @param a Object Alpha value
+ * @param r2 Outline Red value
+ * @param g2 Outline Green value
+ * @param b2 Outline Blue value
+ * @param a2 Outline Alpha value
+ * @param r3 Shadow Red value
+ * @param g3 Shadow Green value
+ * @param b3 Shadow Blue value
+ * @param a3 Shadow Alpha value
+ *
+ * Sets the color values for an object level color class. This will cause all
+ * edje parts in the specified object that have the specified color class to
+ * have their colors multiplied by these values.
+ *
+ * The first color is the object, the second is the text outline, and the
+ * third is the text shadow. (Note that the second two only apply to text parts)
+ */
+EAPI void
+edje_object_color_class_set(Evas_Object *obj, const char *color_class, int r, int g, int b, int a, int r2, int g2, int b2, int a2, int r3, int g3, int b3, int a3)
+{
+   Edje *ed;
+   Evas_List *l;
+   Edje_Color_Class *cc;
+   int i;
+
+   ed = _edje_fetch(obj);
+   if ((!ed) || (!color_class)) return;
+   if (r < 0)   r = 0;
+   if (r > 255) r = 255;
+   if (g < 0)   g = 0;
+   if (g > 255) g = 255;
+   if (b < 0)   b = 0;
+   if (b > 255) b = 255;
+   if (a < 0)   a = 0;
+   if (a > 255) a = 255;
+   for (l = ed->color_classes; l; l = l->next)
+     {
+       cc = l->data;
+       if ((cc->name) && (!strcmp(cc->name, color_class)))
+         {
+            if ((cc->r == r) && (cc->g == g) &&
+                (cc->b == b) && (cc->a == a) &&
+                (cc->r2 == r2) && (cc->g2 == g2) &&
+                (cc->b2 == b2) && (cc->a2 == a2) &&
+                (cc->r3 == r3) && (cc->g3 == g3) &&
+                (cc->b3 == b3) && (cc->a3 == a3))
+              return;
+            cc->r = r;
+            cc->g = g;
+            cc->b = b;
+            cc->a = a;
+            cc->r2 = r2;
+            cc->g2 = g2;
+            cc->b2 = b2;
+            cc->a2 = a2;
+            cc->r3 = r3;
+            cc->g3 = g3;
+            cc->b3 = b3;
+            cc->a3 = a3;
+            ed->dirty = 1;
+            _edje_recalc(ed);
+            return;
+         }
+     }
+   cc = malloc(sizeof(Edje_Color_Class));
+   if (!cc) return;
+   cc->name = evas_stringshare_add(color_class);
+   if (!cc->name)
+     {
+       free(cc);
+       return;
+     }
+   cc->r = r;
+   cc->g = g;
+   cc->b = b;
+   cc->a = a;
+   cc->r2 = r2;
+   cc->g2 = g2;
+   cc->b2 = b2;
+   cc->a2 = a2;
+   cc->r3 = r3;
+   cc->g3 = g3;
+   cc->b3 = b3;
+   cc->a3 = a3;
+   ed->color_classes = evas_list_append(ed->color_classes, cc);
+   ed->dirty = 1;
+
+   for (i = 0; i < ed->table_parts_size; i++)
+     {
+       Edje_Real_Part *rp;
+       rp = ed->table_parts[i];
+       if (rp->part->type == EDJE_PART_TYPE_GROUP && rp->swallowed_object)
+         edje_object_color_class_set(rp->swallowed_object, color_class, r, g, b, a, r2, g2, b2, a2, r3, g3, b3, a3);
+     }
+
+   _edje_recalc(ed);
+}
+
+/**
+ * @param color_class
+ *
+ * Deletes any values at the object level for the specified object and
+ * color class.
+ */
+void
+edje_object_color_class_del(Evas_Object *obj, const char *color_class)
+{
+   Edje *ed;
+   Evas_List *l;
+   Edje_Color_Class *cc = NULL;
+   int i;
+
+   if (!color_class) return;
+
+   ed = _edje_fetch(obj);
+   for (l = ed->color_classes; l; l = l->next)
+     {
+       cc = l->data;
+       if (!strcmp(cc->name, color_class))
+         {
+            ed->color_classes = evas_list_remove(ed->color_classes, cc);
+            evas_stringshare_del(cc->name);
+            free(cc);
+            return;
+         }
+     }
+
+   for (i = 0; i < ed->table_parts_size; i++)
+     {
+       Edje_Real_Part *rp;
+       rp = ed->table_parts[i];
+       if (rp->part->type == EDJE_PART_TYPE_GROUP && rp->swallowed_object)
+         edje_object_color_class_del(rp->swallowed_object, color_class);
+     }
+
+   ed->dirty = 1;
+   _edje_recalc(ed);
+}
+
+/** Set the Edje text class
+ * @param text_class The text class name ?!
+ * @param font The font name
+ * @param size The font size
+ *
+ * This sets updates all edje members which belong to this text class
+ * with the new font attributes.
+ */
+EAPI void
+edje_text_class_set(const char *text_class, const char *font, Evas_Font_Size size)
+{
+   Evas_List *members;
+   Edje_Text_Class *tc;
+
+   if (!text_class) return;
+   if (!font) font = "";
+
+   tc = evas_hash_find(_edje_text_class_hash, text_class);
+   /* Create new text class */
+   if (!tc)
+     {
+        tc = calloc(1, sizeof(Edje_Text_Class));
+       if (!tc) return;
+       tc->name = evas_stringshare_add(text_class);
+       if (!tc->name)
+         {
+            free(tc);
+            return;
+         }
+       _edje_text_class_hash =
+          evas_hash_add(_edje_text_class_hash, text_class, tc);
+       if (evas_hash_alloc_error())
+         {
+            evas_stringshare_del(tc->name);
+            free(tc);
+            return;
+         }
+
+       tc->font = evas_stringshare_add(font);
+       tc->size = size;
+       return;
+     }
+
+   /* If the class found is the same just return */
+   if ((tc->size == size) && (tc->font) && (!strcmp(tc->font, font)))
+     return;
+
+   /* Update the class found */
+   evas_stringshare_del(tc->font);
+   tc->font = evas_stringshare_add(font);
+   if (!tc->font)
+     {
+       _edje_text_class_hash =
+          evas_hash_del(_edje_text_class_hash, text_class, tc);
+       free(tc);
+       return;
+     }
+   tc->size = size;
+
+   /* Tell all members of the text class to recalc */
+   members = evas_hash_find(_edje_text_class_member_hash, text_class);
+   while (members)
+     {
+       Edje *ed;
+
+       ed = members->data;
+       ed->dirty = 1;
+       _edje_textblock_style_all_update(ed);
+       _edje_recalc(ed);
+       members = members->next;
+     }
+}
+
+/**
+ * @param text_class
+ *
+ * Deletes any values at the process level for the specified text class.
+ */
+void
+edje_text_class_del(const char *text_class)
+{
+   Edje_Text_Class *tc;
+   Evas_List *members;
+
+   if (!text_class) return;
+
+   tc = evas_hash_find(_edje_text_class_hash, text_class);
+   if (!tc) return;
+
+   _edje_text_class_hash =
+     evas_hash_del(_edje_text_class_hash, text_class, tc);
+   evas_stringshare_del(tc->name);
+   evas_stringshare_del(tc->font);
+   free(tc);
+
+   members = evas_hash_find(_edje_text_class_member_hash, text_class);
+   while (members)
+     {
+       Edje *ed;
+
+       ed = members->data;
+       ed->dirty = 1;
+       _edje_textblock_style_all_update(ed);
+       _edje_recalc(ed);
+       members = members->next;
+     }
+}
+
+/**
+ * Lists all text classes known about by the current process.
+ *
+ * @return A list of text class names (strings). These strings are stringshares and
+ * the list must be free()'d by the caller.
+ */
+Evas_List *
+edje_text_class_list(void)
+{
+   Edje_List_Foreach_Data fdata;
+
+   memset(&fdata, 0, sizeof(Edje_List_Foreach_Data));
+   evas_hash_foreach(_edje_text_class_member_hash,
+                     _edje_text_class_list_foreach, &fdata);
+
+   return fdata.list;
+}
+
+static Evas_Bool
+_edje_text_class_list_foreach(const Evas_Hash *hash, const char *key, void *data, void *fdata)
+{
+   Edje_List_Foreach_Data *fd;
+
+   fd = fdata;
+   fd->list = evas_list_append(fd->list, evas_stringshare_add(key));
+   return 1;
+}
+
+/** Sets Edje text class
+ * @param obj A valid Evas_Object handle
+ * @param text_class The text class name
+ * @param font Font name
+ * @param size Font Size
+ *
+ * Sets the text class for the Edje.
+ */
+EAPI void
+edje_object_text_class_set(Evas_Object *obj, const char *text_class, const char *font, Evas_Font_Size size)
+{
+   Edje *ed;
+   Evas_List *l;
+   Edje_Text_Class *tc;
+   int i;
+
+   ed = _edje_fetch(obj);
+   if ((!ed) || (!text_class)) return;
+
+   /* for each text_class in the edje */
+   for (l = ed->text_classes; l; l = l->next)
+     {
+       tc = l->data;
+       if ((tc->name) && (!strcmp(tc->name, text_class)))
+         {
+            /* Match and the same, return */
+            if ((tc->font) && (font) && (!strcmp(tc->font, font)) &&
+                (tc->size == size))
+              return;
+
+            /* No font but size is the same, return */
+            if ((!tc->font) && (!font) && (tc->size == size)) return;
+
+            /* Update new text class properties */
+            if (tc->font) evas_stringshare_del(tc->font);
+            if (font) tc->font = evas_stringshare_add(font);
+            else tc->font = NULL;
+            tc->size = size;
+
+            /* Update edje */
+            ed->dirty = 1;
+            _edje_recalc(ed);
+            return;
+         }
+     }
+
+   /* No matches, create a new text class */
+   tc = calloc(1, sizeof(Edje_Text_Class));
+   if (!tc) return;
+   tc->name = evas_stringshare_add(text_class);
+   if (!tc->name)
+     {
+       free(tc);
+       return;
+     }
+   if (font) tc->font = evas_stringshare_add(font);
+   else tc->font = NULL;
+   tc->size = size;
+
+   for (i = 0; i < ed->table_parts_size; i++)
+     {
+       Edje_Real_Part *rp;
+       rp = ed->table_parts[i];
+       if (rp->part->type == EDJE_PART_TYPE_GROUP && rp->swallowed_object)
+         edje_object_text_class_set(rp->swallowed_object, text_class, font, size);
+     }
+
+   /* Add to edje's text class list */
+   ed->text_classes = evas_list_append(ed->text_classes, tc);
+   ed->dirty = 1;
+   _edje_textblock_style_all_update(ed);
+   _edje_recalc(ed);
+}
+
+/** Check if Edje part exists
+ * @param obj A valid Evas_Object handle
+ * @param part The part name to check
+ * @return 0 on Error\n
+ * 1 if Edje part exists
+ */
+EAPI int
+edje_object_part_exists(const Evas_Object *obj, const char *part)
+{
+   Edje *ed;
+   Edje_Real_Part *rp;
+
+   ed = _edje_fetch(obj);
+   if ((!ed) || (!part)) return 0;
+   rp = _edje_real_part_recursive_get(ed, (char *)part);
+   if (!rp) return 0;
+   return 1;
+}
+
+/**
+ * Gets the Evas_Object corresponding to a given part.
+ * You should never modify the state of the returned object
+ * (with evas_object_move() or evas_object_hide() for example),
+ * but you can safely query info about its current state
+ * (with evas_object_visible_get() or evas_object_color_get() for example)
+ *
+ * @param obj A valid Evas_Object handle
+ * @param part The Edje part
+ * @return Returns the Evas_Object corresponding to the given part,
+ * or NULL on failure (if the part doesn't exist)
+ **/
+EAPI const Evas_Object *
+edje_object_part_object_get(const Evas_Object *obj, const char *part)
+{
+   Edje *ed;
+   Edje_Real_Part *rp;
+
+   ed = _edje_fetch(obj);
+   if ((!ed) || (!part)) return NULL;
+   rp = _edje_real_part_recursive_get(ed, (char *)part);
+   if (!rp) return NULL;
+   return rp->object;
+}
+
+/** Get the geometry of an Edje part
+ * @param obj A valid Evas_Object handle
+ * @param part The Edje part
+ * @param x The x coordinate pointer
+ * @param y The y coordinate pointer
+ * @param w The width pointer
+ * @param h The height pointer
+ *
+ * Gets the geometry of an Edje part
+ *
+ * It is valid to pass NULL as any of @a x, @a y, @a w or @a h, whose
+ * values you are uninterested in.
+ */
+EAPI void
+edje_object_part_geometry_get(const Evas_Object *obj, const char *part, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h )
+{
+   Edje *ed;
+   Edje_Real_Part *rp;
+
+   ed = _edje_fetch(obj);
+   if ((!ed) || (!part))
+     {
+       if (x) *x = 0;
+       if (y) *y = 0;
+       if (w) *w = 0;
+       if (h) *h = 0;
+       return;
+     }
+   rp = _edje_real_part_recursive_get(ed, (char *)part);
+   if (!rp)
+     {
+       if (x) *x = 0;
+       if (y) *y = 0;
+       if (w) *w = 0;
+       if (h) *h = 0;
+       return;
+     }
+   if (x) *x = rp->x;
+   if (y) *y = rp->y;
+   if (w) *w = rp->w;
+   if (h) *h = rp->h;
+}
+
+/* FIXDOC: New Function */
+EAPI void
+edje_object_text_change_cb_set(Evas_Object *obj, void (*func) (void *data, Evas_Object *obj, const char *part), void *data)
+{
+   Edje *ed;
+   int i;
+
+   ed = _edje_fetch(obj);
+   if (!ed) return;
+   ed->text_change.func = func;
+   ed->text_change.data = data;
+
+   for (i = 0; i < ed->table_parts_size; i++)
+     {
+       Edje_Real_Part *rp;
+       rp = ed->table_parts[i];
+       if (rp->part->type == EDJE_PART_TYPE_GROUP && rp->swallowed_object)
+         edje_object_text_change_cb_set(rp->swallowed_object, func, data);
+     }
+}
+
+/** Sets the text for an object part
+ * @param obj A valid Evas Object handle
+ * @param part The part name
+ * @param text The text string
+ */
+EAPI void
+edje_object_part_text_set(Evas_Object *obj, const char *part, const char *text)
+{
+   Edje *ed;
+   Edje_Real_Part *rp;
+
+   ed = _edje_fetch(obj);
+   if ((!ed) || (!part)) return;
+   rp = _edje_real_part_recursive_get(ed, (char *)part);
+   if (!rp) return;
+   if ((rp->part->type != EDJE_PART_TYPE_TEXT) &&
+       (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK)) return;
+   if ((!rp->text.text) && (!text))
+     return;
+   if ((rp->text.text) && (text) &&
+       (!strcmp(rp->text.text, text)))
+     return;
+   if (rp->text.text) evas_stringshare_del(rp->text.text);
+   if (text) rp->text.text = evas_stringshare_add(text);
+   else rp->text.text = NULL;
+   rp->edje->dirty = 1;
+   _edje_recalc(rp->edje);
+   if (rp->edje->text_change.func)
+     rp->edje->text_change.func(rp->edje->text_change.data, obj, part);
+}
+
+/** Returns the text of the object part
+ * @param obj A valid Evas_Object handle
+ * @param part The part name
+ * @return The text string
+ */
+EAPI const char *
+edje_object_part_text_get(const Evas_Object *obj, const char *part)
+{
+   Edje *ed;
+   Edje_Real_Part *rp;
+
+   ed = _edje_fetch(obj);
+   if ((!ed) || (!part)) return NULL;
+   rp = _edje_real_part_recursive_get(ed, (char *)part);
+   if (!rp) return NULL;
+   if (rp->part->type == EDJE_PART_TYPE_TEXT)
+     return rp->text.text;
+   return NULL;
+}
+
+/** Swallows an object into the edje
+ * @param obj A valid Evas_Object handle
+ * @param part The part name
+ * @param obj_swallow The object to swallow
+ *
+ * Swallows the object into the edje part so that all geometry changes
+ * for the part affect the swallowed object. (e.g. resize, move, show,
+ * raise/lower, etc.).
+ *
+ * If an object has already been swallowed into this part, then it will
+ * first be unswallowed before the new object is swallowed.
+ */
+EAPI void
+edje_object_part_swallow(Evas_Object *obj, const char *part, Evas_Object *obj_swallow)
+{
+   Edje *ed;
+   Edje_Real_Part *rp;
+
+   ed = _edje_fetch(obj);
+   if ((!ed) || (!part)) return;
+   rp = _edje_real_part_recursive_get(ed, (char *)part);
+   if (!rp) return;
+   if (rp->part->type != EDJE_PART_TYPE_SWALLOW) return;
+   _edje_real_part_swallow(rp, obj_swallow);
+}
+
+static void
+_recalc_extern_parent(Evas_Object *obj)
+{
+   Evas_Object *parent;
+   Edje *ed;
+
+   parent = evas_object_smart_parent_get(obj);
+   ed = _edje_fetch(parent);
+
+   ed->dirty = 1;
+   _edje_recalc(ed);
+}
+
+/** Set the object minimum size
+ * @param obj A valid Evas_Object handle
+ * @param minw The minimum width
+ * @param minh The minimum height
+ *
+ * This sets the minimum size restriction for the object.
+ */
+EAPI void
+edje_extern_object_min_size_set(Evas_Object *obj, Evas_Coord minw, Evas_Coord minh)
+{
+   int mw, mh;
+   Edje_Real_Part *rp;
+
+   mw = minw;
+   mh = minh;
+   if (mw < 0) mw = 0;
+   if (mh < 0) mh = 0;
+   if (mw > 0)
+     evas_object_data_set(obj, "\377 edje.minw", (void *)(long)mw);
+   else
+     evas_object_data_del(obj, "\377 edje.minw");
+   if (mh > 0)
+     evas_object_data_set(obj, "\377 edje.minh", (void *)(long)mh);
+   else
+     evas_object_data_del(obj, "\377 edje.minh");
+
+   rp = evas_object_data_get(obj, "\377 edje.swallowing_part");
+   if (rp)
+     {
+       rp->swallow_params.min.w = mw;
+       rp->swallow_params.min.h = mh;
+
+       _recalc_extern_parent(obj);
+     }
+}
+
+/** Set the object maximum size
+ * @param obj A valid Evas_Object handle
+ * @param maxw The maximum width
+ * @param maxh The maximum height
+ *
+ * This sets the maximum size restriction for the object.
+ */
+EAPI void
+edje_extern_object_max_size_set(Evas_Object *obj, Evas_Coord maxw, Evas_Coord maxh)
+{
+   int mw, mh;
+   Edje_Real_Part *rp;
+
+   mw = maxw;
+   mh = maxh;
+   if (mw >= 0)
+     evas_object_data_set(obj, "\377 edje.maxw", (void *)(long)mw);
+   else
+     evas_object_data_del(obj, "\377 edje.maxw");
+   if (mh >= 0)
+     evas_object_data_set(obj, "\377 edje.maxh", (void *)(long)mh);
+   else
+     evas_object_data_del(obj, "\377 edje.maxh");
+
+   rp = evas_object_data_get(obj, "\377 edje.swallowing_part");
+   if (rp)
+     {
+       rp->swallow_params.max.w = mw >= 0 ? mw : -1;
+       rp->swallow_params.max.h = mh >= 0 ? mh : -1;
+
+       _recalc_extern_parent(obj);
+     }
+}
+
+/** Set the object aspect size
+ * @param obj A valid Evas_Object handle
+ * @param aspect The aspect control axes
+ * @param aw The aspect radio width
+ * @param ah The aspect ratio height
+ *
+ * This sets the desired aspect ratio to keep an object that will be swallowed
+ * by Edje. The width and height define a preferred size ASPECT and the
+ * object may be scaled to be larger or smaller, but retaining the relative
+ * scale of both aspect width and height.
+ */
+EAPI void
+edje_extern_object_aspect_set(Evas_Object *obj, Edje_Aspect_Control aspect, Evas_Coord aw, Evas_Coord ah)
+{
+   int mw, mh;
+   int mc;
+   Edje_Real_Part *rp;
+
+   mc = aspect;
+   mw = aw;
+   mh = ah;
+   if (mc > 0)
+     evas_object_data_set(obj, "\377 edje.aspm", (void *)(long)mc);
+   else
+     evas_object_data_del(obj, "\377 edje.aspm");
+   if (mw > 0)
+     evas_object_data_set(obj, "\377 edje.aspw", (void *)(long)mw);
+   else
+     evas_object_data_del(obj, "\377 edje.aspw");
+   if (mh > 0)
+     evas_object_data_set(obj, "\377 edje.asph", (void *)(long)mh);
+   else
+     evas_object_data_del(obj, "\377 edje.asph");
+
+   rp = evas_object_data_get(obj, "\377 edje.swallowing_part");
+   if (rp)
+     {
+       rp->swallow_params.aspect.mode = mc > 0 ? mc : 0;
+       rp->swallow_params.aspect.w = mw > 0 ? mw : 0;
+       rp->swallow_params.aspect.h = mh > 0 ? mh : 0;
+
+        _recalc_extern_parent(obj);
+     }
+}
+
+/** Unswallow an object
+ * @param obj A valid Evas_Object handle
+ * @param obj_swallow The swallowed object
+ *
+ * Causes the edje to regurgitate a previously swallowed object.  :)
+ */
+EAPI void
+edje_object_part_unswallow(Evas_Object *obj, Evas_Object *obj_swallow)
+{
+   Edje_Real_Part *rp;
+
+   if (!obj_swallow) return;
+
+   rp = (Edje_Real_Part *)evas_object_data_get(obj_swallow, "\377 edje.swallowing_part");
+   if (rp && rp->swallowed_object == obj_swallow)
+     {
+       evas_object_smart_member_del(rp->swallowed_object);
+       evas_object_event_callback_del(rp->swallowed_object,
+                                       EVAS_CALLBACK_FREE,
+                                       _edje_object_part_swallow_free_cb);
+       evas_object_clip_unset(rp->swallowed_object);
+       evas_object_data_del(rp->swallowed_object, "\377 edje.swallowing_part");
+
+       if (rp->part->mouse_events)
+         _edje_callbacks_del(rp->swallowed_object);
+
+       rp->swallowed_object = NULL;
+       rp->swallow_params.min.w = 0;
+       rp->swallow_params.min.h = 0;
+       rp->swallow_params.max.w = 0;
+       rp->swallow_params.max.h = 0;
+       rp->edje->dirty = 1;
+       _edje_recalc(rp->edje);
+       return;
+     }
+}
+
+/** Get the object currently swallowed by a part
+ * @param obj A valid Evas_Object handle
+ * @param part The part name
+ * @return The swallowed object, or NULL if there is none.
+ */
+EAPI Evas_Object *
+edje_object_part_swallow_get(const Evas_Object *obj, const char *part)
+{
+   Edje *ed;
+   Edje_Real_Part *rp;
+
+   ed = _edje_fetch(obj);
+   if ((!ed) || (!part)) return NULL;
+   rp = _edje_real_part_recursive_get(ed, (char *)part);
+   if (!rp) return NULL;
+   return rp->swallowed_object;
+}
+
+/** Get the minimum size for an object
+ * @param obj A valid Evas_Object handle
+ * @param minw Minimum width pointer
+ * @param minh Minimum height pointer
+ *
+ * Gets the object's minimum size values from the Edje. These are set
+ * to zero if no Edje is connected to the Evas Object.
+ */
+EAPI void
+edje_object_size_min_get(const Evas_Object *obj, Evas_Coord *minw, Evas_Coord *minh)
+{
+   Edje *ed;
+
+   ed = _edje_fetch(obj);
+   if ((!ed) || (!ed->collection))
+     {
+       if (minw) *minw = 0;
+       if (minh) *minh = 0;
+       return;
+     }
+   if (minw) *minw = ed->collection->prop.min.w;
+   if (minh) *minh = ed->collection->prop.min.h;
+}
+
+/** Get the maximum size for an object
+ * @param obj A valid Evas_Object handle
+ * @param maxw Maximum width pointer
+ * @param maxh Maximum height pointer
+ *
+ * Gets the object's maximum size values from the Edje.  These are set
+ * to zero if no Edje is connected to the Evas Object.
+ */
+EAPI void
+edje_object_size_max_get(const Evas_Object *obj, Evas_Coord *maxw, Evas_Coord *maxh)
+{
+   Edje *ed;
+
+   ed = _edje_fetch(obj);
+   if ((!ed) || (!ed->collection))
+     {
+       if (maxw) *maxw = 0;
+       if (maxh) *maxh = 0;
+       return;
+     }
+   if (ed->collection->prop.max.w == 0)
+     {
+       /* XXX TODO: convert maxw to 0, fix things that break. */
+       if (maxw) *maxw = EDJE_INF_MAX_W;
+     }
+   else
+     {
+       if (maxw) *maxw = ed->collection->prop.max.w;
+     }
+   if (ed->collection->prop.max.h == 0)
+     {
+       /* XXX TODO: convert maxh to 0, fix things that break. */
+       if (maxh) *maxh = EDJE_INF_MAX_H;
+     }
+   else
+     {
+       if (maxh) *maxh = ed->collection->prop.max.h;
+     }
+}
+
+/** Force a Size/Geometry calculation
+ * @param obj A valid Evas_Object handle
+ *
+ * Forces the object @p obj to recalculation layout regardless of
+ * freeze/thaw.
+ */
+EAPI void
+edje_object_calc_force(Evas_Object *obj)
+{
+   Edje *ed;
+   int pf;
+
+   ed = _edje_fetch(obj);
+   if (!ed) return;
+   ed->dirty = 1;
+   pf = ed->freeze;
+   ed->freeze = 0;
+   _edje_recalc(ed);
+   ed->freeze = pf;
+}
+
+/** Calculate minimum size
+ * @param obj A valid Evas_Object handle
+ * @param minw Minimum width pointer
+ * @param minh Minimum height pointer
+ *
+ * Calculates the object's minimum size ?!
+ */
+EAPI void
+edje_object_size_min_calc(Evas_Object *obj, Evas_Coord *minw, Evas_Coord *minh)
+{
+   edje_object_size_min_restricted_calc(obj, minw, minh, 0, 0);
+}
+
+/** Calculate minimum size
+ * @param obj A valid Evas_Object handle
+ * @param minw Minimum width pointer
+ * @param minh Minimum height pointer
+ * @param restrictedw Do not allow object min width calc to be less than this
+ * @param restrictedh Do not allow object min height calc to be less than this
+ *
+ * Calculates the object's minimum size ?!
+ */
+EAPI void
+edje_object_size_min_restricted_calc(Evas_Object *obj, Evas_Coord *minw, Evas_Coord *minh, Evas_Coord restrictedw, Evas_Coord restrictedh)
+{
+   Edje *ed;
+   Evas_Coord pw, ph;
+   int maxw, maxh;
+   int ok;
+   int reset_maxwh;
+   Edje_Real_Part *pep = NULL;
+
+   ed = _edje_fetch(obj);
+   if ((!ed) || (!ed->collection))
+     {
+       if (minw) *minw = restrictedw;
+       if (minh) *minh = restrictedh;
+       return;
+     }
+   reset_maxwh = 1;
+   ed->calc_only = 1;
+   pw = ed->w;
+   ph = ed->h;
+
+   again:
+   ed->w = restrictedw;
+   ed->h = restrictedh;
+
+   maxw = 0;
+   maxh = 0;
+
+   ok = 1;
+   while (ok)
+     {
+       int i;
+
+       ok = 0;
+       ed->dirty = 1;
+       _edje_recalc(ed);
+       if (reset_maxwh)
+         {
+            maxw = 0;
+            maxh = 0;
+         }
+       pep = NULL;
+       for (i = 0; i < ed->table_parts_size; i++)
+         {
+            Edje_Real_Part *ep;
+            int w, h;
+            int didw;
+
+            ep = ed->table_parts[i];
+            w = ep->w - ep->req.w;
+            h = ep->h - ep->req.h;
+            didw = 0;
+            if (!((ep->chosen_description) &&
+                  (ep->chosen_description->fixed.w)))
+              {
+                 if (w > maxw)
+                   {
+                      maxw = w;
+                      ok = 1;
+                      pep = ep;
+                      didw = 1;
+                   }
+                 if ((ep->part->type == EDJE_PART_TYPE_TEXTBLOCK))
+                   {
+                      /* FIXME: do something */
+                   }
+              }
+            if (!((ep->chosen_description) &&
+                  (ep->chosen_description->fixed.h)))
+              {
+                 if (!((ep->part->type == EDJE_PART_TYPE_TEXTBLOCK) &&
+                       (!ep->chosen_description->text.min_x) &&
+                       (didw)))
+                   {
+                      if (h > maxh)
+                        {
+                           maxh = h;
+                           ok = 1;
+                           pep = ep;
+                        }
+                   }
+              }
+         }
+       if (ok)
+         {
+            ed->w += maxw;
+            ed->h += maxh;
+            if (ed->w < restrictedw) ed->w = restrictedw;
+            if (ed->h < restrictedh) ed->h = restrictedh;
+         }
+       if ((ed->w > 4000) || (ed->h > 4000))
+         {
+            printf("EDJE ERROR: file %s, group %s has a non-fixed part. add fixed: 1 1; ???\n",
+                   ed->path, ed->group);
+            if (pep)
+              printf("  Problem part is: %s\n", pep->part->name);
+            printf("  Will recalc min size not allowing broken parts to affect the result.\n");
+            if (reset_maxwh)
+              {
+                 reset_maxwh = 0;
+                 goto again;
+              }
+         }
+     }
+   ed->min.w = ed->w;
+   ed->min.h = ed->h;
+
+   if (minw) *minw = ed->min.w;
+   if (minh) *minh = ed->min.h;
+
+   ed->w = pw;
+   ed->h = ph;
+   ed->dirty = 1;
+   _edje_recalc(ed);
+   ed->calc_only = 0;
+}
+
+/** Returns the state of the Edje part
+ * @param obj A valid Evas_Object handle
+ * @param part The part name
+ * @param val_ret
+ *
+ * @return The part state:\n
+ * "default" for the default state\n
+ * "" for other states
+ */
+/* FIXME: Correctly return other states */
+EAPI const char *
+edje_object_part_state_get(const Evas_Object *obj, const char *part, double *val_ret)
+{
+   Edje *ed;
+   Edje_Real_Part *rp;
+
+   ed = _edje_fetch(obj);
+   if ((!ed) || (!part))
+     {
+       if (val_ret) *val_ret = 0;
+       return "";
+     }
+   rp = _edje_real_part_recursive_get(ed, (char *)part);
+   if (!rp)
+     {
+       if (val_ret) *val_ret = 0;
+       return "";
+     }
+   if (!rp->chosen_description)
+     {
+       if (val_ret) *val_ret = rp->chosen_description->state.value;
+       if (rp->chosen_description->state.name)
+         return rp->chosen_description->state.name;
+       return "default";
+     }
+   else
+     {
+       if (rp->param1.description)
+         {
+            if (val_ret) *val_ret = rp->param1.description->state.value;
+            if (rp->param1.description->state.name)
+              return rp->param1.description->state.name;
+            return "default";
+         }
+     }
+   if (val_ret) *val_ret = 0;
+   return "";
+}
+
+/** Determine dragable directions
+ * @param obj A valid Evas_Object handle
+ * @param part The part name
+ *
+ * @return 0: Not dragable\n
+ * 1: Dragable in X direction\n
+ * 2: Dragable in Y direction\n
+ * 3: Dragable in X & Y directions
+ */
+EAPI int
+edje_object_part_drag_dir_get(const Evas_Object *obj, const char *part)
+{
+   Edje *ed;
+   Edje_Real_Part *rp;
+
+   ed = _edje_fetch(obj);
+   if ((!ed) || (!part)) return EDJE_DRAG_DIR_NONE;
+   rp = _edje_real_part_recursive_get(ed, (char *)part);
+   if (!rp) return EDJE_DRAG_DIR_NONE;
+   if ((rp->part->dragable.x) && (rp->part->dragable.y)) return EDJE_DRAG_DIR_XY;
+   else if (rp->part->dragable.x) return EDJE_DRAG_DIR_X;
+   else if (rp->part->dragable.y) return EDJE_DRAG_DIR_Y;
+   return EDJE_DRAG_DIR_NONE;
+}
+
+/** Set the dragable object location
+ * @param obj A valid Evas_Object handle
+ * @param part The part name
+ * @param dx The x value
+ * @param dy The y value
+ *
+ * Places the dragable object at the given location.
+ */
+EAPI void
+edje_object_part_drag_value_set(Evas_Object *obj, const char *part, double dx, double dy)
+{
+   Edje *ed;
+   Edje_Real_Part *rp;
+
+   ed = _edje_fetch(obj);
+   if ((!ed) || (!part)) return;
+   rp = _edje_real_part_recursive_get(ed, (char *)part);
+   if (!rp) return;
+   if (rp->drag.down.count > 0) return;
+   if (rp->part->dragable.confine_id != -1)
+     {
+       dx = CLAMP(dx, 0.0, 1.0);
+       dy = CLAMP(dy, 0.0, 1.0);
+     }
+   if (rp->part->dragable.x < 0) dx = 1.0 - dx;
+   if (rp->part->dragable.y < 0) dy = 1.0 - dy;
+   if ((rp->drag.val.x == dx) && (rp->drag.val.y == dy)) return;
+   rp->drag.val.x = dx;
+   rp->drag.val.y = dy;
+   _edje_dragable_pos_set(rp->edje, rp, dx, dy);
+   _edje_emit(rp->edje, "drag,set", rp->part->name);
+}
+
+/** Get the dragable object location
+ * @param obj A valid Evas_Object handle
+ * @param part The part name
+ * @param dx The X value pointer
+ * @param dy The Y value pointer
+ *
+ * Gets the drag location values.
+ */
+/* FIXME: Should this be x and y instead of dx/dy? */
+EAPI void
+edje_object_part_drag_value_get(const Evas_Object *obj, const char *part, double *dx, double *dy)
+{
+   Edje *ed;
+   Edje_Real_Part *rp;
+   double ddx, ddy;
+
+   ed = _edje_fetch(obj);
+   if ((!ed) || (!part))
+     {
+       if (dx) *dx = 0;
+       if (dy) *dy = 0;
+       return;
+     }
+   rp = _edje_real_part_recursive_get(ed, (char *)part);
+   if (!rp)
+     {
+       if (dx) *dx = 0;
+       if (dy) *dy = 0;
+       return;
+     }
+   ddx = rp->drag.val.x;
+   ddy = rp->drag.val.y;
+   if (rp->part->dragable.x < 0) ddx = 1.0 - ddx;
+   if (rp->part->dragable.y < 0) ddy = 1.0 - ddy;
+   if (dx) *dx = ddx;
+   if (dy) *dy = ddy;
+}
+
+/** Set the dragable object size
+ * @param obj A valid Evas_Object handle
+ * @param part The part name
+ * @param dw The drag width
+ * @param dh The drag height
+ *
+ * Sets the size of the dragable object.
+ */
+EAPI void
+edje_object_part_drag_size_set(Evas_Object *obj, const char *part, double dw, double dh)
+{
+   Edje *ed;
+   Edje_Real_Part *rp;
+
+   ed = _edje_fetch(obj);
+   if ((!ed) || (!part)) return;
+   rp = _edje_real_part_recursive_get(ed, (char *)part);
+   if (!rp) return;
+   if (dw < 0.0) dw = 0.0;
+   else if (dw > 1.0) dw = 1.0;
+   if (dh < 0.0) dh = 0.0;
+   else if (dh > 1.0) dh = 1.0;
+   if ((rp->drag.size.x == dw) && (rp->drag.size.y == dh)) return;
+   rp->drag.size.x = dw;
+   rp->drag.size.y = dh;
+   rp->edje->dirty = 1;
+   _edje_recalc(rp->edje);
+}
+
+/** Get the dragable object size
+ * @param obj A valid Evas_Object handle
+ * @param part The part name
+ * @param dw The drag width pointer
+ * @param dh The drag height pointer
+ *
+ * Gets the dragable object size.
+ */
+EAPI void
+edje_object_part_drag_size_get(const Evas_Object *obj, const char *part, double *dw, double *dh)
+{
+   Edje *ed;
+   Edje_Real_Part *rp;
+
+   ed = _edje_fetch(obj);
+   if ((!ed) || (!part))
+     {
+       if (dw) *dw = 0;
+       if (dh) *dh = 0;
+       return;
+     }
+   rp = _edje_real_part_recursive_get(ed, (char *)part);
+   if (!rp)
+     {
+       if (dw) *dw = 0;
+       if (dh) *dh = 0;
+       return;
+     }
+   if (dw) *dw = rp->drag.size.x;
+   if (dh) *dh = rp->drag.size.y;
+}
+
+/** Sets the drag step increment
+ * @param obj A valid Evas_Object handle
+ * @param part The part name
+ * @param dx The x step ammount
+ * @param dy The y step ammount
+ *
+ * Sets the x,y step increments for a dragable object.
+ */
+EAPI void
+edje_object_part_drag_step_set(Evas_Object *obj, const char *part, double dx, double dy)
+{
+   Edje *ed;
+   Edje_Real_Part *rp;
+
+   ed = _edje_fetch(obj);
+   if ((!ed) || (!part)) return;
+   rp = _edje_real_part_recursive_get(ed, (char *)part);
+   if (!rp) return;
+   if (dx < 0.0) dx = 0.0;
+   else if (dx > 1.0) dx = 1.0;
+   if (dy < 0.0) dy = 0.0;
+   else if (dy > 1.0) dy = 1.0;
+   rp->drag.step.x = dx;
+   rp->drag.step.y = dy;
+}
+
+/** Gets the drag step increment values.
+ * @param obj A valid Evas_Object handle
+ * @param part The part
+ * @param dx The x step increment pointer
+ * @param dy The y step increment pointer
+ *
+ * Gets the x and y step increments for the dragable object.
+ */
+EAPI void
+edje_object_part_drag_step_get(const Evas_Object *obj, const char *part, double *dx, double *dy)
+{
+   Edje *ed;
+   Edje_Real_Part *rp;
+
+   ed = _edje_fetch(obj);
+   if ((!ed) || (!part))
+     {
+       if (dx) *dx = 0;
+       if (dy) *dy = 0;
+       return;
+     }
+   rp = _edje_real_part_recursive_get(ed, (char *)part);
+   if (!rp)
+     {
+       if (dx) *dx = 0;
+       if (dy) *dy = 0;
+       return;
+     }
+   if (dx) *dx = rp->drag.step.x;
+   if (dy) *dy = rp->drag.step.y;
+}
+
+/** Sets the page step increments
+ * @param obj A valid Evas_Object handle
+ * @param part The part name
+ * @param dx The x page step increment
+ * @param dy The y page step increment
+ *
+ * Sets the x,y page step increment values.
+ */
+EAPI void
+edje_object_part_drag_page_set(Evas_Object *obj, const char *part, double dx, double dy)
+{
+   Edje *ed;
+   Edje_Real_Part *rp;
+
+   ed = _edje_fetch(obj);
+   if ((!ed) || (!part)) return;
+   rp = _edje_real_part_recursive_get(ed, (char *)part);
+   if (!rp) return;
+   if (dx < 0.0) dx = 0.0;
+   else if (dx > 1.0) dx = 1.0;
+   if (dy < 0.0) dy = 0.0;
+   else if (dy > 1.0) dy = 1.0;
+   rp->drag.page.x = dx;
+   rp->drag.page.y = dy;
+}
+
+/** Gets the page step increments
+ * @param obj A valid Evas_Object handle
+ * @param part The part name
+ * @param dx The dx page increment pointer
+ * @param dy The dy page increment pointer
+ *
+ * Gets the x,y page step increments for the dragable object.
+ */
+EAPI void
+edje_object_part_drag_page_get(const Evas_Object *obj, const char *part, double *dx, double *dy)
+{
+   Edje *ed;
+   Edje_Real_Part *rp;
+
+   ed = _edje_fetch(obj);
+   if ((!ed) || (!part))
+     {
+       if (dx) *dx = 0;
+       if (dy) *dy = 0;
+       return;
+     }
+   rp = _edje_real_part_recursive_get(ed, (char *)part);
+   if (!rp)
+     {
+       if (dx) *dx = 0;
+       if (dy) *dy = 0;
+       return;
+     }
+   if (dx) *dx = rp->drag.page.x;
+   if (dy) *dy = rp->drag.page.y;
+}
+
+/** Steps the dragable x,y steps
+ * @param obj A valid Evas_Object handle
+ * @param part The part name
+ * @param dx The x step
+ * @param dy The y step
+ *
+ * Steps x,y where the step increment is the amount set by
+ * edje_object_part_drag_step_set.
+ */
+EAPI void
+edje_object_part_drag_step(Evas_Object *obj, const char *part, double dx, double dy)
+{
+   Edje *ed;
+   Edje_Real_Part *rp;
+   double px, py;
+
+   ed = _edje_fetch(obj);
+   if ((!ed) || (!part)) return;
+   rp = _edje_real_part_recursive_get(ed, (char *)part);
+   if (!rp) return;
+   if (rp->drag.down.count > 0) return;
+   px = rp->drag.val.x;
+   py = rp->drag.val.y;
+   rp->drag.val.x += dx * rp->drag.step.x * rp->part->dragable.x;
+   rp->drag.val.y += dy * rp->drag.step.y * rp->part->dragable.y;
+   rp->drag.val.x = CLAMP (rp->drag.val.x, 0.0, 1.0);
+   rp->drag.val.y = CLAMP (rp->drag.val.y, 0.0, 1.0);
+   if ((px == rp->drag.val.x) && (py == rp->drag.val.y)) return;
+   _edje_dragable_pos_set(rp->edje, rp, rp->drag.val.x, rp->drag.val.y);
+   _edje_emit(rp->edje, "drag,step", rp->part->name);
+}
+
+/** Pages x,y steps
+ * @param obj A valid Evas_Object handle
+ * @param part The part name
+ * @param dx The x step
+ * @param dy The y step
+ *
+ * Pages x,y where the increment is defined by edje_object_part_drag_page_set.\n
+ * WARNING: Paging is bugged!
+ */
+EAPI void
+edje_object_part_drag_page(Evas_Object *obj, const char *part, double dx, double dy)
+{
+   Edje *ed;
+   Edje_Real_Part *rp;
+   double px, py;
+
+   ed = _edje_fetch(obj);
+   if ((!ed) || (!part)) return;
+   rp = _edje_real_part_recursive_get(ed, (char *)part);
+   if (!rp) return;
+   if (rp->drag.down.count > 0) return;
+   px = rp->drag.val.x;
+   py = rp->drag.val.y;
+   rp->drag.val.x += dx * rp->drag.page.x * rp->part->dragable.x;
+   rp->drag.val.y += dy * rp->drag.page.y * rp->part->dragable.y;
+   rp->drag.val.x = CLAMP (rp->drag.val.x, 0.0, 1.0);
+   rp->drag.val.y = CLAMP (rp->drag.val.y, 0.0, 1.0);
+   if ((px == rp->drag.val.x) && (py == rp->drag.val.y)) return;
+   _edje_dragable_pos_set(rp->edje, rp, rp->drag.val.x, rp->drag.val.y);
+   _edje_emit(rp->edje, "drag,page", rp->part->name);
+}
+
+Edje_Real_Part *
+_edje_real_part_recursive_get(Edje *ed, const char *part)
+{
+   Edje_Real_Part *rp;
+   char **path;
+   path = ecore_str_split(part, EDJE_PART_PATH_SEPARATOR_STRING, 0);
+   if (!path) return NULL;
+
+   //printf("recursive get: %s\n", part);
+   rp = _edje_real_part_recursive_get_helper(ed, path);
+
+   free(*path);
+   free(path);
+   return rp;
+}
+
+Edje_Real_Part *
+_edje_real_part_recursive_get_helper(Edje *ed, char **path)
+{
+   Edje_Real_Part *rp;
+   //printf("  lookup: %s on %s\n", path[0], ed->parent ? ed->parent : "-");
+   rp = _edje_real_part_get(ed, path[0]);
+   if (path[1] == NULL) return rp;
+
+   if ((!rp) || (rp->part->type != EDJE_PART_TYPE_GROUP) ||
+       (!rp->swallowed_object)) return NULL;
+
+   ed = _edje_fetch(rp->swallowed_object);
+   if (!ed) return NULL;
+
+   path++;
+   return _edje_real_part_recursive_get_helper(ed, path);
+}
+
+
+/* Private Routines */
+
+Edje_Real_Part *
+_edje_real_part_get(Edje *ed, const char *part)
+{
+   int i;
+
+   for (i = 0; i < ed->table_parts_size; i++)
+     {
+       Edje_Real_Part *rp;
+
+       rp = ed->table_parts[i];
+       if ((rp->part->name) && (!strcmp(rp->part->name, part))) return rp;
+     }
+   return NULL;
+}
+
+Edje_Color_Class *
+_edje_color_class_find(Edje *ed, const char *color_class)
+{
+   Evas_List *l;
+   Edje_Color_Class *cc = NULL;
+
+   if ((!ed) || (!color_class)) return NULL;
+
+   /* first look through the object scope */
+   for (l = ed->color_classes; l; l = l->next)
+     {
+       cc = l->data;
+       if ((cc->name) && (!strcmp(color_class, cc->name))) return cc;
+     }
+
+   /* next look through the global scope */
+   cc = evas_hash_find(_edje_color_class_hash, color_class);
+   if (cc) return cc;
+
+   /* finally, look through the file scope */
+   for (l = ed->file->color_classes; l; l = l->next)
+     {
+       cc = l->data;
+       if ((cc->name) && (!strcmp(color_class, cc->name))) return cc;
+     }
+
+   return NULL;
+}
+
+void
+_edje_color_class_member_add(Edje *ed, const char *color_class)
+{
+   Evas_List *members;
+
+   if ((!ed) || (!color_class)) return;
+   members = evas_hash_find(_edje_color_class_member_hash, color_class);
+   if (members)
+     {
+        _edje_color_class_member_hash =
+          evas_hash_del(_edje_color_class_member_hash, color_class, members);
+     }
+
+   members = evas_list_prepend(members, ed);
+   _edje_color_class_member_hash =
+     evas_hash_add(_edje_color_class_member_hash, color_class, members);
+}
+
+void
+_edje_color_class_member_del(Edje *ed, const char *color_class)
+{
+   Evas_List *members;
+
+   if ((!ed) || (!color_class)) return;
+   members = evas_hash_find(_edje_color_class_member_hash, color_class);
+   if (!members) return;
+
+   _edje_color_class_member_hash =
+     evas_hash_del(_edje_color_class_member_hash, color_class, members);
+   members = evas_list_remove(members, ed);
+   if (members)
+     {
+        _edje_color_class_member_hash =
+          evas_hash_add(_edje_color_class_member_hash, color_class, members);
+     }
+}
+
+/**
+ * Used to free the member lists that are stored in the text_class
+ * and color_class hashtables.
+ */
+static Evas_Bool
+member_list_free(const Evas_Hash *hash, const char *key, void *data, void *fdata)
+{
+   evas_list_free(data);
+   return 1;
+}
+
+void
+_edje_color_class_members_free(void)
+{
+   if (!_edje_color_class_member_hash) return;
+   evas_hash_foreach(_edje_color_class_member_hash, member_list_free, NULL);
+   evas_hash_free(_edje_color_class_member_hash);
+   _edje_color_class_member_hash = NULL;
+}
+
+static Evas_Bool
+color_class_hash_list_free(const Evas_Hash *hash, const char *key, void *data, void *fdata)
+{
+   Edje_Color_Class *cc;
+
+   cc = data;
+   if (cc->name) evas_stringshare_del(cc->name);
+   free(cc);
+   return 1;
+}
+
+void
+_edje_color_class_hash_free(void)
+{
+   if (!_edje_color_class_hash) return;
+   evas_hash_foreach(_edje_color_class_hash, color_class_hash_list_free, NULL);
+   evas_hash_free(_edje_color_class_hash);
+   _edje_color_class_hash = NULL;
+}
+
+void
+_edje_color_class_on_del(Edje *ed, Edje_Part *ep)
+{
+   Evas_List *tmp;
+
+   if ((ep->default_desc) && (ep->default_desc->color_class))
+     _edje_color_class_member_del(ed, ep->default_desc->color_class);
+
+   for (tmp = ep->other_desc; tmp; tmp = tmp->next)
+     {
+        Edje_Part_Description *desc;
+
+       desc = tmp->data;
+       if (desc->color_class)
+          _edje_color_class_member_del(ed, desc->color_class);
+     }
+}
+
+Edje_Text_Class *
+_edje_text_class_find(Edje *ed, const char *text_class)
+{
+   Evas_List *l;
+
+   if ((!ed) || (!text_class)) return NULL;
+   for (l = ed->text_classes; l; l = l->next)
+     {
+       Edje_Text_Class *tc;
+
+       tc = l->data;
+       if ((tc->name) && (!strcmp(text_class, tc->name))) return tc;
+     }
+   return evas_hash_find(_edje_text_class_hash, text_class);
+}
+
+void
+_edje_text_class_member_add(Edje *ed, const char *text_class)
+{
+   Evas_List *members;
+
+   if ((!ed) || (!text_class)) return;
+
+   /* Get members list */
+   members = evas_hash_find(_edje_text_class_member_hash, text_class);
+
+   /* Remove members list */
+   if (members)
+     {
+        _edje_text_class_member_hash =
+          evas_hash_del(_edje_text_class_member_hash, text_class, members);
+     }
+
+   /* Update the member list */
+   members = evas_list_prepend(members, ed);
+
+   /* Add the member list back */
+   _edje_text_class_member_hash =
+     evas_hash_add(_edje_text_class_member_hash, text_class, members);
+}
+
+void
+_edje_text_class_member_del(Edje *ed, const char *text_class)
+{
+   Evas_List *members;
+
+   if ((!ed) || (!text_class)) return;
+   members = evas_hash_find(_edje_text_class_member_hash, text_class);
+   if (!members) return;
+
+   _edje_text_class_member_hash =
+     evas_hash_del(_edje_text_class_member_hash, text_class, members);
+
+   members = evas_list_remove(members, ed);
+   if (members)
+     {
+        _edje_text_class_member_hash =
+          evas_hash_add(_edje_text_class_member_hash, text_class, members);
+     }
+}
+
+void
+_edje_text_class_members_free(void)
+{
+   if (!_edje_text_class_member_hash) return;
+   evas_hash_foreach(_edje_text_class_member_hash, member_list_free, NULL);
+   evas_hash_free(_edje_text_class_member_hash);
+   _edje_text_class_member_hash = NULL;
+}
+
+static Evas_Bool
+text_class_hash_list_free(const Evas_Hash *hash, const char *key, void *data, void *fdata)
+{
+   Edje_Text_Class *tc;
+
+   tc = data;
+   if (tc->name) evas_stringshare_del(tc->name);
+   if (tc->font) evas_stringshare_del(tc->font);
+   free(tc);
+  return 1;
+}
+
+void
+_edje_text_class_hash_free(void)
+{
+   if (!_edje_text_class_hash) return;
+   evas_hash_foreach(_edje_text_class_hash, text_class_hash_list_free, NULL);
+   evas_hash_free(_edje_text_class_hash);
+   _edje_text_class_hash = NULL;
+}
+
+Edje *
+_edje_fetch(const Evas_Object *obj)
+{
+   Edje *ed;
+   char *type;
+
+   type = (char *)evas_object_type_get(obj);
+   if (!type) return NULL;
+   if (strcmp(type, "edje")) return NULL;
+   ed = evas_object_smart_data_get(obj);
+   if ((ed) && (ed->delete_me)) return NULL;
+   return ed;
+}
+
+int
+_edje_freeze(Edje *ed)
+{
+   ed->freeze++;
+//   printf("FREEZE %i\n", ed->freeze);
+   return ed->freeze;
+}
+
+int
+_edje_thaw(Edje *ed)
+{
+   ed->freeze--;
+   if (ed->freeze < 0)
+     {
+//     printf("-------------########### OVER THAW\n");
+       ed->freeze = 0;
+     }
+   if ((ed->freeze == 0) && (ed->recalc))
+     {
+//     printf("thaw recalc\n");
+       _edje_recalc(ed);
+     }
+   return ed->freeze;
+}
+
+int
+_edje_block(Edje *ed)
+{
+   _edje_ref(ed);
+   ed->block++;
+   return ed->block;
+}
+
+int
+_edje_unblock(Edje *ed)
+{
+   int ret = 0;
+   if (!ed) return ret;
+
+   ed->block--;
+   if (ed->block == 0) ed->block_break = 0;
+   ret = ed->block;
+   _edje_unref(ed);
+   return ret;
+}
+
+int
+_edje_block_break(Edje *ed)
+{
+   if (ed->block_break) return 1;
+   return 0;
+}
+
+void
+_edje_block_violate(Edje *ed)
+{
+   if (ed->block > 0) ed->block_break = 1;
+}
+
+void
+_edje_object_part_swallow_free_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
+{
+   Evas_Object *edje_obj;
+
+   edje_obj = data;
+   edje_object_part_unswallow(edje_obj, obj);
+   return;
+   e = NULL;
+   event_info = NULL;
+}
+
+void
+_edje_real_part_swallow(Edje_Real_Part *rp, Evas_Object *obj_swallow)
+{
+   char *type;
+
+   if (rp->swallowed_object)
+     {
+       evas_object_smart_member_del(rp->swallowed_object);
+       evas_object_event_callback_del(rp->swallowed_object,
+                                      EVAS_CALLBACK_FREE,
+                                      _edje_object_part_swallow_free_cb);
+       evas_object_clip_unset(rp->swallowed_object);
+       evas_object_data_del(rp->swallowed_object, "\377 edje.swallowing_part");
+        if (rp->part->mouse_events)
+          _edje_callbacks_del(rp->swallowed_object);
+       rp->swallowed_object = NULL;
+     }
+   if (!obj_swallow) return;
+   rp->swallowed_object = obj_swallow;
+   evas_object_smart_member_add(rp->swallowed_object, rp->edje->obj);
+   if (rp->clip_to)
+     evas_object_clip_set(rp->swallowed_object, rp->clip_to->object);
+   else evas_object_clip_set(rp->swallowed_object, rp->edje->clipper);
+   evas_object_stack_above(rp->swallowed_object, rp->object);
+   evas_object_event_callback_add(rp->swallowed_object, EVAS_CALLBACK_FREE,
+                                 _edje_object_part_swallow_free_cb,
+                                 rp->edje->obj);
+   type = (char *)evas_object_type_get(obj_swallow);
+   rp->swallow_params.min.w = 0;
+   rp->swallow_params.min.w = 0;
+   rp->swallow_params.max.w = -1;
+   rp->swallow_params.max.h = -1;
+   if ((type) && (!strcmp(type, "edje")))
+     {
+       Evas_Coord w, h;
+
+       edje_object_size_min_get(obj_swallow, &w, &h);
+       rp->swallow_params.min.w = w;
+       rp->swallow_params.min.h = h;
+       edje_object_size_max_get(obj_swallow, &w, &h);
+       rp->swallow_params.max.w = w;
+       rp->swallow_params.max.h = h;
+     }
+   else if ((type) && ((!strcmp(type, "text")) || (!strcmp(type, "polygon")) ||
+                      (!strcmp(type, "line"))))
+     {
+       Evas_Coord w, h;
+
+       evas_object_geometry_get(obj_swallow, NULL, NULL, &w, &h);
+       rp->swallow_params.min.w = w;
+       rp->swallow_params.min.h = h;
+       rp->swallow_params.max.w = w;
+       rp->swallow_params.max.h = h;
+     }
+     {
+       int w1, h1, w2, h2, am, aw, ah;
+
+       w1 = (int)(long)evas_object_data_get(obj_swallow, "\377 edje.minw");
+       h1 = (int)(long)evas_object_data_get(obj_swallow, "\377 edje.minh");
+       w2 = (int)(long)evas_object_data_get(obj_swallow, "\377 edje.maxw");
+       h2 = (int)(long)evas_object_data_get(obj_swallow, "\377 edje.maxh");
+       am = (int)(long)evas_object_data_get(obj_swallow, "\377 edje.aspm");
+       aw = (int)(long)evas_object_data_get(obj_swallow, "\377 edje.aspw");
+       ah = (int)(long)evas_object_data_get(obj_swallow, "\377 edje.asph");
+       rp->swallow_params.min.w = w1;
+       rp->swallow_params.min.h = h1;
+       if (w2 > 0) rp->swallow_params.max.w = w2;
+       if (h2 > 0) rp->swallow_params.max.h = h2;
+       rp->swallow_params.aspect.mode = am;
+       rp->swallow_params.aspect.w = aw;
+       rp->swallow_params.aspect.h = ah;
+       evas_object_data_set(rp->swallowed_object, "\377 edje.swallowing_part", rp);
+     }
+
+   if (rp->part->mouse_events)
+     {
+        _edje_callbacks_add(obj_swallow, rp->edje, rp);
+       if (rp->part->repeat_events)
+           evas_object_repeat_events_set(obj_swallow, 1);
+       if (rp->part->pointer_mode != EVAS_OBJECT_POINTER_MODE_AUTOGRAB)
+         evas_object_pointer_mode_set(obj_swallow, rp->part->pointer_mode);
+       evas_object_pass_events_set(obj_swallow, 0);
+     }
+   else
+     evas_object_pass_events_set(obj_swallow, 1);
+
+   if (rp->part->precise_is_inside)
+     evas_object_precise_is_inside_set(obj_swallow, 1);
+
+   rp->edje->dirty = 1;
+   _edje_recalc(rp->edje);
+}
diff --git a/src/lib/edje_var.c b/src/lib/edje_var.c
new file mode 100644 (file)
index 0000000..af47980
--- /dev/null
@@ -0,0 +1,1063 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#include "edje_private.h"
+
+static int _edje_var_timer_cb(void *data);
+static int _edje_var_anim_cb(void *data);
+
+static Ecore_Animator *_edje_animator = NULL;
+static Evas_List   *_edje_anim_list = NULL;
+
+static int
+_edje_var_timer_cb(void *data)
+{
+   Edje_Var_Timer *et;
+   Edje *ed;
+   Embryo_Function fn;
+
+   et = data;
+   if (!et) return 0;
+   ed = et->edje;
+//      _edje_embryo_script_reset(ed);
+   embryo_program_vm_push(ed->collection->script);
+   _edje_embryo_globals_init(ed);
+   embryo_parameter_cell_push(ed->collection->script, (Embryo_Cell)et->val);
+   ed->var_pool->timers = evas_list_remove(ed->var_pool->timers, et);
+   fn = et->func;
+   free(et);
+     {
+       void *pdata;
+
+       pdata = embryo_program_data_get(ed->collection->script);
+       embryo_program_data_set(ed->collection->script, ed);
+        embryo_program_max_cycle_run_set(ed->collection->script, 5000000);
+       embryo_program_run(ed->collection->script, fn);
+       embryo_program_data_set(ed->collection->script, pdata);
+       embryo_program_vm_pop(ed->collection->script);
+       _edje_recalc(ed);
+     }
+   return 0;
+}
+
+static int
+_edje_var_anim_cb(void *data)
+{
+   Evas_List *l, *tl = NULL;
+   double t;
+
+   t = ecore_time_get();
+   for (l = _edje_anim_list; l; l = l->next)
+     tl = evas_list_append(tl, l->data);
+   while (tl)
+     {
+       Edje *ed;
+       Evas_List *tl2;
+
+       ed = tl->data;
+       _edje_ref(ed);
+       _edje_block(ed);
+       _edje_freeze(ed);
+       tl = evas_list_remove(tl, ed);
+       if (!ed->var_pool) continue;
+       tl2 = NULL;
+       for (l = ed->var_pool->animators; l; l = l->next)
+         tl2 = evas_list_append(tl2, l->data);
+       ed->var_pool->walking_list++;
+       while (tl2)
+         {
+            Edje_Var_Animator *ea;
+
+            ea = tl2->data;
+            if ((ed->var_pool) && (!ea->delete_me))
+              {
+                 if ((!ed->paused) && (!ed->delete_me))
+                   {
+                      Embryo_Function fn;
+                      float v;
+
+                      v = (t - ea->start)  / ea->len;
+                      if (v > 1.0) v= 1.0;
+//                    _edje_embryo_script_reset(ed);
+                      embryo_program_vm_push(ed->collection->script);
+                      _edje_embryo_globals_init(ed);
+                      embryo_parameter_cell_push(ed->collection->script, (Embryo_Cell)ea->val);
+                      embryo_parameter_cell_push(ed->collection->script, EMBRYO_FLOAT_TO_CELL(v));
+                      fn = ea->func;
+                        {
+                           void *pdata;
+
+                           pdata = embryo_program_data_get(ed->collection->script);
+                           embryo_program_data_set(ed->collection->script, ed);
+                           embryo_program_max_cycle_run_set(ed->collection->script, 5000000);
+                           embryo_program_run(ed->collection->script, fn);
+                           embryo_program_data_set(ed->collection->script, pdata);
+                           embryo_program_vm_pop(ed->collection->script);
+                           _edje_recalc(ed);
+                        }
+                      if (v == 1.0) ea->delete_me = 1;
+                   }
+              }
+            tl2 = evas_list_remove(tl2, ea);
+            if (ed->block_break)
+              {
+                 evas_list_free(tl2);
+                 break;
+              }
+         }
+       ed->var_pool->walking_list--;
+       for (l = ed->var_pool->animators; l;)
+         {
+            Edje_Var_Animator *ea;
+
+            ea = l->data;
+            if (ea->delete_me)
+              {
+                 l = l->next;
+                 ed->var_pool->animators = evas_list_remove(ed->var_pool->animators, ea);
+                 free(ea);
+              }
+            else
+              l = l->next;
+         }
+       if (!ed->var_pool->animators)
+         _edje_anim_list = evas_list_remove(_edje_anim_list, ed);
+       _edje_unblock(ed);
+       _edje_thaw(ed);
+       _edje_unref(ed);
+     }
+   if (!_edje_anim_list)
+     {
+       if (_edje_animator)
+         {
+            ecore_animator_del(_edje_animator);
+            _edje_animator = NULL;
+         }
+     }
+   return !!_edje_animator;
+}
+
+Edje_Var *
+_edje_var_new(void)
+{
+   return calloc(1, sizeof(Edje_Var));
+}
+
+void
+_edje_var_free(Edje_Var *var)
+{
+   if (var->type == EDJE_VAR_STRING)
+     {
+       if (var->data.s.v)
+         {
+            free(var->data.s.v);
+         }
+     }
+   free(var);
+}
+
+void
+_edje_var_init(Edje *ed)
+{
+   if (!ed) return;
+   if (!ed->collection) return;
+   if (!ed->collection->script) return;
+   if (ed->var_pool) return;
+   ed->var_pool = calloc(1, sizeof(Edje_Var_Pool));
+   if (!ed->var_pool) return;
+   embryo_program_vm_push(ed->collection->script);
+   ed->var_pool->size = embryo_program_variable_count_get(ed->collection->script);
+   embryo_program_vm_pop(ed->collection->script);
+   if (ed->var_pool->size > 0)
+     ed->var_pool->vars = calloc(1, sizeof(Edje_Var) * ed->var_pool->size);
+}
+
+void
+_edje_var_shutdown(Edje *ed)
+{
+   if (!ed->var_pool) return;
+   if (ed->var_pool->vars)
+     {
+       int i;
+
+       for (i = 0; i < ed->var_pool->size; i++)
+         {
+            if (ed->var_pool->vars[i].type == EDJE_VAR_STRING)
+              {
+                 if (ed->var_pool->vars[i].data.s.v)
+                   {
+                      free(ed->var_pool->vars[i].data.s.v);
+                      ed->var_pool->vars[i].data.s.v = NULL;
+                   }
+              }
+            else if (ed->var_pool->vars[i].type == EDJE_VAR_LIST)
+              {
+                 while (ed->var_pool->vars[i].data.l.v)
+                   {
+                      _edje_var_free(ed->var_pool->vars[i].data.l.v->data);
+                      ed->var_pool->vars[i].data.l.v = evas_list_remove_list(ed->var_pool->vars[i].data.l.v, ed->var_pool->vars[i].data.l.v);
+                   }
+              }
+         }
+       free(ed->var_pool->vars);
+     }
+   while (ed->var_pool->timers)
+     {
+       Edje_Var_Timer *et;
+
+       et = ed->var_pool->timers->data;
+       ecore_timer_del(et->timer);
+       free(et);
+       ed->var_pool->timers = evas_list_remove(ed->var_pool->timers, et);
+     }
+   if (ed->var_pool->animators)
+     {
+       _edje_anim_list = evas_list_remove(_edje_anim_list, ed);
+       if (!_edje_anim_list)
+         {
+            if (_edje_animator)
+              {
+                 ecore_animator_del(_edje_animator);
+                 _edje_animator = NULL;
+              }
+         }
+     }
+   while (ed->var_pool->animators)
+     {
+       Edje_Var_Animator *ea;
+
+       ea = ed->var_pool->animators->data;
+       free(ea);
+       ed->var_pool->animators = evas_list_remove(ed->var_pool->animators, ea);
+     }
+   free(ed->var_pool);
+   ed->var_pool = NULL;
+}
+
+int
+_edje_var_string_id_get(Edje *ed, const char *string)
+{
+   Embryo_Cell cell, *cptr;
+
+   if (!ed) return 0;
+   if (!ed->collection) return 0;
+   if (!ed->collection->script) return 0;
+   if (!string) return 0;
+   cell = embryo_program_variable_find(ed->collection->script, (char *)string);
+   if (cell == EMBRYO_CELL_NONE) return  0;
+   cptr = embryo_data_address_get(ed->collection->script, cell);
+   if (!cptr) return 0;
+   return (int)(*cptr);
+}
+
+int
+_edje_var_var_int_get(Edje *ed, Edje_Var *var)
+{
+   /* auto-cast */
+   if (var->type == EDJE_VAR_STRING)
+     {
+       if (var->data.s.v)
+         {
+            double f;
+
+            f = atof(var->data.s.v);
+            free(var->data.s.v);
+            var->data.s.v = NULL;
+            var->data.i.v = (int)f;
+         }
+       var->type = EDJE_VAR_INT;
+     }
+   else if (var->type == EDJE_VAR_FLOAT)
+     {
+       var->data.i.v = (int)(var->data.f.v);
+       var->type = EDJE_VAR_INT;
+     }
+   else if (var->type == EDJE_VAR_NONE)
+     {
+       var->type = EDJE_VAR_INT;
+     }
+   else if (var->type == EDJE_VAR_LIST)
+     {
+       return 0;
+     }
+   else if (var->type == EDJE_VAR_HASH)
+     {
+       return 0;
+     }
+   return var->data.i.v;
+}
+
+void
+_edje_var_var_int_set(Edje *ed, Edje_Var *var, int v)
+{
+   /* auto-cast */
+   if (var->type == EDJE_VAR_STRING)
+     {
+       if (var->data.s.v)
+         {
+            free(var->data.s.v);
+            var->data.s.v = NULL;
+         }
+       var->type = EDJE_VAR_INT;
+     }
+   else if (var->type == EDJE_VAR_FLOAT)
+     {
+       var->type = EDJE_VAR_INT;
+     }
+   else if (var->type == EDJE_VAR_NONE)
+     {
+       var->type = EDJE_VAR_INT;
+     }
+   else if (var->type == EDJE_VAR_LIST)
+     {
+       return;
+     }
+   else if (var->type == EDJE_VAR_HASH)
+     {
+       return;
+     }
+   var->data.i.v = v;
+}
+
+double
+_edje_var_var_float_get(Edje *ed, Edje_Var *var)
+{
+   /* auto-cast */
+   if (var->type == EDJE_VAR_STRING)
+     {
+       if (var->data.s.v)
+         {
+            double f;
+
+            f = atof(var->data.s.v);
+            free(var->data.s.v);
+            var->data.s.v = NULL;
+            var->data.f.v = f;
+         }
+       var->type = EDJE_VAR_FLOAT;
+     }
+   else if (var->type == EDJE_VAR_INT)
+     {
+       var->data.f.v = (double)(var->data.i.v);
+       var->type = EDJE_VAR_FLOAT;
+     }
+   else if (var->type == EDJE_VAR_NONE)
+     {
+       var->type = EDJE_VAR_FLOAT;
+     }
+   else if (var->type == EDJE_VAR_LIST)
+     {
+       return 0.0;
+     }
+   else if (var->type == EDJE_VAR_HASH)
+     {
+       return 0.0;
+     }
+   return var->data.f.v;
+}
+
+void
+_edje_var_var_float_set(Edje *ed, Edje_Var *var, double v)
+{
+   /* auto-cast */
+   if (var->type == EDJE_VAR_STRING)
+     {
+       if (var->data.s.v)
+         {
+            free(var->data.s.v);
+            var->data.s.v = NULL;
+         }
+       var->type = EDJE_VAR_FLOAT;
+     }
+   else if (var->type == EDJE_VAR_INT)
+     {
+       var->data.f.v = 0;
+       var->type = EDJE_VAR_FLOAT;
+     }
+   else if (var->type == EDJE_VAR_NONE)
+     {
+       var->type = EDJE_VAR_FLOAT;
+     }
+   else if (var->type == EDJE_VAR_LIST)
+     {
+       return;
+     }
+   else if (var->type == EDJE_VAR_HASH)
+     {
+       return;
+     }
+   var->data.f.v = v;
+}
+
+const char *
+_edje_var_var_str_get(Edje *ed, Edje_Var *var)
+{
+   /* auto-cast */
+   if (var->type == EDJE_VAR_INT)
+     {
+       char buf[64];
+
+       snprintf(buf, sizeof(buf), "%i", var->data.i.v);
+       var->data.s.v = strdup(buf);
+       var->type = EDJE_VAR_STRING;
+     }
+   else if (var->type == EDJE_VAR_FLOAT)
+     {
+       char buf[64];
+
+       snprintf(buf, sizeof(buf), "%f", var->data.f.v);
+       var->data.s.v = strdup(buf);
+       var->type = EDJE_VAR_STRING;
+     }
+   else if (var->type == EDJE_VAR_NONE)
+     {
+       var->data.s.v = strdup("");
+       var->type = EDJE_VAR_STRING;
+     }
+   else if (var->type == EDJE_VAR_LIST)
+     {
+       return NULL;
+     }
+   else if (var->type == EDJE_VAR_HASH)
+     {
+       return NULL;
+     }
+   return var->data.s.v;
+}
+
+void
+_edje_var_var_str_set(Edje *ed, Edje_Var *var, const char *str)
+{
+   /* auto-cast */
+   if (var->type == EDJE_VAR_STRING)
+     {
+       if (var->data.s.v)
+         {
+            free(var->data.s.v);
+            var->data.s.v = NULL;
+         }
+     }
+   else if (var->type == EDJE_VAR_INT)
+     {
+       var->type = EDJE_VAR_STRING;
+     }
+   else if (var->type == EDJE_VAR_FLOAT)
+     {
+       var->type = EDJE_VAR_STRING;
+     }
+   else if (var->type == EDJE_VAR_NONE)
+     {
+       var->type = EDJE_VAR_STRING;
+     }
+   else if (var->type == EDJE_VAR_LIST)
+     {
+       return;
+     }
+   else if (var->type == EDJE_VAR_HASH)
+     {
+       return;
+     }
+   var->data.s.v = strdup(str);
+}
+
+int
+_edje_var_int_get(Edje *ed, int id)
+{
+   if (!ed) return 0;
+   if (!ed->var_pool) return 0;
+   id -= EDJE_VAR_MAGIC_BASE;
+   if ((id < 0) || (id >= ed->var_pool->size)) return 0;
+   return _edje_var_var_int_get(ed, &(ed->var_pool->vars[id]));
+}
+
+void
+_edje_var_int_set(Edje *ed, int id, int v)
+{
+   if (!ed) return;
+   if (!ed->var_pool) return;
+   id -= EDJE_VAR_MAGIC_BASE;
+   if ((id < 0) || (id >= ed->var_pool->size)) return;
+   _edje_var_var_int_set(ed, &(ed->var_pool->vars[id]), v);
+}
+
+double
+_edje_var_float_get(Edje *ed, int id)
+{
+   if (!ed) return 0;
+   if (!ed->var_pool) return 0;
+   id -= EDJE_VAR_MAGIC_BASE;
+   if ((id < 0) || (id >= ed->var_pool->size)) return 0;
+   return _edje_var_var_float_get(ed, &(ed->var_pool->vars[id]));
+}
+
+void
+_edje_var_float_set(Edje *ed, int id, double v)
+{
+   if (!ed) return;
+   if (!ed->var_pool) return;
+   id -= EDJE_VAR_MAGIC_BASE;
+   if ((id < 0) || (id >= ed->var_pool->size)) return;
+   _edje_var_var_float_set(ed, &(ed->var_pool->vars[id]), v);
+}
+
+const char *
+_edje_var_str_get(Edje *ed, int id)
+{
+   if (!ed) return NULL;
+   if (!ed->var_pool) return NULL;
+   id -= EDJE_VAR_MAGIC_BASE;
+   if ((id < 0) || (id >= ed->var_pool->size)) return NULL;
+   return _edje_var_var_str_get(ed, &(ed->var_pool->vars[id]));
+}
+
+void
+_edje_var_str_set(Edje *ed, int id, const char *str)
+{
+   if (!ed) return;
+   if (!ed->var_pool) return;
+   if (!str) return;
+   id -= EDJE_VAR_MAGIC_BASE;
+   if ((id < 0) || (id >= ed->var_pool->size)) return;
+   _edje_var_var_str_set(ed, &(ed->var_pool->vars[id]), str);
+}
+
+/* list stuff */
+
+void
+_edje_var_list_var_append(Edje *ed, int id, Edje_Var *var)
+{
+   if (!ed) return;
+   if (!ed->var_pool) return;
+   id -= EDJE_VAR_MAGIC_BASE;
+   if ((id < 0) || (id >= ed->var_pool->size)) return;
+   if (ed->var_pool->vars[id].type != EDJE_VAR_LIST) return;
+   ed->var_pool->vars[id].data.l.v = evas_list_append(ed->var_pool->vars[id].data.l.v, var);
+}
+
+void
+_edje_var_list_var_prepend(Edje *ed, int id, Edje_Var *var)
+{
+   if (!ed) return;
+   if (!ed->var_pool) return;
+   id -= EDJE_VAR_MAGIC_BASE;
+   if ((id < 0) || (id >= ed->var_pool->size)) return;
+   if (ed->var_pool->vars[id].type != EDJE_VAR_LIST) return;
+   ed->var_pool->vars[id].data.l.v = evas_list_prepend(ed->var_pool->vars[id].data.l.v, var);
+}
+
+void
+_edje_var_list_var_append_relative(Edje *ed, int id, Edje_Var *var, Edje_Var *relative)
+{
+   if (!ed) return;
+   if (!ed->var_pool) return;
+   id -= EDJE_VAR_MAGIC_BASE;
+   if ((id < 0) || (id >= ed->var_pool->size)) return;
+   if (ed->var_pool->vars[id].type != EDJE_VAR_LIST) return;
+   ed->var_pool->vars[id].data.l.v = evas_list_append_relative(ed->var_pool->vars[id].data.l.v, var, relative);
+}
+
+void
+_edje_var_list_var_prepend_relative(Edje *ed, int id, Edje_Var *var, Edje_Var *relative)
+{
+   if (!ed) return;
+   if (!ed->var_pool) return;
+   id -= EDJE_VAR_MAGIC_BASE;
+   if ((id < 0) || (id >= ed->var_pool->size)) return;
+   if (ed->var_pool->vars[id].type != EDJE_VAR_LIST) return;
+   ed->var_pool->vars[id].data.l.v = evas_list_prepend_relative(ed->var_pool->vars[id].data.l.v, var, relative);
+}
+
+Edje_Var *
+_edje_var_list_nth(Edje *ed, int id, int n)
+{
+   if (!ed) return NULL;
+   if (!ed->var_pool) return NULL;
+   id -= EDJE_VAR_MAGIC_BASE;
+   if ((id < 0) || (id >= ed->var_pool->size)) return NULL;
+   if (ed->var_pool->vars[id].type != EDJE_VAR_LIST) return NULL;
+   return evas_list_nth(ed->var_pool->vars[id].data.l.v, n);
+}
+
+int
+_edje_var_list_count_get(Edje *ed, int id)
+{
+   if (!ed) return 0;
+   if (!ed->var_pool) return 0;
+   id -= EDJE_VAR_MAGIC_BASE;
+   if ((id < 0) || (id >= ed->var_pool->size)) return 0;
+   if (ed->var_pool->vars[id].type == EDJE_VAR_NONE)
+     ed->var_pool->vars[id].type = EDJE_VAR_LIST;
+   else if (ed->var_pool->vars[id].type != EDJE_VAR_LIST) return 0;
+   return evas_list_count(ed->var_pool->vars[id].data.l.v);
+}
+
+void
+_edje_var_list_remove_nth(Edje *ed, int id, int n)
+{
+   if (!ed) return;
+   if (!ed->var_pool) return;
+   id -= EDJE_VAR_MAGIC_BASE;
+   if ((id < 0) || (id >= ed->var_pool->size)) return;
+   if (ed->var_pool->vars[id].type == EDJE_VAR_NONE)
+     ed->var_pool->vars[id].type = EDJE_VAR_LIST;
+   else if (ed->var_pool->vars[id].type != EDJE_VAR_LIST) return;
+     {
+       Evas_List *nth;
+
+       nth = evas_list_nth_list(ed->var_pool->vars[id].data.l.v, n);
+       if (nth)
+         {
+            _edje_var_free(nth->data);
+            ed->var_pool->vars[id].data.l.v = evas_list_remove_list(ed->var_pool->vars[id].data.l.v, nth);
+         }
+     }
+}
+
+int
+_edje_var_list_nth_int_get(Edje *ed, int id, int n)
+{
+   if (!ed) return 0;
+   if (!ed->var_pool) return 0;
+   id -= EDJE_VAR_MAGIC_BASE;
+   if ((id < 0) || (id >= ed->var_pool->size)) return 0;
+   if (ed->var_pool->vars[id].type == EDJE_VAR_NONE)
+     ed->var_pool->vars[id].type = EDJE_VAR_LIST;
+   else if (ed->var_pool->vars[id].type != EDJE_VAR_LIST) return 0;
+     {
+       Edje_Var *var;
+
+       id += EDJE_VAR_MAGIC_BASE;
+       var = _edje_var_list_nth(ed, id, n);
+       if (!var) return 0;
+       return _edje_var_var_int_get(ed, var);
+     }
+}
+
+void
+_edje_var_list_nth_int_set(Edje *ed, int id, int n, int v)
+{
+   if (!ed) return;
+   if (!ed->var_pool) return;
+   id -= EDJE_VAR_MAGIC_BASE;
+   if ((id < 0) || (id >= ed->var_pool->size)) return;
+   if (ed->var_pool->vars[id].type == EDJE_VAR_NONE)
+     ed->var_pool->vars[id].type = EDJE_VAR_LIST;
+   else if (ed->var_pool->vars[id].type != EDJE_VAR_LIST) return;
+     {
+       Edje_Var *var;
+
+       id += EDJE_VAR_MAGIC_BASE;
+       var = _edje_var_list_nth(ed, id, n);
+       if (!var) return;
+       _edje_var_var_int_set(ed, var, v);
+     }
+}
+
+void
+_edje_var_list_int_append(Edje *ed, int id, int v)
+{
+   if (!ed) return;
+   if (!ed->var_pool) return;
+   id -= EDJE_VAR_MAGIC_BASE;
+   if ((id < 0) || (id >= ed->var_pool->size)) return;
+   if (ed->var_pool->vars[id].type == EDJE_VAR_NONE)
+     ed->var_pool->vars[id].type = EDJE_VAR_LIST;
+   else if (ed->var_pool->vars[id].type != EDJE_VAR_LIST) return;
+     {
+       Edje_Var *var;
+
+       var = _edje_var_new();
+       if (!var) return;
+       id += EDJE_VAR_MAGIC_BASE;
+       _edje_var_var_int_set(ed, var, v);
+       _edje_var_list_var_append(ed, id, var);
+     }
+}
+
+void
+_edje_var_list_int_prepend(Edje *ed, int id, int v)
+{
+   if (!ed) return;
+   if (!ed->var_pool) return;
+   id -= EDJE_VAR_MAGIC_BASE;
+   if ((id < 0) || (id >= ed->var_pool->size)) return;
+   if (ed->var_pool->vars[id].type == EDJE_VAR_NONE)
+     ed->var_pool->vars[id].type = EDJE_VAR_LIST;
+   else if (ed->var_pool->vars[id].type != EDJE_VAR_LIST) return;
+     {
+       Edje_Var *var;
+
+       var = _edje_var_new();
+       if (!var) return;
+       id += EDJE_VAR_MAGIC_BASE;
+       _edje_var_var_int_set(ed, var, v);
+       _edje_var_list_var_prepend(ed, id, var);
+     }
+}
+
+void
+_edje_var_list_int_insert(Edje *ed, int id, int n, int v)
+{
+   if (!ed) return;
+   if (!ed->var_pool) return;
+   id -= EDJE_VAR_MAGIC_BASE;
+   if ((id < 0) || (id >= ed->var_pool->size)) return;
+   if (ed->var_pool->vars[id].type == EDJE_VAR_NONE)
+     ed->var_pool->vars[id].type = EDJE_VAR_LIST;
+   else if (ed->var_pool->vars[id].type != EDJE_VAR_LIST) return;
+     {
+       Edje_Var *var, *var_rel;
+
+       var = _edje_var_new();
+       if (!var) return;
+       id += EDJE_VAR_MAGIC_BASE;
+       _edje_var_var_int_set(ed, var, v);
+       var_rel = _edje_var_list_nth(ed, id, n);
+       if (!var_rel)
+         _edje_var_list_var_append(ed, id, var);
+       else
+         _edje_var_list_var_prepend_relative(ed, id, var, var_rel);
+     }
+}
+
+double
+_edje_var_list_nth_float_get(Edje *ed, int id, int n)
+{
+   if (!ed) return 0;
+   if (!ed->var_pool) return 0;
+   id -= EDJE_VAR_MAGIC_BASE;
+   if ((id < 0) || (id >= ed->var_pool->size)) return 0;
+   if (ed->var_pool->vars[id].type == EDJE_VAR_NONE)
+     ed->var_pool->vars[id].type = EDJE_VAR_LIST;
+   else if (ed->var_pool->vars[id].type != EDJE_VAR_LIST) return 0;
+     {
+       Edje_Var *var;
+
+       id += EDJE_VAR_MAGIC_BASE;
+       var = _edje_var_list_nth(ed, id, n);
+       if (!var) return 0;
+       return _edje_var_var_float_get(ed, var);
+     }
+}
+
+void
+_edje_var_list_nth_float_set(Edje *ed, int id, int n, double v)
+{
+   if (!ed) return;
+   if (!ed->var_pool) return;
+   id -= EDJE_VAR_MAGIC_BASE;
+   if ((id < 0) || (id >= ed->var_pool->size)) return;
+   if (ed->var_pool->vars[id].type == EDJE_VAR_NONE)
+     ed->var_pool->vars[id].type = EDJE_VAR_LIST;
+   else if (ed->var_pool->vars[id].type != EDJE_VAR_LIST) return;
+     {
+       Edje_Var *var;
+
+       id += EDJE_VAR_MAGIC_BASE;
+       var = _edje_var_list_nth(ed, id, n);
+       if (!var) return;
+       _edje_var_var_float_set(ed, var, v);
+     }
+}
+
+void
+_edje_var_list_float_append(Edje *ed, int id, double v)
+{
+   if (!ed) return;
+   if (!ed->var_pool) return;
+   id -= EDJE_VAR_MAGIC_BASE;
+   if ((id < 0) || (id >= ed->var_pool->size)) return;
+   if (ed->var_pool->vars[id].type == EDJE_VAR_NONE)
+     ed->var_pool->vars[id].type = EDJE_VAR_LIST;
+   else if (ed->var_pool->vars[id].type != EDJE_VAR_LIST) return;
+     {
+       Edje_Var *var;
+
+       var = _edje_var_new();
+       if (!var) return;
+       id += EDJE_VAR_MAGIC_BASE;
+       _edje_var_var_float_set(ed, var, v);
+       _edje_var_list_var_append(ed, id, var);
+     }
+}
+
+void
+_edje_var_list_float_prepend(Edje *ed, int id, double v)
+{
+   if (!ed) return;
+   if (!ed->var_pool) return;
+   id -= EDJE_VAR_MAGIC_BASE;
+   if ((id < 0) || (id >= ed->var_pool->size)) return;
+   if (ed->var_pool->vars[id].type == EDJE_VAR_NONE)
+     ed->var_pool->vars[id].type = EDJE_VAR_LIST;
+   else if (ed->var_pool->vars[id].type != EDJE_VAR_LIST) return;
+     {
+       Edje_Var *var;
+
+       var = _edje_var_new();
+       if (!var) return;
+       id += EDJE_VAR_MAGIC_BASE;
+       _edje_var_var_float_set(ed, var, v);
+       _edje_var_list_var_prepend(ed, id, var);
+     }
+}
+
+void
+_edje_var_list_float_insert(Edje *ed, int id, int n, double v)
+{
+   if (!ed) return;
+   if (!ed->var_pool) return;
+   id -= EDJE_VAR_MAGIC_BASE;
+   if ((id < 0) || (id >= ed->var_pool->size)) return;
+   if (ed->var_pool->vars[id].type == EDJE_VAR_NONE)
+     ed->var_pool->vars[id].type = EDJE_VAR_LIST;
+   else if (ed->var_pool->vars[id].type != EDJE_VAR_LIST) return;
+     {
+       Edje_Var *var, *var_rel;
+
+       var = _edje_var_new();
+       if (!var) return;
+       id += EDJE_VAR_MAGIC_BASE;
+       _edje_var_var_float_set(ed, var, v);
+       var_rel = _edje_var_list_nth(ed, id, n);
+       if (!var_rel)
+         _edje_var_list_var_append(ed, id, var);
+       else
+         _edje_var_list_var_prepend_relative(ed, id, var, var_rel);
+     }
+}
+
+const char *
+_edje_var_list_nth_str_get(Edje *ed, int id, int n)
+{
+   if (!ed) return NULL;
+   if (!ed->var_pool) return NULL;
+   id -= EDJE_VAR_MAGIC_BASE;
+   if ((id < 0) || (id >= ed->var_pool->size)) return NULL;
+   if (ed->var_pool->vars[id].type == EDJE_VAR_NONE)
+     ed->var_pool->vars[id].type = EDJE_VAR_LIST;
+   else if (ed->var_pool->vars[id].type != EDJE_VAR_LIST) return NULL;
+     {
+       Edje_Var *var;
+
+       id += EDJE_VAR_MAGIC_BASE;
+       var = _edje_var_list_nth(ed, id, n);
+       if (!var) return NULL;
+       return _edje_var_var_str_get(ed, var);
+     }
+}
+
+void
+_edje_var_list_nth_str_set(Edje *ed, int id, int n, const char *v)
+{
+   if (!ed) return;
+   if (!ed->var_pool) return;
+   id -= EDJE_VAR_MAGIC_BASE;
+   if ((id < 0) || (id >= ed->var_pool->size)) return;
+   if (ed->var_pool->vars[id].type == EDJE_VAR_NONE)
+     ed->var_pool->vars[id].type = EDJE_VAR_LIST;
+   else if (ed->var_pool->vars[id].type != EDJE_VAR_LIST) return;
+     {
+       Edje_Var *var;
+
+       id += EDJE_VAR_MAGIC_BASE;
+       var = _edje_var_list_nth(ed, id, n);
+       if (!var) return;
+       _edje_var_var_str_set(ed, var, v);
+     }
+}
+
+void
+_edje_var_list_str_append(Edje *ed, int id, const char *v)
+{
+   if (!ed) return;
+   if (!ed->var_pool) return;
+   id -= EDJE_VAR_MAGIC_BASE;
+   if ((id < 0) || (id >= ed->var_pool->size)) return;
+   if (ed->var_pool->vars[id].type == EDJE_VAR_NONE)
+     ed->var_pool->vars[id].type = EDJE_VAR_LIST;
+   else if (ed->var_pool->vars[id].type != EDJE_VAR_LIST) return;
+     {
+       Edje_Var *var;
+
+       var = _edje_var_new();
+       if (!var) return;
+       id += EDJE_VAR_MAGIC_BASE;
+       _edje_var_var_str_set(ed, var, v);
+       _edje_var_list_var_append(ed, id, var);
+     }
+}
+
+void
+_edje_var_list_str_prepend(Edje *ed, int id, const char *v)
+{
+   if (!ed) return;
+   if (!ed->var_pool) return;
+   id -= EDJE_VAR_MAGIC_BASE;
+   if ((id < 0) || (id >= ed->var_pool->size)) return;
+   if (ed->var_pool->vars[id].type == EDJE_VAR_NONE)
+     ed->var_pool->vars[id].type = EDJE_VAR_LIST;
+   else if (ed->var_pool->vars[id].type != EDJE_VAR_LIST) return;
+     {
+       Edje_Var *var;
+
+       var = _edje_var_new();
+       if (!var) return;
+       id += EDJE_VAR_MAGIC_BASE;
+       _edje_var_var_str_set(ed, var, v);
+       _edje_var_list_var_prepend(ed, id, var);
+     }
+}
+
+void
+_edje_var_list_str_insert(Edje *ed, int id, int n, const char *v)
+{
+   if (!ed) return;
+   if (!ed->var_pool) return;
+   id -= EDJE_VAR_MAGIC_BASE;
+   if ((id < 0) || (id >= ed->var_pool->size)) return;
+   if (ed->var_pool->vars[id].type == EDJE_VAR_NONE)
+     ed->var_pool->vars[id].type = EDJE_VAR_LIST;
+   else if (ed->var_pool->vars[id].type != EDJE_VAR_LIST) return;
+     {
+       Edje_Var *var, *var_rel;
+
+       var = _edje_var_new();
+       if (!var) return;
+       id += EDJE_VAR_MAGIC_BASE;
+       _edje_var_var_str_set(ed, var, v);
+       var_rel = _edje_var_list_nth(ed, id, n);
+       if (!var_rel)
+         _edje_var_list_var_append(ed, id, var);
+       else
+         _edje_var_list_var_prepend_relative(ed, id, var, var_rel);
+     }
+}
+
+int
+_edje_var_timer_add(Edje *ed, double in, const char *fname, int val)
+{
+   Edje_Var_Timer *et;
+   Embryo_Function fn;
+
+   if (!ed->var_pool) return 0;
+   fn = embryo_program_function_find(ed->collection->script, (char *)fname);
+   if (fn == EMBRYO_FUNCTION_NONE) return 0;
+   et = calloc(1, sizeof(Edje_Var_Timer));
+   if (!et) return 0;
+   et->id = ++ed->var_pool->id_count;
+   et->edje = ed;
+   et->func = fn;
+   et->val = val;
+   et->timer = ecore_timer_add(in, _edje_var_timer_cb, et);
+   if (!et->timer)
+     {
+       free(et);
+       return 0;
+     }
+   ed->var_pool->timers = evas_list_prepend(ed->var_pool->timers, et);
+   return et->id;
+}
+
+static Edje_Var_Timer *
+_edje_var_timer_find(Edje *ed, int id)
+{
+   Evas_List *l;
+
+   if (!ed->var_pool) return NULL;
+
+   for (l = ed->var_pool->timers; l; l = l->next)
+     {
+       Edje_Var_Timer *et = l->data;
+
+       if (et->id == id) return et;
+     }
+
+   return NULL;
+}
+
+void
+_edje_var_timer_del(Edje *ed, int id)
+{
+   Edje_Var_Timer *et;
+
+   et = _edje_var_timer_find(ed, id);
+   if (!et) return;
+
+   ed->var_pool->timers = evas_list_remove(ed->var_pool->timers, et);
+   ecore_timer_del(et->timer);
+   free(et);
+}
+
+int
+_edje_var_anim_add(Edje *ed, double len, const char *fname, int val)
+{
+   Edje_Var_Animator *ea;
+   Embryo_Function fn;
+
+   if (!ed->var_pool) return 0;
+   if (len <= 0.0) return 0;
+   fn = embryo_program_function_find(ed->collection->script, (char *)fname);
+   if (fn == EMBRYO_FUNCTION_NONE) return 0;
+   ea = calloc(1, sizeof(Edje_Var_Animator));
+   if (!ea) return 0;
+   ea->start = ecore_time_get();
+   ea->len = len;
+   ea->id = ++ed->var_pool->id_count;
+   ea->edje = ed;
+   ea->func = fn;
+   ea->val = val;
+   _edje_anim_list = evas_list_append(_edje_anim_list, ed);
+   ed->var_pool->animators = evas_list_prepend(ed->var_pool->animators, ea);
+   if (!_edje_animator)
+     _edje_animator = ecore_animator_add(_edje_var_anim_cb, NULL);
+   return ea->id;
+}
+
+static Edje_Var_Animator *
+_edje_var_anim_find(Edje *ed, int id)
+{
+   Evas_List *l;
+
+   if (!ed->var_pool) return NULL;
+
+   for (l = ed->var_pool->animators; l; l = l->next)
+     {
+       Edje_Var_Animator *ea = l->data;
+
+       if (ea->id == id) return ea;
+     }
+
+   return NULL;
+}
+
+void
+_edje_var_anim_del(Edje *ed, int id)
+{
+   Edje_Var_Animator *ea;
+
+   ea = _edje_var_anim_find(ed, id);
+   if (!ea) return;
+
+   if (ed->var_pool->walking_list)
+     {
+       ea->delete_me = 1;
+       return;
+     }
+
+   ed->var_pool->animators = evas_list_remove(ed->var_pool->animators, ea);
+   free(ea);
+
+   if (ed->var_pool->animators) return;
+
+   _edje_anim_list = evas_list_remove(_edje_anim_list, ed);
+   if (!_edje_anim_list)
+     {
+       if (_edje_animator)
+         {
+            ecore_animator_del(_edje_animator);
+            _edje_animator = NULL;
+         }
+     }
+}