aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaurent Ghigonis <laurent@p1sec.com>2013-03-10 16:31:50 +0100
committerLaurent Ghigonis <laurent@p1sec.com>2013-03-10 16:31:50 +0100
commit36d264dbb5c83b6bee6c9a1786778c646a3b2f8b (patch)
tree36a883eb4a642f468885a5227aafa9b37dddbc6d
parentMerge branch 'master' into traceroute (diff)
parentgg_sniff: fix missing usage() \n (diff)
downloadglouglou-36d264dbb5c83b6bee6c9a1786778c646a3b2f8b.tar.xz
glouglou-36d264dbb5c83b6bee6c9a1786778c646a3b2f8b.zip
Merge branch 'master' into traceroute
-rw-r--r--egraph/AUTHORS1
-rw-r--r--egraph/COPYING15
-rw-r--r--egraph/Egraph.h233
-rw-r--r--egraph/Makefile36
-rw-r--r--egraph/README47
-rw-r--r--egraph/data/blob.pngbin0 -> 3649 bytes
-rw-r--r--egraph/data/edge.pngbin0 -> 372 bytes
-rw-r--r--egraph/data/edge.xcfbin0 -> 8278 bytes
-rw-r--r--egraph/data/vertice.pngbin0 -> 4488 bytes
-rw-r--r--egraph/doc/TODO.txt118
-rw-r--r--egraph/doc/bug_lockup_evas.txt646
-rw-r--r--egraph/doc/egraph.xojbin0 -> 105411 bytes
-rw-r--r--egraph/doc/internals.txt89
-rw-r--r--egraph/egraph.c1275
-rw-r--r--egraph/egraph.edc250
-rw-r--r--egraph/examples/Makefile12
-rw-r--r--egraph/examples/demoapp.c371
-rw-r--r--egraph/examples/simplegraph.c59
-rwxr-xr-xegraph/retest.sh9
-rw-r--r--egraph/tests/Makefile32
-rw-r--r--egraph/tests/README.txt4
-rw-r--r--egraph/tests/creategraph.c37
-rw-r--r--gg_elife/.gitignore68
-rw-r--r--gg_elife/AUTHORS1
-rw-r--r--gg_elife/COPYING1
-rw-r--r--gg_elife/ChangeLog1
-rw-r--r--gg_elife/Makefile.am6
-rw-r--r--gg_elife/NEWS6
-rw-r--r--gg_elife/README79
-rwxr-xr-xgg_elife/autogen.sh17
-rw-r--r--gg_elife/configure.ac64
-rw-r--r--gg_elife/data/Makefile.am18
-rw-r--r--gg_elife/data/elife.edc48
-rw-r--r--gg_elife/in_separate_git.txt6
-rw-r--r--gg_elife/m4/efl_binary.m471
-rw-r--r--gg_elife/src/Makefile.am37
-rw-r--r--gg_elife/src/elife.c106
-rw-r--r--gg_elife/src/elife_edje_external.c192
-rw-r--r--gg_elife/src/elife_evas_smart.c558
-rw-r--r--gg_elife/src/elife_evas_smart.h8
-rw-r--r--gg_sniff/gg_sniff.c2
-rw-r--r--gg_sniff/pcap.c776
-rw-r--r--glougloud/glougloud.c2
43 files changed, 4905 insertions, 396 deletions
diff --git a/egraph/AUTHORS b/egraph/AUTHORS
new file mode 100644
index 0000000..4e42cdc
--- /dev/null
+++ b/egraph/AUTHORS
@@ -0,0 +1 @@
+Laurent Ghigonis <laurent@p1sec.com>
diff --git a/egraph/COPYING b/egraph/COPYING
new file mode 100644
index 0000000..bae178d
--- /dev/null
+++ b/egraph/COPYING
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2012 Laurent Ghigonis <laurent@p1sec.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
diff --git a/egraph/Egraph.h b/egraph/Egraph.h
new file mode 100644
index 0000000..553d5cd
--- /dev/null
+++ b/egraph/Egraph.h
@@ -0,0 +1,233 @@
+#include <Eina.h>
+#include <Evas.h>
+#include <Ecore.h>
+#include <igraph/igraph.h>
+
+#define EGRAPH_VERTICES_MAX 16384 /* cannot be more that u_int32_t */
+#define EGRAPH_VERTICE_NAME_MAXLEN 60
+
+typedef struct Egraph Egraph;
+typedef struct Egraph_Edge Egraph_Edge;
+typedef struct Egraph_Vertice Egraph_Vertice;
+
+typedef enum {
+ EGRAPH_LAYOUT_GRAPHOPT = 0,
+ EGRAPH_LAYOUT_KAMADAKAWAI = 1,
+ EGRAPH_LAYOUT_FRUCHTERMANREINGOLD = 2,
+} Egraph_Layout;
+#define EGRAPH_LAYOUT_DEFAULT EGRAPH_LAYOUT_GRAPHOPT
+#define EGRAPH_LAYOUTING_IMPROVEMENTS 5
+
+struct Egraph {
+ Evas_Object_Smart_Clipped_Data __clipped_data;
+ Evas_Object *obj;
+ Evas_Object *split_vertice_edge;
+ Evas *evas;
+ int graph_directed;
+ int display_vertices;
+ int display_names;
+ int display_edges;
+ int use_animations;
+ int do_improvements;
+ char *theme_path;
+ int theme_edges;
+ Egraph_Layout layout;
+ struct {
+ Ecore_Thread *thread;
+ int running;
+ int todo;
+ int changes_diff;
+ int improvement; /* special pass to improve the graph layout */
+ } layouting;
+ Eina_Hash *vertices;
+ int vertices_count;
+ u_int32_t vertices_freeids[EGRAPH_VERTICES_MAX];
+ int vertice_max_w;
+ int vertice_max_h;
+ Eina_List *edges;
+ igraph_t graph;
+ int graph_vcount;
+ igraph_matrix_t coords;
+ igraph_t graph2; // XXX remove use of graph here, see _repos()
+ int graph2_vcount;
+ igraph_vector_t graph2_wmin, graph2_wmax, graph2_hmin, graph2_hmax;
+ int graph_wmin, graph_wmax, graph_hmin, graph_hmax;
+ igraph_matrix_t coords2;
+};
+
+struct Egraph_Vertice {
+ u_int32_t id;
+ char *name;
+ char *type;
+ u_int status : 1;
+ Evas_Object *o;
+ Eina_List *edges;
+ Eina_List *blobs_incoming;
+ void *data;
+ u_int is_group : 1;
+ Eina_List *group_vertices; /* used if the vertice is a group */
+ u_int new : 1;
+ u_int v2_new : 1;
+ u_int v2_del : 1;
+ u_int v3_new : 1;
+ u_int v3_del : 1;
+};
+
+struct Egraph_Edge {
+ Egraph_Vertice *a;
+ Egraph_Vertice *b;
+ char *type;
+ Evas_Object *o;
+ u_int o_usetheme : 1;
+ void *data;
+ u_int new : 1;
+ u_int v2_new : 1;
+ u_int v2_del : 1;
+ u_int v3_new : 1;
+ u_int v3_del : 1;
+};
+
+/**
+ * Creates Egraph Evas_Object
+ */
+Evas_Object *egraph_new(Evas *evas, int directed);
+
+/**
+ * Remove all nodes and edges
+ */
+void egraph_clear(Evas_Object *obj);
+
+/**
+ * Configure egraph to use an edje theme
+ */
+void egraph_theme_file_set(Evas_Object *obj, char *path);
+
+/**
+ * Sets if egraph should theme the edges
+ */
+void egraph_theme_edges_set(Evas_Object *obj, int set);
+
+/**
+ * Sets the layout of Egraph
+ */
+void egraph_layout_set(Evas_Object *obj, Egraph_Layout layout);
+
+/**
+ * Configure if Egraph should display vertices
+ */
+void egraph_display_vertices_set(Evas_Object *obj, int set);
+
+/**
+ * Configure if Egraph should display vertices names
+ */
+void egraph_display_names_set(Evas_Object *obj, int set);
+
+/**
+ * Configure if Egraph should display edges
+ */
+void egraph_display_edges_set(Evas_Object *obj, int set);
+
+/**
+ * Configure if Egraph should use animations
+ */
+void egraph_use_animations_set(Evas_Object *obj, int set);
+
+/**
+ * Configure if Egraph should do improvements after a graph change
+ */
+void egraph_do_improvements_set(Evas_Object *obj, int set);
+
+/**
+ * Adds an edge between existing vertices
+ *
+ * @param obj The Egraph object
+ * @param a First vertice
+ * @param b Second vertice
+ * @param data The pointer to attach
+ * @return The new Egraph_Egde object
+ */
+Egraph_Edge *egraph_edge_add(Evas_Object *obj,
+ Egraph_Vertice *a, Egraph_Vertice *b, void *data);
+
+/**
+ * Delete an edge
+ *
+ * Hint: This does not delete vertices
+ */
+void egraph_edge_del(Evas_Object *obj, Egraph_Edge *e);
+
+/**
+ * Sets the type of an edge, to make it appear differently in the graph,
+ * depending on theme
+ */
+void egraph_edge_type_set(Evas_Object *obj,
+ Egraph_Edge *e, const char *type);
+/**
+ * Finds if an edge exists between 2 vertices
+ */
+Egraph_Edge *egraph_edge_find(Evas_Object *obj,
+ Egraph_Vertice *a, Egraph_Vertice *b);
+
+/**
+ * Add a vertice to the graph
+ *
+ * @param obj The Egraph object
+ * @param name The name of the vertice to be displayed. If NULL, no name is
+ * displayed
+ * @param data The pointer to attach
+ */
+Egraph_Vertice *egraph_vertice_add(Evas_Object *obj,
+ const char *name, void *data);
+
+/**
+ * Delete a vertice
+ *
+ * Hint: Also deletes all the edges attached to it
+ *
+ * @param obj The Egraph object
+ * @todo add user callback where edges are deleted
+ */
+void egraph_vertice_del(Evas_Object *obj, Egraph_Vertice *v);
+
+/**
+ * Update the name of a vertice
+ */
+void egraph_vertice_rename(Evas_Object *obj, Egraph_Vertice *v,
+ const char *name);
+
+/**
+ * Sets the type of a vertice, to make it appear differently in the graph,
+ * depending on theme
+ */
+void
+egraph_vertice_type_set(Evas_Object *obj, Egraph_Vertice *v, const char *type);
+
+ /**
+ * Send a blob from vertice to vertice
+ *
+ * A blob is a visual object that will move quickly from the first node to the
+ * second node.
+ */
+void egraph_vertice_send_blob(Evas_Object *obj,
+ Egraph_Vertice *a, Egraph_Vertice *b,
+ int size, u_int32_t color);
+
+/**
+ * Add a group of vertices, for later attaching nodes to it.
+ *
+ * The group is represented by an Egraph_Vertice with special properties.
+ */
+Egraph_Vertice *egraph_group_add(Evas_Object *obj,
+ const char *name, void *data);
+
+/**
+ * Attach a vertice to a group
+ */
+int egraph_group_vertice_attach(Evas_Object *obj,
+ Egraph_Vertice *group, Egraph_Vertice *v);
+
+/**
+ * Detach a vertice from a group
+ */
+void egraph_group_vertice_detach(Evas_Object *obj,
+ Egraph_Vertice *group, Egraph_Vertice *v);
diff --git a/egraph/Makefile b/egraph/Makefile
new file mode 100644
index 0000000..99e8310
--- /dev/null
+++ b/egraph/Makefile
@@ -0,0 +1,36 @@
+# CFLAGS += -Werror -Wall -O2 -fPIC -shared -g
+CFLAGS += -Werror -Wall -fPIC -shared -g
+CFLAGS += $(shell pkg-config --libs --cflags edje efx igraph)
+
+PREFIX=/usr/local
+INCLUDEDIR=$(PREFIX)/include
+SHAREDIR=$(PREFIX)/share/egraph
+LIBDIR=$(PREFIX)/lib
+
+SOURCES = egraph.c
+HEADERS = Egraph.h
+EDC = egraph.edc
+EDJ = $(EDC:.edc=.edj)
+OBJECTS = $(SOURCES:.c=.o)
+LIBNAME = libegraph
+TARGET = ${LIBNAME}.so
+
+all: $(TARGET) $(EDJ)
+
+$(TARGET): $(OBJECTS)
+ $(CC) $(CFLAGS) -o $(TARGET) $(OBJECTS)
+
+$(EDJ):
+ edje_cc $(EDC) $(EDJ)
+
+install:
+ @echo "installation of $(LIBNAME)"
+ mkdir -p $(LIBDIR)
+ mkdir -p $(INCLUDEDIR)
+ mkdir -p $(SHAREDIR)
+ install -m 0644 $(TARGET) $(LIBDIR)
+ install -m 0644 $(HEADERS) $(INCLUDEDIR)
+ install -m 0644 $(EDJ) $(SHAREDIR)
+
+clean:
+ rm -f $(TARGET) $(OBJECTS) $(EDJ)
diff --git a/egraph/README b/egraph/README
new file mode 100644
index 0000000..4f15401
--- /dev/null
+++ b/egraph/README
@@ -0,0 +1,47 @@
+egraph - library for rendering dynamic graphs in evas
+
+Requirements
+============
+
+* Enlightenment Foundation Libraries
+http://www.enlightenment.org
+ * eina
+ * evas
+ * ecore
+ * efx
+
+* igraph v0.6
+http://igraph.sourceforge.net/index.html
+ * for Ubuntu: v0.6 is *not* available in ubuntu packages
+You can download it here :
+http://sourceforge.net/projects/igraph/files/C%20library/0.6/igraph-0.6.tar.gz/download
+ * for Archlinux: yaourt -S igraph
+
+Installation
+============
+
+make
+sudo make install
+
+You can run the demoapp in examples :
+make -C examples
+./examples/demoapp
+
+You can use OpenGL rendering :
+ELM_ENGINE=opengl_x11 ./examples/demoapp
+
+Thanks
+======
+
+Thanks to ntamas (http://sixdegrees.hu/) for her advices on igraph.
+Thanks to cedric for tech advices on evas / edje.
+Thanks to vtorri for tech advices on evas / edje.
+Thanks to zmike for tech advices on efx.
+Thanks to raster for tech advices on evas / elementary.
+Thanks to ludivina for graphical advices.
+
+History
+=======
+
+Egraph was developped for the Glouglou Network Map (gg_map), a tool for
+live computer network visualisation based on the Glouglou framework.
diff --git a/egraph/data/blob.png b/egraph/data/blob.png
new file mode 100644
index 0000000..96e4aff
--- /dev/null
+++ b/egraph/data/blob.png
Binary files differ
diff --git a/egraph/data/edge.png b/egraph/data/edge.png
new file mode 100644
index 0000000..f6bbfc4
--- /dev/null
+++ b/egraph/data/edge.png
Binary files differ
diff --git a/egraph/data/edge.xcf b/egraph/data/edge.xcf
new file mode 100644
index 0000000..9481336
--- /dev/null
+++ b/egraph/data/edge.xcf
Binary files differ
diff --git a/egraph/data/vertice.png b/egraph/data/vertice.png
new file mode 100644
index 0000000..54c556b
--- /dev/null
+++ b/egraph/data/vertice.png
Binary files differ
diff --git a/egraph/doc/TODO.txt b/egraph/doc/TODO.txt
new file mode 100644
index 0000000..beed508
--- /dev/null
+++ b/egraph/doc/TODO.txt
@@ -0,0 +1,118 @@
+CURRENT
+=======
+
+vertice / vertice_text visibility will be broken
+need to implement it in the edje object and send signals
+
+* BUG: show nodes labels does not show old nodes labels
+reproduce: do not show labels, add edges, show label, add edges
+
+* BUG: layer stacking is wrong, edges end up on top of nodes, despite
+eg->split_vertice_edge
+
+* BUG: vertices / vertices text fight for being on top. use evas layers ?
+add 500 edges to reproduce, and watch the nodes
+
+TODO
+====
+
+* missing function declaration for static _color_int_to_rgb()
+* reorder static funcs
+
+* BUG: sometimes when you add nodes during layouting, the graph is broken
+a new edge attaches to the wrong new vertice
+it seems to be always the same node numbers that gets this wrong edge
+
+* BUG: EGRAPH_LAYOUT_FRUCHTERMANREINGOLD is broken when adding many edges
+
+* zoom
+10:16 < glouglou> i want to implement zooming with mouse scroll, do you have some ideas about that ?
+10:16 < zmike> that should be trivial
+10:16 < zmike> just hook mouse wheel and use efx_zoom
+10:18 < glouglou> does efx_zoom resize the objects ?
+10:18 < glouglou> all the graph is one evas smart object
+10:18 < zmike> it does not resize, it just maps
+10:18 < glouglou> that clips everything
+10:18 < zmike> it should work, you can see the elm test is working, and that uses smart objects
+10:18 < glouglou> yeah i want to update the coordinates i guess, not really "zoom"
+10:19 < zmike> hm there's no efx_scale yet, but you could use efx_resize I would think
+10:19 < glouglou> i would prefer to resize / update the coords
+10:19 < glouglou> scale yes, that would be it
+10:19 < glouglou> ok
+10:19 < zmike> just calculate the size you want and use efx_resize
+10:20 < zmike> it will animate the resizing
+
+* blobs
+05:17 < glouglou> cedric: t'as vu dans ma demo les packets qui vont d'une node a l'autre quand les nodes bougent et ben les paquets arrivent a l'ancien endroit
+05:17 < glouglou> j'ai regarde un peu dans efx mais j'ai pas trouve de bon moyen
+05:18 < glouglou> il faudrait que les paquets ne puissent pas sortir de l'edge (le trait) entre les 2 nodes
+05:18 < glouglou> si tu as une idee ...
+05:22 -!- Munto [~frugal@2a01:e35:139d:91e0:221:85ff:fee1:5c3c] has quit [Read error: Connection reset by peer]
+05:33 -!- sharinganex [~sharingan@233.208.85.79.rev.sfr.net] has joined #e.fr
+06:22 <@cedric> glouglou: oui, swallow un smart objet
+06:22 <@cedric> qui n'a qu'une seule tache faire bouger des paquets de haut en bas et de bas en haut
+06:22 <@cedric> parcontre ca a un probleme, la taille des objets de tes paquets est limite par la taille de ton objet edje parent
+06:40 < glouglou> cedric: mais un smart object dans un edje object qui est ensuite mappe, juste pour faire un trait, ca va etre un peu lourd non ?
+06:40 < glouglou> et complexe
+06:40 < glouglou> mais c'est vrai que ca resous mon probleme
+06:41 <@cedric> bah, de toute facon, tu vas avoir une surface cree pour mettre ton edje dans ta map
+06:41 <@cedric> dc ca reviendra au meme voir tu fairas l'economie d'une surface
+06:49 < glouglou> cedric: donc quand tu swallow un evas smart object dans un edje object, les coordonnes pour le smart object sont relatifs a la part swallow ?
+06:50 < glouglou> genre si je fais un geometry_get dans mon smart obj, le 0x0 sera en fait en haut a gauche de ma part swallow edje ?
+06:52 <@cedric> oui
+06:52 < glouglou> mais c'est magnifique
+06:52 < glouglou> et splendide a fois
+06:53 < glouglou> merci :D
+
+TODO LATER
+==========
+
+* find a better storage type for vertices
+quick access O(1) -> table
+possibility to foreach and remove at the same time
+
+* possible future API: no edges no vertices for the user
+
+struct Egraph_Vertice {
+ const char *name;
+ int vertice_id;
+ Evas_Object *o;
+ void *data;
+}
+egraph_vertice_add(Egraph *eg, const char *name, void *data);
+egraph_edge_add(Egraph *eg,
+ const char *a, const char *b, void *data);
+
+* speed: draw directly to a surface and map to evas via invisible polygons
+see elementary/src/bin/test_gesture_layer3.c
+04:45 < glouglou> i would like to draw directly in a surface and then give it to evas, but i want in the future to have user interaction with the nodes of my
+ graph, like click click reaction, so i guess i cannot escape from creating one evas object for each node and edge
+04:46 <@raster> trick:
+04:47 <@raster> u can just create invisible rects
+04:47 < glouglou> (i can imagine crazy mapping of the clicks on my surface that triggers evas callbacks, but i'm not that crazy)
+04:47 <@raster> and overlay them on your image
+04:47 <@raster> use them for event stuff
+04:47 < glouglou> lol
+04:47 <@raster> or polygons tyoo
+04:47 <@raster> thats about the only use of polygons
+04:47 <@raster> as u can do exact inside/outside poly checks for events
+04:48 < glouglou> i think you are talking about the crazy things i don't want to do :p
+04:48 <@raster> one of the elm demos does this
+04:48 <@raster> for soming/rotating with little photos
+04:48 <@raster> multitouch test stuff
+
+* speed: from Thanatermesis :
+the Core library (https://github.com/acaudwell/Core)
+renders to OpenGL directly
+used by :
+http://code.google.com/p/logstalgia/
+https://github.com/acaudwell/Gource (http://code.google.com/p/gource/)
+
+OLD
+===
+
+* speed: evas_object_rectangles
+04:40 <@raster> they add clipoouts
+04:41 <@raster> make them just a bit translucent
+04:41 <@raster> and it'll be faster
+
diff --git a/egraph/doc/bug_lockup_evas.txt b/egraph/doc/bug_lockup_evas.txt
new file mode 100644
index 0000000..4f194c5
--- /dev/null
+++ b/egraph/doc/bug_lockup_evas.txt
@@ -0,0 +1,646 @@
+===============================================================================
+This bug is a lockup of evas during rendering in my efl app.
+App freeze and takes 100% CPU. Below are backtraces when gdb was running and
+I interrupt it with Ctrl-C.
+
+At the time of crash, around 300objects total :
+elementary interface + ~100 edje + ~100 evas_object_line
+
+This crash is not predictible from what I see, sometimes it goes fine for a long
+time.
+It seem to crash more when using more edje objects.
+
+svn info
+Revision: 79909
+
+uname -a
+Linux balboa 3.6.7-1-ARCH #1 SMP PREEMPT Sun Nov 18 10:11:22 CET 2012 x86_64 GNU/Linux
+
+===============================================================================
+2012-12-09_18-10
+
+ELM_ENGINE=opengl_x11 gdb ./examples/demoapp
+run
+
+// use the app, and it locks up during an animation (app takes 100% CPU)
+// Ctrl-C
+
+(gdb) bt
+#0 0x00007ffff7233fe6 in _calc_intra_outer_rect_area (outer=<synthetic pointer>, intra=<synthetic pointer>, a=..., b=...) at lib/evas/common/evas_tiler.c:468
+#1 rect_list_add_split_fuzzy (node=0x1967160, rects=0xdf91a8, accepted_error=<optimized out>) at lib/evas/common/evas_tiler.c:652
+#2 rect_list_add_split_fuzzy_and_merge (node=0x1967160, rects=0xdf91a8, split_accepted_error=<optimized out>, merge_accepted_error=<optimized out>)
+ at lib/evas/common/evas_tiler.c:849
+#3 _add_redraw (h=16, w=24, y=200, x=882, rects=0xdf91a8) at lib/evas/common/evas_tiler.c:956
+#4 evas_common_tilebuf_add_redraw (tb=0xdf9170, x=882, y=200, w=24, h=16) at lib/evas/common/evas_tiler.c:986
+#5 0x00007ffff71b2af2 in evas_object_render_pre_effect_updates (rects=0x68ad48, eo_obj=<optimized out>, is_v=1, was_v=<optimized out>)
+ at lib/evas/canvas/evas_object_main.c:343
+#6 0x00007ffff71f1bfc in _evas_render_phase1_direct (render_objects=0x1498d30, active_objects=0x68ab50, e=<optimized out>, restack_objects=<optimized out>,
+ delete_objects=<optimized out>) at lib/evas/canvas/evas_render.c:231
+#7 evas_render_updates_internal (eo_e=0x68aac0, make_updates=make_updates@entry=1 '\001', do_draw=do_draw@entry=1 '\001') at lib/evas/canvas/evas_render.c:1357
+#8 0x00007ffff71f3cd7 in _canvas_render_updates (eo_e=<optimized out>, _pd=<optimized out>, list=<optimized out>) at lib/evas/canvas/evas_render.c:1795
+#9 0x00007ffff6acba35 in _eo_op_internal (obj=0x68aac0, op_type=EO_OP_TYPE_REGULAR, op=402, p_list=0x7fffffffe1b8) at lib/eo/eo.c:363
+#10 0x00007ffff6acd6cd in _eo_dov_internal (p_list=0x7fffffffe1b8, op_type=EO_OP_TYPE_REGULAR, obj=0x68aac0) at lib/eo/eo.c:403
+#11 eo_do_internal (obj=0x68aac0, op_type=op_type@entry=EO_OP_TYPE_REGULAR) at lib/eo/eo.c:434
+#12 0x00007ffff71f3c5f in evas_render_updates (eo_e=<optimized out>) at lib/evas/canvas/evas_render.c:1779
+#13 0x00007fffe73da43a in _ecore_evas_x_render (ee=0x6892f0) at modules/ecore_evas/engines/x/ecore_evas_x.c:447
+#14 0x00007ffff68ba7f1 in _ecore_evas_idle_enter (data=<optimized out>) at lib/ecore_evas/ecore_evas.c:59
+#15 0x00007ffff6f3c019 in _ecore_call_task_cb (data=<optimized out>, func=<optimized out>) at lib/ecore/ecore_private.h:300
+#16 _ecore_idle_enterer_call () at lib/ecore/ecore_idle_enterer.c:235
+#17 0x00007ffff6f3e47b in _ecore_main_loop_iterate_internal (once_only=once_only@entry=0) at lib/ecore/ecore_main.c:1866
+#18 0x00007ffff6f3eb27 in ecore_main_loop_begin () at lib/ecore/ecore_main.c:964
+#19 0x00000000004027bf in elm_main (argc=1, argv=0x7fffffffe568) at demoapp.c:248
+#20 0x0000000000402804 in main (argc=1, argv=0x7fffffffe568) at demoapp.c:255
+
+===============================================================================
+
+===============================================================================
+2012-12-10_15-48
+
+ELM_ENGINE=opengl_x11 gdb ./examples/demoapp
+run
+
+// use the app, and it locks up during an animation (app takes 100% CPU)
+// Ctrl-C
+
+^C
+Program received signal SIGINT, Interrupt.
+0x00007ffff7233fd3 in rect_list_add_split_fuzzy (node=0x1ce6300, rects=0x9c49b8, accepted_error=<optimized out>) at lib/evas/common/evas_tiler.c:650
+650 current = ((rect_node_t *)cur_node)->rect;
+(gdb) bt
+#0 0x00007ffff7233fd3 in rect_list_add_split_fuzzy (node=0x1ce6300, rects=0x9c49b8, accepted_error=<optimized out>) at lib/evas/common/evas_tiler.c:650
+#1 rect_list_add_split_fuzzy_and_merge (node=0x1ce6300, rects=0x9c49b8, split_accepted_error=<optimized out>, merge_accepted_error=<optimized out>)
+ at lib/evas/common/evas_tiler.c:849
+#2 _add_redraw (h=7, w=34, y=254, x=698, rects=0x9c49b8) at lib/evas/common/evas_tiler.c:956
+#3 evas_common_tilebuf_add_redraw (tb=0x9c4980, x=698, y=254, w=34, h=7) at lib/evas/common/evas_tiler.c:986
+#4 0x00007ffff71b2af2 in evas_object_render_pre_effect_updates (rects=0x68bed8, eo_obj=<optimized out>, is_v=1, was_v=<optimized out>)
+ at lib/evas/canvas/evas_object_main.c:343
+#5 0x00007ffff71f1bfc in _evas_render_phase1_direct (render_objects=0x139e3a0, active_objects=0x68bce0, e=<optimized out>, restack_objects=<optimized out>,
+ delete_objects=<optimized out>) at lib/evas/canvas/evas_render.c:231
+#6 evas_render_updates_internal (eo_e=0x68bc50, make_updates=make_updates@entry=1 '\001', do_draw=do_draw@entry=1 '\001') at lib/evas/canvas/evas_render.c:1357
+#7 0x00007ffff71f3cd7 in _canvas_render_updates (eo_e=<optimized out>, _pd=<optimized out>, list=<optimized out>) at lib/evas/canvas/evas_render.c:1795
+#8 0x00007ffff6acba35 in _eo_op_internal (obj=0x68bc50, op_type=EO_OP_TYPE_REGULAR, op=402, p_list=0x7fffffffe158) at lib/eo/eo.c:363
+#9 0x00007ffff6acd6cd in _eo_dov_internal (p_list=0x7fffffffe158, op_type=EO_OP_TYPE_REGULAR, obj=0x68bc50) at lib/eo/eo.c:403
+#10 eo_do_internal (obj=0x68bc50, op_type=op_type@entry=EO_OP_TYPE_REGULAR) at lib/eo/eo.c:434
+#11 0x00007ffff71f3c5f in evas_render_updates (eo_e=<optimized out>) at lib/evas/canvas/evas_render.c:1779
+#12 0x00007fffe73d943a in _ecore_evas_x_render (ee=0x68a480) at modules/ecore_evas/engines/x/ecore_evas_x.c:447
+#13 0x00007ffff68ba7f1 in _ecore_evas_idle_enter (data=<optimized out>) at lib/ecore_evas/ecore_evas.c:59
+#14 0x00007ffff6f3c019 in _ecore_call_task_cb (data=<optimized out>, func=<optimized out>) at lib/ecore/ecore_private.h:300
+#15 _ecore_idle_enterer_call () at lib/ecore/ecore_idle_enterer.c:235
+#16 0x00007ffff6f3e47b in _ecore_main_loop_iterate_internal (once_only=once_only@entry=0) at lib/ecore/ecore_main.c:1866
+#17 0x00007ffff6f3eb27 in ecore_main_loop_begin () at lib/ecore/ecore_main.c:964
+#18 0x00000000004028de in elm_main (argc=1, argv=0x7fffffffe508) at demoapp.c:284
+#19 0x0000000000402923 in main (argc=1, argv=0x7fffffffe508) at demoapp.c:291
+
+===============================================================================
+2012-12-10_23-49
+
+Lockup without opengl !
+I was using software rendering.
+
+gdb ./examples/demoapp
+run
+
+// use the app, and it locks up during an animation (app takes 100% CPU)
+// Ctrl-C
+
+^C
+Program received signal SIGINT, Interrupt.
+_calc_intra_outer_rect_area (outer=<synthetic pointer>, intra=<synthetic pointer>, a=..., b=...) at lib/evas/common/evas_tiler.c:524
+524 intra->area = intra->width * intra->height;
+(gdb) bt
+#0 _calc_intra_outer_rect_area (outer=<synthetic pointer>, intra=<synthetic pointer>, a=..., b=...) at lib/evas/common/evas_tiler.c:524
+#1 rect_list_add_split_fuzzy (node=0xb54050, rects=0x6927f8, accepted_error=<optimized out>) at lib/evas/common/evas_tiler.c:652
+#2 rect_list_add_split_fuzzy_and_merge (node=0xb54050, rects=0x6927f8, split_accepted_error=<optimized out>, merge_accepted_error=<optimized out>)
+ at lib/evas/common/evas_tiler.c:849
+#3 _add_redraw (h=72, w=348, y=429, x=296, rects=0x6927f8) at lib/evas/common/evas_tiler.c:956
+#4 evas_common_tilebuf_add_redraw (tb=0x6927c0, x=296, y=429, w=348, h=72) at lib/evas/common/evas_tiler.c:986
+#5 0x00007ffff71b2af2 in evas_object_render_pre_effect_updates (rects=rects@entry=0x689ac8, eo_obj=eo_obj@entry=0x8d2360, is_v=is_v@entry=1, was_v=was_v@entry=
+ 1) at lib/evas/canvas/evas_object_main.c:343
+#6 0x00007ffff71ab60d in evas_object_image_render_pre (eo_obj=0x8d2360, obj=0x8d23f0) at lib/evas/canvas/evas_object_image.c:3768
+#7 0x00007ffff71f1668 in evas_render_updates_internal (eo_e=0x689840, make_updates=make_updates@entry=1 '\001', do_draw=do_draw@entry=1 '\001')
+ at lib/evas/canvas/evas_render.c:1365
+#8 0x00007ffff71f3cd7 in _canvas_render_updates (eo_e=<optimized out>, _pd=<optimized out>, list=<optimized out>) at lib/evas/canvas/evas_render.c:1795
+#9 0x00007ffff6acba35 in _eo_op_internal (obj=0x689840, op_type=EO_OP_TYPE_REGULAR, op=402, p_list=0x7fffffffe168) at lib/eo/eo.c:363
+#10 0x00007ffff6acd6cd in _eo_dov_internal (p_list=0x7fffffffe168, op_type=EO_OP_TYPE_REGULAR, obj=0x689840) at lib/eo/eo.c:403
+#11 eo_do_internal (obj=0x689840, op_type=op_type@entry=EO_OP_TYPE_REGULAR) at lib/eo/eo.c:434
+#12 0x00007ffff71f3c5f in evas_render_updates (eo_e=<optimized out>) at lib/evas/canvas/evas_render.c:1779
+#13 0x00007fffe73d943a in _ecore_evas_x_render (ee=0x6880c0) at modules/ecore_evas/engines/x/ecore_evas_x.c:447
+#14 0x00007ffff68ba7f1 in _ecore_evas_idle_enter (data=<optimized out>) at lib/ecore_evas/ecore_evas.c:59
+#15 0x00007ffff6f3c019 in _ecore_call_task_cb (data=<optimized out>, func=<optimized out>) at lib/ecore/ecore_private.h:300
+#16 _ecore_idle_enterer_call () at lib/ecore/ecore_idle_enterer.c:235
+#17 0x00007ffff6f3e47b in _ecore_main_loop_iterate_internal (once_only=once_only@entry=0) at lib/ecore/ecore_main.c:1866
+#18 0x00007ffff6f3eb27 in ecore_main_loop_begin () at lib/ecore/ecore_main.c:964
+#19 0x00000000004028de in elm_main (argc=1, argv=0x7fffffffe518) at demoapp.c:284
+#20 0x0000000000402923 in main (argc=1, argv=0x7fffffffe518) at demoapp.c:291
+
+===============================================================================
+2012-12-10_23-58
+
+// Same scenario
+
+^C
+Program received signal SIGINT, Interrupt.
+rect_list_add_split_fuzzy (node=0xfe0150, rects=0x6927f8, accepted_error=<optimized out>) at lib/evas/common/evas_tiler.c:653
+653 area = current.area + r.area - intra.area;
+(gdb) bt
+#0 rect_list_add_split_fuzzy (node=0xfe0150, rects=0x6927f8, accepted_error=<optimized out>) at lib/evas/common/evas_tiler.c:653
+#1 rect_list_add_split_fuzzy_and_merge (node=0xfe0150, rects=0x6927f8, split_accepted_error=<optimized out>, merge_accepted_error=<optimized out>)
+ at lib/evas/common/evas_tiler.c:849
+#2 _add_redraw (h=63, w=85, y=314, x=493, rects=0x6927f8) at lib/evas/common/evas_tiler.c:956
+#3 evas_common_tilebuf_add_redraw (tb=0x6927c0, x=493, y=314, w=85, h=63) at lib/evas/common/evas_tiler.c:986
+#4 0x00007ffff71b2b9d in evas_object_render_pre_effect_updates (rects=0x689ac8, eo_obj=<optimized out>, is_v=1, was_v=<optimized out>)
+ at lib/evas/canvas/evas_object_main.c:356
+#5 0x00007ffff71f1bfc in _evas_render_phase1_direct (render_objects=0x1b79f50, active_objects=0x6898d0, e=<optimized out>, restack_objects=<optimized out>,
+ delete_objects=<optimized out>) at lib/evas/canvas/evas_render.c:231
+#6 evas_render_updates_internal (eo_e=0x689840, make_updates=make_updates@entry=1 '\001', do_draw=do_draw@entry=1 '\001') at lib/evas/canvas/evas_render.c:1357
+#7 0x00007ffff71f3cd7 in _canvas_render_updates (eo_e=<optimized out>, _pd=<optimized out>, list=<optimized out>) at lib/evas/canvas/evas_render.c:1795
+#8 0x00007ffff6acba35 in _eo_op_internal (obj=0x689840, op_type=EO_OP_TYPE_REGULAR, op=402, p_list=0x7fffffffe168) at lib/eo/eo.c:363
+#9 0x00007ffff6acd6cd in _eo_dov_internal (p_list=0x7fffffffe168, op_type=EO_OP_TYPE_REGULAR, obj=0x689840) at lib/eo/eo.c:403
+#10 eo_do_internal (obj=0x689840, op_type=op_type@entry=EO_OP_TYPE_REGULAR) at lib/eo/eo.c:434
+#11 0x00007ffff71f3c5f in evas_render_updates (eo_e=<optimized out>) at lib/evas/canvas/evas_render.c:1779
+#12 0x00007fffe73d943a in _ecore_evas_x_render (ee=0x6880c0) at modules/ecore_evas/engines/x/ecore_evas_x.c:447
+#13 0x00007ffff68ba7f1 in _ecore_evas_idle_enter (data=<optimized out>) at lib/ecore_evas/ecore_evas.c:59
+#14 0x00007ffff6f3c019 in _ecore_call_task_cb (data=<optimized out>, func=<optimized out>) at lib/ecore/ecore_private.h:300
+#15 _ecore_idle_enterer_call () at lib/ecore/ecore_idle_enterer.c:235
+#16 0x00007ffff6f3e47b in _ecore_main_loop_iterate_internal (once_only=once_only@entry=0) at lib/ecore/ecore_main.c:1866
+#17 0x00007ffff6f3eb27 in ecore_main_loop_begin () at lib/ecore/ecore_main.c:964
+#18 0x00000000004028de in elm_main (argc=1, argv=0x7fffffffe518) at demoapp.c:284
+#19 0x0000000000402923 in main (argc=1, argv=0x7fffffffe518) at demoapp.c:291
+
+===============================================================================
+2012-12-11_00-34
+
+// Same scenario
+
+^C
+Program received signal SIGINT, Interrupt.
+rect_list_add_split_fuzzy (node=0xb54370, rects=0x6927f8, accepted_error=<optimized out>) at lib/evas/common/evas_tiler.c:702
+702 else if (intra.area <= accepted_error)
+(gdb) bt
+#0 rect_list_add_split_fuzzy (node=0xb54370, rects=0x6927f8, accepted_error=<optimized out>) at lib/evas/common/evas_tiler.c:702
+#1 rect_list_add_split_fuzzy_and_merge (node=0xb54370, rects=0x6927f8, split_accepted_error=<optimized out>, merge_accepted_error=<optimized out>)
+ at lib/evas/common/evas_tiler.c:849
+#2 _add_redraw (h=39, w=49, y=156, x=486, rects=0x6927f8) at lib/evas/common/evas_tiler.c:956
+#3 evas_common_tilebuf_add_redraw (tb=0x6927c0, x=486, y=156, w=49, h=39) at lib/evas/common/evas_tiler.c:986
+#4 0x00007ffff71b2af2 in evas_object_render_pre_effect_updates (rects=0x689ac8, eo_obj=<optimized out>, is_v=1, was_v=<optimized out>)
+ at lib/evas/canvas/evas_object_main.c:343
+#5 0x00007ffff71f1bfc in _evas_render_phase1_direct (render_objects=0x1671880, active_objects=0x6898d0, e=<optimized out>, restack_objects=<optimized out>,
+ delete_objects=<optimized out>) at lib/evas/canvas/evas_render.c:231
+#6 evas_render_updates_internal (eo_e=0x689840, make_updates=make_updates@entry=1 '\001', do_draw=do_draw@entry=1 '\001') at lib/evas/canvas/evas_render.c:1357
+#7 0x00007ffff71f3cd7 in _canvas_render_updates (eo_e=<optimized out>, _pd=<optimized out>, list=<optimized out>) at lib/evas/canvas/evas_render.c:1795
+#8 0x00007ffff6acba35 in _eo_op_internal (obj=0x689840, op_type=EO_OP_TYPE_REGULAR, op=402, p_list=0x7fffffffe168) at lib/eo/eo.c:363
+#9 0x00007ffff6acd6cd in _eo_dov_internal (p_list=0x7fffffffe168, op_type=EO_OP_TYPE_REGULAR, obj=0x689840) at lib/eo/eo.c:403
+#10 eo_do_internal (obj=0x689840, op_type=op_type@entry=EO_OP_TYPE_REGULAR) at lib/eo/eo.c:434
+#11 0x00007ffff71f3c5f in evas_render_updates (eo_e=<optimized out>) at lib/evas/canvas/evas_render.c:1779
+#12 0x00007fffe73d943a in _ecore_evas_x_render (ee=0x6880c0) at modules/ecore_evas/engines/x/ecore_evas_x.c:447
+#13 0x00007ffff68ba7f1 in _ecore_evas_idle_enter (data=<optimized out>) at lib/ecore_evas/ecore_evas.c:59
+#14 0x00007ffff6f3c019 in _ecore_call_task_cb (data=<optimized out>, func=<optimized out>) at lib/ecore/ecore_private.h:300
+#15 _ecore_idle_enterer_call () at lib/ecore/ecore_idle_enterer.c:235
+#16 0x00007ffff6f3e47b in _ecore_main_loop_iterate_internal (once_only=once_only@entry=0) at lib/ecore/ecore_main.c:1866
+#17 0x00007ffff6f3eb27 in ecore_main_loop_begin () at lib/ecore/ecore_main.c:964
+#18 0x00000000004028de in elm_main (argc=1, argv=0x7fffffffe518) at demoapp.c:284
+#19 0x0000000000402923 in main (argc=1, argv=0x7fffffffe518) at demoapp.c:291
+
+===============================================================================
+2012-12-11_05-39
+
+Without any evas_object_line
+
+^C
+Program received signal SIGINT, Interrupt.
+rect_list_add_split_fuzzy (node=0xcf4c20, rects=0x692788, accepted_error=<optimized out>) at lib/evas/common/evas_tiler.c:650
+650 current = ((rect_node_t *)cur_node)->rect;
+(gdb) bt
+#0 rect_list_add_split_fuzzy (node=0xcf4c20, rects=0x692788, accepted_error=<optimized out>) at lib/evas/common/evas_tiler.c:650
+#1 rect_list_add_split_fuzzy_and_merge (node=0xcf4c20, rects=0x692788, split_accepted_error=<optimized out>, merge_accepted_error=<optimized out>)
+ at lib/evas/common/evas_tiler.c:849
+#2 _add_redraw (h=16, w=1047, y=240, x=263, rects=0x692788) at lib/evas/common/evas_tiler.c:956
+#3 evas_common_tilebuf_add_redraw (tb=0x692750, x=263, y=240, w=1047, h=16) at lib/evas/common/evas_tiler.c:986
+#4 0x00007ffff71b2af2 in evas_object_render_pre_effect_updates (rects=rects@entry=0x689a58, eo_obj=eo_obj@entry=0x1100690, is_v=is_v@entry=1,
+ was_v=was_v@entry=1) at lib/evas/canvas/evas_object_main.c:343
+#5 0x00007ffff71ab60d in evas_object_image_render_pre (eo_obj=0x1100690, obj=0x1100720) at lib/evas/canvas/evas_object_image.c:3768
+#6 0x00007ffff71f1bfc in _evas_render_phase1_direct (render_objects=0x1100690, active_objects=0x689860, e=<optimized out>, restack_objects=<optimized out>,
+ delete_objects=<optimized out>) at lib/evas/canvas/evas_render.c:231
+#7 evas_render_updates_internal (eo_e=0x6897d0, make_updates=make_updates@entry=1 '\001', do_draw=do_draw@entry=1 '\001') at lib/evas/canvas/evas_render.c:1357
+#8 0x00007ffff71f3cd7 in _canvas_render_updates (eo_e=<optimized out>, _pd=<optimized out>, list=<optimized out>) at lib/evas/canvas/evas_render.c:1795
+#9 0x00007ffff6acba35 in _eo_op_internal (obj=0x6897d0, op_type=EO_OP_TYPE_REGULAR, op=402, p_list=0x7fffffffe1d8) at lib/eo/eo.c:363
+#10 0x00007ffff6acd6cd in _eo_dov_internal (p_list=0x7fffffffe1d8, op_type=EO_OP_TYPE_REGULAR, obj=0x6897d0) at lib/eo/eo.c:403
+#11 eo_do_internal (obj=0x6897d0, op_type=op_type@entry=EO_OP_TYPE_REGULAR) at lib/eo/eo.c:434
+#12 0x00007ffff71f3c5f in evas_render_updates (eo_e=<optimized out>) at lib/evas/canvas/evas_render.c:1779
+#13 0x00007fffe73d743a in _ecore_evas_x_render (ee=0x688050) at modules/ecore_evas/engines/x/ecore_evas_x.c:447
+#14 0x00007ffff68ba7f1 in _ecore_evas_idle_enter (data=<optimized out>) at lib/ecore_evas/ecore_evas.c:59
+#15 0x00007ffff6f3c019 in _ecore_call_task_cb (data=<optimized out>, func=<optimized out>) at lib/ecore/ecore_private.h:300
+#16 _ecore_idle_enterer_call () at lib/ecore/ecore_idle_enterer.c:235
+#17 0x00007ffff6f3e47b in _ecore_main_loop_iterate_internal (once_only=once_only@entry=0) at lib/ecore/ecore_main.c:1866
+#18 0x00007ffff6f3eb27 in ecore_main_loop_begin () at lib/ecore/ecore_main.c:964
+#19 0x00000000004028ce in elm_main (argc=1, argv=0x7fffffffe588) at demoapp.c:284
+#20 0x0000000000402913 in main (argc=1, argv=0x7fffffffe588) at demoapp.c:291
+
+===============================================================================
+2012-12-11_05-42
+
+with 500 nodes = 1500 objects, no evas_object_line, but 500 evas_map
+
+^C
+Program received signal SIGINT, Interrupt.
+_calc_intra_outer_rect_area (outer=<synthetic pointer>, intra=<synthetic pointer>, a=..., b=...) at lib/evas/common/evas_tiler.c:498
+498 if (a.top < b.top)
+(gdb) bt
+#0 _calc_intra_outer_rect_area (outer=<synthetic pointer>, intra=<synthetic pointer>, a=..., b=...) at lib/evas/common/evas_tiler.c:498
+#1 rect_list_add_split_fuzzy (node=0x1acbb00, rects=0x93f238, accepted_error=<optimized out>) at lib/evas/common/evas_tiler.c:652
+#2 rect_list_add_split_fuzzy_and_merge (node=0x1acbb00, rects=0x93f238, split_accepted_error=<optimized out>, merge_accepted_error=<optimized out>)
+ at lib/evas/common/evas_tiler.c:849
+#3 _add_redraw (h=52, w=371, y=437, x=826, rects=0x93f238) at lib/evas/common/evas_tiler.c:956
+#4 evas_common_tilebuf_add_redraw (tb=0x93f200, x=826, y=437, w=371, h=52) at lib/evas/common/evas_tiler.c:986
+#5 0x00007ffff71ed67f in _evas_render_prev_cur_clip_cache_add (obj=obj@entry=0x1c752b0, e=0x68bc90, e=0x68bc90) at lib/evas/canvas/evas_render.c:158
+#6 0x00007ffff71ee940 in _evas_render_phase1_object_process (e=e@entry=0x68bc90, eo_obj=0x1c75220, active_objects=active_objects@entry=0x68bda8,
+ restack_objects=restack_objects@entry=0x68bdc8, delete_objects=delete_objects@entry=0x68bd88, render_objects=render_objects@entry=0x68bde8, restack=0,
+ redraw_all=redraw_all@entry=0x7fffffffe0ec, mapped_parent=mapped_parent@entry=0 '\000') at lib/evas/canvas/evas_render.c:355
+#7 0x00007ffff71eeaf6 in _evas_render_phase1_object_process (e=e@entry=0x68bc90, eo_obj=<optimized out>, active_objects=active_objects@entry=0x68bda8,
+ restack_objects=restack_objects@entry=0x68bdc8, delete_objects=delete_objects@entry=0x68bd88, render_objects=render_objects@entry=0x68bde8, restack=0,
+ redraw_all=redraw_all@entry=0x7fffffffe0ec, mapped_parent=mapped_parent@entry=0 '\000') at lib/evas/canvas/evas_render.c:413
+#8 0x00007ffff71eeaf6 in _evas_render_phase1_object_process (e=e@entry=0x68bc90, eo_obj=<optimized out>, active_objects=active_objects@entry=0x68bda8,
+ restack_objects=restack_objects@entry=0x68bdc8, delete_objects=delete_objects@entry=0x68bd88, render_objects=render_objects@entry=0x68bde8, restack=0,
+ redraw_all=redraw_all@entry=0x7fffffffe0ec, mapped_parent=mapped_parent@entry=0 '\000') at lib/evas/canvas/evas_render.c:413
+#9 0x00007ffff71eeaf6 in _evas_render_phase1_object_process (e=e@entry=0x68bc90, eo_obj=<optimized out>, active_objects=active_objects@entry=0x68bda8,
+ restack_objects=restack_objects@entry=0x68bdc8, delete_objects=delete_objects@entry=0x68bd88, render_objects=render_objects@entry=0x68bde8, restack=0,
+ redraw_all=redraw_all@entry=0x7fffffffe0ec, mapped_parent=mapped_parent@entry=0 '\000') at lib/evas/canvas/evas_render.c:413
+#10 0x00007ffff71eeaf6 in _evas_render_phase1_object_process (e=e@entry=0x68bc90, eo_obj=<optimized out>, active_objects=active_objects@entry=0x68bda8,
+ restack_objects=restack_objects@entry=0x68bdc8, delete_objects=delete_objects@entry=0x68bd88, render_objects=render_objects@entry=0x68bde8, restack=0,
+ redraw_all=redraw_all@entry=0x7fffffffe0ec, mapped_parent=mapped_parent@entry=0 '\000') at lib/evas/canvas/evas_render.c:413
+#11 0x00007ffff71eeaf6 in _evas_render_phase1_object_process (e=e@entry=0x68bc90, eo_obj=<optimized out>, active_objects=active_objects@entry=0x68bda8,
+ restack_objects=restack_objects@entry=0x68bdc8, delete_objects=delete_objects@entry=0x68bd88, render_objects=render_objects@entry=0x68bde8,
+ restack=restack@entry=0, redraw_all=redraw_all@entry=0x7fffffffe0ec, mapped_parent=mapped_parent@entry=0 '\000') at lib/evas/canvas/evas_render.c:413
+#12 0x00007ffff71f0f29 in _evas_render_phase1_process (redraw_all=0x7fffffffe0dc, render_objects=0x68bde8, delete_objects=0x68bd88, restack_objects=0x68bdc8,
+ active_objects=0x68bda8, e=0x68bc90) at lib/evas/canvas/evas_render.c:557
+#13 evas_render_updates_internal (eo_e=0x68bc00, make_updates=make_updates@entry=1 '\001', do_draw=do_draw@entry=1 '\001') at lib/evas/canvas/evas_render.c:1337
+#14 0x00007ffff71f3cd7 in _canvas_render_updates (eo_e=<optimized out>, _pd=<optimized out>, list=<optimized out>) at lib/evas/canvas/evas_render.c:1795
+#15 0x00007ffff6acba35 in _eo_op_internal (obj=0x68bc00, op_type=EO_OP_TYPE_REGULAR, op=402, p_list=0x7fffffffe1b8) at lib/eo/eo.c:363
+#16 0x00007ffff6acd6cd in _eo_dov_internal (p_list=0x7fffffffe1b8, op_type=EO_OP_TYPE_REGULAR, obj=0x68bc00) at lib/eo/eo.c:403
+#17 eo_do_internal (obj=0x68bc00, op_type=op_type@entry=EO_OP_TYPE_REGULAR) at lib/eo/eo.c:434
+#18 0x00007ffff71f3c5f in evas_render_updates (eo_e=<optimized out>) at lib/evas/canvas/evas_render.c:1779
+#19 0x00007fffe73d743a in _ecore_evas_x_render (ee=0x68a430) at modules/ecore_evas/engines/x/ecore_evas_x.c:447
+#20 0x00007ffff68ba7f1 in _ecore_evas_idle_enter (data=<optimized out>) at lib/ecore_evas/ecore_evas.c:59
+#21 0x00007ffff6f3c019 in _ecore_call_task_cb (data=<optimized out>, func=<optimized out>) at lib/ecore/ecore_private.h:300
+#22 _ecore_idle_enterer_call () at lib/ecore/ecore_idle_enterer.c:235
+#23 0x00007ffff6f3e47b in _ecore_main_loop_iterate_internal (once_only=once_only@entry=0) at lib/ecore/ecore_main.c:1866
+#24 0x00007ffff6f3eb27 in ecore_main_loop_begin () at lib/ecore/ecore_main.c:964
+#25 0x00000000004028ce in elm_main (argc=1, argv=0x7fffffffe568) at demoapp.c:284
+#26 0x0000000000402913 in main (argc=1, argv=0x7fffffffe568) at demoapp.c:291
+
+
+===============================================================================
+2012-12-13_06-32
+
+
+(gdb) bt
+#0 0x00007ffff53ddff7 in _calc_intra_outer_rect_area (
+ outer=<synthetic pointer>, intra=<synthetic pointer>, a=..., b=...)
+ at lib/evas/common/evas_tiler.c:479
+#1 rect_list_add_split_fuzzy (node=0x8ed9c0, rects=0x691668,
+ accepted_error=<optimized out>) at lib/evas/common/evas_tiler.c:652
+#2 rect_list_add_split_fuzzy_and_merge (node=0x8ed9c0, rects=0x691668,
+ split_accepted_error=<optimized out>, merge_accepted_error=<optimized out>)
+ at lib/evas/common/evas_tiler.c:849
+#3 _add_redraw (h=115, w=327, y=203, x=504, rects=0x691668)
+ at lib/evas/common/evas_tiler.c:956
+#4 evas_common_tilebuf_add_redraw (tb=0x691630, x=504, y=203, w=327, h=115)
+ at lib/evas/common/evas_tiler.c:986
+#5 0x00007ffff535cb9d in evas_object_render_pre_effect_updates (rects=
+ 0x688938, eo_obj=<optimized out>, is_v=1, was_v=<optimized out>)
+ at lib/evas/canvas/evas_object_main.c:356
+#6 0x00007ffff539bbfc in _evas_render_phase1_direct (render_objects=0x9baa60,
+ active_objects=0x688740, e=<optimized out>,
+ restack_objects=<optimized out>, delete_objects=<optimized out>)
+ at lib/evas/canvas/evas_render.c:231
+#7 evas_render_updates_internal (eo_e=0x6886b0,
+ make_updates=make_updates@entry=1 '\001', do_draw=do_draw@entry=1 '\001')
+ at lib/evas/canvas/evas_render.c:1357
+#8 0x00007ffff539dcd7 in _canvas_render_updates (eo_e=<optimized out>,
+ _pd=<optimized out>, list=<optimized out>)
+ at lib/evas/canvas/evas_render.c:1795
+#9 0x00007ffff706fa35 in _eo_op_internal (obj=0x6886b0, op_type=
+ EO_OP_TYPE_REGULAR, op=402, p_list=0x7fffffffe228) at lib/eo/eo.c:363
+#10 0x00007ffff70716cd in _eo_dov_internal (p_list=0x7fffffffe228, op_type=
+ EO_OP_TYPE_REGULAR, obj=0x6886b0) at lib/eo/eo.c:403
+#11 eo_do_internal (obj=0x6886b0, op_type=op_type@entry=EO_OP_TYPE_REGULAR)
+ at lib/eo/eo.c:434
+#12 0x00007ffff539dc5f in evas_render_updates (eo_e=<optimized out>)
+ at lib/evas/canvas/evas_render.c:1779
+#13 0x00007fffe6f7a43a in _ecore_evas_x_render (ee=0x686f30)
+ at modules/ecore_evas/engines/x/ecore_evas_x.c:447
+#14 0x00007ffff6e5e7f1 in _ecore_evas_idle_enter (data=<optimized out>)
+ at lib/ecore_evas/ecore_evas.c:59
+#15 0x00007ffff50e6019 in _ecore_call_task_cb (data=<optimized out>,
+ func=<optimized out>) at lib/ecore/ecore_private.h:300
+#16 _ecore_idle_enterer_call () at lib/ecore/ecore_idle_enterer.c:235
+#17 0x00007ffff50e862d in _ecore_main_loop_iterate_internal (
+ once_only=once_only@entry=0) at lib/ecore/ecore_main.c:1841
+#18 0x00007ffff50e8b27 in ecore_main_loop_begin () at lib/ecore/ecore_main.c:964
+#19 0x000000000040230e in elm_main (argc=1, argv=0x7fffffffe5b8) at gg_map.c:269
+#20 0x0000000000402359 in main (argc=1, argv=0x7fffffffe5b8) at gg_map.c:276
+
+
+===============================================================================
+2012-12-13_06-42
+
+^C
+Program received signal SIGINT, Interrupt.
+rect_list_add_split_fuzzy (node=0x884d70, rects=0x691668,
+ accepted_error=<optimized out>) at lib/evas/common/evas_tiler.c:653
+653 area = current.area + r.area - intra.area;
+
+(gdb) bt
+#0 rect_list_add_split_fuzzy (node=0x884d70, rects=0x691668,
+ accepted_error=<optimized out>) at lib/evas/common/evas_tiler.c:653
+#1 rect_list_add_split_fuzzy_and_merge (node=0x884d70, rects=0x691668,
+ split_accepted_error=<optimized out>, merge_accepted_error=<optimized out>)
+ at lib/evas/common/evas_tiler.c:849
+#2 _add_redraw (h=12, w=542, y=356, x=118, rects=0x691668)
+ at lib/evas/common/evas_tiler.c:956
+#3 evas_common_tilebuf_add_redraw (tb=tb@entry=0x691630, x=118, y=356, w=542,
+ h=12) at lib/evas/common/evas_tiler.c:986
+#4 0x00007fffe6d672ac in _merge_rects (tb=0x691630, r1=<optimized out>, r2=
+ 0x0, r3=0x0) at modules/evas/engines/software_x11/evas_engine.c:713
+#5 0x00007fffe6d6759b in eng_output_redraws_next_update_get (data=0x691c00, x=
+ 0x7fffffffe13c, y=0x7fffffffe140, w=0x7fffffffe144, h=0x7fffffffe148,
+ cx=<optimized out>, cy=0x7fffffffe150, cw=0x7fffffffe154, ch=
+ 0x7fffffffe158) at modules/evas/engines/software_x11/evas_engine.c:821
+#6 0x00007ffff539bf4f in evas_render_updates_internal (eo_e=0x6886b0,
+ make_updates=make_updates@entry=1 '\001', do_draw=do_draw@entry=1 '\001')
+ at lib/evas/canvas/evas_render.c:1533
+#7 0x00007ffff539dcd7 in _canvas_render_updates (eo_e=<optimized out>,
+ _pd=<optimized out>, list=<optimized out>)
+ at lib/evas/canvas/evas_render.c:1795
+#8 0x00007ffff706fa35 in _eo_op_internal (obj=0x6886b0, op_type=
+ EO_OP_TYPE_REGULAR, op=402, p_list=0x7fffffffe228) at lib/eo/eo.c:363
+#9 0x00007ffff70716cd in _eo_dov_internal (p_list=0x7fffffffe228, op_type=
+ EO_OP_TYPE_REGULAR, obj=0x6886b0) at lib/eo/eo.c:403
+#10 eo_do_internal (obj=0x6886b0, op_type=op_type@entry=EO_OP_TYPE_REGULAR)
+ at lib/eo/eo.c:434
+#11 0x00007ffff539dc5f in evas_render_updates (eo_e=<optimized out>)
+ at lib/evas/canvas/evas_render.c:1779
+#12 0x00007fffe6f7a43a in _ecore_evas_x_render (ee=0x686f30)
+ at modules/ecore_evas/engines/x/ecore_evas_x.c:447
+#13 0x00007ffff6e5e7f1 in _ecore_evas_idle_enter (data=<optimized out>)
+ at lib/ecore_evas/ecore_evas.c:59
+#14 0x00007ffff50e6019 in _ecore_call_task_cb (data=<optimized out>,
+ func=<optimized out>) at lib/ecore/ecore_private.h:300
+#15 _ecore_idle_enterer_call () at lib/ecore/ecore_idle_enterer.c:235
+#16 0x00007ffff50e847b in _ecore_main_loop_iterate_internal (
+ once_only=once_only@entry=0) at lib/ecore/ecore_main.c:1866
+#17 0x00007ffff50e8b27 in ecore_main_loop_begin ()
+ at lib/ecore/ecore_main.c:964
+#18 0x000000000040230e in elm_main (argc=1, argv=0x7fffffffe5b8)
+ at gg_map.c:269
+#19 0x0000000000402359 in main (argc=1, argv=0x7fffffffe5b8) at gg_map.c:276
+
+===============================================================================
+2012-12-13_15-32
+
+^C 0x7fffe6d61700 (LWP 21696)]
+[Thread 0x7fffe6d61700 (LWP 21696) exited]
+[New Thread 0x7fffe6d61700 (LWP 21697)]
+[Thread 0x7fffe6d61700 (LWP 21697) exited]
+[New Thread 0x7fffe6d61700 (LWP 21711)]
+[Thread 0x7fffe6d61700 (LWP 21711) exited]
+[New Thread 0x7fffe6d61700 (LWP 21712)]
+[Thread 0x7fffe6d61700 (LWP 21712) exited]
+
+Program received signal SIGINT, Interrupt.
+rect_list_add_split_fuzzy (node=0xa977b0, rects=0x691668,
+ accepted_error=<optimized out>) at lib/evas/common/evas_tiler.c:680
+680 else if ((outer.area - area) <= accepted_error)
+
+
+(gdb) bt
+#0 rect_list_add_split_fuzzy (node=0xa977b0, rects=0x691668,
+ accepted_error=<optimized out>) at lib/evas/common/evas_tiler.c:680
+#1 rect_list_add_split_fuzzy_and_merge (node=0xa977b0, rects=0x691668,
+ split_accepted_error=<optimized out>, merge_accepted_error=<optimized out>)
+ at lib/evas/common/evas_tiler.c:849
+#2 _add_redraw (h=6, w=126, y=110, x=463, rects=0x691668)
+ at lib/evas/common/evas_tiler.c:956
+#3 evas_common_tilebuf_add_redraw (tb=0x691630, x=463, y=110, w=126, h=6)
+ at lib/evas/common/evas_tiler.c:986
+#4 0x00007ffff535cb9d in evas_object_render_pre_effect_updates (
+ rects=rects@entry=0x688938, eo_obj=eo_obj@entry=0xa83500, is_v=is_v@entry=
+ 1, was_v=was_v@entry=1) at lib/evas/canvas/evas_object_main.c:356
+#5 0x00007ffff535560d in evas_object_image_render_pre (eo_obj=0xa83500, obj=
+ 0xa83590) at lib/evas/canvas/evas_object_image.c:3768
+#6 0x00007ffff539bbfc in _evas_render_phase1_direct (render_objects=0xa83500,
+ active_objects=0x688740, e=<optimized out>,
+ restack_objects=<optimized out>, delete_objects=<optimized out>)
+ at lib/evas/canvas/evas_render.c:231
+#7 evas_render_updates_internal (eo_e=0x6886b0,
+ make_updates=make_updates@entry=1 '\001', do_draw=do_draw@entry=1 '\001')
+ at lib/evas/canvas/evas_render.c:1357
+#8 0x00007ffff539dcd7 in _canvas_render_updates (eo_e=<optimized out>,
+ _pd=<optimized out>, list=<optimized out>)
+ at lib/evas/canvas/evas_render.c:1795
+#9 0x00007ffff706fa35 in _eo_op_internal (obj=0x6886b0, op_type=
+ EO_OP_TYPE_REGULAR, op=402, p_list=0x7fffffffe228) at lib/eo/eo.c:363
+#10 0x00007ffff70716cd in _eo_dov_internal (p_list=0x7fffffffe228, op_type=
+ EO_OP_TYPE_REGULAR, obj=0x6886b0) at lib/eo/eo.c:403
+#11 eo_do_internal (obj=0x6886b0, op_type=op_type@entry=EO_OP_TYPE_REGULAR)
+ at lib/eo/eo.c:434
+#12 0x00007ffff539dc5f in evas_render_updates (eo_e=<optimized out>)
+ at lib/evas/canvas/evas_render.c:1779
+#13 0x00007fffe6f7943a in _ecore_evas_x_render (ee=0x686f30)
+ at modules/ecore_evas/engines/x/ecore_evas_x.c:447
+#14 0x00007ffff6e5e7f1 in _ecore_evas_idle_enter (data=<optimized out>)
+ at lib/ecore_evas/ecore_evas.c:59
+#15 0x00007ffff50e6019 in _ecore_call_task_cb (data=<optimized out>,
+ func=<optimized out>) at lib/ecore/ecore_private.h:300
+#16 _ecore_idle_enterer_call () at lib/ecore/ecore_idle_enterer.c:235
+#17 0x00007ffff50e847b in _ecore_main_loop_iterate_internal (
+ once_only=once_only@entry=0) at lib/ecore/ecore_main.c:1866
+#18 0x00007ffff50e8b27 in ecore_main_loop_begin ()
+ at lib/ecore/ecore_main.c:964
+#19 0x00000000004022f1 in elm_main (argc=1, argv=0x7fffffffe5b8)
+ at gg_map.c:273
+#20 0x000000000040233c in main (argc=1, argv=0x7fffffffe5b8) at gg_map.c:280
+(gdb)
+
+
+===============================================================================
+2012-12-13_17-19
+
+
+rect_list_add_split_fuzzy (node=0xb07d60, rects=0x692668, [0/1873]
+ accepted_error=<optimized out>) at lib/evas/common/evas_tiler.c:653
+653 area = current.area + r.area - intra.area;
+(gdb) bt
+#0 rect_list_add_split_fuzzy (node=0xb07d60, rects=0x692668,
+ accepted_error=<optimized out>) at lib/evas/common/evas_tiler.c:653
+#1 rect_list_add_split_fuzzy_and_merge (node=0xb07d60, rects=0x692668,
+ split_accepted_error=<optimized out>, merge_accepted_error=<optimized out>)
+ at lib/evas/common/evas_tiler.c:849
+#2 _add_redraw (h=30, w=79, y=539, x=665, rects=0x692668)
+ at lib/evas/common/evas_tiler.c:956
+#3 evas_common_tilebuf_add_redraw (tb=0x692630, x=665, y=539, w=79, h=30)
+ at lib/evas/common/evas_tiler.c:986
+#4 0x00007ffff539bd1c in _evas_render_phase1_direct (render_objects=0xb61c40,
+ active_objects=0x689740, e=<optimized out>,
+ restack_objects=<optimized out>, delete_objects=<optimized out>)
+ at lib/evas/canvas/evas_render.c:257
+#5 evas_render_updates_internal (eo_e=0x6896b0,
+ make_updates=make_updates@entry=1 '\001', do_draw=do_draw@entry=1 '\001')
+ at lib/evas/canvas/evas_render.c:1357
+#6 0x00007ffff539dcd7 in _canvas_render_updates (eo_e=<optimized out>,
+ _pd=<optimized out>, list=<optimized out>)
+ at lib/evas/canvas/evas_render.c:1795
+#7 0x00007ffff706fa35 in _eo_op_internal (obj=0x6896b0, op_type=
+ EO_OP_TYPE_REGULAR, op=402, p_list=0x7fffffffe228) at lib/eo/eo.c:363
+#8 0x00007ffff70716cd in _eo_dov_internal (p_list=0x7fffffffe228, op_type=
+ EO_OP_TYPE_REGULAR, obj=0x6896b0) at lib/eo/eo.c:403
+#9 eo_do_internal (obj=0x6896b0, op_type=op_type@entry=EO_OP_TYPE_REGULAR)
+ at lib/eo/eo.c:434
+#10 0x00007ffff539dc5f in evas_render_updates (eo_e=<optimized out>)
+ at lib/evas/canvas/evas_render.c:1779
+#11 0x00007fffe6f7943a in _ecore_evas_x_render (ee=0x687f30)
+ at modules/ecore_evas/engines/x/ecore_evas_x.c:447
+#12 0x00007ffff6e5e7f1 in _ecore_evas_idle_enter (data=<optimized out>)
+ at lib/ecore_evas/ecore_evas.c:59
+#13 0x00007ffff50e6019 in _ecore_call_task_cb (data=<optimized out>,
+ func=<optimized out>) at lib/ecore/ecore_private.h:300
+#14 _ecore_idle_enterer_call () at lib/ecore/ecore_idle_enterer.c:235
+#15 0x00007ffff50e847b in _ecore_main_loop_iterate_internal (
+ once_only=once_only@entry=0) at lib/ecore/ecore_main.c:1866
+#16 0x00007ffff50e8b27 in ecore_main_loop_begin () at lib/ecore/ecore_main.c:964
+#17 0x00000000004025d9 in elm_main (argc=1, argv=0x7fffffffe5b8) at gg_map.c:324
+#18 0x0000000000402624 in main (argc=1, argv=0x7fffffffe5b8) at gg_map.c:331
+
+===============================================================================
+2012-12-16_04-22
+
+This bug is a lockup of evas during rendering in my efl app.
+App freeze and takes 100% CPU. Below are backtraces when gdb was running and
+I interrupt it with Ctrl-C.
+
+At the time of crash, around 300objects total :
+elementary interface + ~100 edje + 100 edje mapped with evas_map + ~100 evas_object_text
+
+This crash is not predictible from what I see, sometimes it goes fine for a long
+time.
+It seem to crash more when using more edje objects.
+
+happened AFTER raster's fix
+------------------------------------------------------------------------
+r81039 | raster | 2012-12-16 03:01:11 +0100 (Sun, 16 Dec 2012) | 5 lines
+small change - dont let update rect list for image object become a
+runaway endless list if evas doenst come around and render (pick it
+up) any time soon - limit to 512 update rects.
+
+
+^C
+Program received signal SIGINT, Interrupt.
+0x00007ffff53ddc54 in _calc_intra_outer_rect_area (outer=<synthetic pointer>,
+ intra=<synthetic pointer>, a=..., b=...) at lib/evas/common/evas_tiler.c:530
+530 outer->height = max_bottom - min_top;
+(gdb) bt
+#0 0x00007ffff53ddc54 in _calc_intra_outer_rect_area (
+ outer=<synthetic pointer>, intra=<synthetic pointer>, a=..., b=...)
+ at lib/evas/common/evas_tiler.c:530
+#1 rect_list_add_split_fuzzy (node=0x9d27c0, rects=0x6942b8,
+ accepted_error=<optimized out>) at lib/evas/common/evas_tiler.c:652
+#2 rect_list_add_split_fuzzy_and_merge (node=0x9d27c0, rects=0x6942b8,
+ split_accepted_error=<optimized out>, merge_accepted_error=<optimized out>)
+ at lib/evas/common/evas_tiler.c:849
+#3 _add_redraw (h=76, w=276, y=453, x=990, rects=0x6942b8)
+ at lib/evas/common/evas_tiler.c:956
+#4 evas_common_tilebuf_add_redraw (tb=0x694280, x=990, y=453, w=276, h=76)
+ at lib/evas/common/evas_tiler.c:986
+#5 0x00007ffff539736f in _evas_render_prev_cur_clip_cache_add (obj=obj@entry=
+ 0xbee890, e=0x68b390, e=0x68b390) at lib/evas/canvas/evas_render.c:158
+#6 0x00007ffff539ba0c in _evas_render_phase1_direct (render_objects=0xbee800,
+ active_objects=0x68b390, e=<optimized out>,
+ restack_objects=<optimized out>, delete_objects=<optimized out>)
+ at lib/evas/canvas/evas_render.c:257
+#7 evas_render_updates_internal (eo_e=0x68b300,
+ make_updates=make_updates@entry=1 '\001', do_draw=do_draw@entry=1 '\001')
+ at lib/evas/canvas/evas_render.c:1357
+#8 0x00007ffff539d9c7 in _canvas_render_updates (eo_e=<optimized out>,
+ _pd=<optimized out>, list=<optimized out>)
+ at lib/evas/canvas/evas_render.c:1795
+#9 0x00007ffff706fa45 in _eo_op_internal (obj=0x68b300, op_type=
+ EO_OP_TYPE_REGULAR, op=402, p_list=0x7fffffffe1f8) at lib/eo/eo.c:363
+#10 0x00007ffff70716dd in _eo_dov_internal (p_list=0x7fffffffe1f8, op_type=
+ EO_OP_TYPE_REGULAR, obj=0x68b300) at lib/eo/eo.c:403
+#11 eo_do_internal (obj=0x68b300, op_type=op_type@entry=EO_OP_TYPE_REGULAR)
+ at lib/eo/eo.c:434
+#12 0x00007ffff539d94f in evas_render_updates (eo_e=<optimized out>)
+ at lib/evas/canvas/evas_render.c:1779
+#13 0x00007fffe6f7743a in _ecore_evas_x_render (ee=0x689b80)
+ at modules/ecore_evas/engines/x/ecore_evas_x.c:447
+#14 0x00007ffff6e5e841 in _ecore_evas_idle_enter (data=<optimized out>)
+ at lib/ecore_evas/ecore_evas.c:59
+#15 0x00007ffff50e5059 in _ecore_call_task_cb (data=<optimized out>,
+ func=<optimized out>) at lib/ecore/ecore_private.h:300
+#16 _ecore_idle_enterer_call () at lib/ecore/ecore_idle_enterer.c:235
+#17 0x00007ffff50e74bb in _ecore_main_loop_iterate_internal (
+ once_only=once_only@entry=0) at lib/ecore/ecore_main.c:1866
+#18 0x00007ffff50e7b67 in ecore_main_loop_begin () at lib/ecore/ecore_main.c:964
+#19 0x00000000004035b0 in elm_main (argc=1, argv=0x7fffffffe5b8) at gg_map.c:461
+---Type <return> to continue, or q <return> to quit---
+#20 0x00000000004035fb in main (argc=1, argv=0x7fffffffe5b8) at gg_map.c:468
+
+===============================================================================
+2012-12-16_18-16
+
+
+^C
+Program received signal SIGINT, Interrupt.
+0x00007ffff53ddd20 in _calc_intra_outer_rect_area (outer=<synthetic pointer>,
+ intra=<synthetic pointer>, a=..., b=...)
+ at lib/evas/common/evas_tiler.c:509
+509 if (a.bottom < b.bottom)
+(gdb) bt
+#0 0x00007ffff53ddd20 in _calc_intra_outer_rect_area (
+ outer=<synthetic pointer>, intra=<synthetic pointer>, a=..., b=...)
+ at lib/evas/common/evas_tiler.c:509
+#1 rect_list_add_split_fuzzy (node=0x16b03d0, rects=0x692668,
+ accepted_error=<optimized out>) at lib/evas/common/evas_tiler.c:652
+#2 rect_list_add_split_fuzzy_and_merge (node=0x16b03d0, rects=0x692668,
+ split_accepted_error=<optimized out>, merge_accepted_error=<optimized out>)
+ at lib/evas/common/evas_tiler.c:849
+#3 _add_redraw (h=31, w=323, y=264, x=696, rects=0x692668)
+ at lib/evas/common/evas_tiler.c:956
+#4 evas_common_tilebuf_add_redraw (tb=0x692630, x=696, y=264, w=323, h=31)
+ at lib/evas/common/evas_tiler.c:986
+#5 0x00007ffff539736f in _evas_render_prev_cur_clip_cache_add (obj=obj@entry=
+ 0x36cef40, e=0x689740, e=0x689740) at lib/evas/canvas/evas_render.c:158
+#6 0x00007ffff539ba0c in _evas_render_phase1_direct (render_objects=
+ 0x36ceeb0, active_objects=0x689740, e=<optimized out>,
+ restack_objects=<optimized out>, delete_objects=<optimized out>)
+ at lib/evas/canvas/evas_render.c:257
+#7 evas_render_updates_internal (eo_e=0x6896b0,
+ make_updates=make_updates@entry=1 '\001', do_draw=do_draw@entry=1 '\001')
+ at lib/evas/canvas/evas_render.c:1357
+#8 0x00007ffff539d9c7 in _canvas_render_updates (eo_e=<optimized out>,
+ _pd=<optimized out>, list=<optimized out>)
+ at lib/evas/canvas/evas_render.c:1795
+#9 0x00007ffff706fa45 in _eo_op_internal (obj=0x6896b0, op_type=
+ EO_OP_TYPE_REGULAR, op=402, p_list=0x7fffffffe1f8) at lib/eo/eo.c:363
+#10 0x00007ffff70716dd in _eo_dov_internal (p_list=0x7fffffffe1f8, op_type=
+ EO_OP_TYPE_REGULAR, obj=0x6896b0) at lib/eo/eo.c:403
+#11 eo_do_internal (obj=0x6896b0, op_type=op_type@entry=EO_OP_TYPE_REGULAR)
+ at lib/eo/eo.c:434
+#12 0x00007ffff539d94f in evas_render_updates (eo_e=<optimized out>)
+ at lib/evas/canvas/evas_render.c:1779
+#13 0x00007fffe6f7743a in _ecore_evas_x_render (ee=0x687f30)
+ at modules/ecore_evas/engines/x/ecore_evas_x.c:447
+#14 0x00007ffff6e5e841 in _ecore_evas_idle_enter (data=<optimized out>)
+ at lib/ecore_evas/ecore_evas.c:59
+#15 0x00007ffff50e5059 in _ecore_call_task_cb (data=<optimized out>,
+ func=<optimized out>) at lib/ecore/ecore_private.h:300
+#16 _ecore_idle_enterer_call () at lib/ecore/ecore_idle_enterer.c:235
+#17 0x00007ffff50e766d in _ecore_main_loop_iterate_internal (
+ once_only=once_only@entry=0) at lib/ecore/ecore_main.c:1841
+#18 0x00007ffff50e7b67 in ecore_main_loop_begin ()
+ at lib/ecore/ecore_main.c:964
+#19 0x00000000004031c1 in elm_main (argc=1, argv=0x7fffffffe5b8)
+ at gg_map.c:447
+#20 0x000000000040320c in main (argc=1, argv=0x7fffffffe5b8) at gg_map.c:454
+
+
diff --git a/egraph/doc/egraph.xoj b/egraph/doc/egraph.xoj
new file mode 100644
index 0000000..59ca038
--- /dev/null
+++ b/egraph/doc/egraph.xoj
Binary files differ
diff --git a/egraph/doc/internals.txt b/egraph/doc/internals.txt
new file mode 100644
index 0000000..7a8b34d
--- /dev/null
+++ b/egraph/doc/internals.txt
@@ -0,0 +1,89 @@
+Internals
+=========
+
+=== algo to handle threaded graph layouting correctly ===
+
+###### GENERAL ALGO
+_layouting_start(graph-2, coords-2);
+
+_add/del(structs-3);
+_repositionning(graph, structs, coords);
+
+_layouting_end(coords-2);
+
+_v2_updtate(structs-2, graph-2, coords-2);
+ _v2_structs/graph_update(structs-2, graph);
+ -> structs, graph // real add/del
+ _coords_copy(coords-2);
+ -> coords
+
+_repositionning(graph, structs, coords);
+
+_v3_update(structs-3);
+ _v3_structs/graph_update(structs-3, graph-2);
+ -> structs-2, graph-2
+
+###### TIMELINE VERTICE ADD
+egraph_vertice_add();
+ id = freeids[vertices_count];
+ v = vertices[id];
+ v->id = id;
+ vertices_count++;
+ v->v3-new = 1;
+
+_v3_update();
+ v->v2-new = v->v3-new;
+ v->v3-new = 0;
+ _v2_add()
+ v->graph2_vid = graph2_vcount;
+ graph2_vcount++;
+ igraph_add_vertices(graph2);
+
+_layouting_start();
+ // end up in coords2
+
+_layouting_end();
+_coords_copy();
+ // end up in coords
+
+_v2_update();
+ _add()
+ v->v2-new = 0;
+ v->graph_vid = graph_vcount;
+ graph_vcount++;
+ igraph_add_vertices(graph);
+ evas_object
+
+// in structs, graph, coords
+
+###### TIMELINE VERTICE DEL
+egraph_vertice_del();
+ v->v3-del = 1;
+
+_v3_update();
+ v->v2-del = v->v3-del;
+ v->v3-del = 0;
+ _v2_del()
+ igraph_delete_vertices(v->graph2_vid);
+ graph2_vcount--;
+
+_layouting_start();
+ // not in coords2
+
+_layouting_end();
+_coords_copy();
+ // not in coords
+
+_v2_update();
+ _del();
+ igraph_delete_vertices(v->graph_vid);
+ graph_vcount--;
+ freeids[vertices_count] = v->id;
+ vertices_count--;
+ free(v);
+
+// removed from structs, graph, coords
+
+###### TIMELINE VERTICE DEL
+
+
diff --git a/egraph/egraph.c b/egraph/egraph.c
new file mode 100644
index 0000000..bffcebf
--- /dev/null
+++ b/egraph/egraph.c
@@ -0,0 +1,1275 @@
+#include <err.h>
+#include <Efx.h>
+#include <Edje.h>
+
+#include "Egraph.h"
+
+#define DEBUG 0
+
+#define TYPE_MAXLEN 30
+
+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 _edge_v2_add(Egraph *eg, Egraph_Edge *e);
+static void _edge_add(Egraph *eg, Egraph_Edge *e);
+static void _edge_signal(Egraph *eg, Egraph_Edge *e, const char *signal);
+static void _edge_v2_del(Egraph *eg, Egraph_Edge *e);
+static void _edge_del(Egraph *eg, Egraph_Edge *e);
+static void _vertice_v2_add(Egraph *eg, Egraph_Vertice *v);
+static void _vertice_add(Egraph *eg, Egraph_Vertice *v);
+static void _vertice_v2_del(Egraph *eg, Egraph_Vertice *v);
+static void _vertice_del(Egraph *eg, Egraph_Vertice *v);
+static void _vertice_update_status(Egraph *eg, Egraph_Vertice *v);
+static void _vertice_signal(Egraph *eg, Egraph_Vertice *v, const char *signal);
+static void _vertice_geometry_update(Egraph *eg, Egraph_Vertice *v);
+static void _v2_update(Egraph *eg);
+static void _v3_update(Egraph *eg);
+static void _coords2_copy(Egraph *eg);
+static void _cb_blob_arrived(void *data, Efx_Map_Data *e, Evas_Object *obj);
+static void _blob_send(Evas_Object *blob,
+ Egraph_Vertice *v, Evas_Coord x, Evas_Coord y);
+static void _layouting_schedule(Egraph *eg);
+static Eina_Bool _cb_layouting_start(void *data);
+static void _cb_layouting_run(void *data, Ecore_Thread *thread);
+static void _cb_layouting_end(void *data, Ecore_Thread *thread);
+static void _cb_layouting_cancel(void *data, Ecore_Thread *thread);
+static int _igraph_query_vid(igraph_t *g, int g_len, int id);
+static void _cb_vertice_move(void *data,
+ Evas *evas, Evas_Object *obj, void *event_info);
+static void _reposition(Egraph *eg, int no_animation);
+static void _matrix_minmax_2v(const igraph_matrix_t *m, int row_count,
+ float *c1min, float *c1max,
+ float *c2min, float *c2max);
+static Evas_Object *_edje_obj_new(Egraph *eg, const char *group);
+static Evas_Object *_edje_obj_set(Egraph *eg, Evas_Object *o, const char *group);
+
+static const Evas_Smart_Cb_Description _smart_callbacks[] = {{NULL, NULL}};
+#define EGRAPH_DATA_GET(o, ptr) \
+ Egraph * ptr = evas_object_smart_data_get(o)
+/* defines _egraph_parent_sc and _egraph_smart_class_new */
+EVAS_SMART_SUBCLASS_NEW("Egraph", _egraph,
+ Evas_Smart_Class, Evas_Smart_Class,
+ evas_object_smart_clipped_class_get, _smart_callbacks);
+
+static void
+_egraph_smart_set_user(Evas_Smart_Class *sc)
+{
+ /* specializing these two */
+ sc->add = _smart_add;
+ sc->del = _smart_del;
+ sc->move = _smart_move;
+ /* clipped smart object has no hook on resizes or calculations */
+ sc->resize = _smart_resize;
+}
+
+static void
+_smart_add(Evas_Object *obj)
+{
+ EVAS_SMART_DATA_ALLOC(obj, Egraph);
+
+ priv->evas = evas_object_evas_get(obj);
+
+ _egraph_parent_sc->add(obj);
+}
+
+static void
+_smart_del(Evas_Object *obj)
+{
+ EGRAPH_DATA_GET(obj, eg);
+
+ igraph_destroy(&eg->graph);
+ if (eg->layouting.running == 2)
+ ecore_thread_cancel(eg->layouting.thread);
+
+ _egraph_parent_sc->del(obj);
+}
+
+static void
+_smart_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
+{
+ EGRAPH_DATA_GET(obj, eg);
+
+ _reposition(eg, 1);
+
+ _egraph_parent_sc->move(obj, x, y);
+}
+
+static void
+_smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
+{
+ EGRAPH_DATA_GET(obj, eg);
+
+ _reposition(eg, 1);
+}
+
+Evas_Object *
+egraph_new(Evas *evas, int directed)
+{
+ Evas_Object *obj = NULL;
+ Evas_Object *rect;
+ Egraph *eg;
+ int i;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(evas, NULL);
+
+ efx_init();
+ eina_log_domain_level_set("efx", EINA_LOG_LEVEL_WARN);
+
+ obj = evas_object_smart_add(evas, _egraph_smart_class_new());
+ eg = evas_object_smart_data_get(obj);
+ if (!eg) goto err;
+ eg->obj = obj;
+ rect = evas_object_rectangle_add(eg->evas);
+ evas_object_color_set(rect, 0, 0, 0, 0);
+ evas_object_smart_member_add(rect, obj);
+ eg->split_vertice_edge = rect;
+
+ eg->graph_directed = directed;
+ eg->display_vertices = 1;
+ eg->display_names = 1;
+ eg->display_edges = 1;
+ eg->use_animations = 1;
+ eg->do_improvements = 1;
+ egraph_theme_file_set(obj, NULL);
+ eg->theme_edges = 1;
+ eg->layout = EGRAPH_LAYOUT_DEFAULT;
+
+ /* needed for igraph attribute handling */
+ igraph_i_set_attribute_table(&igraph_cattribute_table);
+
+ eg->vertices = eina_hash_int32_new(NULL);
+ for (i=0; i<EGRAPH_VERTICES_MAX-1; i++)
+ eg->vertices_freeids[i] = i;
+ if (igraph_empty(&eg->graph, 0, directed))
+ goto err;
+ if (igraph_empty(&eg->graph2, 0, directed))
+ goto err;
+ igraph_matrix_init(&eg->coords, 0, 2);
+ igraph_matrix_init(&eg->coords2, 0, 2);
+ eg->graph_wmin = 0;
+ eg->graph_wmax = 200;
+ eg->graph_hmin = 0;
+ eg->graph_hmax = 200;
+ eg->vertice_max_w = 0;
+ eg->vertice_max_h = 0;
+
+ return obj;
+
+err:
+ if (obj)
+ evas_object_del(obj);
+ return NULL;
+}
+
+void
+egraph_clear(Evas_Object *obj)
+{
+ EGRAPH_DATA_GET(obj, eg);
+ Eina_Iterator *it;
+ Egraph_Vertice *v;
+ void *data;
+
+ it = eina_hash_iterator_tuple_new(eg->vertices);
+ while (eina_iterator_next(it, &data)) {
+ Eina_Hash_Tuple *t = data;
+ v = t->data;
+ egraph_vertice_del(obj, v);
+ }
+}
+
+void
+egraph_theme_file_set(Evas_Object *obj, char *path)
+{
+ EGRAPH_DATA_GET(obj, eg);
+
+ if (eg->theme_path)
+ free(eg->theme_path);
+
+ if (!path) {
+ char buf[256];
+
+ snprintf(buf, sizeof(buf),
+ "%s/egraph.edj",
+ "/usr/local/share/egraph"); /* XXX use eina_prefix */
+ path = buf;
+ }
+ eg->theme_path = strndup(path, 256);
+}
+
+void
+egraph_theme_edges_set(Evas_Object *obj, int set)
+{
+ EGRAPH_DATA_GET(obj, eg);
+
+ eg->theme_edges = set;
+}
+
+void
+egraph_layout_set(Evas_Object *obj, Egraph_Layout layout)
+{
+ EGRAPH_DATA_GET(obj, eg);
+
+ eg->layout = layout;
+ _layouting_schedule(eg);
+}
+
+void
+egraph_display_vertices_set(Evas_Object *obj, int set)
+{
+ EGRAPH_DATA_GET(obj, eg);
+ Eina_Iterator *it;
+ Egraph_Vertice *v;
+ void *data;
+
+ eg->display_vertices = set;
+
+ it = eina_hash_iterator_tuple_new(eg->vertices);
+ while (eina_iterator_next(it, &data)) {
+ Eina_Hash_Tuple *t = data;
+ v = t->data;
+ if (v->o) {
+ if (set == 0)
+ evas_object_hide(v->o);
+ else
+ evas_object_show(v->o);
+ }
+ }
+
+ _reposition(eg, 0);
+}
+
+void
+egraph_display_names_set(Evas_Object *obj, int set)
+{
+ EGRAPH_DATA_GET(obj, eg);
+ Eina_Iterator *it;
+ Egraph_Vertice *v;
+ void *data;
+
+ eg->display_names = set;
+
+ it = eina_hash_iterator_tuple_new(eg->vertices);
+ while (eina_iterator_next(it, &data)) {
+ Eina_Hash_Tuple *t = data;
+ v = t->data;
+ egraph_vertice_rename(obj, v, set ? v->name : NULL);
+ }
+}
+
+void
+egraph_display_edges_set(Evas_Object *obj, int set)
+{
+ EGRAPH_DATA_GET(obj, eg);
+ Eina_List *l;
+ Egraph_Edge *e;
+
+ eg->display_edges = set;
+
+ EINA_LIST_FOREACH(eg->edges, l, e) {
+ if (e->o) {
+ if (set == 0)
+ evas_object_hide(e->o);
+ else
+ evas_object_show(e->o);
+ }
+ }
+}
+
+void
+egraph_use_animations_set(Evas_Object *obj, int set)
+{
+ EGRAPH_DATA_GET(obj, eg);
+
+ eg->use_animations = set;
+}
+
+void
+egraph_do_improvements_set(Evas_Object *obj, int set)
+{
+ EGRAPH_DATA_GET(obj, eg);
+
+ eg->do_improvements = set;
+}
+
+Egraph_Edge *
+egraph_edge_add(Evas_Object *obj, Egraph_Vertice *a, Egraph_Vertice *b,
+ void *data)
+{
+ EGRAPH_DATA_GET(obj, eg);
+ Egraph_Edge *e;
+
+ e = calloc(1, sizeof(Egraph_Edge));
+ if (!e)
+ err(1, "egraph_edge_add: cannot calloc");
+ e->v3_new = 1;
+ e->a = a;
+ e->b = b;
+ e->data = data;
+ eg->edges = eina_list_append(eg->edges, e);
+ if (DEBUG)
+ printf("egraph_edge_add %d %d\n", e->a->id, e->b->id);
+
+ egraph_edge_type_set(obj, e, "edge_normal");
+
+ _layouting_schedule(eg);
+ return e;
+}
+
+static void
+_edge_v2_add(Egraph *eg, Egraph_Edge *e)
+{
+ int a_pos, b_pos;
+
+ if (DEBUG)
+ printf("_edge_v2_add %d %d\n", e->a->id, e->b->id);
+
+ e->v2_new = 1;
+ e->v3_new = 0;
+
+ a_pos = _igraph_query_vid(&eg->graph2, eg->graph2_vcount, e->a->id);
+ b_pos = _igraph_query_vid(&eg->graph2, eg->graph2_vcount, e->b->id);
+ igraph_add_edge(&eg->graph2, a_pos, b_pos);
+}
+
+static void
+_edge_add(Egraph *eg, Egraph_Edge *e)
+{
+ Evas_Object *eobj = NULL;
+ int a_pos, b_pos;
+
+ e->new = 1;
+ e->v2_new = 0;
+
+ a_pos = _igraph_query_vid(&eg->graph, eg->graph_vcount, e->a->id);
+ b_pos = _igraph_query_vid(&eg->graph, eg->graph_vcount, e->b->id);
+ igraph_add_edge(&eg->graph, a_pos, b_pos);
+
+ if (eg->theme_edges) {
+ eobj = _edje_obj_new(eg, e->type);
+ if (eobj) {
+ e->o_usetheme = 1;
+ evas_object_resize(eobj, eg->vertice_max_w, eg->vertice_max_h); // XXX rm
+ }
+ }
+ if (!eobj) {
+ eobj = evas_object_line_add(eg->evas);
+ evas_object_color_set(eobj, 255, 0, 0, 255);
+ }
+ evas_object_smart_member_add(eobj, eg->obj);
+ evas_object_stack_below(eobj, eg->split_vertice_edge);
+ e->o = eobj;
+ _edge_signal(eg, e, "become_active");
+
+ e->a->edges = eina_list_append(e->a->edges, e);
+ e->b->edges = eina_list_append(e->b->edges, e);
+ _vertice_update_status(eg, e->a);
+ _vertice_update_status(eg, e->b);
+}
+
+void
+egraph_edge_type_set(Evas_Object *obj, Egraph_Edge *e, const char *type)
+{
+ EGRAPH_DATA_GET(obj, eg);
+
+ if (e->type)
+ free(e->type);
+
+ e->type = strndup(type, TYPE_MAXLEN);
+ if (eg->theme_edges && e->o) {
+ _edje_obj_set(eg, e->o, type);
+ }
+}
+
+static void
+_edge_signal(Egraph *eg, Egraph_Edge *e, const char *signal)
+{
+ if (eg->theme_edges && e->o);
+ edje_object_signal_emit(e->o, signal, "");
+}
+
+void
+egraph_edge_del(Evas_Object *obj, Egraph_Edge *e)
+{
+ EGRAPH_DATA_GET(obj, eg);
+
+ // XXX DEBUG find mem corrupt, del already del edge
+ if (!egraph_edge_find(obj, e->a, e->b))
+ printf("XXX DEBUG: egraph_edge_del on unknown edge !!!\n");
+ if (DEBUG)
+ printf("egraph_edge_del: %d %d\n", e->a->id, e->b->id);
+
+ e->v3_del = 1;
+ _layouting_schedule(eg);
+}
+
+static void
+_edge_v2_del(Egraph *eg, Egraph_Edge *e)
+{
+ igraph_es_t es;
+ int a_pos, b_pos;
+
+ if (e->v2_del == 1)
+ return;
+
+ if (DEBUG)
+ printf("_edge_v2_del %d %d\n", e->a->id, e->b->id);
+
+ e->v2_del = 1;
+ e->v3_del = 0;
+
+ if (!e->v3_new) {
+ a_pos = _igraph_query_vid(&eg->graph2, eg->graph2_vcount, e->a->id);
+ b_pos = _igraph_query_vid(&eg->graph2, eg->graph2_vcount, e->b->id);
+ igraph_es_pairs_small(&es, eg->graph_directed, a_pos, b_pos, -1);
+ igraph_delete_edges(&eg->graph2, es);
+ }
+}
+
+static void
+_edge_del(Egraph *eg, Egraph_Edge *e)
+{
+ igraph_es_t es;
+ int a_pos, b_pos;
+
+ if (!e->v3_new && !e->v2_new) {
+ a_pos = _igraph_query_vid(&eg->graph, eg->graph_vcount, e->a->id);
+ b_pos = _igraph_query_vid(&eg->graph, eg->graph_vcount, e->b->id);
+ igraph_es_pairs_small(&es, eg->graph_directed, a_pos, b_pos, -1);
+ igraph_delete_edges(&eg->graph, es);
+
+ e->a->edges = eina_list_remove(e->a->edges, e);
+ e->b->edges = eina_list_remove(e->b->edges, e);
+ _vertice_update_status(eg, e->a);
+ _vertice_update_status(eg, e->b);
+
+ evas_object_del(e->o);
+ }
+ eg->edges = eina_list_remove(eg->edges, e);
+ free(e);
+}
+
+Egraph_Edge *
+egraph_edge_find(Evas_Object *obj, Egraph_Vertice *a, Egraph_Vertice *b)
+{
+ EGRAPH_DATA_GET(obj, eg);
+ Egraph_Edge *e;
+ Eina_List *l;
+
+ EINA_LIST_FOREACH(eg->edges, l, e)
+ if (!(e->v3_del || e->v2_del) &&
+ ((e->a == a && e->b == b) ||
+ (e->a == b && e->b == a)))
+ return e;
+ return NULL;
+}
+
+Egraph_Vertice *
+egraph_vertice_add(Evas_Object *obj, const char *name, void *data)
+{
+ EGRAPH_DATA_GET(obj, eg);
+ Egraph_Vertice *v;
+ u_int32_t id;
+
+ if (eg->vertices_count == EGRAPH_VERTICES_MAX) {
+ printf("egraph error: maximum number of vertices reached !\n");
+ return NULL;
+ }
+ v = calloc(1, sizeof(Egraph_Vertice));
+ if (!v)
+ err(1, "egraph_vertice_add: cannot calloc");
+ id = eg->vertices_freeids[eg->vertices_count];
+ v->id = id;
+ eina_hash_add(eg->vertices, &id, v);
+ eg->vertices_count++;
+ v->v3_new = 1;
+ if (DEBUG)
+ printf("egraph_vertice_add %d\n", id);
+
+ if (name)
+ v->name = strndup(name, EGRAPH_VERTICE_NAME_MAXLEN);
+ egraph_vertice_type_set(obj, v, "vertice_normal");
+
+ v->data = data;
+
+ _layouting_schedule(eg);
+ return v;
+}
+
+static void
+_vertice_v2_add(Egraph *eg, Egraph_Vertice *v)
+{
+ v->v2_new = 1;
+ v->v3_new = 0;
+
+ igraph_add_vertices(&eg->graph2, 1, 0);
+ SETVAN(&eg->graph2, "id", eg->graph2_vcount, v->id);
+ eg->graph2_vcount++;
+}
+
+static void
+_vertice_add(Egraph *eg, Egraph_Vertice *v)
+{
+ Evas_Object *vobj = NULL;
+
+ v->new = 1;
+ v->v2_new = 0;
+
+ vobj = _edje_obj_new(eg, v->type);
+ if (!vobj) {
+ printf("egraph: could not load theme for vertice !");
+ v->v2_new = 1;
+ v->new = 0;
+ _vertice_v2_del(eg, v);
+ return;
+ }
+ evas_object_smart_member_add(vobj, eg->obj);
+ evas_object_stack_above(vobj, eg->split_vertice_edge);
+ evas_object_event_callback_add(vobj, EVAS_CALLBACK_MOVE, _cb_vertice_move, v);
+ v->o = vobj;
+ _vertice_geometry_update(eg, v);
+
+ igraph_add_vertices(&eg->graph, 1, 0);
+ SETVAN(&eg->graph, "id", eg->graph_vcount, v->id);
+ eg->graph_vcount++;
+
+ if (v->name)
+ egraph_vertice_rename(eg->obj, v, v->name);
+}
+
+void
+egraph_vertice_del(Evas_Object *obj, Egraph_Vertice *v)
+{
+ EGRAPH_DATA_GET(obj, eg);
+ Egraph_Edge *e;
+ Eina_List *l;
+
+ v->v3_del = 1;
+
+ EINA_LIST_FOREACH(eg->edges, l, e)
+ if (e->a == v || e->b == v)
+ egraph_edge_del(obj, e);
+
+ _layouting_schedule(eg);
+}
+
+static void
+_vertice_v2_del(Egraph *eg, Egraph_Vertice *v)
+{
+ Egraph_Edge *e;
+ Eina_List *l;
+ int pos;
+
+ if (v->v2_del == 1)
+ return;
+
+ v->v2_del = 1;
+ v->v3_del = 0;
+
+ if (DEBUG)
+ printf("_vertice_v2_del %d\n", v->id);
+ EINA_LIST_FOREACH(eg->edges, l, e)
+ if (e->a == v || e->b == v)
+ _edge_v2_del(eg, e);
+
+ if (!v->v3_new) {
+ pos = _igraph_query_vid(&eg->graph2, eg->graph2_vcount, v->id);
+ igraph_delete_vertices(&eg->graph2, igraph_vss_1(pos));
+ eg->graph2_vcount--;
+ }
+}
+
+static void
+_vertice_del(Egraph *eg, Egraph_Vertice *v)
+{
+ Egraph_Edge *e;
+ Eina_List *l, *lprev;
+ Evas_Object *blob;
+ int pos;
+
+ if (!v->v3_new && !v->v2_new) {
+ EINA_LIST_FOREACH_SAFE(eg->edges, l, lprev, e)
+ if (e->a == v || e->b == v)
+ _edge_del(eg, e);
+ eina_list_free(v->edges);
+
+ pos = _igraph_query_vid(&eg->graph, eg->graph_vcount, v->id);
+ igraph_delete_vertices(&eg->graph, igraph_vss_1(pos));
+ eg->graph_vcount--;
+
+ EINA_LIST_FOREACH(v->blobs_incoming, l, blob)
+ evas_object_del(blob);
+ eina_list_free(v->blobs_incoming);
+
+ evas_object_del(v->o);
+ }
+
+ eina_hash_del(eg->vertices, &v->id, NULL);
+ eg->vertices_count--;
+ eg->vertices_freeids[eg->vertices_count] = v->id;
+
+ free(v);
+}
+
+void
+egraph_vertice_type_set(Evas_Object *obj, Egraph_Vertice *v, const char *type)
+{
+ EGRAPH_DATA_GET(obj, eg);
+
+ if (v->type)
+ free(v->type);
+
+ v->type = strndup(type, TYPE_MAXLEN);
+ if (v->o)
+ _edje_obj_set(eg, v->o, type);
+}
+
+static void
+_vertice_update_status(Egraph *eg, Egraph_Vertice *v)
+{
+ Eina_List *l;
+ Egraph_Edge *e;
+ int status = 0;
+
+ if (v->is_group && (eina_list_count(v->edges) >= 1)) {
+ status = 1; /* we are a group with childs */
+ } else {
+ EINA_LIST_FOREACH(v->edges, l, e) {
+ if ((v == e->a && !e->b->is_group) ||
+ (v == e->b && !e->a->is_group)) {
+ status = 1; /* we are connected to at least on other non group node */
+ break;
+ }
+ }
+ }
+
+ if (status != v->status) {
+ if (status)
+ _vertice_signal(eg, v, "become_active");
+ else
+ _vertice_signal(eg, v, "become_inactive");
+ v->status = status;
+ }
+}
+
+static void
+_vertice_signal(Egraph *eg, Egraph_Vertice *v, const char *signal)
+{
+ if (v->o)
+ edje_object_signal_emit(v->o, signal, "");
+}
+
+void
+egraph_vertice_rename(Evas_Object *obj, Egraph_Vertice *v, const char *name)
+{
+ EGRAPH_DATA_GET(obj, eg);
+
+ if (eg->display_names == 0)
+ return;
+
+ if (name) {
+ if (v->name != name) {
+ if (v->name)
+ free(v->name);
+ v->name = strndup(name, EGRAPH_VERTICE_NAME_MAXLEN);
+ }
+ }
+ if (v->o) {
+ if (v->name)
+ edje_object_part_text_set(v->o, "label", v->name);
+ else
+ edje_object_part_text_set(v->o, "label", "");
+ _vertice_geometry_update(eg, v);
+ }
+}
+
+static void
+_vertice_geometry_update(Egraph *eg, Egraph_Vertice *v)
+{
+ int w, h;
+
+ edje_object_size_min_calc(v->o, &w, &h);
+ if (DEBUG)
+ printf("_vertice_geometry_update: %d %d\n", w, h);
+ evas_object_resize(v->o, w, h);
+ if (w > eg->vertice_max_w)
+ eg->vertice_max_w = w;
+ if (h > eg->vertice_max_h)
+ eg->vertice_max_h = h;
+ if (DEBUG)
+ printf("_vertice_geometry_update: end %d %d\n",
+ eg->vertice_max_w, eg->vertice_max_h);
+}
+
+void
+_color_int_to_rgb(u_int32_t color, int *r, int *g , int *b)
+{
+ *r = (color & 0xFF000000) >> 24;
+ *g = (color & 0x00FF0000) >> 16;
+ *b = (color & 0x0000FF00) >> 8;
+}
+
+void
+egraph_vertice_send_blob(Evas_Object *obj,
+ Egraph_Vertice *a, Egraph_Vertice *b,
+ int size, u_int32_t color)
+{
+ EGRAPH_DATA_GET(obj, eg);
+ Evas_Object *blob;
+ int ax, ay, aw, ah, bx, by, bw, bh;
+ int cr, cg, cb;
+
+ if (!a->o || !b->o)
+ return;
+ evas_object_geometry_get(a->o, &ax, &ay, &aw, &ah);
+ evas_object_geometry_get(b->o, &bx, &by, &bw, &bh);
+ _color_int_to_rgb(color, &cr, &cg, &cb);
+
+ blob = _edje_obj_new(eg, "blob");
+ if (!blob)
+ blob = evas_object_rectangle_add(eg->evas);
+ evas_object_color_set(blob, cr, cg, cb, 255);
+ evas_object_smart_member_add(blob, eg->obj);
+ evas_object_stack_above(blob, eg->split_vertice_edge);
+ evas_object_move(blob, ax, ay);
+ evas_object_resize(blob, size, size);
+ evas_object_show(blob);
+ b->blobs_incoming = eina_list_append(b->blobs_incoming, blob);
+ _blob_send(blob, b, bx, by);
+}
+
+static void
+_cb_blob_arrived(void *data, Efx_Map_Data *e, Evas_Object *obj)
+{
+ Egraph_Vertice *v;
+
+ v = data;
+ v->blobs_incoming = eina_list_remove(v->blobs_incoming, obj);
+ evas_object_del(obj);
+}
+
+static void
+_blob_send(Evas_Object *blob, Egraph_Vertice *v, Evas_Coord x, Evas_Coord y)
+{
+ if (DEBUG)
+ printf("blob_send %d %d\n", x, y);
+ efx_move(blob, EFX_EFFECT_SPEED_SINUSOIDAL,
+ &(Evas_Point){ x, y }, 0.6, _cb_blob_arrived, v);
+}
+
+static void
+_layouting_schedule(Egraph *eg)
+{
+ if (eg->layouting.running > 0) {
+ eg->layouting.todo = 1;
+ return;
+ }
+
+ eg->layouting.running = 1;
+ ecore_timer_add(0.0, _cb_layouting_start, eg); /* delayed start */
+}
+
+static void
+_v2_update(Egraph *eg)
+{
+ Eina_List *l, *lprev, *todel, *toadd;
+ Eina_Iterator *it;
+ Egraph_Vertice *v;
+ Egraph_Edge *e;
+ void *data;
+
+ /* update graph and structs based on v2_add / v2_del */
+ it = eina_hash_iterator_tuple_new(eg->vertices);
+ todel = NULL; toadd = NULL;
+ while (eina_iterator_next(it, &data)) {
+ Eina_Hash_Tuple *t = data;
+ v = t->data;
+ if (v->v2_del)
+ todel = eina_list_append(todel, v);
+ else if (v->v2_new)
+ toadd = eina_list_append(toadd, v);
+ }
+ eina_iterator_free(it);
+ EINA_LIST_FOREACH(todel, l, v)
+ _vertice_del(eg, v);
+ EINA_LIST_FOREACH(toadd, l, v)
+ _vertice_add(eg, v);
+ todel = eina_list_free(todel);
+ toadd = eina_list_free(toadd);
+ EINA_LIST_FOREACH_SAFE(eg->edges, l, lprev, e) {
+ if (e->v2_del)
+ _edge_del(eg, e);
+ else if (e->v2_new)
+ _edge_add(eg, e);
+ }
+}
+
+static void
+_v3_update(Egraph *eg)
+{
+ Eina_List *l, *lprev;
+ Eina_Iterator *it;
+ Egraph_Vertice *v;
+ Egraph_Edge *e;
+ void *data;
+ float ranx, rany;
+ int changes_count = 0;
+ int changes_diff = 0;
+ int i, id;
+
+ if (DEBUG)
+ printf("_v3_update\n");
+ /* update graph2 and structs based on v3_add / v3_del */
+ it = eina_hash_iterator_tuple_new(eg->vertices);
+ while (eina_iterator_next(it, &data)) {
+ Eina_Hash_Tuple *t = data;
+ v = t->data;
+ if (v->v3_del) {
+ _vertice_v2_del(eg, v); changes_diff--; changes_count++;
+ } else if (v->v3_new) {
+ _vertice_v2_add(eg, v); changes_diff++; changes_count++;
+ }
+ }
+ eina_iterator_free(it);
+ if (DEBUG)
+ printf("_v3_update edges\n");
+ EINA_LIST_FOREACH_SAFE(eg->edges, l, lprev, e) {
+ if (e->v3_del) {
+ _edge_v2_del(eg, e); changes_count++;
+ } else if (e->v3_new) {
+ _edge_v2_add(eg, e); changes_count++;
+ }
+ }
+
+ /* set correct coords2 size */
+ if (changes_diff > 0) {
+ for (i=0; i<changes_diff; i++) {
+ id = (eg->graph2_vcount - changes_diff) + i;
+ igraph_matrix_add_rows(&eg->coords2, 1);
+ ranx = eg->graph_wmin + fmod((float)random() / 1000, (float)((eg->graph_wmax + 1) - eg->graph_wmin));
+ rany = eg->graph_hmin + fmod((float)random() / 1000, (float)((eg->graph_hmax + 1) - eg->graph_hmin));
+ if (DEBUG)
+ printf("ranx %6.3f rany %6.3f\n", ranx, rany);
+ igraph_matrix_set(&eg->coords2, id, 0, ranx);
+ igraph_matrix_set(&eg->coords2, id, 1, rany);
+ }
+ } else if (changes_diff < 0) {
+ changes_diff = -changes_diff;
+ for (i=0; i<changes_diff; i++) {
+ id = (eg->graph2_vcount + changes_diff) - i;
+ igraph_matrix_remove_row(&eg->coords2, 0);
+ }
+ }
+
+ if (eg->layout == EGRAPH_LAYOUT_FRUCHTERMANREINGOLD) {
+ /* set minimum and maximum for each node */
+ /* XXX do that in layouting thread ? */
+ if (DEBUG)
+ printf("g wmin %d wmax %d hmin %d hmax %d\n",
+ eg->graph_wmin, eg->graph_wmax, eg->graph_hmin, eg->graph_hmax);
+ igraph_vector_init(&eg->graph2_wmin, eg->graph2_vcount);
+ igraph_vector_init(&eg->graph2_wmax, eg->graph2_vcount);
+ igraph_vector_init(&eg->graph2_hmin, eg->graph2_vcount);
+ igraph_vector_init(&eg->graph2_hmax, eg->graph2_vcount);
+ igraph_vector_fill(&eg->graph2_wmin, eg->graph_wmin);
+ igraph_vector_fill(&eg->graph2_wmax, eg->graph_wmax);
+ igraph_vector_fill(&eg->graph2_hmin, eg->graph_hmin);
+ igraph_vector_fill(&eg->graph2_hmax, eg->graph_hmax);
+ }
+
+ eg->layouting.changes_diff = changes_diff;
+}
+
+static Eina_Bool
+_cb_layouting_start(void *data)
+{
+ Egraph *eg;
+
+ eg = data;
+
+ eg->layouting.todo = 0;
+
+ _v3_update(eg);
+
+ eg->layouting.running = 2;
+ eg->layouting.thread = ecore_thread_run(_cb_layouting_run, _cb_layouting_end,
+ _cb_layouting_cancel, eg);
+
+ return EINA_FALSE; /* no repeat */
+}
+
+void
+_cb_layouting_run(void *data, Ecore_Thread *thread)
+{
+ Egraph *eg;
+ int niter;
+
+ eg = data;
+
+ if (DEBUG)
+ printf("[-] _cb_layouting_run begin (%d)\n", eg->layout);
+
+ switch(eg->layout) {
+ case EGRAPH_LAYOUT_KAMADAKAWAI:
+ if (eg->layouting.improvement) {
+ niter = 300;
+ } else {
+ if (eg->layouting.changes_diff == 0)
+ niter = 1000;
+ else
+ niter = 1000 * eg->layouting.changes_diff;
+ if (niter > 2000)
+ niter = 2000;
+ }
+ /* http://igraph.sourceforge.net/doc/html/ch18s01.html#igraph_layout_kamada_kawai
+ * int igraph_layout_kamada_kawai(const igraph_t *g, igraph_matrix_t *res,
+ * igraph_integer_t niter, igraph_real_t sigma,
+ * igraph_real_t initemp, igraph_real_t coolexp,
+ * igraph_real_t kkconst, igraph_bool_t use_seed,
+ * const igraph_vector_t *minx,
+ * const igraph_vector_t *maxx,
+ * const igraph_vector_t *miny,
+ * const igraph_vector_t *maxy);
+ * Defaults :
+ * igraph_layout_kamada_kawai(&eg->graph2, &eg->coords2,
+ * 1000, eg->vertices_count / 4, 10, 0.99,
+ * eg->vertices_count ^ 2, 1,
+ * NULL, NULL, NULL, NULL);
+ */
+ igraph_layout_kamada_kawai(&eg->graph2, &eg->coords2,
+ niter, eg->graph2_vcount, 10, 0.99,
+ eg->vertices_count ^ 2, 1,
+ NULL, NULL, NULL, NULL);
+ break;
+
+ case EGRAPH_LAYOUT_GRAPHOPT:
+ if (eg->layouting.improvement) {
+ niter = 300;
+ } else {
+ if (eg->layouting.changes_diff == 0)
+ niter = 100;
+ else
+ niter = 50 * eg->layouting.changes_diff;
+ if (niter > 500)
+ niter = 500;
+ }
+ /* http://igraph.sourceforge.net/doc/html/ch18s01.html#igraph_layout_graphopt
+ * int igraph_layout_graphopt(const igraph_t *g, igraph_matrix_t *res,
+ * igraph_integer_t niter,
+ * igraph_real_t node_charge, igraph_real_t node_mass,
+ * igraph_real_t spring_length,
+ * igraph_real_t spring_constant,
+ * igraph_real_t max_sa_movement,
+ * igraph_bool_t use_seed);
+ * Defaults :
+ * igraph_layout_graphopt(&eg->graph2, &eg->coords2,
+ * 1000, 0.001, 30, 0, 1, 5, 0);
+ */
+ igraph_layout_graphopt(&eg->graph2, &eg->coords2,
+ niter, 0.003, 10, 10, 1, 5, 1);
+ break;
+
+ case EGRAPH_LAYOUT_FRUCHTERMANREINGOLD:
+ niter = 1000;
+ /* http://igraph.sourceforge.net/doc/html/ch18s01.html#igraph_layout_fruchterman_reingold
+ * int igraph_layout_fruchterman_reingold(const igraph_t *graph, igraph_matrix_t *res,
+ * igraph_integer_t niter, igraph_real_t maxdelta,
+ * igraph_real_t area, igraph_real_t coolexp,
+ * igraph_real_t repulserad, igraph_bool_t use_seed,
+ * const igraph_vector_t *weight,
+ * const igraph_vector_t *minx,
+ * const igraph_vector_t *maxx,
+ * const igraph_vector_t *miny,
+ * const igraph_vector_t *maxy);
+ * Defaults:
+ * igraph_layout_fruchterman_reingold(&eg->graph2, &eg->coords2,
+ * 500, eg->graph2_vcount,
+ * sqrt(eg->graph2_vcount) * sqrt(eg->graph2_vcount), 1.5,
+ * eg->graph2_vcount, 0,
+ * NULL, NULL, NULL, NULL, NULL);
+ */
+ igraph_layout_fruchterman_reingold(&eg->graph2, &eg->coords2,
+ niter, 0.05,
+ sqrt(eg->graph2_vcount), 1.5,
+ sqrt(eg->graph2_vcount) * eg->graph2_vcount, 1,
+ NULL, NULL, NULL, NULL, NULL);
+ //&eg->graph2_wmin, &eg->graph2_wmax,
+ //&eg->graph2_hmin, &eg->graph2_hmax);
+ break;
+ }
+ if (DEBUG)
+ printf("[-] _cb_layouting_run end\n");
+}
+
+static void
+_coords2_copy(Egraph *eg)
+{
+ igraph_matrix_copy(&eg->coords, &eg->coords2);
+}
+
+void
+_cb_layouting_end(void *data, Ecore_Thread *thread)
+{
+ Egraph *eg;
+
+ eg = data;
+ _v2_update(eg);
+ _coords2_copy(eg);
+ _reposition(eg, 0);
+ eg->layouting.running = 0;
+ if (eg->layouting.todo) {
+ eg->layouting.todo = 0;
+ eg->layouting.improvement = 0;
+ _layouting_schedule(eg);
+ } else {
+ if (eg->do_improvements) {
+ if (eg->layouting.improvement < EGRAPH_LAYOUTING_IMPROVEMENTS) {
+ eg->layouting.improvement++;
+ _layouting_schedule(eg);
+ } else {
+ eg->layouting.improvement = 0;
+ }
+ }
+ }
+}
+
+void
+_cb_layouting_cancel(void *data, Ecore_Thread *thread)
+{
+ Egraph *eg;
+
+ eg = data;
+ eg->layouting.running = 0;
+ eg->layouting.todo = 0;
+ /* we are not in a clean state now, but it happends on exit only */
+}
+
+/* XXX slow ! possible to do edge/vertice delete on repositionning ? */
+static int
+_igraph_query_vid(igraph_t *g, int g_len, int id)
+{
+ int i;
+
+ for (i=0; i<g_len; i++) {
+ if (VAN(g, "id", i) == id)
+ return i;
+ }
+ printf("egraph: WARNING: _igraph_query_id %d not found !\n", id);
+ return -1;
+}
+
+/* Apply vertice move to it's edges */
+static void
+_cb_vertice_move(void *data, Evas *evas, Evas_Object *obj, void *event_info)
+{
+ EGRAPH_DATA_GET(evas_object_smart_parent_get(obj), eg);
+ Egraph_Vertice *v;
+ Egraph_Edge *e;
+ Evas_Map *m;
+ Eina_List *l;
+ int x, y, w, h;
+ int ax, ay, bx, by, aw, ah, bw, bh;
+ int p0x, p0y, p1x, p1y, p2x, p2y, p3x, p3y;
+ float a;
+
+ v = data;
+ evas_object_geometry_get(v->o, &x, &y, &w, &h);
+
+ EINA_LIST_FOREACH(v->edges, l, e) {
+ if (e->new) {
+ if (eg->display_edges)
+ evas_object_show(e->o);
+ e->new = 0;
+ }
+ if (e->o_usetheme) {
+ /* XXX we map the edges once per node = 2 times ... */
+ evas_object_move(e->o, x, y);
+ m = evas_map_new(4);
+ evas_map_smooth_set(m, 1);
+ evas_map_util_points_populate_from_object(m, e->o);
+ evas_object_geometry_get(e->a->o, &ax, &ay, &aw, &ah);
+ evas_object_geometry_get(e->b->o, &bx, &by, &bw, &bh);
+ ax = ax + aw / 2; ay = ay + ah / 2;
+ bx = bx + bw / 2; by = by + bh / 2;
+ aw = aw / 2; ah = ah / 2;
+ bw = bw / 2; bh = bh / 2;
+ /* rotate edge endpoints */
+ a = atan2(by - ay, bx - ax);
+#define ROTX(x, h, a) (-sin(a)*h + x)
+#define ROTY(y, h, a) (cos(a)*h + y)
+ p0x = ROTX(ax, ah, a); p0y = ROTY(ay, ah, a);
+ p1x = ROTX(ax, -ah, a); p1y = ROTY(ay, -ah, a);
+ p2x = ROTX(bx, bh, a); p2y = ROTY(by, bh, a);
+ p3x = ROTX(bx, -bh, a); p3y = ROTY(by, -bh, a);
+ /* set edge endpoints */
+ evas_map_point_coord_set(m, 0, p2x, p2y, 0);
+ evas_map_point_coord_set(m, 1, p0x, p0y, 0);
+ evas_map_point_coord_set(m, 2, p1x, p1y, 0);
+ evas_map_point_coord_set(m, 3, p3x, p3y, 0);
+ evas_object_map_set(e->o, m);
+ evas_object_map_enable_set(e->o, EINA_TRUE); // XXX do at init
+ evas_map_free(m);
+ } else {
+ evas_object_line_xy_get(e->o, &ax, &ay, &bx, &by);
+ if (e->a == v) {
+ ax = x + w/2;
+ ay = y + h/2;
+ } else {
+ bx = x + w/2;
+ by = y + h/2;
+ }
+ evas_object_line_xy_set(e->o, ax, ay, bx, by);
+ }
+ }
+}
+
+static void
+_reposition(Egraph *eg, int no_animation)
+{
+ Egraph_Vertice *v;
+ u_int32_t id;
+ float gw_min, gw_max, gh_min, gh_max, factor_w, factor_h;
+ float x, y;
+ int obj_x, obj_y, obj_w, obj_h;
+ int vcur;
+
+ if (DEBUG)
+ printf("[-] _reposition\n");
+ if (eg->graph_vcount == 0)
+ return;
+
+ evas_object_geometry_get(eg->obj, &obj_x, &obj_y, &obj_w, &obj_h);
+ _matrix_minmax_2v(&eg->coords, eg->graph_vcount,
+ &gw_min, &gw_max, &gh_min, &gh_max);
+ eg->graph_wmin = gw_min;
+ eg->graph_wmax = gw_max;
+ eg->graph_hmin = gh_min;
+ eg->graph_hmax = gh_max;
+
+ if (DEBUG)
+ printf("gw_min %6.3f gw_max %6.3f gh_min %6.3f gh_max %6.3f\n",
+ gw_min, gw_max, gh_min, gh_max);
+ if (gw_max == gw_min)
+ factor_w = 1;
+ else
+ factor_w = (obj_w - eg->vertice_max_w) / (gw_max - gw_min);
+ if (gh_max == gh_min)
+ factor_h = 1;
+ else
+ factor_h = (obj_h - eg->vertice_max_h) / (gh_max - gh_min);
+ if (DEBUG)
+ printf("factor_w %6.3f factor_h %6.3f\n", factor_w, factor_h);
+
+ for (vcur=0; vcur<eg->graph_vcount; vcur++) {
+ id = VAN(&eg->graph, "id", vcur);
+
+ x = MATRIX(eg->coords, vcur, 0);
+ y = MATRIX(eg->coords, vcur, 1);
+ if (DEBUG)
+ printf("%d: %6.3f %6.3f id %d\n", vcur, x, y, id);
+ x = obj_x + ((x - gw_min) * factor_w);
+ y = obj_y + ((y - gh_min) * factor_h);
+ if (DEBUG)
+ printf(" inobj: %6.3f %6.3f\n", x, y);
+
+ v = eina_hash_find(eg->vertices, &id);
+ if (eg->use_animations && !no_animation) {
+ efx_move(v->o, EFX_EFFECT_SPEED_DECELERATE,
+ &(Evas_Point){ x, y }, 0.5, NULL, NULL);
+ }
+ else
+ evas_object_move(v->o, x, y);
+ /* XXX fix blob repositionning
+ Evas_Object *blob;
+ Eina_List *l;
+ EINA_LIST_FOREACH(v->blobs_incoming, l, blob)
+ _blob_send(blob, v, x, y);
+ */
+ if (v->new) {
+ evas_object_show(v->o);
+ v->new = 0;
+ }
+ }
+}
+
+/**
+ * Compute minimum and maximum of a matrices of 2 colum vectors
+ *
+ * @note igraph is crazy in the coconut
+ */
+static void
+_matrix_minmax_2v(const igraph_matrix_t *m, int row_count,
+ float *c1min, float *c1max, float *c2min, float *c2max)
+{
+ float val;
+ int row;
+
+ *c1min=MATRIX(*m, 0, 0); *c1max=MATRIX(*m, 0, 0);
+ *c2min=MATRIX(*m, 0, 1); *c2max=MATRIX(*m, 0, 1);
+
+ for (row=1; row<row_count; row++) {
+ val = MATRIX(*m, row, 0);
+ if (val < *c1min) *c1min = val;
+ else if (val > *c1max) *c1max = val;
+ val = MATRIX(*m, row, 1);
+ if (val < *c2min) *c2min = val;
+ else if (val > *c2max) *c2max = val;
+ }
+}
+
+static Evas_Object *
+_edje_obj_new(Egraph *eg, const char *group)
+{
+ Evas_Object *obj;
+
+ obj = edje_object_add(eg->evas);
+ return _edje_obj_set(eg, obj, group);
+}
+
+static Evas_Object *
+_edje_obj_set(Egraph *eg, Evas_Object *obj, const char *group)
+{
+ if (!obj || !edje_object_file_set(obj, eg->theme_path, group)) {
+ int err = edje_object_load_error_get(obj);
+ const char *errmsg = edje_load_error_str(err);
+ if (DEBUG)
+ fprintf(stderr, "Could not load the edje file - reason:%s\n", errmsg);
+ return NULL;
+ }
+ return obj;
+}
+
+Egraph_Vertice *
+egraph_group_add(Evas_Object *obj, const char *name, void *data)
+{
+ Egraph_Vertice *g;
+
+ g = egraph_vertice_add(obj, name, data);
+ g->is_group = 1;
+ egraph_vertice_type_set(obj, g, "vertice_group");
+ return g;
+}
+
+int
+egraph_group_vertice_attach(Evas_Object *obj,
+ Egraph_Vertice *group, Egraph_Vertice *v)
+{
+ Egraph_Edge *e;
+
+ group->group_vertices = eina_list_append(group->group_vertices, v);
+ e = egraph_edge_add(obj, group, v, NULL);
+ egraph_edge_type_set(obj, e, "edge_group");
+ return 1;
+}
+
+void
+egraph_group_vertice_detach(Evas_Object *obj,
+ Egraph_Vertice *group, Egraph_Vertice *v)
+{
+ Egraph_Edge *e;
+
+ group->group_vertices = eina_list_remove(group->group_vertices, v);
+ e = egraph_edge_find(obj, group, v);
+ egraph_edge_del(obj, e);
+}
diff --git a/egraph/egraph.edc b/egraph/egraph.edc
new file mode 100644
index 0000000..399442a
--- /dev/null
+++ b/egraph/egraph.edc
@@ -0,0 +1,250 @@
+collections {
+ group {
+ name: "vertice_normal";
+ max: 700 700;
+ min: 700 700;
+ images {
+ image: "data/vertice.png" COMP;
+ }
+ parts {
+ part {
+ name: "image";
+ type: IMAGE;
+ description {
+ state: "default" 0.0;
+ max: 15 15;
+ min: 15 15;
+ image{
+ normal: "data/vertice.png";
+ }
+ rel1.relative: 0.0 0.0;
+ rel2.relative: 1.0 1.0;
+ color: 255 255 255 100;
+ }
+ description {
+ state: "active" 1.0;
+ inherit: "default" 0.0;
+ color: 255 255 255 255;
+ }
+ }
+ part {
+ name: "label";
+ type: TEXT;
+ description {
+ state: "default" 0.0;
+ max: 50 8;
+ fixed: 1 1;
+ color: 200 255 0 50; /* yellow low */
+ text {
+ font: "vera";
+ size: 10;
+ min: 1 1;
+ }
+ rel1.to: "image";
+ rel1.relative: 0.5 1.0;
+ rel2.to: "image";
+ rel2.relative: 0.5 1.0;
+ rel2.offset: 0 8;
+ }
+ description {
+ state: "active" 1.0;
+ inherit: "default" 0.0;
+ color: 200 255 0 255; /* yellow visible */
+ }
+ }
+ }
+ programs {
+ program {
+ name: "state_active";
+ signal: "become_active";
+ source: "";
+ action: STATE_SET "active" 0.0;
+ target: "image";
+ target: "label";
+ transition: DECELERATE 0.5;
+ }
+ program {
+ name: "state_inactive";
+ signal: "become_inactive";
+ source: "";
+ action: STATE_SET "default" 0.0;
+ target: "image";
+ target: "label";
+ transition: DECELERATE 0.5;
+ }
+ }
+ }
+ group {
+ name: "vertice_group";
+ max: 700 700;
+ min: 700 700;
+ images {
+ image: "data/vertice.png" COMP;
+ }
+ parts {
+ part {
+ name: "image";
+ type: IMAGE;
+ description {
+ state: "default" 0.0;
+ max: 15 15;
+ min: 15 15;
+ image{
+ normal: "data/vertice.png";
+ }
+ rel1.relative: 0.0 0.0;
+ rel2.relative: 1.0 1.0;
+ color: 160 120 40 70;
+ }
+ description {
+ state: "active" 1.0;
+ inherit: "default" 0.0;
+ color: 160 120 40 170;
+ }
+ }
+ part {
+ name: "label";
+ type: TEXT;
+ description {
+ state: "default" 0.0;
+ max: 50 8;
+ fixed: 1 1;
+ color: 160 120 40 70; /* yellow low */
+ text {
+ font: "vera";
+ size: 10;
+ min: 1 1;
+ }
+ rel1.to: "image";
+ rel1.relative: 0.5 1.0;
+ rel2.to: "image";
+ rel2.relative: 0.5 1.0;
+ rel2.offset: 0 8;
+ }
+ description {
+ state: "active" 1.0;
+ inherit: "default" 0.0;
+ color: 160 120 40 170; /* yellow visible */
+ }
+ }
+ }
+ programs {
+ program {
+ name: "state_active";
+ signal: "become_active";
+ action: STATE_SET "active" 0.0;
+ target: "image";
+ transition: DECELERATE 0.5;
+ }
+ program {
+ name: "state_inactive";
+ signal: "become_inactive";
+ action: STATE_SET "default" 0.0;
+ target: "image";
+ transition: DECELERATE 0.5;
+ }
+ }
+ }
+ group {
+ name: "edge_normal";
+ max: 700 700;
+ min: 700 700;
+ images {
+ image: "data/edge.png" COMP;
+ }
+ parts {
+ part {
+ name: "image";
+ type: IMAGE;
+ description {
+ state: "default" 0.0;
+ max: 50 10;
+ min: 50 10;
+ image{
+ normal: "data/edge.png";
+ }
+ rel1.relative: 0.0 0.0;
+ rel2.relative: 1.0 1.0;
+ color: 255 255 255 50;
+ }
+ description {
+ state: "active" 1.0;
+ inherit: "default" 0.0;
+ color: 255 255 255 255;
+ }
+ }
+ }
+ programs {
+ program {
+ name: "state_active";
+ signal: "become_active";
+ action: STATE_SET "active" 0.0;
+ target: "image";
+ transition: DECELERATE 0.5;
+ }
+ }
+ }
+ group {
+ name: "edge_group";
+ max: 700 700;
+ min: 700 700;
+ images {
+ image: "data/edge.png" COMP;
+ }
+ parts {
+ part {
+ name: "image";
+ type: IMAGE;
+ description {
+ state: "default" 0.0;
+ max: 50 10;
+ min: 50 10;
+ image{
+ normal: "data/edge.png";
+ }
+ rel1.relative: 0.0 0.0;
+ rel2.relative: 1.0 1.0;
+ color: 255 120 40 70;
+ }
+ description {
+ state: "active" 1.0;
+ inherit: "default" 0.0;
+ color: 255 120 40 170;
+ }
+ }
+ }
+ programs {
+ program {
+ name: "state_active";
+ signal: "become_active";
+ action: STATE_SET "active" 0.0;
+ target: "image";
+ transition: DECELERATE 0.5;
+ }
+ }
+ }
+ group {
+ name: "blob";
+ max: 700 700;
+ min: 700 700;
+ images {
+ image: "data/blob.png" COMP;
+ }
+ parts {
+ part {
+ name: "image";
+ type: IMAGE;
+ description {
+ state: "default" 0.0;
+ max: 50 50;
+ min: 3 3;
+ image{
+ normal: "data/blob.png";
+ }
+ rel1.relative: 0.0 0.0;
+ rel2.relative: 1.0 1.0;
+ }
+ }
+ }
+ }
+}
diff --git a/egraph/examples/Makefile b/egraph/examples/Makefile
new file mode 100644
index 0000000..9ac573e
--- /dev/null
+++ b/egraph/examples/Makefile
@@ -0,0 +1,12 @@
+CFLAGS += -Wall -g
+CFLAGS += $(shell pkg-config --libs --cflags elementary)
+CFLAGS += -L../ -legraph -lecore_evas
+
+SOURCES = $(shell echo *.c)
+OBJECTS = $(SOURCES:.c=.o)
+TARGETS = $(SOURCES:.c=)
+
+all: $(TARGETS)
+
+clean:
+ rm -f $(TARGETS) $(OBJECTS)
diff --git a/egraph/examples/demoapp.c b/egraph/examples/demoapp.c
new file mode 100644
index 0000000..4e64363
--- /dev/null
+++ b/egraph/examples/demoapp.c
@@ -0,0 +1,371 @@
+#include <err.h>
+
+#include <Elementary.h>
+#include <Egraph.h>
+
+Evas_Object *_mainwin;
+Evas_Object *_egraph;
+Eina_List *_vertice_list = NULL;
+Eina_List *_group_list = NULL;
+
+static void
+_cb_add_edge(void *data, Evas_Object *obj, void *event_info)
+{
+ Egraph_Vertice *a, *b;
+ int ran, count;
+ char buf[64];
+
+ if (!_egraph)
+ return;
+
+ count = eina_list_count(_vertice_list);
+ if (count == 0) {
+ a = egraph_vertice_add(_egraph, "first", NULL);
+ _vertice_list = eina_list_append(_vertice_list, a);
+ } else {
+ ran = random() % count;
+ a = eina_list_nth(_vertice_list, ran);
+ }
+ b = egraph_vertice_add(_egraph, NULL, NULL);
+ snprintf(buf, sizeof(buf), "%d", b->id);
+ egraph_vertice_rename(_egraph, b, buf);
+ _vertice_list = eina_list_append(_vertice_list, b);
+
+ egraph_edge_add(_egraph, a, b, NULL);
+}
+
+static void
+_cb_add_50edges(void *data, Evas_Object *obj, void *event_info)
+{
+ int i;
+
+ if (!_egraph)
+ return;
+
+ for (i=0; i<50; i++)
+ _cb_add_edge(data, obj, event_info);
+}
+
+static void
+_cb_add_500edges(void *data, Evas_Object *obj, void *event_info)
+{
+ int i;
+
+ if (!_egraph)
+ return;
+
+ for (i=0; i<500; i++)
+ _cb_add_edge(data, obj, event_info);
+}
+
+static void
+_cb_del_edges(void *data, Evas_Object *obj, void *event_info)
+{
+ Eina_List *l;
+ Egraph_Vertice *v;
+
+ if (!_egraph)
+ return;
+
+ egraph_clear(_egraph);
+ _vertice_list = eina_list_free(_vertice_list);
+ _group_list = eina_list_free(_group_list);
+}
+
+static void
+_cb_add_node(void *data, Evas_Object *obj, void *event_info)
+{
+ Egraph_Vertice *v;
+ char buf[64];
+
+ if (!_egraph)
+ return;
+
+ v = egraph_vertice_add(_egraph, NULL, NULL);
+ snprintf(buf, sizeof(buf), "%d", v->id);
+ egraph_vertice_rename(_egraph, v, buf);
+ _vertice_list = eina_list_append(_vertice_list, v);
+}
+
+static void
+_cb_send_100blobs(void *data, Evas_Object *obj, void *event_info)
+{
+ Egraph_Vertice *a, *b;
+ int count, ran, i;
+
+ count = eina_list_count(_vertice_list);
+ if (!count)
+ return;
+
+ for (i=0; i<100; i++) {
+ ran = random() % count;
+ a = eina_list_nth(_vertice_list, ran);
+ ran = random() % count;
+ b = eina_list_nth(_vertice_list, ran);
+ egraph_vertice_send_blob(_egraph, a, b, 5, 0xFF000000);
+ }
+}
+
+static void
+_cb_add_10n_group(void *data, Evas_Object *obj, void *event_info)
+{
+ Egraph_Vertice *group, *v;
+ char buf[64];
+ int i;
+
+ if (!_egraph)
+ return;
+
+ group = egraph_group_add(_egraph, NULL, NULL);
+ snprintf(buf, sizeof(buf), "%d-group", group->id);
+ egraph_vertice_rename(_egraph, group, buf);
+ _group_list = eina_list_append(_group_list, group);
+ for (i=0; i<10; i++) {
+ v = egraph_vertice_add(_egraph, NULL, NULL);
+ snprintf(buf, sizeof(buf), "%d-child(%d)", v->id, group->id);
+ egraph_vertice_rename(_egraph, v, buf);
+ egraph_group_vertice_attach(_egraph, group, v);
+ _vertice_list = eina_list_append(_vertice_list, v);
+ }
+}
+
+
+static void
+_cb_show_nodes(void *data, Evas_Object *obj, void *event_info)
+{
+ egraph_display_vertices_set(_egraph, elm_check_state_get(obj));
+}
+
+static void
+_cb_show_labels(void *data, Evas_Object *obj, void *event_info)
+{
+ if (!_egraph)
+ return;
+
+ egraph_display_names_set(_egraph, elm_check_state_get(obj));
+}
+
+static void
+_cb_show_edges(void *data, Evas_Object *obj, void *event_info)
+{
+ if (!_egraph)
+ return;
+
+ egraph_display_edges_set(_egraph, elm_check_state_get(obj));
+}
+
+static void
+_cb_use_animations(void *data, Evas_Object *obj, void *event_info)
+{
+ if (!_egraph)
+ return;
+
+ egraph_use_animations_set(_egraph, elm_check_state_get(obj));
+}
+
+static void
+_cb_do_improvements(void *data, Evas_Object *obj, void *event_info)
+{
+ if (!_egraph)
+ return;
+
+ egraph_do_improvements_set(_egraph, elm_check_state_get(obj));
+}
+
+static void
+_cb_use_theme_e(void *data, Evas_Object *obj, void *event_info)
+{
+ if (!_egraph)
+ return;
+
+ egraph_theme_edges_set(_egraph, elm_check_state_get(obj));
+}
+
+static void
+_cb_layout_changed(void *data, Evas_Object *obj, void *event_info)
+{
+ Elm_Object_Item *it;
+ char *selected;
+ int layout;
+
+ if (!_egraph)
+ return;
+
+ it = event_info;
+ selected = elm_object_item_text_get(it);
+ layout = EGRAPH_LAYOUT_DEFAULT;
+ if (!strcmp(selected, "Kamada K."))
+ layout = EGRAPH_LAYOUT_KAMADAKAWAI;
+ else if (!strcmp(selected, "GraphOpt"))
+ layout = EGRAPH_LAYOUT_GRAPHOPT;
+ else if (!strcmp(selected, "Fruchterman R."))
+ layout = EGRAPH_LAYOUT_FRUCHTERMANREINGOLD;
+
+ egraph_layout_set(_egraph, layout);
+}
+
+static void
+_cb_on_done(void *data, Evas_Object *obj, void *event_info)
+{
+ elm_exit();
+}
+
+EAPI_MAIN int
+elm_main(int argc, char **argv)
+{
+ Evas_Object *win, *bg, *egraph, *panes;
+ Evas_Object *bx, *tb, *tb_it, *ck, *sc, *seg_it, *lb;
+ Evas *evas;
+ int retval = -1;
+
+ win = elm_win_add(NULL, "panes", ELM_WIN_BASIC);
+ evas = evas_object_evas_get(win);
+ elm_win_title_set(win, "Egraph demo app");
+ evas_object_smart_callback_add(win, "delete,request", _cb_on_done, NULL);
+
+ bg = elm_bg_add(win);
+ elm_win_resize_object_add(win, bg);
+ evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ evas_object_color_set(bg, 0, 0, 0, 255);
+ evas_object_show(bg);
+
+ bx = elm_box_add(win);
+ elm_box_horizontal_set(bx, EINA_TRUE);
+ evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ elm_win_resize_object_add(win, bx);
+ evas_object_show(bx);
+
+ tb = elm_toolbar_add(win);
+ elm_toolbar_homogeneous_set(tb, EINA_FALSE);
+ elm_toolbar_horizontal_set(tb, EINA_FALSE);
+ elm_toolbar_shrink_mode_set(tb, ELM_TOOLBAR_SHRINK_EXPAND);
+ elm_toolbar_select_mode_set(tb, ELM_OBJECT_SELECT_MODE_ALWAYS);
+ elm_toolbar_transverse_expanded_set(tb, EINA_TRUE);
+ elm_object_style_set(tb, "item_centered");
+ evas_object_size_hint_weight_set(tb, 0.0, EVAS_HINT_EXPAND);
+ evas_object_size_hint_align_set(tb, EVAS_HINT_FILL, EVAS_HINT_FILL);
+ elm_box_pack_end(bx, tb);
+ evas_object_show(tb);
+ elm_toolbar_item_append(tb, "object-rotate-right", "Add 1 edge",
+ _cb_add_edge, NULL);
+ elm_toolbar_item_append(tb, "object-rotate-right", "Add 50 edges",
+ _cb_add_50edges, NULL);
+ elm_toolbar_item_append(tb, "object-rotate-right", "Add 500 edges",
+ _cb_add_500edges, NULL);
+ elm_toolbar_item_append(tb, "object-rotate-right", "Add 1 node alone",
+ _cb_add_node, NULL);
+ elm_toolbar_item_append(tb, "edit-delete", "Delete all",
+ _cb_del_edges, NULL);
+ elm_toolbar_item_append(tb, "object-rotate-right", "Send 100 blobs",
+ _cb_send_100blobs, NULL);
+ elm_toolbar_item_append(tb, "object-rotate-right", "Add a 10n group",
+ _cb_add_10n_group, NULL);
+ elm_toolbar_item_separator_set(elm_toolbar_item_append(tb, NULL, NULL, NULL, NULL), EINA_FALSE);
+ lb = elm_label_add(win);
+ elm_object_text_set(lb, "<b>Layout</b>");
+ evas_object_size_hint_weight_set(lb, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ evas_object_size_hint_align_set(lb, EVAS_HINT_FILL, EVAS_HINT_FILL);
+ tb_it = elm_toolbar_item_append(tb, NULL, NULL, NULL, NULL);
+ elm_object_item_part_content_set(tb_it, "object", lb);
+ sc = elm_segment_control_add(win);
+ //evas_object_size_hint_weight_set(sc, em->weight.w, em->weight.h);
+ //evas_object_size_hint_align_set(sc, em->align.x, em->align.y);
+ seg_it = elm_segment_control_item_add(sc, NULL, "GraphOpt");
+ elm_segment_control_item_selected_set(seg_it, EINA_TRUE);
+ seg_it = elm_segment_control_item_add(sc, NULL, "Kamada K.");
+ elm_segment_control_item_selected_set(seg_it, EINA_FALSE);
+ seg_it = elm_segment_control_item_add(sc, NULL, "Fruchterman R.");
+ elm_segment_control_item_selected_set(seg_it, EINA_FALSE);
+ evas_object_smart_callback_add(sc, "changed", _cb_layout_changed, NULL);
+ evas_object_show(sc);
+ tb_it = elm_toolbar_item_append(tb, NULL, NULL, NULL, NULL);
+ elm_object_item_part_content_set(tb_it, "object", sc);
+ //elm_toolbar_item_separator_set(elm_toolbar_item_append(tb, NULL, NULL, NULL, NULL), EINA_FALSE);
+ ck = elm_check_add(win);
+ elm_object_text_set(ck, "Show Node");
+ elm_check_state_set(ck, EINA_TRUE);
+ evas_object_show(ck);
+ evas_object_smart_callback_add(ck, "changed", _cb_show_nodes, NULL);
+ tb_it = elm_toolbar_item_append(tb, NULL, NULL, NULL, NULL);
+ elm_object_item_part_content_set(tb_it, "object", ck);
+ ck = elm_check_add(win);
+ elm_object_text_set(ck, "Show Label");
+ elm_check_state_set(ck, EINA_TRUE);
+ evas_object_show(ck);
+ evas_object_smart_callback_add(ck, "changed", _cb_show_labels, NULL);
+ tb_it = elm_toolbar_item_append(tb, NULL, NULL, NULL, NULL);
+ elm_object_item_part_content_set(tb_it, "object", ck);
+ ck = elm_check_add(win);
+ elm_object_text_set(ck, "Show Edges");
+ elm_check_state_set(ck, EINA_TRUE);
+ evas_object_show(ck);
+ evas_object_smart_callback_add(ck, "changed", _cb_show_edges, NULL);
+ tb_it = elm_toolbar_item_append(tb, NULL, NULL, NULL, NULL);
+ elm_object_item_part_content_set(tb_it, "object", ck);
+ ck = elm_check_add(win);
+ elm_object_text_set(ck, "Use animations");
+ elm_check_state_set(ck, EINA_TRUE);
+ evas_object_show(ck);
+ evas_object_smart_callback_add(ck, "changed", _cb_use_animations, NULL);
+ tb_it = elm_toolbar_item_append(tb, NULL, NULL, NULL, NULL);
+ elm_object_item_part_content_set(tb_it, "object", ck);
+ ck = elm_check_add(win);
+ elm_object_text_set(ck, "Do improvements");
+ elm_check_state_set(ck, EINA_TRUE);
+ evas_object_show(ck);
+ evas_object_smart_callback_add(ck, "changed", _cb_do_improvements, NULL);
+ tb_it = elm_toolbar_item_append(tb, NULL, NULL, NULL, NULL);
+ elm_object_item_part_content_set(tb_it, "object", ck);
+ ck = elm_check_add(win);
+ elm_object_text_set(ck, "Use theme for edges");
+ elm_check_state_set(ck, EINA_TRUE);
+ evas_object_show(ck);
+ evas_object_smart_callback_add(ck, "changed", _cb_use_theme_e, NULL);
+ tb_it = elm_toolbar_item_append(tb, NULL, NULL, NULL, NULL);
+ elm_object_item_part_content_set(tb_it, "object", ck);
+ //elm_toolbar_item_separator_set(elm_toolbar_item_append(tb, NULL, NULL, NULL, NULL), EINA_FALSE);
+ elm_toolbar_item_append(tb, "exit", "Quit",
+ _cb_on_done, NULL);
+
+ panes = elm_panes_add(win);
+ evas_object_size_hint_weight_set(panes, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ evas_object_size_hint_align_set(panes, EVAS_HINT_FILL, EVAS_HINT_FILL);
+ elm_panes_content_right_size_set(panes, 0.0);
+ elm_box_pack_end(bx, panes);
+ evas_object_show(panes);
+
+ egraph = egraph_new(evas, 1);
+ if (!egraph)
+ goto quit;
+ evas_object_size_hint_weight_set(egraph, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ evas_object_size_hint_align_set(egraph, EVAS_HINT_FILL, EVAS_HINT_FILL);
+ evas_object_show(egraph);
+ elm_object_part_content_set(panes, "left", egraph);
+
+ lb = elm_label_add(win);
+ elm_object_style_set(lb, "marker");
+ evas_object_color_set(lb, 255, 255, 255, 255);
+ elm_object_text_set(lb,
+ "Demo application for Egraph<br/>"
+ "<br/>"
+ "Enjoy !<br/>");
+ evas_object_show(lb);
+ elm_object_part_content_set(panes, "right", lb);
+
+ evas_object_resize(win, 150, 150); // XXX workaround elm sizing issue
+ evas_object_show(win);
+ evas_object_resize(win, 950, 715);
+ evas_object_show(win);
+ _egraph = egraph;
+ _mainwin = win;
+
+ _cb_add_50edges(NULL, NULL, NULL);
+
+ elm_run();
+ retval = 0;
+
+quit:
+ elm_shutdown();
+ return retval;
+}
+ELM_MAIN()
diff --git a/egraph/examples/simplegraph.c b/egraph/examples/simplegraph.c
new file mode 100644
index 0000000..43e6d59
--- /dev/null
+++ b/egraph/examples/simplegraph.c
@@ -0,0 +1,59 @@
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <stdio.h>
+#include <errno.h>
+
+#include "../Egraph.h"
+
+Evas_Object *_egraph_obj = NULL;
+
+static void
+_on_destroy(Ecore_Evas *ee)
+{
+ ecore_main_loop_quit();
+}
+
+static void
+_canvas_resize_cb(Ecore_Evas *ee)
+{
+ int w, h;
+
+ printf("_canvas_resize_cb\n");
+ ecore_evas_geometry_get(ee, NULL, NULL, &w, &h);
+ evas_object_resize(_egraph_obj, w, h);
+}
+
+int
+main(void)
+{
+ Ecore_Evas *ee;
+ Evas *evas;
+ Egraph_Vertice *a, *b;
+ Egraph_Edge *e;
+
+ if (!ecore_evas_init())
+ return EXIT_FAILURE;
+ ee = ecore_evas_new(NULL, 10, 10, 100, 100, NULL);
+ if (!ee)
+ return -1;
+ ecore_evas_callback_destroy_set(ee, _on_destroy);
+ ecore_evas_callback_resize_set(ee, _canvas_resize_cb);
+ ecore_evas_show(ee);
+ evas = ecore_evas_get(ee);
+
+ _egraph_obj = egraph_new(evas, 1);
+ evas_object_resize(_egraph_obj, 100, 100);
+ evas_object_show(_egraph_obj);
+
+ a = egraph_vertice_add(_egraph_obj, "a", NULL);
+ b = egraph_vertice_add(_egraph_obj, "b", NULL);
+ e = egraph_edge_add(_egraph_obj, a, b, NULL);
+
+ ecore_main_loop_begin();
+
+ evas_object_del(_egraph_obj);
+ ecore_evas_free(ee);
+ ecore_evas_shutdown();
+
+ return (!_egraph_obj);
+}
diff --git a/egraph/retest.sh b/egraph/retest.sh
new file mode 100755
index 0000000..c778fa1
--- /dev/null
+++ b/egraph/retest.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+make clean && \
+ make && \
+ sudo make install && \
+ make -C tests/ clean && \
+ make -C tests/ run && \
+ make -C examples clean && \
+ make -C examples
diff --git a/egraph/tests/Makefile b/egraph/tests/Makefile
new file mode 100644
index 0000000..8b70170
--- /dev/null
+++ b/egraph/tests/Makefile
@@ -0,0 +1,32 @@
+CFLAGS += -Wall -g
+CFLAGS += $(shell pkg-config --libs --cflags igraph)
+CFLAGS += $(shell pkg-config --libs --cflags efx)
+CFLAGS += -L../ -legraph -lecore_evas
+
+SOURCES = $(shell echo *.c)
+OBJECTS = $(SOURCES:.c=.o)
+TARGETS = $(SOURCES:.c=)
+
+all: $(TARGETS)
+
+run: $(TARGETS)
+ @count=0 ;\
+ errors=0 ;\
+ for test in $(TARGETS); do \
+ echo =============================================================================== ;\
+ echo $$test ;\
+ LD_LIBRARY_PATH=$$LD_LIBRARY_PATH:../ ./$$test ;\
+ if [ $$? -eq 0 ]; then \
+ echo OK ;\
+ else \
+ echo FAILED ;\
+ errors=$$(($$errors + 1)) ;\
+ fi ;\
+ count=$$(($$count + 1)) ;\
+ done ;\
+ echo =============================================================================== ;\
+ echo "$$count tests executed, $$errors errors" ;\
+ exit $$errors
+
+clean:
+ rm -f $(TARGETS) $(OBJECTS)
diff --git a/egraph/tests/README.txt b/egraph/tests/README.txt
new file mode 100644
index 0000000..9a25111
--- /dev/null
+++ b/egraph/tests/README.txt
@@ -0,0 +1,4 @@
+egraph library unit tests
+
+do "make run" to execute them
+returns the number of tests that failed
diff --git a/egraph/tests/creategraph.c b/egraph/tests/creategraph.c
new file mode 100644
index 0000000..d27e3d5
--- /dev/null
+++ b/egraph/tests/creategraph.c
@@ -0,0 +1,37 @@
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <stdio.h>
+#include <errno.h>
+
+#include "../Egraph.h"
+
+int
+main(void)
+{
+ Ecore_Evas *ee;
+ Evas *evas;
+ Evas_Object *obj = NULL;
+ Egraph_Vertice *a, *b;
+ Egraph_Edge *e;
+
+ if (!ecore_evas_init())
+ return EXIT_FAILURE;
+ ee = ecore_evas_new(NULL, 10, 10, 100, 100, NULL);
+ if (!ee)
+ return -1;
+ ecore_evas_show(ee);
+ evas = ecore_evas_get(ee);
+
+ obj = egraph_new(evas, 1);
+
+ a = egraph_vertice_add(obj, "a", NULL);
+ b = egraph_vertice_add(obj, NULL, NULL);
+ e = egraph_edge_add(obj, a, b, NULL);
+ egraph_vertice_del(obj, a);
+
+ evas_object_del(obj);
+ ecore_evas_free(ee);
+ ecore_evas_shutdown();
+
+ return (!obj);
+}
diff --git a/gg_elife/.gitignore b/gg_elife/.gitignore
new file mode 100644
index 0000000..a8e7ece
--- /dev/null
+++ b/gg_elife/.gitignore
@@ -0,0 +1,68 @@
+/INSTALL
+/Makefile
+/Makefile.in
+/aclocal.m4
+/autom4te.cache/
+/config.guess
+/config.h
+/config.h.in
+/config.log
+/config.status
+/config.sub
+/configure
+/depcomp
+/install-sh
+/libtool
+/ltmain.sh
+/m4/libtool.m4
+/m4/ltoptions.m4
+/m4/ltsugar.m4
+/m4/ltversion.m4
+/m4/lt~obsolete.m4
+/missing
+/src/.deps/
+/src/.libs/
+/src/Makefile
+/src/Makefile.in
+/src/elife
+/src/*.lo
+/src/*.o
+/src/module.la
+/stamp-h1
+/compile
+/data/Makefile
+/data/Makefile.in
+/data/elife.edj
+/intl
+/ABOUT-NLS
+/config.rpath
+/m4/codeset.m4
+/m4/gettext.m4
+/m4/glibc2.m4
+/m4/glibc21.m4
+/m4/iconv.m4
+/m4/intdiv0.m4
+/m4/intl.m4
+/m4/intldir.m4
+/m4/intlmacosx.m4
+/m4/intmax.m4
+/m4/inttypes-pri.m4
+/m4/inttypes_h.m4
+/m4/lcmessage.m4
+/m4/lib-ld.m4
+/m4/lib-link.m4
+/m4/lib-prefix.m4
+/m4/lock.m4
+/m4/longlong.m4
+/m4/nls.m4
+/m4/po.m4
+/m4/printf-posix.m4
+/m4/progtest.m4
+/m4/size_max.m4
+/m4/stdint_h.m4
+/m4/uintmax_t.m4
+/m4/visibility.m4
+/m4/wchar_t.m4
+/m4/wint_t.m4
+/m4/xsize.m4
+/po/
diff --git a/gg_elife/AUTHORS b/gg_elife/AUTHORS
new file mode 100644
index 0000000..4e42cdc
--- /dev/null
+++ b/gg_elife/AUTHORS
@@ -0,0 +1 @@
+Laurent Ghigonis <laurent@p1sec.com>
diff --git a/gg_elife/COPYING b/gg_elife/COPYING
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/gg_elife/COPYING
@@ -0,0 +1 @@
+
diff --git a/gg_elife/ChangeLog b/gg_elife/ChangeLog
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/gg_elife/ChangeLog
@@ -0,0 +1 @@
+
diff --git a/gg_elife/Makefile.am b/gg_elife/Makefile.am
new file mode 100644
index 0000000..215bf9f
--- /dev/null
+++ b/gg_elife/Makefile.am
@@ -0,0 +1,6 @@
+AUTOMAKE_OPTIONS = 1.4 foreign
+MAINTAINERCLEANFILES = Makefile.in
+
+SUBDIRS = src data
+
+ACLOCAL_AMFLAGS = -I m4
diff --git a/gg_elife/NEWS b/gg_elife/NEWS
new file mode 100644
index 0000000..5c5261f
--- /dev/null
+++ b/gg_elife/NEWS
@@ -0,0 +1,6 @@
+bal$ git log --reverse --tags --simplify-by-decoration --pretty="format:%ai %d"
+2012-10-14 16:35:56 +0200
+2012-11-04 18:59:46 +0100 (v1.0)
+2012-11-04 19:14:50 +0100 (v1.1)
+2012-11-05 04:09:01 +0100 (origin/master, origin/manual_draw, manual_draw)
+2012-11-05 04:12:52 +0100 (HEAD, v1.2, master)
diff --git a/gg_elife/README b/gg_elife/README
new file mode 100644
index 0000000..1906131
--- /dev/null
+++ b/gg_elife/README
@@ -0,0 +1,79 @@
+elife - Game of life / Living graphic
+v1.2
+
+Packaging and general structure from EEnvader.fractal by Boris Faure <billiob@gmail.com>
+Many thanks to you Boris !
+
+Dependencies
+============
+
+Enlightenment 0.16.999 (aka e17)
+
+Install
+=======
+
+./autogen.sh
+make
+sudo make install
+
+"elife" will then appear in the "System" category of e17 wallpapers configuration panel.
+A binary called "elife" is also created and installed to run elife in standalone.
+
+Glouglou support
+================
+
+To enable glouglou support, pass --enable-glouglou to automake scripts :
+./autogen.sh --enable-glouglou
+OR
+./configure --enable-glouglou
+
+You will need libglouglou and glougloud
+
+Elife slows down my e17 !
+=========================
+
+elife is running in the same process as e17 therefore it can slow down the
+whole window manager, depending on your machine CPU.
+
+To improve this, you can:
+
+* Use OpenGL rendering in e17 by using the Composite module, and set the engine
+to OpenGL in Composite > Rendering pannel
+
+* Reduce the size of the elife grid by modifying the source code, in
+src/elife_evas_smart.c at the definitions of NCELL_X and NCELL_Y
+
+TODO
+====
+
+* make install without sudo rights
+* make a gadget
+
+Code organisation
+=================
+
+The core code is in src/elife_evas_smart.c
+All the other files are here to build standalone binary and edje file.
+
+src/elife_evas_smart.c
+ At each life cycle, grid_evolution() gets called
+
+Ideas
+=====
+
+freenode #e
+20:08 < loran> for the moment each cell is an evas_object. having the whole grid as one evas object and filling polygons manually (i'll take a look at seed
+ algorithm) might be faster, not sure
+20:10 < loran> but if i can have opengl rendering for the background with composite module for example, then i will improve other parts of elife, like having cell
+ created on external events like new processes, packets blocked by firewall, ...
+20:10 < loran> :p
+20:15 < drohan> it sounds interesting, but for future reference, you need a way to gain trust from the users, a background that uses cpu is not trusted, if you
+ change it as a widget or something else or try to comment all the code so the users can see what you are doing with it
+20:16 < loran> haha good point :p
+20:17 < drohan> and even then you will have a little problem with trust, change everything so you don't have to install it system wide, just local .e dir
+20:17 < loran> i think you can run make install without system rights
+20:17 < loran> without sudo
+
+Optimisation ideas:
+* one evas_object_rectangle, manualy write memory inside it (DONE)
+
diff --git a/gg_elife/autogen.sh b/gg_elife/autogen.sh
new file mode 100755
index 0000000..ae01364
--- /dev/null
+++ b/gg_elife/autogen.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+rm -rf autom4te.cache
+rm -f aclocal.m4 ltmain.sh
+
+touch README
+
+echo "Running autopoint..." ; autopoint -f || :
+echo "Running aclocal..." ; aclocal -I m4 $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/gg_elife/configure.ac b/gg_elife/configure.ac
new file mode 100644
index 0000000..60d1703
--- /dev/null
+++ b/gg_elife/configure.ac
@@ -0,0 +1,64 @@
+dnl Process this file with autoconf to produce a configure script.
+
+# get rid of that stupid cache mechanism
+rm -f config.cache
+
+AC_INIT(elife, 0.1, laurent@p1sec.com)
+AC_PREREQ(2.52)
+AC_CONFIG_SRCDIR(configure.ac)
+AC_CANONICAL_BUILD
+AC_CANONICAL_HOST
+AC_ISC_POSIX
+
+AM_INIT_AUTOMAKE(1.6)
+AM_CONFIG_HEADER(config.h)
+m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
+
+AC_PROG_CC_C99
+AC_HEADER_STDC
+AC_C_CONST
+AM_PROG_CC_C_O
+
+define([AC_LIBTOOL_LANG_CXX_CONFIG], [:])dnl
+define([AC_LIBTOOL_LANG_F77_CONFIG], [:])dnl
+AC_PROG_LIBTOOL
+
+m4_ifdef([AM_GNU_GETTEXT_VERSION], [
+AM_GNU_GETTEXT_VERSION([0.17])
+])
+
+PKG_PROG_PKG_CONFIG
+PKG_CHECK_MODULES([ELIFE], [edje ecore-evas ecore evas eina])
+datadir_edj=$($PKG_CONFIG --variable=prefix enlightenment)/share/enlightenment/data/backgrounds
+
+EFL_WITH_BIN([edje], [edje-cc], [edje_cc])
+vmaj=$($PKG_CONFIG --variable=vmaj edje)
+MODULE_ARCH="$host_os-$host_cpu-$vmaj.0.0"
+AC_SUBST(MODULE_ARCH)
+AC_DEFINE_UNQUOTED(MODULE_ARCH, "$MODULE_ARCH", "Module architecture")
+
+datadir=$(pkg-config --variable=modules edje)/${PACKAGE}
+AC_ARG_ENABLE(homedir-install,
+ AS_HELP_STRING([--enable-homedir-install], [Install module in homedir]),
+ [
+ datadir="${HOME}/.edje/modules/${PACKAGE}";
+ datadir_edj="${HOME}/.e/e/backgrounds"
+ ]
+)
+AC_SUBST(datadir_edj)
+
+AC_ARG_ENABLE(glouglou,
+[ --enable-glouglou Enable glouglou support],
+[case "${enableval}" in
+ yes) glouglou=true ;;
+ no) glouglou=false ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-glouglou) ;;
+esac],[glouglou=false])
+AM_CONDITIONAL(HAVE_GLOUGLOU, test x$glouglou = xtrue)
+
+AC_OUTPUT([
+Makefile
+data/Makefile
+src/Makefile
+], [
+])
diff --git a/gg_elife/data/Makefile.am b/gg_elife/data/Makefile.am
new file mode 100644
index 0000000..8664660
--- /dev/null
+++ b/gg_elife/data/Makefile.am
@@ -0,0 +1,18 @@
+AUTOMAKE_OPTIONS = 1.4 foreign
+MAINTAINERCLEANFILES = Makefile.in
+
+EDJE_FLAGS = -v
+
+filesdir = @datadir_edj@
+files_DATA = elife.edj
+
+EXTRA_DIST = elife.edc
+
+elife.edj: elife.edc
+ $(edje_cc) $(EDJE_FLAGS) $< $@
+
+clean-local:
+ rm -rf elife.edj *~
+
+uninstall:
+ rm -rf $(DESTDIR)@datadir_edj@/elife.edj
diff --git a/gg_elife/data/elife.edc b/gg_elife/data/elife.edc
new file mode 100644
index 0000000..69df75c
--- /dev/null
+++ b/gg_elife/data/elife.edc
@@ -0,0 +1,48 @@
+externals {
+ external: "elife";
+}
+
+collections {
+ group {
+ name: "e/desktop/background";
+
+ script {
+ public clock_cb(unused) {
+ emit("elife:refresh", "☃");
+ timer(0.5, "clock_cb", 1);
+ }
+ }
+
+ parts {
+ part {
+ name: "bg";
+ type: RECT;
+ description {
+ state: "default" 0.0;
+ color: 0 0 0 255;
+ }
+ }
+ part {
+ name: "elife";
+ type: EXTERNAL;
+ source: "elife";
+
+ description {
+ state: "default" 0.0;
+ }
+ }
+ }
+
+ // Get everything started at load
+ programs {
+ program {
+ name: "init";
+ signal: "load";
+ source: "";
+ script {
+ clock_cb(0);
+ }
+ }
+ }
+ }
+}
diff --git a/gg_elife/in_separate_git.txt b/gg_elife/in_separate_git.txt
deleted file mode 100644
index 6bdc618..0000000
--- a/gg_elife/in_separate_git.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-git clone git@gouloum.fr:elife
-
-cd elife
-./configure --enable-glouglou
-make
-sudo make install
diff --git a/gg_elife/m4/efl_binary.m4 b/gg_elife/m4/efl_binary.m4
new file mode 100644
index 0000000..c774688
--- /dev/null
+++ b/gg_elife/m4/efl_binary.m4
@@ -0,0 +1,71 @@
+dnl Copyright (C) 2010 Vincent Torri <vtorri at univ-evry dot fr>
+dnl That code is public domain and can be freely used or copied.
+
+dnl Macro that check if a binary is built or not
+
+dnl Usage: EFL_ENABLE_BIN(binary)
+dnl Call AC_SUBST(BINARY_PRG) (BINARY is the uppercase of binary, - being transformed into _)
+dnl Define have_binary (- is transformed into _)
+dnl Define conditional BUILD_BINARY (BINARY is the uppercase of binary, - being transformed into _)
+
+AC_DEFUN([EFL_ENABLE_BIN],
+[
+
+m4_pushdef([UP], m4_translit([[$1]], [-a-z], [_A-Z]))dnl
+m4_pushdef([DOWN], m4_translit([[$1]], [-A-Z], [_a-z]))dnl
+
+have_[]m4_defn([DOWN])="yes"
+
+dnl configure option
+
+AC_ARG_ENABLE([$1],
+ [AC_HELP_STRING([--disable-$1], [disable building of ]DOWN)],
+ [
+ if test "x${enableval}" = "xyes" ; then
+ have_[]m4_defn([DOWN])="yes"
+ else
+ have_[]m4_defn([DOWN])="no"
+ fi
+ ])
+
+AC_MSG_CHECKING([whether to build ]DOWN[ binary])
+AC_MSG_RESULT([$have_[]m4_defn([DOWN])])
+
+if test "x$have_[]m4_defn([DOWN])" = "xyes"; then
+ UP[]_PRG=DOWN[${EXEEXT}]
+fi
+
+AC_SUBST(UP[]_PRG)
+
+AM_CONDITIONAL(BUILD_[]UP, test "x$have_[]m4_defn([DOWN])" = "xyes")
+
+AS_IF([test "x$have_[]m4_defn([DOWN])" = "xyes"], [$2], [$3])
+
+])
+
+
+dnl Macro that check if a binary is built or not
+
+dnl Usage: EFL_WITH_BIN(package, binary, default_value)
+dnl Call AC_SUBST(_binary) (_binary is the lowercase of binary, - being transformed into _ by default, or the value set by the user)
+
+AC_DEFUN([EFL_WITH_BIN],
+[
+
+m4_pushdef([DOWN], m4_translit([[$2]], [-A-Z], [_a-z]))dnl
+
+dnl configure option
+
+AC_ARG_WITH([$2],
+ [AC_HELP_STRING([--with-$2=PATH], [specify a specific path to ]DOWN[ @<:@default=$3@:>@])],
+ [_efl_with_binary=${withval}],
+ [_efl_with_binary=$(pkg-config --variable=prefix $1)/bin/$3])
+
+DOWN=${_efl_with_binary}
+AC_MSG_NOTICE(DOWN[ set to ${_efl_with_binary}])
+
+with_binary_[]m4_defn([DOWN])=${_efl_with_binary}
+
+AC_SUBST(DOWN)
+
+])
diff --git a/gg_elife/src/Makefile.am b/gg_elife/src/Makefile.am
new file mode 100644
index 0000000..f8135a0
--- /dev/null
+++ b/gg_elife/src/Makefile.am
@@ -0,0 +1,37 @@
+MAINTAINERCLEANFILES = Makefile.in
+INCLUDES = -I. \
+ -I$(top_srcdir) \
+ -I$(includedir) \
+ @ELIFE_CFLAGS@
+
+
+pkgdir = $(datadir)/$(MODULE_ARCH)
+pkg_LTLIBRARIES = module.la
+module_la_SOURCES = \
+ elife_evas_smart.c \
+ elife_edje_external.c
+
+module_la_LIBADD = @ELIFE_LIBS@
+module_la_DEPENDENCIES = $(top_builddir)/config.h
+
+bin_PROGRAMS = elife
+elife_SOURCES = \
+ elife_evas_smart.c \
+ elife.c
+elife_CPPFLAGS = \
+ @ELIFE_CFLAGS@
+
+if HAVE_GLOUGLOU
+module_la_LDFLAGS = -module -avoid-version -lglouglou -levent
+module_la_CFLAGS = -DHAVE_GLOUGLOU
+elife_LDADD = \
+ @ELIFE_LIBS@ -lglouglou -levent
+elife_CFLAGS = -DHAVE_GLOUGLOU
+else
+module_la_LDFLAGS = -module -avoid-version
+elife_LDADD = \
+ @ELIFE_LIBS@
+endif
+
+clean-local:
+ rm -rf *~
diff --git a/gg_elife/src/elife.c b/gg_elife/src/elife.c
new file mode 100644
index 0000000..8b97cb8
--- /dev/null
+++ b/gg_elife/src/elife.c
@@ -0,0 +1,106 @@
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <Evas.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+
+#include "elife_evas_smart.h"
+
+#define BG 0xff002b36
+#define FG 0xff839496
+
+#define MIN(a,b) (((a)<(b))?(a):(b))
+
+static struct {
+ Ecore_Evas *ee;
+ Evas *evas;
+ Evas_Coord w, h;
+ Evas_Object *bg;
+ Evas_Object *elife;
+} elife_g;
+#define _G elife_g
+
+static void
+resize_cb(Ecore_Evas *ee)
+{
+ int w, h;
+
+ ecore_evas_geometry_get(ee, NULL, NULL, &w, &h);
+ evas_object_resize(_G.bg, w, h);
+ evas_object_resize(_G.elife, w, h);
+}
+
+static Eina_Bool
+timer_cb(void *data)
+{
+ Evas_Object *o = (Evas_Object *)data;
+
+ evas_object_smart_callback_call(o, "refresh", NULL);
+
+ return EINA_TRUE;
+}
+
+int
+main(void)
+{
+ unsigned int seedval;
+ int fd;
+
+ if (!ecore_evas_init())
+ return -1;
+
+ _G.w = 600;
+ _G.h = 350;
+
+
+ /*open file */
+ if ((fd = open("/dev/urandom", O_RDONLY)) < 0) {
+ perror(NULL);
+ exit(1);
+ }
+ if (read(fd, &seedval, sizeof(seedval)) != sizeof(seedval)) {
+ perror(NULL);
+ close(fd);
+ exit(1);
+ }
+ close(fd);
+ srand(seedval);
+
+ _G.ee = ecore_evas_software_x11_new(
+ NULL, /* const char * disp_name */
+ 0, /* Ecore_X_Window parent */
+ 0, 0, _G.w, _G.h);
+
+ ecore_evas_title_set(_G.ee, "elife");
+ ecore_evas_borderless_set(_G.ee, 0);
+ ecore_evas_show(_G.ee);
+ _G.evas = ecore_evas_get(_G.ee);
+
+ _G.bg = evas_object_rectangle_add(_G.evas);
+ evas_object_color_set(_G.bg,
+ (BG >> 16) & 0xff,
+ (BG >> 8) & 0xff,
+ BG & 0xff,
+ BG >> 24);
+ evas_object_move(_G.bg, 0, 0);
+ evas_object_resize(_G.bg, _G.w, _G.h);
+ evas_object_show(_G.bg);
+
+ _G.elife = elife_smart_new(_G.evas);
+ evas_object_resize(_G.elife, _G.w, _G.h);
+ evas_object_show(_G.elife);
+
+ ecore_timer_add(0.1, timer_cb, _G.elife);
+
+ ecore_evas_callback_resize_set(_G.ee, &resize_cb);
+
+ ecore_main_loop_begin();
+
+ ecore_evas_shutdown();
+ ecore_shutdown();
+
+ return 0;
+}
diff --git a/gg_elife/src/elife_edje_external.c b/gg_elife/src/elife_edje_external.c
new file mode 100644
index 0000000..14035d2
--- /dev/null
+++ b/gg_elife/src/elife_edje_external.c
@@ -0,0 +1,192 @@
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <Evas.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Edje.h>
+
+#include "elife_evas_smart.h"
+
+/* Prototypes -{{{-*/
+
+static Evas_Object *
+elife_ext_add(void *data, Evas *evas, Evas_Object *parent,
+ const Eina_List *params, const char *part_name);
+static void
+elife_ext_state_set(void *data, Evas_Object *obj,
+ const void *from_params,
+ const void *to_params, float pos);
+static void
+elife_ext_signal_emit(void *data, Evas_Object *obj,
+ const char *emission, const char *source);
+static Eina_Bool
+elife_ext_param_set(void *data, Evas_Object *obj,
+ const Edje_External_Param *param);
+static Eina_Bool
+elife_ext_param_get(void *data, const Evas_Object *obj,
+ Edje_External_Param *param);
+static Evas_Object *
+elife_ext_content_get(void *data, const Evas_Object *obj,
+ const char *content);
+static void*
+elife_ext_params_parse(void *data, Evas_Object *obj,
+ const Eina_List *params);
+static void
+elife_ext_params_free(void *params);
+static const char*
+elife_ext_label_get(void *data);
+static const char*
+elife_ext_description_get(void *data);
+static Evas_Object *
+elife_ext_icon_add(void *data, Evas *e);
+static Evas_Object *
+elife_ext_preview_add(void *data, Evas *e);
+static const char*
+elife_ext_translate(void *data, const char *orig);
+
+/* }}} */
+/* Globals -{{{-*/
+
+static struct {
+ Edje_External_Type ext_type;
+} elife_g = {
+ .ext_type = {
+ .abi_version = EDJE_EXTERNAL_TYPE_ABI_VERSION,
+ .module = "elife",
+ .module_name = "elife",
+ .add = elife_ext_add,
+ .state_set = elife_ext_state_set,
+ .signal_emit = elife_ext_signal_emit,
+ .param_set = elife_ext_param_set,
+ .param_get = elife_ext_param_get,
+ .content_get = elife_ext_content_get,
+ .params_parse = elife_ext_params_parse,
+ .params_free = elife_ext_params_free,
+ .label_get = elife_ext_label_get,
+ .description_get = elife_ext_description_get,
+ .icon_add = elife_ext_icon_add,
+ .preview_add = elife_ext_preview_add,
+ .translate = elife_ext_translate,
+ },
+};
+#define _G elife_g
+
+/* }}} */
+/* Edje External -{{{-*/
+
+static Evas_Object *
+elife_ext_add(void *data, Evas *evas, Evas_Object *parent,
+ const Eina_List *params, const char *part_name)
+{
+ return elife_smart_new(evas);
+}
+
+static void
+elife_ext_state_set(void *data, Evas_Object *obj,
+ const void *from_params,
+ const void *to_params, float pos)
+{
+}
+
+static void
+elife_ext_signal_emit(void *data, Evas_Object *obj,
+ const char *emission, const char *source)
+{
+ evas_object_smart_callback_call(obj, emission, NULL);
+}
+
+static Eina_Bool
+elife_ext_param_set(void *data, Evas_Object *obj,
+ const Edje_External_Param *param)
+{
+ return EINA_TRUE;
+}
+
+static Eina_Bool
+elife_ext_param_get(void *data, const Evas_Object *obj,
+ Edje_External_Param *param)
+{
+ return EINA_TRUE;
+}
+
+static Evas_Object *
+elife_ext_content_get(void *data, const Evas_Object *obj,
+ const char *content)
+{
+ return NULL;
+}
+
+static void*
+elife_ext_params_parse(void *data, Evas_Object *obj,
+ const Eina_List *params)
+{
+ return NULL;
+}
+
+static void
+elife_ext_params_free(void *params)
+{
+}
+
+static const char*
+elife_ext_label_get(void *data)
+{
+ return NULL;
+}
+
+static const char*
+elife_ext_description_get(void *data)
+{
+ return NULL;
+}
+
+static Evas_Object *
+elife_ext_icon_add(void *data, Evas *e)
+{
+ return NULL;
+}
+
+static Evas_Object *
+elife_ext_preview_add(void *data, Evas *e)
+{
+ return NULL;
+}
+
+static const char*
+elife_ext_translate(void *data, const char *orig)
+{
+ return NULL;
+}
+/* }}} */
+/* Init/Shutdown -{{{-*/
+
+Eina_Bool
+elife_init(void)
+{
+ unsigned int seedval = time(NULL);
+ int fd;
+
+ if ((fd = open("/dev/random", O_RDONLY)) >= 0) {
+ read(fd, &seedval, sizeof(seedval));
+ close(fd);
+ }
+ srand(seedval);
+
+ edje_external_type_register("elife", &_G.ext_type);
+
+ return EINA_TRUE;
+}
+
+void
+elife_shutdown(void)
+{
+ edje_external_type_unregister("elife");
+}
+
+EINA_MODULE_INIT(elife_init);
+EINA_MODULE_SHUTDOWN(elife_shutdown);
+
+/* }}} */
diff --git a/gg_elife/src/elife_evas_smart.c b/gg_elife/src/elife_evas_smart.c
new file mode 100644
index 0000000..acbd9a2
--- /dev/null
+++ b/gg_elife/src/elife_evas_smart.c
@@ -0,0 +1,558 @@
+/*
+ * elife - Game of life / Living graphic
+ */
+
+/*
+ * Copyright (c) 2012 Laurent Ghigonis <laurent@p1sec.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <stdlib.h>
+#include <err.h>
+
+#include "elife_evas_smart.h"
+
+#ifdef HAVE_GLOUGLOU
+#include <libglouglou.h>
+#endif
+
+#define NCELL_X 100
+#define NCELL_Y 100
+#define INJECT_PROBA 40
+#define INITCELL_PROBA 7
+#define CONWAY_GROW_DIE 600
+#define DEBUG 0
+
+#define MIN(a,b) (((a)<(b))?(a):(b))
+#define CELL_GET(grid, x, y) &(grid->cells[(y*grid->w) + x])
+
+typedef struct lifepattern_s {
+ const int w;
+ const int h;
+ const char *pat;
+} lifepattern_s;
+
+enum lifepattern_t {
+ ELIFE_PAT_BEEHIVE = 0,
+ ELIFE_PAT_BOAT = 1,
+ ELIFE_PAT_SHIP = 2,
+ ELIFE_PAT_LOAF = 3,
+ ELIFE_PAT_QUEENBEE = 4,
+ ELIFE_PAT_GLIDER = 5,
+ ELIFE_PAT_LWSS = 6,
+};
+#define PATTERN_COUNT 7
+
+lifepattern_s lifepatterns[] = {
+ [ELIFE_PAT_BEEHIVE] = {3, 4, "010101101010"},
+ [ELIFE_PAT_BOAT] = {3, 3, "010101011"},
+ [ELIFE_PAT_SHIP] = {3, 3, "110101011"},
+ [ELIFE_PAT_LOAF] = {4, 4, "0110100101010010"},
+ [ELIFE_PAT_QUEENBEE] = {4, 7, "1100001000010001000100101100"},
+ [ELIFE_PAT_GLIDER] = {3, 3, "010011101"},
+ [ELIFE_PAT_LWSS] = {5, 4, "10010000011000101111"},
+};
+
+enum lifemode {
+ ELIFE_MODE_CONWAY,
+ ELIFE_MODE_CONWAY_GROW,
+ ELIFE_MODE_LORAN_CIVILISATION,
+};
+
+struct cell {
+ int age, newage;
+ u_int32_t forced_color;
+ int x, y;
+ int r, g, b;
+};
+
+struct grid {
+ Evas_Object *container;
+ struct cell *cells;
+ Evas_Object *image;
+ int *mem;
+ int w, h;
+ int pix_w, pix_h;
+ int cell_pix_w, cell_pix_h;
+ int age;
+ enum lifemode mode;
+#ifdef HAVE_GLOUGLOU
+ struct gg_client *ggcli;
+ struct event_base *ev_base;
+#endif
+};
+
+static struct grid *grid_new(Evas_Object *container,
+ int w, int h, enum lifemode mode);
+static void grid_del(struct grid *grid);
+static int grid_evolution(struct grid *grid);
+static void grid_inject_pattern(struct grid *grid, u_int32_t color);
+static int grid_redraw(struct grid *grid, int w, int h);
+static int cell_neighbours_count(struct cell *cell, struct grid *grid);
+static void cell_redraw(struct cell *c, struct grid *g);
+static void grid_mouse_down(void *data, Evas *evas, Evas_Object *child,
+ void *event_info);
+
+Evas_Object *elife_smart_new(Evas *e);
+static void elife_on_refresh(void *data, Evas_Object *o,
+ void *event_info);
+static Evas_Object *elife_object_new(Evas *evas);
+static Evas_Smart *_elife_object_smart_get(void);
+static void _elife_object_del(Evas_Object *o);
+static void _elife_object_move(Evas_Object *o,
+ Evas_Coord x, Evas_Coord y);
+static void _elife_object_resize(Evas_Object *o,
+ Evas_Coord w, Evas_Coord h);
+/* Not implemented
+static void _elife_object_show(Evas_Object *o);
+static void _elife_object_hide(Evas_Object *o);
+static void _elife_object_color_set(Evas_Object *o, int r, int g, int b, int a);
+static void _elife_object_clip_set(Evas_Object *o, Evas_Object *clip);
+static void _elife_object_clip_unset(Evas_Object *o);
+*/
+void *xmalloc(size_t size);
+
+static struct {
+ Evas_Smart_Class klass;
+} elife_evas_smart_g = {
+ .klass = {
+ .name = "elife_object",
+ .version = EVAS_SMART_CLASS_VERSION,
+ .add = NULL,
+ .del = _elife_object_del,
+ .move = _elife_object_move,
+ .resize = _elife_object_resize,
+ .show = NULL,
+ .hide = NULL,
+ .color_set = NULL,
+ .clip_set = NULL,
+ .clip_unset = NULL,
+ .calculate = NULL,
+ .member_add = NULL,
+ .member_del = NULL,
+ .parent = NULL,
+ .callbacks = NULL,
+ .interfaces = NULL,
+ .data = NULL,
+ },
+#define _G elife_evas_smart_g
+};
+
+#ifdef HAVE_GLOUGLOU
+int
+gg_packet(struct gg_client *cli, struct gg_packet *pkt)
+{
+ struct grid *grid;
+ u_int32_t color;
+
+ grid = cli->usrdata;
+ switch(pkt->type) {
+ case PACKET_FORK: color=0xff0000; break;
+ case PACKET_EXEC: color=0x00ff00; break;
+ case PACKET_EXIT: color=0x0000ff; break;
+ default: return 0;
+ }
+ grid_inject_pattern(grid, color);
+
+ return 0;
+}
+#endif
+
+static struct grid *
+grid_new(Evas_Object *container, int w, int h, enum lifemode mode)
+{
+ struct grid *g;
+ struct cell *cell;
+ Evas_Object *o;
+ int i, j;
+
+ g = xmalloc(sizeof(struct grid));
+ g->container = container;
+ o = evas_object_image_filled_add(evas_object_evas_get(container));
+ if (!o)
+ err(1, "Cannot create image for grid");
+ evas_object_image_alpha_set(o, EINA_FALSE);
+ evas_object_image_smooth_scale_set(o, EINA_FALSE);
+ evas_object_data_set(o, "grid", g);
+ evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_DOWN,
+ grid_mouse_down, g);
+ evas_object_smart_member_add(o, container);
+ evas_object_show(o);
+ g->image = o;
+ g->mem = NULL;
+ g->w = w;
+ g->h = h;
+ g->age = 0;
+ g->mode = mode;
+ g->cells = xmalloc(sizeof(struct cell) * w * h);
+ for (j=0; j<h; j++) {
+ for (i=0; i<w; i++) {
+ cell = CELL_GET(g, i, j);
+ cell->x = i;
+ cell->y = j;
+ cell->r = 0;
+ cell->g = 0;
+ cell->b = 0;
+ cell->forced_color = 0x000000;
+ cell->age = !(rand() % INITCELL_PROBA);
+ }
+ }
+
+#ifdef HAVE_GLOUGLOU
+ g->ev_base = event_base_new();
+ g->ggcli = gg_client_connect(g->ev_base, "127.0.0.1", GLOUGLOU_ANALY_DEFAULT_PORT,
+ NULL, gg_packet, g);
+#endif
+
+ return g;
+}
+
+static void
+grid_del(struct grid *grid)
+{
+#ifdef HAVE_GLOUGLOU
+ gg_client_disconnect(grid->ggcli);
+#endif
+ free(grid->cells);
+ free(grid->mem);
+ free(grid);
+}
+
+static int
+grid_evolution(struct grid *grid)
+{
+ struct cell *cell;
+ int i, j;
+ int neighbours;
+
+ for (j=0; j<grid->h; j++) {
+ for (i=0; i<grid->w; i++) {
+ cell = CELL_GET(grid, i, j);
+ neighbours = cell_neighbours_count(cell, grid);
+ switch (grid->mode) {
+ case ELIFE_MODE_CONWAY:
+ if (cell->age == 0 && neighbours == 3)
+ cell->newage = 1;
+ else if (cell->age > 0 && (neighbours == 2 || neighbours == 3))
+ cell->newage = cell->age;
+ else
+ cell->newage = 0;
+ break;
+ case ELIFE_MODE_CONWAY_GROW:
+ if (cell->age == 0 && neighbours == 3)
+ cell->newage = 1;
+ else if (cell->age > 0 && (neighbours == 2 || neighbours == 3))
+ if (cell->age > CONWAY_GROW_DIE)
+ cell->newage = 0;
+ else
+ cell->newage = cell->age + 1;
+ else
+ cell->newage = 0;
+ break;
+ case ELIFE_MODE_LORAN_CIVILISATION:
+ if (neighbours == 4 || neighbours < 2)
+ cell->newage = 0;
+ else if (neighbours > 2 && neighbours != 5)
+ cell->newage = cell->age + 1;
+ else if (neighbours == 2 && cell->age > 1)
+ cell->newage = 0;
+ else
+ cell->newage = cell->age;
+ if (cell->age > 100)
+ cell->newage = 0;
+ break;
+ }
+ if (cell->newage == 0 && cell->forced_color)
+ cell->forced_color = 0;
+ if (DEBUG)
+ printf("evolution: %d %d n %d age %d newage %d\n", i, j,
+ neighbours, cell->age, cell->newage);
+ }
+ }
+
+#ifdef HAVE_GLOUGLOU
+ event_base_loop(grid->ev_base, EVLOOP_NONBLOCK);
+#else
+ if (rand() % INJECT_PROBA == 0)
+ grid_inject_pattern(grid, 0);
+#endif
+
+ for (j=0; j<grid->h; j++) {
+ for (i=0; i<grid->w; i++) {
+ cell = CELL_GET(grid, i, j);
+ cell->age = cell->newage;
+ cell_redraw(cell, grid);
+ }
+ }
+ evas_object_image_pixels_dirty_set(grid->image, EINA_TRUE);
+
+ grid->age++;
+}
+
+static void
+grid_inject_pattern(struct grid *grid, u_int32_t color)
+{
+ struct cell *cell;
+ enum lifepattern_t npat;
+ lifepattern_s *pat;
+ int x, y, cx, cy;
+ int i, j;
+ int age;
+
+ npat = rand() % PATTERN_COUNT;
+ if (DEBUG)
+ printf("grid_inject_pattern: %d\n", npat);
+ pat = &lifepatterns[npat];
+ x = rand() % (grid->w - pat->w);
+ y = rand() % (grid->h - pat->h);
+ for (j=0; j<pat->h; j++) {
+ for (i=0; i<pat->w; i++) {
+ cx = x + i;
+ cy = y + j;
+ if (cx >= grid->w || cy >= grid->h)
+ continue;
+ cell = CELL_GET(grid, cx, cy);
+ age = (pat->pat[pat->w*j + i] - '0') * 27;
+ if (age != 0)
+ cell->newage = age;
+ cell->forced_color = color;
+ cell->age = cell->newage;
+ // cell_redraw(cell, grid);
+ }
+ }
+}
+
+static int
+grid_redraw(struct grid *grid, int w, int h)
+{
+ struct cell *cell;
+ int i,j;
+ Evas_Object *o;
+
+ grid->cell_pix_w = w / grid->w;
+ grid->cell_pix_h = h / grid->h;
+ grid->pix_w = (w / grid->w) * grid->w;
+ grid->pix_h = (h / grid->h) * grid->h;
+ if (DEBUG)
+ printf("redraw: container %d %d cell %d %d\n", w, h, grid->cell_pix_w, grid->cell_pix_h);
+
+ evas_object_image_fill_set(grid->image, 0, 0, grid->pix_w, grid->pix_h);
+ evas_object_image_size_set (grid->image, grid->pix_w, grid->pix_h);
+ evas_object_resize(grid->image, w, h);
+ /* XXX could be optimized to avoid flickering on resize */
+ if (grid->mem)
+ free(grid->mem);
+ grid->mem = calloc(w * h, sizeof(int));
+ if (!grid->mem)
+ err(1, "could not calloc grid->mem");
+ evas_object_image_data_set(grid->image, (void *) grid->mem);
+ for (j=0; j<grid->h; j++) {
+ for (i=0; i<grid->w; i++) {
+ cell = CELL_GET(grid, i, j);
+ cell_redraw(cell, grid);
+ }
+ }
+}
+
+static int
+cell_neighbours_count(struct cell *cell, struct grid *grid)
+{
+ struct cell *ncell;
+ int m, n, cx, cy;
+ int count;
+
+ count = 0;
+ for (n=-1; n<=1; n++) {
+ for (m=-1; m<=1; m++) {
+ if (m == 0 && n == 0)
+ continue;
+ cx = cell->x + m;
+ cy = cell->y + n;
+ if (cx < 0 || cx >= grid->w || cy < 0 || cy >= grid->h)
+ continue;
+ ncell = CELL_GET(grid, cx, cy);
+ if (ncell->age > 0)
+ count++;
+ }
+ }
+
+ return count;
+}
+
+static void
+cell_redraw(struct cell *c, struct grid *grid)
+{
+ u_int8_t r, g, b, a;
+ int x, y, w, h;
+ int i, j;
+ int color;
+
+ if (c->forced_color && c->age > 0) {
+ r = (c->forced_color & 0xff0000) >> 16;
+ g = (c->forced_color & 0xff00) >> 8;
+ b = (c->forced_color & 0xff);
+ } else if (c->age < 100) {
+ r = (c->age > 0) ? 128 : 0;
+ g = (c->age > 0) ? (33 + c->age * 7) : 0;
+ b = 0;
+ } else if (c->age < CONWAY_GROW_DIE - 50) {
+ r = 128 - c->age;
+ g = 255 - c->age;
+ b = (c->age - 100) * 2;
+ } else {
+ r = 255;
+ g = (c->age % 2) * 255;
+ b = 255;
+ }
+ a = 255;
+ if (r == c->r && g == c->g && b == c->b)
+ return;
+ c->r = r;
+ c->g = g;
+ c->b = b;
+
+ x = c->x * grid->cell_pix_w;
+ y = c->y * grid->cell_pix_h;
+ w = grid->cell_pix_w;
+ h = grid->cell_pix_h;
+ for (j=y; j<y+h; j++) {
+ for (i=x; i<x+w; i++) {
+ color = 0xff000000 + (r << 16) + (g << 8) + (b);
+ grid->mem[j*grid->pix_w + i] = color;
+ }
+ }
+}
+
+static void
+grid_mouse_down(void *data,
+ Evas *evas,
+ Evas_Object *child,
+ void *event_info)
+{
+ Evas_Coord x, y, w, h;
+ Evas_Event_Mouse_Up *evt = event_info;
+ struct grid *grid;
+
+ grid = data;
+ grid_inject_pattern(grid, 0);
+}
+
+Evas_Object *
+elife_smart_new(Evas *e)
+{
+ return elife_object_new(e);
+}
+
+static void
+elife_on_refresh(void *data, Evas_Object *o, void *event_info)
+{
+ Evas_Coord x, y, w, h;
+ Evas_Object *child;
+ struct grid *grid;
+
+ grid = evas_object_data_get(o, "grid");
+
+ grid_evolution(grid);
+}
+
+static Evas_Object *
+elife_object_new(Evas *evas)
+{
+ Evas_Object *elife_object;
+ struct grid *grid;
+
+ elife_object = evas_object_smart_add(evas,
+ _elife_object_smart_get());
+ grid = grid_new(elife_object, NCELL_X, NCELL_Y, ELIFE_MODE_CONWAY_GROW);
+ evas_object_data_set(elife_object, "grid", grid);
+ evas_object_smart_callback_add(elife_object,
+ "refresh",
+ elife_on_refresh,
+ NULL);
+
+ return elife_object;
+}
+
+static Evas_Smart *
+_elife_object_smart_get(void)
+{
+ static Evas_Smart *smart = NULL;
+
+ if (smart)
+ return smart;
+
+ smart = evas_smart_class_new(&_G.klass);
+ return smart;
+}
+
+static void
+_elife_object_del(Evas_Object *o)
+{
+ Evas_Object *child;
+ struct grid *grid;
+ Eina_List *list;
+
+ list = evas_object_smart_members_get(o);
+ EINA_LIST_FREE(list, child) {
+ evas_object_smart_member_del(child);
+ evas_object_del(child);
+ }
+ grid = evas_object_data_del(o, "grid");
+ grid_del(grid);
+}
+
+static void
+_elife_object_move(Evas_Object *o, Evas_Coord x, Evas_Coord y)
+{
+ Evas_Coord orig_x, orig_y, dx, dy;
+ Eina_List *lst;
+ Evas_Object *child;
+ void *data;
+
+ if (DEBUG)
+ printf("oject_move: %d %d\n", x, y);
+ evas_object_geometry_get(o, &orig_x, &orig_y, NULL, NULL);
+ dx = x - orig_x;
+ dy = y - orig_y;
+
+ lst = evas_object_smart_members_get(o);
+ EINA_LIST_FREE(lst, data) {
+ child = data;
+ evas_object_geometry_get(child, &orig_x, &orig_y, NULL, NULL);
+ evas_object_move(child, orig_x + dx, orig_y + dy);
+ }
+}
+
+static void
+_elife_object_resize(Evas_Object *o, Evas_Coord w, Evas_Coord h)
+{
+ struct grid *grid;
+
+ if (DEBUG)
+ printf("oject_resize: %d %d\n", w, h);
+ grid = evas_object_data_get(o, "grid");
+ grid_redraw(grid, w, h);
+}
+
+void *
+xmalloc(size_t size)
+{
+ void *x;
+
+ x = malloc(size);
+ if (!x)
+ err(1, "Error: failed to allocate %d", size);
+ return x;
+}
+
diff --git a/gg_elife/src/elife_evas_smart.h b/gg_elife/src/elife_evas_smart.h
new file mode 100644
index 0000000..b5a5b85
--- /dev/null
+++ b/gg_elife/src/elife_evas_smart.h
@@ -0,0 +1,8 @@
+#ifndef ELIFE_SMART_H
+#define ELIFE_SMART_H
+#include <Evas.h>
+
+Evas_Object *elife_smart_new(Evas *e);
+
+#endif
+
diff --git a/gg_sniff/gg_sniff.c b/gg_sniff/gg_sniff.c
index 656c38c..cd2d2c5 100644
--- a/gg_sniff/gg_sniff.c
+++ b/gg_sniff/gg_sniff.c
@@ -39,7 +39,7 @@ usage(void)
{
extern char *__progname;
- fprintf(stderr, "usage: %s [-hv] [-i interface] [ip [port]]", __progname);
+ fprintf(stderr, "usage: %s [-hv] [-i interface] [ip [port]]\n", __progname);
exit(1);
}
diff --git a/gg_sniff/pcap.c b/gg_sniff/pcap.c
index 4522fc8..fc5b978 100644
--- a/gg_sniff/pcap.c
+++ b/gg_sniff/pcap.c
@@ -46,8 +46,8 @@
#define CONNTIMER 5 // XXX conf ?
struct phandler {
- pcap_handler f;
- int type;
+ pcap_handler f;
+ int type;
};
struct _cap_t {
@@ -63,20 +63,20 @@ struct _cap_t {
};
static pcap_t *my_pcap_open_live(const char *, int, int, int,
- char *, u_int, u_int);
+ char *, u_int, u_int);
static void ip_handle(struct ip *, const u_char *, u_int);
static void conn_del(struct ggnet_conn *);
static void ether_handle(struct ether_header *, const u_char *, u_int);
static pcap_handler lookup_phandler(int);
static void phandler_ether(u_char *,
- const struct pcap_pkthdr *, const u_char *);
+ const struct pcap_pkthdr *, const u_char *);
#if defined(__OpenBSD__)
static void phandler_loop(u_char *,
- const struct pcap_pkthdr *, const u_char *);
+ const struct pcap_pkthdr *, const u_char *);
#endif
#if defined(__linux__)
static void phandler_sll(u_char *,
- const struct pcap_pkthdr *, const u_char *);
+ const struct pcap_pkthdr *, const u_char *);
#endif
static void cb_pcap(int, short, void *);
static void cb_conntimer(int, short, void *);
@@ -97,46 +97,46 @@ static struct phandler phandlers[] = {
static struct _cap_t _cap;
-int
+ int
ggsniff_pcap_init(struct event_base *ev_base, struct gg_client *ggcli,
- struct ggnet *net, char *iface, int active)
+ struct ggnet *net, char *iface, int active)
{
- char errbuf[PCAP_ERRBUF_SIZE];
- struct bpf_program bprog;
+ char errbuf[PCAP_ERRBUF_SIZE];
+ struct bpf_program bprog;
pcap_t *pcap;
#if defined(__OpenBSD__)
if (!iface)
err(1, "On OpenBSD you cannot listen on ANY interface");
#endif
- pcap = my_pcap_open_live(iface, PCAP_SNAPLEN, 1, PCAP_TO,
- errbuf, -1, 0);
- if (pcap == NULL)
- err(1, "capture: pcap_open_live failed on interface %s\n"
- "with snaplen %d : %s",
- iface, PCAP_SNAPLEN, errbuf);
- if (pcap_compile(pcap, &bprog, PCAP_FILTER, 0, 0) < 0)
- err(1, "capture: pcap_compile failed with filter %s : %s",
- PCAP_FILTER, pcap_geterr(pcap));
- if (pcap_setfilter(pcap, &bprog) < 0)
- err(1, "capture: pcap_setfilter failed : %s",
- pcap_geterr(pcap));
-
- _cap.pcap = pcap;
- _cap.handler = lookup_phandler(pcap_datalink(pcap));
- //_cap.tv.tv_sec = 0;
- //_cap.tv.tv_usec = PCAP_TO;
- fd_nonblock(pcap_fileno(pcap));
+ pcap = my_pcap_open_live(iface, PCAP_SNAPLEN, 1, PCAP_TO,
+ errbuf, -1, 0);
+ if (pcap == NULL)
+ err(1, "capture: pcap_open_live failed on interface %s\n"
+ "with snaplen %d : %s",
+ iface, PCAP_SNAPLEN, errbuf);
+ if (pcap_compile(pcap, &bprog, PCAP_FILTER, 0, 0) < 0)
+ err(1, "capture: pcap_compile failed with filter %s : %s",
+ PCAP_FILTER, pcap_geterr(pcap));
+ if (pcap_setfilter(pcap, &bprog) < 0)
+ err(1, "capture: pcap_setfilter failed : %s",
+ pcap_geterr(pcap));
+
+ _cap.pcap = pcap;
+ _cap.handler = lookup_phandler(pcap_datalink(pcap));
+ //_cap.tv.tv_sec = 0;
+ //_cap.tv.tv_usec = PCAP_TO;
+ fd_nonblock(pcap_fileno(pcap));
_cap.ev = event_new(ev_base, pcap_fileno(pcap), EV_READ|EV_PERSIST,
- cb_pcap, NULL);
+ cb_pcap, NULL);
//event_add(_cap.ev, &_cap->tv);
event_add(_cap.ev, NULL);
- _cap.conntimer_tv.tv_sec = CONNTIMER;
- _cap.conntimer_tv.tv_usec = 0;
- _cap.conntimer_ev = evtimer_new(ev_base, cb_conntimer, NULL);
- if (evtimer_add(_cap.conntimer_ev, &_cap.conntimer_tv) == -1)
- gg_log_fatal("user: event_add conntimer failed: %s", strerror(errno));
+ _cap.conntimer_tv.tv_sec = CONNTIMER;
+ _cap.conntimer_tv.tv_usec = 0;
+ _cap.conntimer_ev = evtimer_new(ev_base, cb_conntimer, NULL);
+ if (evtimer_add(_cap.conntimer_ev, &_cap.conntimer_tv) == -1)
+ gg_log_fatal("user: event_add conntimer failed: %s", strerror(errno));
if (active) {
ggnet_set_dns(net, 1, ev_base, cb_nodename);
@@ -146,10 +146,10 @@ ggsniff_pcap_init(struct event_base *ev_base, struct gg_client *ggcli,
_cap.ggcli = ggcli;
_cap.net = net;
- return 1;
+ return 1;
}
-void
+ void
ggsniff_pcap_shutdown(void)
{
event_del(_cap.ev);
@@ -163,125 +163,125 @@ ggsniff_pcap_shutdown(void)
* based on OpenBSD tcpdump, privsep_pcap.c v1.16
*/
-static pcap_t *
+ static pcap_t *
my_pcap_open_live(const char *dev, int slen, int promisc, int to_ms,
- char *ebuf, u_int dlt, u_int dirfilt)
+ char *ebuf, u_int dlt, u_int dirfilt)
{
#if defined(__OpenBSD__)
- struct bpf_version bv;
- u_int v;
- pcap_t *p;
- char bpf[sizeof "/dev/bpf0000000000"];
- int fd, n = 0;
- struct ifreq ifr;
-
- p = xmalloc(sizeof(*p));
- bzero(p, sizeof(*p));
-
- /* priv part */
-
- do {
- snprintf(bpf, sizeof(bpf), "/dev/bpf%d", n++);
- fd = open(bpf, O_RDONLY);
- } while (fd < 0 && errno == EBUSY);
- if (fd < 0)
- return NULL;
-
- v = 32768; /* XXX this should be a user-accessible hook */
- ioctl(fd, BIOCSBLEN, &v);
-
- strlcpy(ifr.ifr_name, dev, sizeof(ifr.ifr_name));
- if (ioctl(fd, BIOCSETIF, &ifr) < 0)
- return NULL;
-
- if (dlt != (u_int) -1 && ioctl(fd, BIOCSDLT, &dlt))
- return NULL;
-
- if (promisc)
- /* this is allowed to fail */
- ioctl(fd, BIOCPROMISC, NULL);
- if (ioctl(fd, BIOCSDIRFILT, &dirfilt) < 0)
- return NULL;
-
- /* lock the descriptor */
- if (ioctl(fd, BIOCLOCK, NULL) < 0)
- return NULL;
-
- /* end of priv part */
-
- /* fd is locked, can only use 'safe' ioctls */
- if (ioctl(fd, BIOCVERSION, &bv) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCVERSION: %s",
- pcap_strerror(errno));
- return NULL;
- }
-
- if (bv.bv_major != BPF_MAJOR_VERSION ||
- bv.bv_minor < BPF_MINOR_VERSION) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE,
- "kernel bpf filter out of date");
- return NULL;
- }
-
- p->fd = fd;
- p->snapshot = slen;
-
- /* Get the data link layer type. */
- if (ioctl(fd, BIOCGDLT, &v) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCGDLT: %s",
- pcap_strerror(errno));
- return NULL;
- }
+ struct bpf_version bv;
+ u_int v;
+ pcap_t *p;
+ char bpf[sizeof "/dev/bpf0000000000"];
+ int fd, n = 0;
+ struct ifreq ifr;
+
+ p = xmalloc(sizeof(*p));
+ bzero(p, sizeof(*p));
+
+ /* priv part */
+
+ do {
+ snprintf(bpf, sizeof(bpf), "/dev/bpf%d", n++);
+ fd = open(bpf, O_RDONLY);
+ } while (fd < 0 && errno == EBUSY);
+ if (fd < 0)
+ return NULL;
+
+ v = 32768; /* XXX this should be a user-accessible hook */
+ ioctl(fd, BIOCSBLEN, &v);
+
+ strlcpy(ifr.ifr_name, dev, sizeof(ifr.ifr_name));
+ if (ioctl(fd, BIOCSETIF, &ifr) < 0)
+ return NULL;
+
+ if (dlt != (u_int) -1 && ioctl(fd, BIOCSDLT, &dlt))
+ return NULL;
+
+ if (promisc)
+ /* this is allowed to fail */
+ ioctl(fd, BIOCPROMISC, NULL);
+ if (ioctl(fd, BIOCSDIRFILT, &dirfilt) < 0)
+ return NULL;
+
+ /* lock the descriptor */
+ if (ioctl(fd, BIOCLOCK, NULL) < 0)
+ return NULL;
+
+ /* end of priv part */
+
+ /* fd is locked, can only use 'safe' ioctls */
+ if (ioctl(fd, BIOCVERSION, &bv) < 0) {
+ snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCVERSION: %s",
+ pcap_strerror(errno));
+ return NULL;
+ }
+
+ if (bv.bv_major != BPF_MAJOR_VERSION ||
+ bv.bv_minor < BPF_MINOR_VERSION) {
+ snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ "kernel bpf filter out of date");
+ return NULL;
+ }
+
+ p->fd = fd;
+ p->snapshot = slen;
+
+ /* Get the data link layer type. */
+ if (ioctl(fd, BIOCGDLT, &v) < 0) {
+ snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCGDLT: %s",
+ pcap_strerror(errno));
+ return NULL;
+ }
#if _BSDI_VERSION - 0 >= 199510
- /* The SLIP and PPP link layer header changed in BSD/OS 2.1 */
- switch (v) {
+ /* The SLIP and PPP link layer header changed in BSD/OS 2.1 */
+ switch (v) {
- case DLT_SLIP:
- v = DLT_SLIP_BSDOS;
- break;
+ case DLT_SLIP:
+ v = DLT_SLIP_BSDOS;
+ break;
- case DLT_PPP:
- v = DLT_PPP_BSDOS;
- break;
- }
+ case DLT_PPP:
+ v = DLT_PPP_BSDOS;
+ break;
+ }
#endif
- p->linktype = v;
-
- /* XXX hack from tcpdump */
- if (p->linktype == DLT_PFLOG && p->snapshot < 160)
- p->snapshot = 160;
-
- /* set timeout */
- if (to_ms != 0) {
- struct timeval to;
- to.tv_sec = to_ms / 1000;
- to.tv_usec = (to_ms * 1000) % 1000000;
- if (ioctl(p->fd, BIOCSRTIMEOUT, &to) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCSRTIMEOUT: %s",
- pcap_strerror(errno));
- return NULL;
- }
- }
-
- if (ioctl(fd, BIOCGBLEN, &v) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCGBLEN: %s",
- pcap_strerror(errno));
- return NULL;
- }
- p->bufsize = v;
- p->buffer = (u_char *)malloc(p->bufsize);
- if (p->buffer == NULL) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
- pcap_strerror(errno));
- return NULL;
- }
- return p;
+ p->linktype = v;
+
+ /* XXX hack from tcpdump */
+ if (p->linktype == DLT_PFLOG && p->snapshot < 160)
+ p->snapshot = 160;
+
+ /* set timeout */
+ if (to_ms != 0) {
+ struct timeval to;
+ to.tv_sec = to_ms / 1000;
+ to.tv_usec = (to_ms * 1000) % 1000000;
+ if (ioctl(p->fd, BIOCSRTIMEOUT, &to) < 0) {
+ snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCSRTIMEOUT: %s",
+ pcap_strerror(errno));
+ return NULL;
+ }
+ }
+
+ if (ioctl(fd, BIOCGBLEN, &v) < 0) {
+ snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCGBLEN: %s",
+ pcap_strerror(errno));
+ return NULL;
+ }
+ p->bufsize = v;
+ p->buffer = (u_char *)malloc(p->bufsize);
+ if (p->buffer == NULL) {
+ snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
+ pcap_strerror(errno));
+ return NULL;
+ }
+ return p;
#else /* defined(__OpenBSD__) */
return pcap_open_live(dev, slen, promisc, to_ms, ebuf);
#endif
}
-static void
+ static void
cb_pcap(int fd, short why, void *data)
{
gg_log_tmp("cb_pcap");
@@ -292,49 +292,49 @@ cb_pcap(int fd, short why, void *data)
// gg_log_fatal("user: event_add pcap failed : %s", strerror(errno));
}
-static void
+ static void
cb_conntimer(int fd, short why, void *data)
{
- struct ggnet_conn *c, *ctmp;
- struct ggnet_node *n, *ntmp;
- int i, to;
-
- gg_log_debug("ev_timer");
- ggnet_time_update(_cap.net, time(NULL));
-
- i = 0;
- LIST_FOREACH_SAFE(c, &_cap.net->conn_list, entry, ctmp) {
- switch (c->proto) {
- case IPPROTO_UDP:
- to = CONN_TIMEOUT_UDP;
- break;
- case IPPROTO_ICMP:
- to = CONN_TIMEOUT_ICMP;
- break;
- default:
- to = CONN_TIMEOUT;
- break;
- }
- if (_cap.net->time > c->lastseen + to)
- conn_del(c);
- else
- i++;
- }
-
- if (_cap.net->node_count > NODE_MAX_WITHOUT_TIMEOUT) {
- LIST_FOREACH_SAFE(n, &_cap.net->node_list, entry, ntmp) {
- if (n->used == 0 &&
- _cap.net->time > n->lastseen + NODE_TIMEOUT)
- ggnet_node_del(_cap.net, n);
- }
- }
-
- gg_log_debug("user: ev_timer leaving with %d active connections and %d active nodes", i, _cap.net->node_count);
- if (evtimer_add(_cap.conntimer_ev, &_cap.conntimer_tv) == -1)
- gg_log_fatal("user: event_add conntimer failed : %s", strerror(errno));
+ struct ggnet_conn *c, *ctmp;
+ struct ggnet_node *n, *ntmp;
+ int i, to;
+
+ gg_log_debug("ev_timer");
+ ggnet_time_update(_cap.net, time(NULL));
+
+ i = 0;
+ LIST_FOREACH_SAFE(c, &_cap.net->conn_list, entry, ctmp) {
+ switch (c->proto) {
+ case IPPROTO_UDP:
+ to = CONN_TIMEOUT_UDP;
+ break;
+ case IPPROTO_ICMP:
+ to = CONN_TIMEOUT_ICMP;
+ break;
+ default:
+ to = CONN_TIMEOUT;
+ break;
+ }
+ if (_cap.net->time > c->lastseen + to)
+ conn_del(c);
+ else
+ i++;
+ }
+
+ if (_cap.net->node_count > NODE_MAX_WITHOUT_TIMEOUT) {
+ LIST_FOREACH_SAFE(n, &_cap.net->node_list, entry, ntmp) {
+ if (n->used == 0 &&
+ _cap.net->time > n->lastseen + NODE_TIMEOUT)
+ ggnet_node_del(_cap.net, n);
+ }
+ }
+
+ gg_log_debug("user: ev_timer leaving with %d active connections and %d active nodes", i, _cap.net->node_count);
+ if (evtimer_add(_cap.conntimer_ev, &_cap.conntimer_tv) == -1)
+ gg_log_fatal("user: event_add conntimer failed : %s", strerror(errno));
}
-static void
+ static void
cb_nodename(struct ggnet *net, struct ggnet_node *n)
{
struct gg_packet pkt;
@@ -379,153 +379,153 @@ cb_nodetraceroute(struct ggnet *net, struct ggnet_node *n)
#define NOTRECEIVED(v) (wirelen < sizeof(v))
#define log_pinvalid(fmt, ...) \
gg_log_info("ggsniff pinvalid: " fmt, ##__VA_ARGS__)
-static void
+ static void
ip_handle(struct ip *ip, const u_char *pend, u_int wirelen)
{
- u_int len, ip_hlen, off;
- const u_char *cp;
- struct tcphdr *tcph;
- struct udphdr *udph;
- struct icmp *icmp;
- struct in_addr src, dst;
- u_int src_port, dst_port;
- u_int proto, close;
- int response;
- struct ggnet_conn *conn;
- struct gg_packet pkt;
-
- if (NOTCAPTURED(ip)) {
- log_pinvalid("user: ip truncated (ip %x pend %x sizeof(ip) %d",
+ u_int len, ip_hlen, off;
+ const u_char *cp;
+ struct tcphdr *tcph;
+ struct udphdr *udph;
+ struct icmp *icmp;
+ struct in_addr src, dst;
+ u_int src_port, dst_port;
+ u_int proto, close;
+ int response;
+ struct ggnet_conn *conn;
+ struct gg_packet pkt;
+
+ if (NOTCAPTURED(ip)) {
+ log_pinvalid("user: ip truncated (ip %x pend %x sizeof(ip) %d",
ip, pend, sizeof(ip));
- _cap.ptruncated++;
- return;
- }
-
- if (ip->ip_v != IPVERSION) {
- log_pinvalid("user: invalid ip version");
- _cap.pinvalid++;
- return;
- }
-
- len = ntohs(ip->ip_len);
- if (wirelen < len) {
- log_pinvalid("user: ip too small");
- _cap.pinvalid++;
- len = wirelen;
- }
-
- ip_hlen = ip->ip_hl * 4;
- if (ip_hlen < sizeof(struct ip) || ip_hlen > len) {
- log_pinvalid("user: ip_hlen invalid, %d", ip_hlen);
- _cap.pinvalid++;
- return;
- }
- len -= ip_hlen;
-
- src.s_addr = ntohl(ip->ip_src.s_addr);
- dst.s_addr = ntohl(ip->ip_dst.s_addr);
- src_port = 0;
- dst_port = 0;
- proto = IPPROTO_IP;
- close = 0;
-
- off = ntohs(ip->ip_off);
- if ((off & IP_OFFMASK) == 0) {
- cp = (const u_char *)ip + ip_hlen;
- switch (ip->ip_p) {
-
- case IPPROTO_TCP:
- tcph = (struct tcphdr *)cp;
- if (NOTCAPTURED(&tcph->th_flags)) {
- log_pinvalid("user: tcp truncated");
- _cap.ptruncated++;
- return;
- }
- if (NOTRECEIVED(*tcph)) {
- log_pinvalid("user: tcp too small");
- _cap.pinvalid++;
- return;
- }
- src_port = ntohs(tcph->th_sport);
- dst_port = ntohs(tcph->th_dport);
- proto = IPPROTO_TCP;
- if ((tcph->th_flags & TH_FIN) &&
- (tcph->th_flags & TH_ACK))
- close = 1;
- break;
-
- case IPPROTO_UDP:
- udph = (struct udphdr *)cp;
- if (NOTCAPTURED(&udph->uh_dport)) {
- log_pinvalid("user: udp truncated, "
- "ip %x, udph %x, uh_port %x, pend %x, ip_hlen %d",
- ip, udph, &udph->uh_dport, pend, ip_hlen);
- _cap.ptruncated++;
- return;
- }
- if (NOTRECEIVED(*udph)) {
- log_pinvalid("user: udp too small");
- _cap.pinvalid++;
- return;
- }
- src_port = ntohs(udph->uh_sport);
- dst_port = ntohs(udph->uh_dport);
- proto = IPPROTO_UDP;
- break;
-
- case IPPROTO_ICMP:
- icmp = (struct icmp *)cp;
- if (NOTRECEIVED(*icmp)) {
- log_pinvalid("user: icmp too small");
- _cap.pinvalid++;
- return;
- }
- proto = IPPROTO_ICMP;
- break;
-
- default:
- gg_log_warn("user: unknown ip protocol !");
- break;
- }
- } else {
- /*
- * if this isn't the first frag, we're missing the
- * next level protocol header.
- */
- gg_log_tmp("user: got a fragmented ip packet !");
- }
+ _cap.ptruncated++;
+ return;
+ }
+
+ if (ip->ip_v != IPVERSION) {
+ log_pinvalid("user: invalid ip version");
+ _cap.pinvalid++;
+ return;
+ }
+
+ len = ntohs(ip->ip_len);
+ if (wirelen < len) {
+ log_pinvalid("user: ip too small");
+ _cap.pinvalid++;
+ len = wirelen;
+ }
+
+ ip_hlen = ip->ip_hl * 4;
+ if (ip_hlen < sizeof(struct ip) || ip_hlen > len) {
+ log_pinvalid("user: ip_hlen invalid, %d", ip_hlen);
+ _cap.pinvalid++;
+ return;
+ }
+ len -= ip_hlen;
+
+ src.s_addr = ntohl(ip->ip_src.s_addr);
+ dst.s_addr = ntohl(ip->ip_dst.s_addr);
+ src_port = 0;
+ dst_port = 0;
+ proto = IPPROTO_IP;
+ close = 0;
+
+ off = ntohs(ip->ip_off);
+ if ((off & IP_OFFMASK) == 0) {
+ cp = (const u_char *)ip + ip_hlen;
+ switch (ip->ip_p) {
+
+ case IPPROTO_TCP:
+ tcph = (struct tcphdr *)cp;
+ if (NOTCAPTURED(&tcph->th_flags)) {
+ log_pinvalid("user: tcp truncated");
+ _cap.ptruncated++;
+ return;
+ }
+ if (NOTRECEIVED(*tcph)) {
+ log_pinvalid("user: tcp too small");
+ _cap.pinvalid++;
+ return;
+ }
+ src_port = ntohs(tcph->th_sport);
+ dst_port = ntohs(tcph->th_dport);
+ proto = IPPROTO_TCP;
+ if ((tcph->th_flags & TH_FIN) &&
+ (tcph->th_flags & TH_ACK))
+ close = 1;
+ break;
+
+ case IPPROTO_UDP:
+ udph = (struct udphdr *)cp;
+ if (NOTCAPTURED(&udph->uh_dport)) {
+ log_pinvalid("user: udp truncated, "
+ "ip %x, udph %x, uh_port %x, pend %x, ip_hlen %d",
+ ip, udph, &udph->uh_dport, pend, ip_hlen);
+ _cap.ptruncated++;
+ return;
+ }
+ if (NOTRECEIVED(*udph)) {
+ log_pinvalid("user: udp too small");
+ _cap.pinvalid++;
+ return;
+ }
+ src_port = ntohs(udph->uh_sport);
+ dst_port = ntohs(udph->uh_dport);
+ proto = IPPROTO_UDP;
+ break;
+
+ case IPPROTO_ICMP:
+ icmp = (struct icmp *)cp;
+ if (NOTRECEIVED(*icmp)) {
+ log_pinvalid("user: icmp too small");
+ _cap.pinvalid++;
+ return;
+ }
+ proto = IPPROTO_ICMP;
+ break;
+
+ default:
+ gg_log_warn("user: unknown ip protocol !");
+ break;
+ }
+ } else {
+ /*
+ * if this isn't the first frag, we're missing the
+ * next level protocol header.
+ */
+ gg_log_tmp("user: got a fragmented ip packet !");
+ }
pkt.ver = PACKET_VERSION;
conn = ggnet_conn_find(_cap.net, &src, src_port, &dst, dst_port,
- proto, &response);
- if (conn) {
- if (!close) {
- pkt.type = PACKET_DATA;
- pkt.data_connid = conn->id;
- GG_PKTDATA_SIZE_ENCODE(pkt.data_size, ip->ip_len, response);
+ proto, &response);
+ if (conn) {
+ if (!close) {
+ pkt.type = PACKET_DATA;
+ pkt.data_connid = conn->id;
+ GG_PKTDATA_SIZE_ENCODE(pkt.data_size, ip->ip_len, response);
gg_client_send(_cap.ggcli, &pkt);
- ggnet_conn_data(_cap.net, conn, ip->ip_len, response);
- } else {
- conn_del(conn);
- }
- } else {
- if (!close) {
- conn = ggnet_conn_add(_cap.net, &src, src_port, &dst, dst_port, proto,
- ip->ip_len, -1);
- pkt.type = PACKET_NEWCONN;
- pkt.newconn_id = conn->id;
- pkt.newconn_src = src.s_addr;
- pkt.newconn_dst = dst.s_addr;
- pkt.newconn_proto = proto;
- GG_PKTDATA_SIZE_ENCODE(pkt.newconn_size, ip->ip_len, 0);
+ ggnet_conn_data(_cap.net, conn, ip->ip_len, response);
+ } else {
+ conn_del(conn);
+ }
+ } else {
+ if (!close) {
+ conn = ggnet_conn_add(_cap.net, &src, src_port, &dst, dst_port, proto,
+ ip->ip_len, -1);
+ pkt.type = PACKET_NEWCONN;
+ pkt.newconn_id = conn->id;
+ pkt.newconn_src = src.s_addr;
+ pkt.newconn_dst = dst.s_addr;
+ pkt.newconn_proto = proto;
+ GG_PKTDATA_SIZE_ENCODE(pkt.newconn_size, ip->ip_len, 0);
gg_client_send(_cap.ggcli, &pkt);
- } else {
- gg_log_warn("user: captured connection close w/o open !");
- }
- }
+ } else {
+ gg_log_warn("user: captured connection close w/o open !");
+ }
+ }
}
-static void
+ static void
conn_del(struct ggnet_conn *c)
{
struct gg_packet pkt;
@@ -537,11 +537,11 @@ conn_del(struct ggnet_conn *c)
ggnet_conn_del(_cap.net, c);
}
-static void
+ static void
ether_handle(struct ether_header *ether, const u_char *pend, u_int wirelen)
{
struct ip *ip;
- u_short ether_type;
+ u_short ether_type;
wirelen -= sizeof(struct ether_header);
@@ -550,19 +550,19 @@ ether_handle(struct ether_header *ether, const u_char *pend, u_int wirelen)
gg_log_tmp("llc packet !");
else {
switch (ether_type) {
- case ETHERTYPE_IP:
- gg_log_tmp("loop family AF_LINK IP");
- ip = (struct ip *)((u_char *)ether + sizeof(struct ether_header));
- ip_handle(ip, pend, wirelen);
- break;
- default:
- gg_log_tmp("loop non ip packet !");
- break;
+ case ETHERTYPE_IP:
+ gg_log_tmp("loop family AF_LINK IP");
+ ip = (struct ip *)((u_char *)ether + sizeof(struct ether_header));
+ ip_handle(ip, pend, wirelen);
+ break;
+ default:
+ gg_log_tmp("loop non ip packet !");
+ break;
}
}
}
-static pcap_handler
+ static pcap_handler
lookup_phandler(int type)
{
struct phandler *p;
@@ -576,21 +576,21 @@ lookup_phandler(int type)
return NULL;
}
-static void
+ static void
phandler_ether(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
{
- struct ether_header *ep;
- const u_char *pend;
- u_int len;
+ struct ether_header *ep;
+ const u_char *pend;
+ u_int len;
- gg_log_debug("user: pcap handler ethernet !");
+ gg_log_debug("user: pcap handler ethernet !");
- /* XXX here i assume that packets are alligned, which might not
- * be the case when using dump files, says tcpdump sources */
+ /* XXX here i assume that packets are alligned, which might not
+ * be the case when using dump files, says tcpdump sources */
- ep = (struct ether_header *)p;
- pend = p + h->caplen;
- len = h->len - sizeof(struct ether_header);
+ ep = (struct ether_header *)p;
+ pend = p + h->caplen;
+ len = h->len - sizeof(struct ether_header);
ether_handle(ep, pend, len);
}
@@ -606,32 +606,32 @@ phandler_ether(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
#define LINUX_SLL_P_CAN 0x000C /* Controller Area Network */
#define LINUX_SLL_P_IRDA_LAP 0x0017 /* IrDA Link Access Protocol */
-static void
+ static void
phandler_sll(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
{
- struct ip *ip;
- struct ether_header *ep;
- u_int family;
- const u_char *pend;
- u_int len;
+ struct ip *ip;
+ struct ether_header *ep;
+ u_int family;
+ const u_char *pend;
+ u_int len;
- gg_log_debug("user: phandler_sll !");
+ gg_log_debug("user: phandler_sll !");
- /* XXX here i assume that packets are alligned, which might not
- * be the case when using dump files, says tcpdump sources */
+ /* XXX here i assume that packets are alligned, which might not
+ * be the case when using dump files, says tcpdump sources */
- pend = p + h->caplen;
- len = h->len - SLL_HDR_LEN;
+ pend = p + h->caplen;
+ len = h->len - SLL_HDR_LEN;
family = ntohs(p[14]);
if (family < 1536) { /* linux and wireshark are good for you */
switch (family) {
- case LINUX_SLL_P_ETHERNET:
- ep = (struct ether_header *)((u_char *)p + SLL_HDR_LEN);
- ether_handle(ep, pend, len);
- default:
- gg_log_tmp("unknown family %x !", family);
- break;
+ case LINUX_SLL_P_ETHERNET:
+ ep = (struct ether_header *)((u_char *)p + SLL_HDR_LEN);
+ ether_handle(ep, pend, len);
+ default:
+ gg_log_tmp("unknown family %x !", family);
+ break;
}
} else {
ip = (struct ip *)(p + SLL_HDR_LEN);
@@ -646,38 +646,38 @@ phandler_sll(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
#if defined(__OpenBSD__)
#define NULL_HDRLEN 4
-static void
+ static void
phandler_loop(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
{
- struct ip *ip;
- struct ether_header *ep;
- u_int family;
- const u_char *pend;
- u_int len;
-
- gg_log_debug("user: pcap handler loop !");
-
- /* XXX here i assume that packets are alligned, which might not
- * be the case when using dump files, says tcpdump sources */
-
- pend = p + h->caplen;
- len = h->len - NULL_HDRLEN;
-
- memcpy((char *)&family, (char *)p, sizeof(family));
- family = ntohl(family);
- switch (family) {
- case AF_INET:
- gg_log_tmp("loop family AF_INET");
- ip = (struct ip *)(p + NULL_HDRLEN);
- ip_handle(ip, pend, len);
- break;
- case AF_LINK:
- ep = (struct ether_header *)((u_char *)p + NULL_HDRLEN);
- ether_handle(ep, pend, len);
- break;
- default:
- gg_log_tmp("unknown family %x !", family);
- break;
- }
+ struct ip *ip;
+ struct ether_header *ep;
+ u_int family;
+ const u_char *pend;
+ u_int len;
+
+ gg_log_debug("user: pcap handler loop !");
+
+ /* XXX here i assume that packets are alligned, which might not
+ * be the case when using dump files, says tcpdump sources */
+
+ pend = p + h->caplen;
+ len = h->len - NULL_HDRLEN;
+
+ memcpy((char *)&family, (char *)p, sizeof(family));
+ family = ntohl(family);
+ switch (family) {
+ case AF_INET:
+ gg_log_tmp("loop family AF_INET");
+ ip = (struct ip *)(p + NULL_HDRLEN);
+ ip_handle(ip, pend, len);
+ break;
+ case AF_LINK:
+ ep = (struct ether_header *)((u_char *)p + NULL_HDRLEN);
+ ether_handle(ep, pend, len);
+ break;
+ default:
+ gg_log_tmp("unknown family %x !", family);
+ break;
+ }
}
#endif /* __OpenBSD__ */
diff --git a/glougloud/glougloud.c b/glougloud/glougloud.c
index 4c08dec..2a87492 100644
--- a/glougloud/glougloud.c
+++ b/glougloud/glougloud.c
@@ -37,7 +37,7 @@ usage(void)
{
extern char *__progname;
- fprintf(stderr, "usage: %s [-vi]", __progname);
+ fprintf(stderr, "usage: %s [-hi]\n", __progname);
exit(1);
}