summaryrefslogtreecommitdiff
path: root/src/gtkext
diff options
context:
space:
mode:
Diffstat (limited to 'src/gtkext')
-rw-r--r--[-rwxr-xr-x]src/gtkext/graph/Makefile.am12
-rw-r--r--src/gtkext/graph/cluster.c1330
-rw-r--r--src/gtkext/graph/cluster.h71
-rw-r--r--src/gtkext/graph/edge.c287
-rw-r--r--src/gtkext/graph/edge.h31
-rw-r--r--src/gtkext/graph/layout.c491
-rw-r--r--src/gtkext/graph/layout.h73
-rw-r--r--src/gtkext/graph/node-int.h83
-rw-r--r--src/gtkext/graph/node.c634
-rw-r--r--src/gtkext/graph/node.h174
-rwxr-xr-xsrc/gtkext/graph/nodes/Makefile.am15
-rw-r--r--src/gtkext/graph/nodes/flow.c1329
-rw-r--r--src/gtkext/graph/nodes/flow.h99
-rw-r--r--src/gtkext/graph/nodes/virtual.c990
-rw-r--r--src/gtkext/graph/nodes/virtual.h77
-rw-r--r--src/gtkext/graph/params.h84
-rw-r--r--src/gtkext/graph/ranks.c695
-rw-r--r--src/gtkext/graph/ranks.h82
-rw-r--r--src/gtkext/gtkgraphview.c206
-rw-r--r--src/gtkext/gtkgraphview.h6
20 files changed, 1653 insertions, 5116 deletions
diff --git a/src/gtkext/graph/Makefile.am b/src/gtkext/graph/Makefile.am
index f54a97b..706811b 100755..100644
--- a/src/gtkext/graph/Makefile.am
+++ b/src/gtkext/graph/Makefile.am
@@ -2,14 +2,10 @@
noinst_LTLIBRARIES = libgtkextgraph.la
libgtkextgraph_la_SOURCES = \
- edge.h edge.c \
- layout.h layout.c \
- node.h node.c \
- params.h \
- ranks.h ranks.c
+ cluster.h cluster.c \
+ edge.h edge.c
-libgtkextgraph_la_LIBADD = \
- nodes/libgtkextgraphnodes.la
+libgtkextgraph_la_LIBADD =
libgtkextgraph_la_LDFLAGS =
@@ -18,4 +14,4 @@ AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS)
AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
-SUBDIRS = nodes
+SUBDIRS =
diff --git a/src/gtkext/graph/cluster.c b/src/gtkext/graph/cluster.c
new file mode 100644
index 0000000..4c92718
--- /dev/null
+++ b/src/gtkext/graph/cluster.c
@@ -0,0 +1,1330 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * cluster.c - mise en place de graphiques
+ *
+ * Copyright (C) 2016 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * OpenIDA is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * OpenIDA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "cluster.h"
+
+
+#include <assert.h>
+#include <malloc.h>
+#include <string.h>
+
+
+#include "../gtkblockview.h"
+#include "../gtkbufferview.h"
+#include "../gtkviewpanel.h"
+#include "../../common/sort.h"
+
+
+
+/* Définition du tracé d'un lien */
+typedef struct _link_def
+{
+ InstructionLinkType type; /* Complexité du tracé */
+
+ GdkPoint y; /* Position des décrochages */
+
+ GdkPoint end; /* Point d'arrivée final */
+
+ GGraphEdge *edge; /* Lien complet en préparation */
+
+} link_def;
+
+/* Découpage vertical */
+typedef struct _graph_rank
+{
+ unsigned int level; /* Niveau des blocs */
+
+ GGraphCluster **clusters; /* Ensembles de blocs */
+ size_t count; /* Nombre de ces ensembles */
+
+} graph_rank;
+
+/* Mise en disposition de blocs en graphique (instance) */
+struct _GGraphCluster
+{
+ GObject parent; /* A laisser en premier */
+
+
+ ////////////////////////////////////////
+ gint top_margin[2]; /* Espaces gauches et droites */
+ gint left_margin; /* Espaces remontant à gauche */
+ gint right_margin; /* Espaces remontant à droite */
+ ////////////////////////////////////////
+
+
+ link_def **top_anchors; /* Accroches supérieures */
+ size_t ta_count; /* Quantité de ces accroches */
+
+ GBasicBlock *block; /* Bloc d'origine représenté */
+ GtkWidget *view; /* Vue graphique associée */
+ GtkAllocation alloc; /* Emplacement final du bloc */
+
+ GdkPoint **bottom_anchors; /* Accroches inférieures */
+ size_t ba_count; /* Quantité de ces accroches */
+
+ graph_rank *ranks; /* Répartition verticale */
+ size_t ranks_count; /* Nombre de divisions */
+
+};
+
+/* Mise en disposition de blocs en graphique (classe) */
+struct _GGraphClusterClass
+{
+ GObjectClass parent; /* A laisser en premier */
+
+};
+
+
+/* Espace minimal horizontal entre les blocs */
+#define HORIZONTAL_MARGIN 20
+
+/* Espace minimal vertical entre les blocs */
+#define VERTICAL_MARGIN 30
+
+/* Espace minimal entre les liens */
+#define LINK_MARGIN 10
+
+
+/* Initialise la classe des mises en disposition graphique. */
+static void g_graph_cluster_class_init(GGraphClusterClass *);
+
+/* Initialise une mise en disposition de blocs en graphique. */
+static void g_graph_cluster_init(GGraphCluster *);
+
+/* Supprime toutes les références externes. */
+static void g_graph_cluster_dispose(GGraphCluster *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_graph_cluster_finalize(GGraphCluster *);
+
+/* Complète un graphique avec un sous-ensemble de blocs. */
+static void g_graph_cluster_add_sub(GGraphCluster *, GGraphCluster *, GBasicBlock *);
+
+/* Organisation la disposition d'un ensemble de blocs basiques. */
+static void g_graph_cluster_dispatch_x(GGraphCluster *);
+
+/* Détermine une position pour un ensemble de blocs basiques. */
+//static void g_graph_cluster_set_x(GGraphCluster *, gint);
+
+/* Décalle vers la droite un ensemble de blocs basiques. */
+static void g_graph_cluster_offset_x(GGraphCluster *, gint);
+
+/* Décalle vers le bas un ensemble de blocs basiques. */
+static void g_graph_cluster_set_y(GGraphCluster *, gint);
+
+
+
+
+
+/* Recherche le bloc basique à l'extrémité d'un lien. */
+//static GGraphCluster *g_graph_cluster_find_lower_dest_cluster(const GGraphCluster *, const GArchInstruction *);
+
+/* Met en place les embryons de liens nécessaires. */
+static void g_graph_cluster_define_links(GGraphCluster *, GHashTable *);
+
+/* Détermine les positions de tous les liens en place. */
+static void g_graph_cluster_compute_link_positions(GGraphCluster *);
+
+/* Applique les positions calculées pour chaque lien graphique. */
+static void g_graph_cluster_resolve_links(const GGraphCluster *);
+
+
+
+
+
+
+/* Indique le type définit par la GLib pour les mises en disposition graphique. */
+G_DEFINE_TYPE(GGraphCluster, g_graph_cluster, G_TYPE_OBJECT);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des mises en disposition graphique. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_graph_cluster_class_init(GGraphClusterClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_graph_cluster_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_graph_cluster_finalize;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : cluster = instance à initialiser. *
+* *
+* Description : Initialise une mise en disposition de blocs en graphique. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_graph_cluster_init(GGraphCluster *cluster)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : cluster = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_graph_cluster_dispose(GGraphCluster *cluster)
+{
+ g_object_unref(G_OBJECT(cluster->block));
+ g_object_unref(G_OBJECT(cluster->view));
+
+ G_OBJECT_CLASS(g_graph_cluster_parent_class)->dispose(G_OBJECT(cluster));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : cluster = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_graph_cluster_finalize(GGraphCluster *cluster)
+{
+ G_OBJECT_CLASS(g_graph_cluster_parent_class)->finalize(G_OBJECT(cluster));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : binary = binaire charger dont le code est à représenter.*
+* list = ensemble de blocs basiques à manipuler. *
+* index = indice du bloc principal à mettre en place. *
+* highlighted = gestionnaire de surbrillance pour segments. *
+* *
+* Description : Construit un graphique à partir de blocs basiques. *
+* *
+* Retour : Adresse de la structure mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GGraphCluster *g_graph_cluster_new(GLoadedBinary *binary, const GBlockList *list, size_t index, segcnt_list *highlighted)
+{
+ GGraphCluster *result; /* Structure à retourner */
+ vmpa2t first; /* Début d'un groupe de lignes */
+ vmpa2t last; /* Fin d'un groupe de lignes */
+ GCodeBuffer *buffer; /* Tampon brut à découper */
+ GBufferView *view; /* Partie affichée du tampon */
+ GtkRequisition requisition; /* Taille à l'écran actuelle */
+
+ result = g_object_new(G_TYPE_GRAPH_CLUSTER, NULL);
+
+ /* Encapsulation du bloc d'entrée */
+
+ result->block = g_block_list_get_block(list, index);
+ g_object_ref(G_OBJECT(result->block));
+
+ result->view = gtk_block_view_new();
+
+ gtk_widget_show(result->view);
+ gtk_view_panel_attach_binary(GTK_VIEW_PANEL(result->view), binary, BVW_GRAPH);
+
+ gtk_view_panel_show_border(GTK_VIEW_PANEL(result->view), true);
+
+ /* Restriction au bloc basique */
+
+ g_basic_block_get_boundary_addresses(result->block, &first, &last);
+
+ buffer = g_loaded_binary_get_disassembled_buffer(binary);
+
+ view = g_buffer_view_new(buffer, highlighted);
+ g_buffer_view_restrict(view, &first, &last);
+ gtk_buffer_view_attach_buffer(GTK_BUFFER_VIEW(result->view), view);
+
+ /* Détermination d'une position initiale centrée */
+
+ gtk_widget_get_preferred_size(result->view, NULL, &requisition);
+
+ result->alloc.x = -requisition.width / 2;
+ result->alloc.y = 0;
+
+ result->alloc.width = requisition.width;
+ result->alloc.height = requisition.height;
+
+ printf("BLOCK INIT :: %d <> %d\n", result->alloc.x, result->alloc.width);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : cluster = graphique de blocs à compléter. *
+* sub = sous-ensemble à intégrer. *
+* block = bloc basique de départ du sous-ensemble. *
+* *
+* Description : Complète un graphique avec un sous-ensemble de blocs. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_graph_cluster_add_sub(GGraphCluster *cluster, GGraphCluster *sub, GBasicBlock *block)
+{
+ unsigned int level; /* Niveau du nouvel ensemble */
+ size_t i; /* Boucle de parcours */
+ graph_rank new; /* Nouvel étage à insérer */
+ graph_rank *rank; /* Nouvel étage à compléter */
+
+ level = g_basic_block_get_rank(block);
+
+ for (i = 0; i < cluster->ranks_count; i++)
+ if (cluster->ranks[i].level == level)
+ break;
+
+ if (i == cluster->ranks_count)
+ {
+ new.level = level;
+
+ new.clusters = (GGraphCluster **)calloc(1, sizeof(GGraphCluster *));
+ new.count = 1;
+
+ new.clusters[0] = sub;
+
+ int cmp_graph_rank(const graph_rank *a, const graph_rank *b)
+ {
+ if (a->level < b->level)
+ return -1;
+
+ else if (a->level > b->level)
+ return 1;
+
+ else
+ return 0;
+
+ }
+
+ cluster->ranks = qinsert(cluster->ranks, &cluster->ranks_count,
+ sizeof(graph_rank), (__compar_fn_t)cmp_graph_rank, &new);
+
+ }
+
+ else
+ {
+ rank = &cluster->ranks[i];
+
+ rank->count++;
+ rank->clusters = (GGraphCluster **)realloc(rank->clusters,
+ sizeof(GGraphCluster *) * rank->count);
+
+ rank->clusters[rank->count - 1] = sub;
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : cluster = graphique de blocs à manipuler. *
+* *
+* Description : Organisation la disposition d'un ensemble de blocs basiques. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_graph_cluster_dispatch_x(GGraphCluster *cluster)
+{
+ size_t k; /* Boucle de parcours #1 */
+ size_t rcount; /* Nombre d'ensembles présents */
+ size_t mid; /* Position centrale de départ */
+ gint start; /* Position initiale de départ */
+
+ void place_sub(GGraphCluster **iter, size_t loop, gint base, int dir)
+ {
+ size_t i; /* Boucle de parcours #2 */
+ GtkAllocation needed; /* Taille requise */
+
+ assert(dir == -1 || dir == 1);
+
+ for (i = 0; i < loop; i++, iter += dir)
+ {
+ g_graph_cluster_dispatch_x(*iter);
+
+ g_graph_cluster_compute_needed_alloc(*iter, &needed);
+
+ if (dir > 0)
+ g_graph_cluster_offset_x(*iter, base - needed.x);
+ else
+ g_graph_cluster_offset_x(*iter, base - needed.x - needed.width);
+
+ base += dir * (needed.width + HORIZONTAL_MARGIN);
+
+ }
+
+ }
+
+
+
+
+ for (k = 0; k < cluster->ranks_count; k++)
+ {
+ rcount = cluster->ranks[k].count;
+
+ if (rcount % 2 == 1)
+ {
+ if (rcount > 1)
+ {
+ mid = rcount / 2;
+
+ start = cluster->ranks[k].clusters[mid]->alloc.x - HORIZONTAL_MARGIN;
+
+ place_sub(cluster->ranks[k].clusters + mid - 1, mid, start, -1);
+
+ start *= -1;
+
+ place_sub(cluster->ranks[k].clusters + mid + 1, mid, start, 1);
+
+ }
+
+ }
+
+ else
+ {
+ mid = rcount / 2 - 1;
+
+ start = - HORIZONTAL_MARGIN / 2;
+
+ place_sub(cluster->ranks[k].clusters + mid, mid + 1, start, -1);
+
+ start *= -1;
+
+ place_sub(cluster->ranks[k].clusters + mid + 1, mid + 1, start, 1);
+
+ }
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : cluster = graphique de blocs à actualiser. *
+* x = position finale sur l'axe des abscisses. *
+* *
+* Description : Détermine une position pour un ensemble de blocs basiques. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+/*
+static void g_graph_cluster_set_x(GGraphCluster *cluster, gint x)
+{
+ g_graph_cluster_offset_x(cluster, -cluster->alloc.x);
+
+ g_graph_cluster_offset_x(cluster, x);
+
+}
+*/
+
+
+/******************************************************************************
+* *
+* Paramètres : cluster = graphique de blocs à actualiser. *
+* offset = décallage à appliquer. *
+* *
+* Description : Décalle vers la droite un ensemble de blocs basiques. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_graph_cluster_offset_x(GGraphCluster *cluster, gint offset)
+{
+ size_t i; /* Boucle de parcours #1 */
+ size_t j; /* Boucle de parcours #2 */
+
+ cluster->alloc.x += offset;
+
+ for (i = 0; i < cluster->ranks_count; i++)
+ for (j = 0; j < cluster->ranks[i].count; j++)
+ g_graph_cluster_offset_x(cluster->ranks[i].clusters[j], offset);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : cluster = graphique de blocs à actualiser. *
+* base = position ordonnée à appliquer. *
+* *
+* Description : Décalle vers le bas un ensemble de blocs basiques. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_graph_cluster_set_y(GGraphCluster *cluster, gint base)
+{
+ size_t i; /* Boucle de parcours #1 */
+ gint max; /* Hauteur maximale rencontrée */
+ size_t j; /* Boucle de parcours #2 */
+ GGraphCluster *sub; /* Sous-ensemble traité */
+ GtkAllocation alloc; /* Allocation courante */
+
+ cluster->alloc.y = base;
+
+ base += cluster->alloc.height;
+
+ for (i = 0; i < cluster->ranks_count; i++)
+ {
+ base += VERTICAL_MARGIN;
+
+ max = 0;
+
+ for (j = 0; j < cluster->ranks[i].count; j++)
+ {
+ sub = cluster->ranks[i].clusters[j];
+
+ g_graph_cluster_set_y(sub, base);
+
+ g_graph_cluster_compute_needed_alloc(sub, &alloc);
+
+ if ((alloc.y + alloc.height) > max)
+ max = alloc.y + alloc.height;
+
+ }
+
+ base = max;
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : cluster = encapsulation à consulter. *
+* alloc = emplacement idéal pour l'affichage. *
+* *
+* Description : Détermine l'emplacement requis d'un ensemble de blocs. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_graph_cluster_compute_needed_alloc(const GGraphCluster *cluster, GtkAllocation *alloc)
+{
+ GtkAllocation needed; /* Taille requise */
+ size_t i; /* Boucle de parcours */
+ size_t rcount; /* Nombre d'ensembles présents */
+
+ *alloc = cluster->alloc;
+
+ for (i = 0; i < cluster->ranks_count; i++)
+ {
+ rcount = cluster->ranks[i].count;
+
+ switch (rcount)
+ {
+ case 1:
+
+ g_graph_cluster_compute_needed_alloc(cluster->ranks[i].clusters[0], &needed);
+
+ if (needed.x < alloc->x)
+ {
+ alloc->width += (alloc->x + needed.x);
+ alloc->x = needed.x;
+ }
+
+ if ((needed.x + needed.width) > (alloc->x + alloc->width))
+ alloc->width += needed.x + needed.width - alloc->x - alloc->width;
+
+ /* La hauteur maximale n'est présente qu'avec le dernier morceau */
+ if ((i + 1) == cluster->ranks_count)
+ {
+ if ((needed.y + needed.height) > (alloc->y + alloc->height))
+ alloc->height += needed.y + needed.height - alloc->y - alloc->height;
+ }
+
+ break;
+
+ default:
+
+ assert(rcount >= 2);
+
+ g_graph_cluster_compute_needed_alloc(cluster->ranks[i].clusters[0], &needed);
+
+ if (needed.x < alloc->x)
+ {
+ alloc->width += (alloc->x + needed.x);
+ alloc->x = needed.x;
+ }
+
+ /* La hauteur maximale n'est présente qu'avec le dernier morceau */
+ if ((i + 1) == cluster->ranks_count)
+ {
+ if ((needed.y + needed.height) > (alloc->y + alloc->height))
+ alloc->height += needed.y + needed.height - alloc->y - alloc->height;
+ }
+
+ g_graph_cluster_compute_needed_alloc(cluster->ranks[i].clusters[rcount - 1], &needed);
+
+ if ((needed.x + needed.width) > (alloc->x + alloc->width))
+ alloc->width += needed.x + needed.width - alloc->x - alloc->width;
+
+ /* La hauteur maximale n'est présente qu'avec le dernier morceau */
+ if ((i + 1) == cluster->ranks_count)
+ {
+ if ((needed.y + needed.height) > (alloc->y + alloc->height))
+ alloc->height += needed.y + needed.height - alloc->y - alloc->height;
+ }
+
+ break;
+
+ }
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : cluster = encapsulation à traiter. *
+* view = support de destination finale. *
+* *
+* Description : Dispose chaque noeud sur la surface de destination donnée. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_graph_cluster_place(GGraphCluster *cluster, GtkGraphView *view)
+{
+ size_t i; /* Boucle de parcours #1 */
+ size_t j; /* Boucle de parcours #2 */
+
+ g_object_ref(G_OBJECT(cluster->view));
+ gtk_graph_view_put(view, cluster->view, &cluster->alloc);
+
+ for (i = 0; i < cluster->ta_count; i++)
+ {
+ g_object_ref(G_OBJECT(cluster->top_anchors[i]->edge));
+ gtk_graph_view_add_edge(view, cluster->top_anchors[i]->edge);
+ }
+
+ for (i = 0; i < cluster->ranks_count; i++)
+ for (j = 0; j < cluster->ranks[i].count; j++)
+ g_graph_cluster_place(cluster->ranks[i].clusters[j], view);
+
+}
+
+
+
+
+
+
+
+
+//////////////////////////////////////////////////////////
+
+
+
+
+
+
+/******************************************************************************
+* *
+* Paramètres : cluster = graphique de blocs à consulter ou remonter. *
+* first = première instruction du bloc basique recherché. *
+* *
+* Description : Recherche le bloc basique à l'extrémité d'un lien. *
+* *
+* Retour : Bloc graphique de destination pour un lien ou NULL si échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+#if 0
+static GGraphCluster *g_graph_cluster_find_lower_dest_cluster(const GGraphCluster *cluster, const GArchInstruction *first)
+{
+ GGraphCluster *result; /* Trouvaille à retourner */
+ size_t i; /* Boucle de parcours #1 */
+ const graph_rank *rank; /* Confort d'accès */
+ size_t j; /* Boucle de parcours #2 */
+ GArchInstruction *instr; /* Instruction à comparer */
+
+ result = NULL;
+
+ for (i = 0; i < cluster->ranks_count && result == NULL; i++)
+ {
+ rank = &cluster->ranks[i];
+
+ for (j = 0; j < rank->count && result == NULL; j++)
+ {
+ g_basic_block_get_boundary(rank->clusters[j]->block, &instr, NULL);
+
+ if (instr == first)
+ result = rank->clusters[j];
+
+ }
+
+ }
+
+ return result;
+
+}
+#endif
+
+/******************************************************************************
+* *
+* Paramètres : cluster = graphique de blocs à actualiser. *
+* all = table regroupant tous les groupes créés. *
+* *
+* Description : Met en place les embryons de liens nécessaires. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_graph_cluster_define_links(GGraphCluster *cluster, GHashTable *all)
+{
+ GArchInstruction *last; /* Dernière instruction du bloc*/
+ GArchInstruction **dests; /* Instr. visée par une autre */
+ InstructionLinkType *types; /* Type de lien entre lignes */
+ size_t dcount; /* Nombre de liens de dest. */
+ size_t i; /* Boucle de parcours #1 */
+ GGraphCluster *target; /* Bloc ciblé par un lien */
+ GdkPoint *start; /* Point de départ d'un lien */
+ link_def *end; /* Définitions d'arrivée */
+ size_t j; /* Boucle de parcours #2 */
+
+ /* Au niveau du bloc courant */
+
+ g_basic_block_get_boundary(cluster->block, NULL, &last);
+
+ g_arch_instruction_rlock_dest(last);
+ dcount = g_arch_instruction_get_destinations(last, &dests, &types, NULL);
+
+ for (i = 0; i < dcount; i++)
+ switch (types[i])
+ {
+ case ILT_EXEC_FLOW:
+ case ILT_JUMP:
+ case ILT_CASE_JUMP:
+ case ILT_JUMP_IF_TRUE:
+ case ILT_JUMP_IF_FALSE:
+
+ target = G_GRAPH_CLUSTER(g_hash_table_lookup(all, dests[i]));
+ assert(target != NULL);
+
+ /* Point de départ */
+
+ start = (GdkPoint *)calloc(1, sizeof(GdkPoint));
+
+ cluster->bottom_anchors = (GdkPoint **)realloc(cluster->bottom_anchors,
+ ++cluster->ba_count * sizeof(GdkPoint *));
+ cluster->bottom_anchors[cluster->ba_count - 1] = start;
+
+ /* Point d'arrivée */
+
+ end = (link_def *)calloc(1, sizeof(link_def));
+
+ target->top_anchors = (link_def **)realloc(target->top_anchors,
+ ++target->ta_count * sizeof(link_def *));
+ target->top_anchors[target->ta_count - 1] = end;
+
+ /* Etablissement d'un embryon de lien */
+
+ end->type = types[i];
+
+ if (types[i] == ILT_JUMP_IF_TRUE)
+ end->edge = g_graph_edge_new_true(start, &end->y, &end->end);
+
+ else if (types[i] == ILT_JUMP_IF_FALSE)
+ end->edge = g_graph_edge_new_false(start, &end->y, &end->end);
+
+ else
+ end->edge = g_graph_edge_new(start, &end->y, &end->end);
+
+ break;
+
+
+ case ILT_LOOP:
+
+ /* TODO */
+ assert(false);
+
+ break;
+
+ default:
+ break;
+
+ }
+
+ g_arch_instruction_runlock_dest(last);
+
+ /* Propagation de la mise en place */
+
+ for (i = 0; i < cluster->ranks_count; i++)
+ for (j = 0; j < cluster->ranks[i].count; j++)
+ g_graph_cluster_define_links(cluster->ranks[i].clusters[j], all);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : cluster = graphique de blocs à actualiser. *
+* *
+* Description : Détermine les positions de tous les liens en place. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_graph_cluster_compute_link_positions(GGraphCluster *cluster)
+{
+ gint mid_x; /* Abscisse centrale */
+ size_t half; /* Indice de répartition égale */
+ gint y; /* Ordonnée d'application */
+
+ size_t i; /* Boucle de parcours #1 */
+ GdkPoint *pt; /* Point à actualiser */
+ size_t j; /* Boucle de parcours #2 */
+
+
+
+ mid_x = cluster->alloc.x + (cluster->alloc.width / 2);
+
+ /* Du côté des départs... */
+
+ if (cluster->ba_count > 0)
+ {
+ half = cluster->ba_count / 2;
+
+ y = cluster->alloc.y + cluster->alloc.height;
+
+ if (cluster->ba_count % 2 == 1)
+ {
+ for (i = half; i > 0; i--)
+ {
+ pt = cluster->bottom_anchors[i - 1];
+
+ pt->x = mid_x - (half - i + 1) * LINK_MARGIN;
+ pt->y = y;
+
+ }
+
+ pt = cluster->bottom_anchors[half];
+
+ pt->x = mid_x;
+ pt->y = y;
+
+ for (i = half + 1; i < cluster->ba_count; i++)
+ {
+ pt = cluster->bottom_anchors[i];
+
+ pt->x = mid_x + (i - half) * LINK_MARGIN;
+ pt->y = y;
+
+ }
+
+ }
+
+ else
+ {
+ for (i = half; i > 0; i--)
+ {
+ pt = cluster->bottom_anchors[i - 1];
+
+ pt->x = mid_x - LINK_MARGIN / 2 - (half - i) * LINK_MARGIN;
+ pt->y = y;
+
+ }
+
+ for (i = half; i < cluster->ba_count; i++)
+ {
+ pt = cluster->bottom_anchors[i];
+
+ pt->x = mid_x + LINK_MARGIN / 2 + (half - i) * LINK_MARGIN;
+ pt->y = y;
+
+ }
+
+ }
+
+ }
+
+ /* Du côté des arrivées... */
+
+ if (cluster->ta_count > 0)
+ {
+ half = cluster->ta_count / 2;
+
+ y = cluster->alloc.y;
+
+ if (cluster->ta_count % 2 == 1)
+ {
+ for (i = half; i > 0; i--)
+ {
+ pt = &cluster->top_anchors[i - 1]->end;
+
+ pt->x = mid_x - (half - i + 1) * LINK_MARGIN;
+ pt->y = y;
+
+ }
+
+ pt = &cluster->top_anchors[half]->end;
+
+ pt->x = mid_x;
+ pt->y = y;
+
+ for (i = half + 1; i < cluster->ta_count; i++)
+ {
+ pt = &cluster->top_anchors[i]->end;
+
+ pt->x = mid_x + (i - half) * LINK_MARGIN;
+ pt->y = y;
+
+ }
+
+ }
+
+ else
+ {
+ for (i = half; i > 0; i--)
+ {
+ pt = &cluster->top_anchors[i - 1]->end;
+
+ pt->x = mid_x - LINK_MARGIN / 2 - (half - i) * LINK_MARGIN;
+ pt->y = y;
+
+ }
+
+ for (i = half; i < cluster->ta_count; i++)
+ {
+ pt = &cluster->top_anchors[i]->end;
+
+ pt->x = mid_x + LINK_MARGIN / 2 + (half - i) * LINK_MARGIN;
+ pt->y = y;
+
+ }
+
+ }
+
+
+
+
+
+
+
+
+ for (i = 0; i < cluster->ta_count; i++)
+ cluster->top_anchors[i]->y.y = cluster->top_anchors[i]->end.y - 18;
+
+
+
+
+
+
+
+ }
+
+ /* Propagation des déterminations */
+
+ for (i = 0; i < cluster->ranks_count; i++)
+ for (j = 0; j < cluster->ranks[i].count; j++)
+ g_graph_cluster_compute_link_positions(cluster->ranks[i].clusters[j]);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : cluster = graphique de blocs à consulter. *
+* *
+* Description : Applique les positions calculées pour chaque lien graphique. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_graph_cluster_resolve_links(const GGraphCluster *cluster)
+{
+ size_t i; /* Boucle de parcours #1 */
+ size_t j; /* Boucle de parcours #2 */
+
+ for (i = 0; i < cluster->ta_count; i++)
+ g_graph_edge_resolve(cluster->top_anchors[i]->edge);
+
+ for (i = 0; i < cluster->ranks_count; i++)
+ for (j = 0; j < cluster->ranks[i].count; j++)
+ g_graph_cluster_resolve_links(cluster->ranks[i].clusters[j]);
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/* Liste de blocs restants à traiter */
+typedef struct _pending_blocks
+{
+ size_t count; /* Taille de la liste */
+ GBasicBlock *list[0]; /* Liste de blocs à traiter */
+
+} pending_blocks;
+
+
+
+
+
+/* Met en place un ensemble de blocs sous forme graphique. */
+static GGraphCluster *setup_graph_clusters(GLoadedBinary *, const GBlockList *, size_t , segcnt_list *, pending_blocks *, GHashTable *);
+
+
+
+
+
+/******************************************************************************
+* *
+* Paramètres : binary = binaire charger dont le code est à représenter.*
+* list = ensemble de blocs basiques à manipuler. *
+* index = indice du bloc principal à mettre en place. *
+* highlighted = gestionnaire de surbrillance pour segments. *
+* pending = liste de blocs restant à traiter. [OUT] *
+* all = table regroupant tous les groupes créés. *
+* *
+* Description : Met en place un ensemble de blocs sous forme graphique. *
+* *
+* Retour : Ensemble de blocs mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GGraphCluster *setup_graph_clusters(GLoadedBinary *binary, const GBlockList *list, size_t index, segcnt_list *highlighted, pending_blocks *pending, GHashTable *all)
+{
+ GGraphCluster *result; /* Instance nouvelle à renvoyer*/
+ GBasicBlock *block; /* Bloc à manipuler */
+ GArchInstruction *first; /* Première instruction du bloc*/
+ GArchInstruction *last; /* Dernière instruction du bloc*/
+#ifndef NDEBUG
+ gboolean new; /* Bloc déjà traité ? */
+#endif
+ GArchInstruction **dests; /* Instr. visée par une autre */
+ InstructionLinkType *types; /* Type de lien entre lignes */
+ size_t dcount; /* Nombre de liens de dest. */
+ size_t i; /* Boucle de parcours #1 */
+ GBasicBlock *target; /* Bloc ciblé par un lien */
+ size_t j; /* Boucle de parcours #2 */
+ bool changed; /* Un ajout a été effectué ? */
+ const bitfield_t *dominators; /* Blocs dominant ce même bloc */
+ size_t next; /* Indice du prochain bloc */
+ GGraphCluster *sub; /* Sous-ensemble à intégrer */
+
+ result = g_graph_cluster_new(binary, list, index, highlighted);
+
+ block = g_block_list_get_block(list, index);
+
+ g_basic_block_get_boundary(block, &first, &last);
+
+#ifndef NDEBUG
+ new = g_hash_table_insert(all, first, result);
+ assert(new);
+#else
+ g_hash_table_insert(all, first, result);
+#endif
+
+ /* Détermination des blocs suivants */
+
+ g_arch_instruction_rlock_dest(last);
+ dcount = g_arch_instruction_get_destinations(last, &dests, &types, NULL);
+
+ printf(" ... block=%p dest=%zu\n", block, dcount);
+
+ for (i = 0; i < dcount; i++)
+ switch (types[i])
+ {
+ case ILT_EXEC_FLOW:
+ case ILT_JUMP:
+ case ILT_CASE_JUMP:
+ case ILT_JUMP_IF_TRUE:
+ case ILT_JUMP_IF_FALSE:
+
+ target = g_block_list_find_by_starting_instr(list, dests[i]);
+
+ /**
+ * Les sauts ne se font pas toujours à l'intérieur d'une même fonction.
+ * Par exemple sous ARM :
+ *
+ * 00008358 <call_gmon_start>:
+ * ....
+ * 8362: f7ff bfcf b.w 8304 <_init+0x38>
+ * ....
+ *
+ */
+
+ printf(" NEW BLK :: %d -> %p\n", types[i], target);
+
+ if (target != NULL)
+ {
+ for (j = 0; j < pending->count; j++)
+ if (pending->list[j] == target)
+ break;
+
+ if (j == pending->count)
+ {
+ assert((pending->count + 1) < g_block_list_count_blocks(list));
+ pending->list[pending->count++] = target;
+ printf(" --push-- %d -> %p\n", types[i], target);
+ }
+
+ do
+ {
+ size_t k;
+ printf(" --stack-- ");
+ for (k = 0; k < pending->count; k++)
+ printf("%p ", pending->list[k]);
+ printf("\n");
+ }
+ while (0);
+
+
+
+ }
+
+ break;
+
+ default:
+ break;
+
+ }
+
+ g_arch_instruction_runlock_dest(last);
+
+ /* Intégration de tous les blocs en attente */
+
+ do
+ {
+ changed = false;
+
+ for (i = 0; i < pending->count && !changed; i++)
+ {
+ block = pending->list[i];
+ dominators = g_basic_block_get_domination(block);
+
+ if (test_in_bit_field(dominators, index, 1))
+ {
+ /* Dépilement */
+
+ changed = true;
+
+ if ((i + 1) < pending->count)
+ memmove(&pending->list[i], &pending->list[i + 1],
+ (pending->count - i - 1) * sizeof(GBasicBlock *));
+
+ pending->count--;
+
+ /* Intégration */
+
+ next = g_block_list_get_index(list, block);
+ assert(next < g_block_list_count_blocks(list));
+
+ printf(" --pop-- block=%p index=%zu\n", block, next);
+
+ sub = setup_graph_clusters(binary, list, next, highlighted, pending, all);
+
+ g_graph_cluster_add_sub(result, sub, block);
+
+ }
+
+ }
+
+ }
+ while (changed);
+
+ return result;
+
+}
+
+
+
+
+
+/******************************************************************************
+* *
+* Paramètres : blocks = ensemble des blocs basiques déjà découpés. *
+* views = morceaux de code à afficher de façon organisée. *
+* count = quantité de ces morceaux de code. *
+* *
+* Description : Construit un graphique à partir de blocs basiques. *
+* *
+* Retour : Adresse de la structure mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GGraphCluster *bootstrap_graph_cluster(GLoadedBinary *binary, const GBlockList *list, segcnt_list *highlighted)
+{
+ GGraphCluster *result; /* Structure à retourner */
+ GHashTable *all; /* Collection des créations */
+ size_t count; /* Taille de la liste de blocs */
+ pending_blocks *pending; /* Suivi des blocs à traiter */
+ GtkAllocation needed; /* Taille requise */
+
+
+ all = g_hash_table_new(NULL, NULL);
+
+ count = g_block_list_count_blocks(list);
+
+ pending = (pending_blocks *)calloc(1, sizeof(pending_blocks) + count * sizeof(GBasicBlock *));
+
+
+
+
+ do
+ {
+ size_t i;
+ GBasicBlock *block;
+ const bitfield_t *domination;
+
+ printf("DBG // count : %zu\n", count);
+
+ for (i = 0; i < count; i++)
+ {
+ block = g_block_list_get_block(list, i);
+ domination = g_basic_block_get_domination(block);
+
+ printf("DBG // block [%zu] : 0x%08lx -- rank = %u\n",
+ i, gfw(domination), g_basic_block_get_rank(block));
+
+ }
+
+ fflush(NULL);
+
+ }
+ while (0);
+
+
+
+
+
+ result = setup_graph_clusters(binary, list, 0, highlighted, pending, all);
+
+ free(pending);
+
+ g_graph_cluster_define_links(result, all);
+
+ /* Positionnements dans l'espace */
+
+ g_graph_cluster_dispatch_x(result);
+
+ g_graph_cluster_set_y(result, 0);
+
+ /* Réajustement vers la droite */
+
+ g_graph_cluster_compute_needed_alloc(result, &needed);
+
+ g_graph_cluster_offset_x(result, -needed.x);
+
+ /* Application finale sur les liens */
+
+ g_graph_cluster_compute_link_positions(result);
+
+ g_graph_cluster_resolve_links(result);
+
+
+
+
+ g_hash_table_unref(all);
+
+
+ return result;
+
+
+}
diff --git a/src/gtkext/graph/cluster.h b/src/gtkext/graph/cluster.h
new file mode 100644
index 0000000..a41adc7
--- /dev/null
+++ b/src/gtkext/graph/cluster.h
@@ -0,0 +1,71 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * cluster.h - prototypes pour la mise en place de graphiques
+ *
+ * Copyright (C) 2016 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * OpenIDA is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * OpenIDA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GTKEXT_GRAPH_CLUSTER_H
+#define _GTKEXT_GRAPH_CLUSTER_H
+
+
+
+#include "../gtkgraphview.h"
+#include "../../analysis/binary.h"
+#include "../../analysis/disass/block.h"
+
+
+
+#define G_TYPE_GRAPH_CLUSTER g_graph_cluster_get_type()
+#define G_GRAPH_CLUSTER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_GRAPH_CLUSTER, GGraphCluster))
+#define G_IS_GRAPH_CLUSTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_GRAPH_CLUSTER))
+#define G_GRAPH_CLUSTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_GRAPH_CLUSTER, GGraphClusterClass))
+#define G_IS_GRAPH_CLUSTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_GRAPH_CLUSTER))
+#define G_GRAPH_CLUSTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_GRAPH_CLUSTER, GGraphClusterClass))
+
+
+/* Mise en disposition de blocs en graphique (instance) */
+typedef struct _GGraphCluster GGraphCluster;
+
+/* Mise en disposition de blocs en graphique (classe) */
+typedef struct _GGraphClusterClass GGraphClusterClass;
+
+
+/* Indique le type définit par la GLib pour les mises en disposition graphique. */
+GType g_graph_cluster_get_type(void);
+
+/* Construit un graphique à partir de blocs basiques. */
+GGraphCluster *g_graph_cluster_new(GLoadedBinary *, const GBlockList *, size_t, segcnt_list *);
+
+/* Détermine l'emplacement requis d'un ensemble de blocs. */
+void g_graph_cluster_compute_needed_alloc(const GGraphCluster *, GtkAllocation *);
+
+/* Dispose chaque noeud sur la surface de destination donnée. */
+void g_graph_cluster_place(GGraphCluster *, GtkGraphView *);
+
+
+
+
+
+GGraphCluster *bootstrap_graph_cluster(GLoadedBinary *binary, const GBlockList *list, segcnt_list *highlighted);
+
+
+
+
+#endif /* _GTKEXT_GRAPH_CLUSTER_H */
diff --git a/src/gtkext/graph/edge.c b/src/gtkext/graph/edge.c
index 5750198..a917cc3 100644
--- a/src/gtkext/graph/edge.c
+++ b/src/gtkext/graph/edge.c
@@ -24,10 +24,10 @@
#include "edge.h"
+#include <assert.h>
+#include <malloc.h>
#include <math.h>
-
-
-#include "nodes/virtual.h"
+#include <string.h>
@@ -36,18 +36,13 @@ struct _GGraphEdge
{
GObject parent; /* A laisser en premier */
- GFlowNode *src_node; /* Bloc de départ du lien */
- node_slot_t *src_slot; /* Numéro d'ancrage initial */
- GFlowNode *dest_node; /* Bloc d'arrivée du lien */
- node_slot_t *dest_slot; /* Numéro d'ancrage final */
+ EdgeColor color; /* Couleur du rendu */
- hspan_slot_t top_step; /* Niveau sup. de destination */
- GVirtualNode *container; /* Conteneur pour les tours */
- bool is_left; /* Tour par la gauche ? */
- vspan_slot_t vert_step; /* Position de contournement */
- hspan_slot_t bottom_step; /* Niveau inf. de source */
+ const GdkPoint *start; /* Point de départ du lien */
+ GdkPoint *mid[2]; /* Etapes intermédiaires */
+ size_t m_count; /* Quantité de ces étapes */
+ const GdkPoint *end; /* Point d'arrivée du lien */
- EdgeColor color; /* Couleur du rendu */
GdkPoint *points; /* Points de la ligne dessinée */
size_t count; /* Quantité de ces points */
@@ -61,6 +56,11 @@ struct _GGraphEdgeClass
};
+/* Dimensions des flêches */
+#define ARROW_LENGHT 10
+#define ARROW_DEGREES 10
+
+
/* Initialise la classe des liens graphiques entre deux noeuds. */
static void g_graph_edge_class_init(GGraphEdgeClass *);
@@ -120,8 +120,6 @@ static void g_graph_edge_class_init(GGraphEdgeClass *klass)
static void g_graph_edge_init(GGraphEdge *edge)
{
- edge->top_step = UNINITIALIZED_HSPAN_SLOT;
- edge->bottom_step = UNINITIALIZED_HSPAN_SLOT;
}
@@ -140,12 +138,6 @@ static void g_graph_edge_init(GGraphEdge *edge)
static void g_graph_edge_dispose(GGraphEdge *edge)
{
- g_object_unref(G_OBJECT(edge->src_node));
- g_object_unref(G_OBJECT(edge->dest_node));
-
- if (edge->container != NULL)
- g_object_unref(G_OBJECT(edge->container));
-
G_OBJECT_CLASS(g_graph_edge_parent_class)->dispose(G_OBJECT(edge));
}
@@ -175,11 +167,11 @@ static void g_graph_edge_finalize(GGraphEdge *edge)
/******************************************************************************
* *
-* Paramètres : src_node = bloc de départ du lien. *
-* src_slot = point d'ancrage associé. *
-* dest_node = bloc d'arrivée du lien. *
-* dest_slot = point d'ancrage associé. *
-* color = couleur de rendu à l'écran. *
+* Paramètres : start = point de départ de la flêche. *
+* mid = points intermédiares variables. *
+* count = nombre de ces points fournis. *
+* end = point d'arrivée de la flêche. *
+* color = couleur de rendu à l'écran. *
* *
* Description : Etablit un lien graphique entre deux noeuds graphiques. *
* *
@@ -189,84 +181,33 @@ static void g_graph_edge_finalize(GGraphEdge *edge)
* *
******************************************************************************/
-GGraphEdge *g_graph_edge_new(GFlowNode *src_node, node_slot_t *src_slot, GFlowNode *dest_node, node_slot_t *dest_slot, EdgeColor color)
+GGraphEdge *_g_graph_edge_new(const GdkPoint *start, const GdkPoint **mid, size_t count, const GdkPoint *end, EdgeColor color)
{
GGraphEdge *result; /* Structure à retourner */
result = g_object_new(G_TYPE_GRAPH_EDGE, NULL);
- g_object_ref(G_OBJECT(src_node));
- g_object_ref(G_OBJECT(dest_node));
-
- result->src_node = src_node;
- result->src_slot = src_slot;
- result->dest_node = dest_node;
- result->dest_slot = dest_slot;
-
result->color = color;
- return G_GRAPH_EDGE(result);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : a = premier lien à considérer. *
-* b = second lien à considérer. *
-* *
-* Description : Etablit la comparaison entre deux liens graphiques. *
-* *
-* Retour : Bilan de la comparaison : -1, 0 ou 1. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-int g_graph_edge_compare(const GGraphEdge **a, const GGraphEdge **b)
-{
- int result; /* Bilan à retourner */
- const GGraphEdge *_a; /* Commodité d'accès #1 */
- const GGraphEdge *_b; /* Commodité d'accès #2 */
- GdkPoint start_a; /* Point de départ A */
- GdkPoint start_b; /* Point de départ B */
-
- _a = *a;
- _b = *b;
-
- /**
- * La comparaison s'établit sur le noeud d'arrivée.
- */
-
- if (_a->dest_node < _b->dest_node)
- result = -1;
+ assert(count == 1 || count == 2);
- else if (_a->dest_node > _b->dest_node)
- result = 1;
+ result->start = start;
- else
- {
- start_a = g_flow_node_get_point_from_slot(_a->src_node, false, _a->src_slot);
- start_b = g_flow_node_get_point_from_slot(_b->src_node, false, _b->src_slot);
+ memcpy(result->mid, mid, count * sizeof(GdkPoint));
+ result->m_count = count;
- result = g_flow_node_compare_slots_for_edges(_a->dest_node,
- _a->dest_slot, start_a.x,
- _b->dest_slot, start_b.x);
-
- }
+ result->end = end;
- return result;
+ return G_GRAPH_EDGE(result);
}
/******************************************************************************
* *
-* Paramètres : edge = ligne de rendu à mettre à jour. *
-* nodes = noeud au sommet de la hiérarchie. *
-* ranks = classement global dans lequel s'intégrer. *
+* Paramètres : edge = ligne de rendu à définir dans les détails. *
* *
-* Description : Prend les dispositions nécessaires à l'insertion du lien. *
+* Description : Détermine les positions finales d'un lien graphique. *
* *
* Retour : - *
* *
@@ -274,177 +215,31 @@ int g_graph_edge_compare(const GGraphEdge **a, const GGraphEdge **b)
* *
******************************************************************************/
-void g_graph_edge_reserve_vertical_space(GGraphEdge *edge, GGraphNode *nodes, GGraphRanks *ranks)
+void g_graph_edge_resolve(GGraphEdge *edge)
{
- GGraphNode *container; /* Conteneur du lien de boucle */
- unsigned int r1; /* Classement de départ */
- unsigned int r2; /* Classement d'arrivée */
-
- switch (edge->color)
- {
- case EGC_BLUE:
-
- container = g_graph_node_find_container(nodes, G_GRAPH_NODE(edge->dest_node));
- g_object_ref(G_OBJECT(container));
- edge->container = G_VIRTUAL_NODE(container);
-
- edge->is_left = true; /* TODO */
-
- r1 = g_graph_node_get_rank(G_GRAPH_NODE(edge->src_node));
- r2 = g_graph_node_get_rank(G_GRAPH_NODE(edge->dest_node));
-
- edge->vert_step = g_virtual_node_reserve_span(edge->container, r1, r2, edge->is_left);
-
- break;
-
- default:
- break;
-
- }
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : edge = ligne de rendu à mettre à jour. *
-* ranks = classement global dans lequel s'intégrer. *
-* *
-* Description : Prend les dispositions nécessaires à l'insertion du lien. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ edge->count = 2 + 2 * edge->m_count;
+ edge->points = (GdkPoint *)calloc(edge->count, sizeof(GdkPoint));
-void g_graph_edge_reserve_horizontal_space(GGraphEdge *edge, GGraphRanks *ranks)
-{
- GdkPoint x_src; /* Abscisse au niveau du départ*/
- GdkPoint x_dest; /* Abscisse au niveau d'arrivée*/
- gint x_step; /* Transition verticale */
- unsigned int rank; /* Indice de classement */
+ edge->points[0] = *edge->start;
- x_src = g_flow_node_get_point_from_slot(edge->src_node, false, edge->src_slot);
- x_dest = g_flow_node_get_point_from_slot(edge->dest_node, true, edge->dest_slot);
+ edge->points[1].x = edge->start->x;
+ edge->points[1].y = edge->mid[0]->y;
- switch (edge->color)
+ if (edge->m_count == 1)
{
- case EGC_BLUE:
-
- x_step = g_virtual_node_get_x_for_vspan_slot(edge->container,
- edge->vert_step, edge->is_left);
-
- rank = g_graph_node_get_rank(G_GRAPH_NODE(edge->src_node));
- edge->bottom_step = g_graph_ranks_reserve_span(ranks, rank, x_src.x, x_step, false);
-
- rank = g_graph_node_get_rank(G_GRAPH_NODE(edge->dest_node));
- edge->top_step = g_graph_ranks_reserve_span(ranks, rank, x_dest.x, x_step, true);
-
- break;
-
- default:
- rank = g_graph_node_get_rank(G_GRAPH_NODE(edge->dest_node));
- edge->top_step = g_graph_ranks_reserve_span(ranks, rank, x_src.x, x_dest.x, true);
- break;
-
+ edge->points[2].x = edge->end->x;
+ edge->points[2].y = edge->mid[0]->y;
}
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : edge = ligne de rendu à mettre à jour. *
-* ranks = classement global dans lequel s'intégrer. *
-* *
-* Description : Etablit le tracé du lien graphique entre deux noeuds. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_graph_edge_compute(GGraphEdge *edge, GGraphRanks *ranks)
-{
- GdkPoint start; /* Point de départ */
- GdkPoint end; /* Point d'arrivée */
- gint x_step; /* Transition verticale */
- unsigned int rank; /* Indice de classement */
-
- start = g_flow_node_get_point_from_slot(edge->src_node, false, edge->src_slot);
- end = g_flow_node_get_point_from_slot(edge->dest_node, true, edge->dest_slot);
-
- /* Point de départ */
-
- edge->count = 2;
- edge->points = (GdkPoint *)calloc(edge->count, sizeof(GdkPoint));
-
- edge->points[0] = start;
- edge->points[1] = start;
- edge->points[1].y += SLOT_VERT_SEP;
-
- /* Points de jonction */
-
- switch (edge->color)
+ else
{
- case EGC_BLUE:
-
- edge->count += 4;
- edge->points = (GdkPoint *)realloc(edge->points, edge->count * sizeof(GdkPoint));
-
- x_step = g_virtual_node_get_x_for_vspan_slot(edge->container,
- edge->vert_step, edge->is_left);
-
- rank = g_graph_node_get_rank(G_GRAPH_NODE(edge->src_node));
-
- edge->points[edge->count - 4].x = start.x;
- edge->points[edge->count - 4].y = g_graph_ranks_get_y_for_hspan_slot(ranks, rank,
- edge->bottom_step,
- false);
+ memcpy(&edge->points[2], edge->mid, edge->m_count * sizeof(GdkPoint));
- edge->points[edge->count - 3].x = x_step;
- edge->points[edge->count - 3].y = edge->points[edge->count - 4].y;
-
- rank = g_graph_node_get_rank(G_GRAPH_NODE(edge->dest_node));
-
- edge->points[edge->count - 2].x = x_step;
- edge->points[edge->count - 2].y = g_graph_ranks_get_y_for_hspan_slot(ranks, rank,
- edge->top_step,
- true);
- edge->points[edge->count - 1].x = end.x;
- edge->points[edge->count - 1].y = edge->points[edge->count - 2].y;
-
- break;
-
- default:
-
- edge->count += 2;
- edge->points = (GdkPoint *)realloc(edge->points, edge->count * sizeof(GdkPoint));
-
- rank = g_graph_node_get_rank(G_GRAPH_NODE(edge->dest_node));
-
- edge->points[edge->count - 2].x = start.x;
- edge->points[edge->count - 2].y = g_graph_ranks_get_y_for_hspan_slot(ranks, rank,
- edge->top_step,
- true);
-
- edge->points[edge->count - 1].x = end.x;
- edge->points[edge->count - 1].y = edge->points[edge->count - 2].y;
-
- break;
+ edge->points[4].x = edge->end->x;
+ edge->points[4].y = edge->mid[3]->y;
}
- /* Point d'arrivée */
-
- edge->count += 2;
- edge->points = (GdkPoint *)realloc(edge->points, edge->count * sizeof(GdkPoint));
-
- edge->points[edge->count - 2] = end;
- edge->points[edge->count - 2].y -= SLOT_VERT_SEP;
- edge->points[edge->count - 1] = end;
+ edge->points[edge->count - 1] = *edge->end;
}
diff --git a/src/gtkext/graph/edge.h b/src/gtkext/graph/edge.h
index 64d9658..602c559 100644
--- a/src/gtkext/graph/edge.h
+++ b/src/gtkext/graph/edge.h
@@ -26,17 +26,16 @@
#include <glib-object.h>
-
-
-#include "ranks.h"
-#include "nodes/flow.h"
+#include <stdbool.h>
+#include <gtk/gtk.h>
#define G_TYPE_GRAPH_EDGE g_graph_edge_get_type()
-#define G_GRAPH_EDGE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_graph_edge_get_type(), GGraphEdge))
-#define G_IS_GRAPH_EDGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_graph_edge_get_type()))
-#define G_GRAPH_EDGE_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), g_graph_edge_get_type(), GGraphEdgeIface))
+#define G_GRAPH_EDGE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_GRAPH_EDGE, GGraphEdge))
+#define G_IS_GRAPH_EDGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_GRAPH_EDGE))
+#define G_GRAPH_EDGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_GRAPH_EDGE, GGraphEdgeClass))
+#define G_IS_GRAPH_EDGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_GRAPH_EDGE))
#define G_GRAPH_EDGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_GRAPH_EDGE, GGraphEdgeClass))
@@ -65,19 +64,19 @@ typedef enum _EdgeColor
GType g_graph_edge_get_type(void);
/* Etablit un lien graphique entre deux noeuds graphiques. */
-GGraphEdge *g_graph_edge_new(GFlowNode *, node_slot_t *, GFlowNode *, node_slot_t *, EdgeColor);
+GGraphEdge *_g_graph_edge_new(const GdkPoint *, const GdkPoint **, size_t, const GdkPoint *, EdgeColor);
-/* Etablit la comparaison entre deux liens graphiques. */
-int g_graph_edge_compare(const GGraphEdge **, const GGraphEdge **);
+#define g_graph_edge_new(start, y, end) \
+ _g_graph_edge_new(start, (const GdkPoint *[]) { y }, 1, end, EGC_DEFAULT)
-/* Prend les dispositions nécessaires à l'insertion du lien. */
-void g_graph_edge_reserve_vertical_space(GGraphEdge *, GGraphNode *, GGraphRanks *);
+#define g_graph_edge_new_true(start, y, end) \
+ _g_graph_edge_new(start, (const GdkPoint *[]) { y }, 1, end, EGC_GREEN)
-/* Prend les dispositions nécessaires à l'insertion du lien. */
-void g_graph_edge_reserve_horizontal_space(GGraphEdge *, GGraphRanks *);
+#define g_graph_edge_new_false(start, y, end) \
+ _g_graph_edge_new(start, (const GdkPoint *[]) { y }, 1, end, EGC_RED)
-/* Etablit le tracé du lien graphique entre deux noeuds. */
-void g_graph_edge_compute(GGraphEdge *, GGraphRanks *);
+/* Détermine les positions finales d'un lien graphique. */
+void g_graph_edge_resolve(GGraphEdge *);
/* Dessine les liens graphiques enregistrés dans le moteur. */
void g_graph_edge_draw(const GGraphEdge *, cairo_t *, bool);
diff --git a/src/gtkext/graph/layout.c b/src/gtkext/graph/layout.c
deleted file mode 100644
index 13f6270..0000000
--- a/src/gtkext/graph/layout.c
+++ /dev/null
@@ -1,491 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * layout.c - mise en place de graphique
- *
- * Copyright (C) 2009-2014 Cyrille Bagard
- *
- * This file is part of Chrysalide.
- *
- * OpenIDA is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * OpenIDA is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#include "layout.h"
-
-
-#include <malloc.h>
-#include <stdlib.h>
-
-
-#include "node.h"
-#include "ranks.h"
-#include "nodes/flow.h"
-#include "nodes/virtual.h"
-
-
-
-/* Mise en disposition de blocs en graphique (instance) */
-struct _GGraphLayout
-{
- GObject parent; /* A laisser en premier */
-
- GGraphNode *nodes; /* Noeuds graphiques gérés */
- GGraphRanks *ranks; /* Classement en rangs */
-
- GGraphEdge **edges; /* Liens entre les noeuds */
- size_t edges_count; /* Quantité de ces liens */
-
-};
-
-/* Mise en disposition de blocs en graphique (classe) */
-struct _GGraphLayoutClass
-{
- GObjectClass parent; /* A laisser en premier */
-
-};
-
-
-/* Initialise la classe des mises en disposition graphique. */
-static void g_graph_layout_class_init(GGraphLayoutClass *);
-
-/* Initialise une mise en disposition de blocs en graphique. */
-static void g_graph_layout_init(GGraphLayout *);
-
-/* Supprime toutes les références externes. */
-static void g_graph_layout_dispose(GGraphLayout *);
-
-/* Procède à la libération totale de la mémoire. */
-static void g_graph_layout_finalize(GGraphLayout *);
-
-
-
-/* Indique le type définit par la GLib pour les mises en disposition graphique. */
-G_DEFINE_TYPE(GGraphLayout, g_graph_layout, G_TYPE_OBJECT);
-
-
-/******************************************************************************
-* *
-* Paramètres : klass = classe à initialiser. *
-* *
-* Description : Initialise la classe des mises en disposition graphique. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_graph_layout_class_init(GGraphLayoutClass *klass)
-{
- GObjectClass *object; /* Autre version de la classe */
-
- object = G_OBJECT_CLASS(klass);
-
- object->dispose = (GObjectFinalizeFunc/* ! */)g_graph_layout_dispose;
- object->finalize = (GObjectFinalizeFunc)g_graph_layout_finalize;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : layout = instance à initialiser. *
-* *
-* Description : Initialise une mise en disposition de blocs en graphique. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_graph_layout_init(GGraphLayout *layout)
-{
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : node = instance d'objet GLib à traiter. *
-* *
-* Description : Supprime toutes les références externes. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_graph_layout_dispose(GGraphLayout *layout)
-{
- g_object_unref(G_OBJECT(layout->nodes));
- g_object_unref(G_OBJECT(layout->ranks));
-
- G_OBJECT_CLASS(g_graph_layout_parent_class)->dispose(G_OBJECT(layout));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : layout = instance d'objet GLib à traiter. *
-* *
-* Description : Procède à la libération totale de la mémoire. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_graph_layout_finalize(GGraphLayout *layout)
-{
- G_OBJECT_CLASS(g_graph_layout_parent_class)->finalize(G_OBJECT(layout));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : blocks = ensemble des blocs basiques déjà découpés. *
-* views = morceaux de code à afficher de façon organisée. *
-* count = quantité de ces morceaux de code. *
-* *
-* Description : Construit un graphique à partir de blocs basiques. *
-* *
-* Retour : Adresse de la structure mise en place. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-#include "../../arch/instruction-int.h" // REMME
-#include "nodes/flow.h"
-GGraphLayout *g_graph_layout_new(GInstrBlock *blocks, GtkBufferView **views, size_t count)
-{
- GGraphLayout *result; /* Structure à retourner */
-
- result = g_object_new(G_TYPE_GRAPH_LAYOUT, NULL);
-
- result->nodes = convert_blocks_into_nodes(blocks, views, count);
-
- result->ranks = g_graph_ranks_new(count);
-
- /* Situations verticales grossières */
-
- bool _register_cb(GFlowNode *node, GNodeVisitState state, GGraphLayout *layout)
- {
- if (state == GVS_NODE)
- g_flow_node_link(node, layout, layout->nodes);
- return true;
- }
-
- g_graph_node_visit_nodes(result->nodes, (graph_node_visitor_cb)_register_cb, result);
-
- bool _print_dbg_cb(GFlowNode *node, GNodeVisitState state, int *depth)
- {
- int i;
-
- if (state == GVS_ENTER || state == GVS_NODE)
- {
- for (i = 0; i < *depth; i++)
- printf(" ");
-
- printf("- %p\n", node);
-
- }
-
- if (state == GVS_ENTER) (*depth)++;
- else if (state == GVS_EXIT) (*depth)--;
-
- return true;
-
- }
-
- printf("==== graph ====\n");
- g_graph_node_visit_nodes(result->nodes, (graph_node_visitor_cb)_print_dbg_cb, (int []){ 0 });
- printf("\n");
-
- /* Actualisation... */
-
- g_graph_layout_refresh(result);
-
- bool _print_dbg_ext_cb(GGraphNode *node, GNodeVisitState state, int *depth)
- {
- int i;
- PendingPositionFlags pending_flag;
- char *flags;
- GtkAllocation alloc;
- GArchInstruction *first;
- GArchInstruction *last;
-
- char *flags_list[] = {
- "NONE",
- "DIRECT_X",
- "LEFT_MARGIN",
- "RIGHT_MARGIN",
- "LEFT_NODE",
- "RIGHT_NODE"
- };
-
-
- if (state == GVS_ENTER || state == GVS_NODE)
- {
-
-
-
- for (i = 0; i < *depth; i++)
- printf(" ");
-
- g_graph_node_get_pending_position(node, &pending_flag, NULL);
- flags = flags_list[pending_flag];
-
- alloc = g_graph_node_get_allocation(node);
- printf("- %p - \"%s\" - (%d ; %d) - (%d ; %d)", node,
- flags,
- alloc.x, alloc.y,
- alloc.width, alloc.height);
-
- if (G_IS_FLOW_NODE(node))
- {
- printf(" - rank = %u -", g_graph_node_get_rank(node));
-
- g_flow_block_get_boundary(g_flow_node_get_block(G_FLOW_NODE(node)), &first, &last);
- printf(" - 0x%08x <-> 0x%08x", first->range.addr.virtual, last->range.addr.virtual);
- }
-
- printf("\n");
-
- }
-
- if (state == GVS_ENTER) (*depth)++;
- else if (state == GVS_EXIT) (*depth)--;
-
- return true;
-
- }
-
- printf("==== graph ====\n");
- g_graph_node_visit_nodes(result->nodes, (graph_node_visitor_cb)_print_dbg_ext_cb, (int []){ 0 });
- printf("\n");
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : layout = disposition en graphique à compléter. *
-* edge = lien entre noeuds à conserver. *
-* *
-* Description : Ajoute un lien entre deux noeuds au graphique. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_graph_layout_add_edge(GGraphLayout *layout, GGraphEdge *edge)
-{
- layout->edges = (GGraphEdge **)realloc(layout->edges,
- ++layout->edges_count * sizeof(GGraphEdge *));
-
- layout->edges[layout->edges_count - 1] = edge;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : layout = graphique à mettre à jour. *
-* *
-* Description : Met à jour les positions des différents noeuds. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-#include "node-int.h"
-void g_graph_layout_refresh(GGraphLayout *layout)
-{
- size_t i; /* Boucle de parcours */
-
-
- int counter = 0;
-
-
- restart:
-
- g_graph_ranks_reset_reservations(layout->ranks);
-
- bool _reset_cb(GGraphNode *node, GNodeVisitState state, void *unused)
- {
- g_graph_node_reset_position(node);
- if (state == GVS_NODE)
- g_flow_node_register_rank(G_FLOW_NODE(node), layout->ranks);
- return true;
- }
-
- g_graph_node_visit_nodes(layout->nodes, (graph_node_visitor_cb)_reset_cb, NULL);
-
- /* Traitement des positions horizontales */
-
- for (i = 0; i < layout->edges_count; i++)
- g_graph_edge_reserve_vertical_space(layout->edges[i], layout->nodes, layout->ranks);
-
- /* Traitement des positions horizontales */
-
- g_graph_node_set_x_position(layout->nodes, GRAPH_HORIZONTAL_MARGIN);
-
- g_graph_node_prepare_x_line(layout->nodes, layout->nodes);
- g_graph_node_apply_position(layout->nodes);
-
-
-
- bool _reorder_cb(GGraphNode *node, GNodeVisitState state, GGraphNode *nodes)
- {
- if (state == GVS_NODE)
- g_flow_node_reorder_slots(G_FLOW_NODE(node), nodes);
- return true;
- }
-
- //qsort(layout->edges, layout->edges_count, sizeof(GGraphEdge *), (__compar_fn_t)g_graph_edge_compare);
-
-
-
- if (counter++ == 0)
- {
- g_graph_node_visit_nodes(layout->nodes, (graph_node_visitor_cb)_reorder_cb, layout->nodes);
- goto restart;
- }
-
- /*
- bool _rinint_cb(GGraphNode *node, GNodeVisitState state, GGraphNode *nodes)
- {
- node->alloc.x = UNINITIALIZED_NODE_POS;
- node->alloc.y = UNINITIALIZED_NODE_POS;
- return true;
- }
-
- g_graph_node_visit_nodes(layout->nodes, (graph_node_visitor_cb)_rinint_cb, layout->nodes);
-
-
- g_graph_node_apply_position(layout->nodes);
- */
-
- qsort(layout->edges, layout->edges_count, sizeof(GGraphEdge *), (__compar_fn_t)g_graph_edge_compare);
-
-
-
- for (i = 0; i < layout->edges_count; i++)
- g_graph_edge_reserve_horizontal_space(layout->edges[i], layout->ranks);
-
- /* Traitement des positions verticales */
-
- g_graph_ranks_compute_y_line(layout->ranks);
-
- bool _apply_cb(GFlowNode *node, GNodeVisitState state, GGraphRanks *ranks)
- {
- if (state == GVS_NODE)
- g_flow_node_apply_rank(node, ranks);
- return true;
- }
-
- g_graph_node_visit_nodes(layout->nodes, (graph_node_visitor_cb)_apply_cb, layout->ranks);
-
- /* Mise en place des liens */
-
- for (i = 0; i < layout->edges_count; i++)
- g_graph_edge_compute(layout->edges[i], layout->ranks);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : layout = disposition en graphique prête. *
-* view = support de destination finale. *
-* *
-* Description : Dispose chaque noeud sur la surface de destination donnée. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_graph_layout_place(GGraphLayout *layout, GtkGraphView *view)
-{
- bool _place_cb(GFlowNode *node, GNodeVisitState state, GtkGraphView *view)
- {
- if (state == GVS_NODE)
- g_flow_node_place(node, view);
- return true;
- }
-
- g_graph_node_visit_nodes(layout->nodes, (graph_node_visitor_cb)_place_cb, view);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : layout = graphique constitué à consulter. *
-* requisition = dimensions souhaitées. [OUT] *
-* *
-* Description : Fournit la taille requise pour un plein rendu du graphique. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_graph_layout_size_request(const GGraphLayout *layout, GtkRequisition *requisition)
-{
- GtkAllocation alloc; /* Largeur totale requise */
-
- alloc = g_graph_node_get_allocation(layout->nodes);
- requisition->width = alloc.width + 2 * GRAPH_HORIZONTAL_MARGIN;
-
- requisition->height = g_graph_ranks_get_height(layout->ranks);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : layout = graphique à représenter. *
-* cairo = assistant pour le rendu graphique. *
-* arrow = indique le besoin en flèche à l'arrivée. *
-* *
-* Description : Dessine les liens graphiques enregistrés dans le moteur. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_graph_layout_draw(const GGraphLayout *layout, cairo_t *cairo, bool arrow)
-{
- size_t i; /* Boucle de parcours */
-
- for (i = 0; i < layout->edges_count; i++)
- g_graph_edge_draw(layout->edges[i], cairo, arrow);
-
-}
diff --git a/src/gtkext/graph/layout.h b/src/gtkext/graph/layout.h
deleted file mode 100644
index 37598e8..0000000
--- a/src/gtkext/graph/layout.h
+++ /dev/null
@@ -1,73 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * layout.h - prototypes pour la mise en place de graphique
- *
- * Copyright (C) 2009-2014 Cyrille Bagard
- *
- * This file is part of Chrysalide.
- *
- * OpenIDA is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * OpenIDA is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#ifndef _GTKEXT_GRAPH_LAYOUT_H
-#define _GTKEXT_GRAPH_LAYOUT_H
-
-
-#include <stdbool.h>
-
-
-#include "edge.h"
-#include "../gtkbufferview.h"
-
-
-
-#define G_TYPE_GRAPH_LAYOUT g_graph_layout_get_type()
-#define G_GRAPH_LAYOUT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_graph_layout_get_type(), GGraphLayout))
-#define G_IS_GRAPH_LAYOUT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_graph_layout_get_type()))
-#define G_GRAPH_LAYOUT_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), g_graph_layout_get_type(), GGraphLayoutIface))
-#define G_GRAPH_LAYOUT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_GRAPH_LAYOUT, GGraphLayoutClass))
-
-
-/* Mise en disposition de blocs en graphique (instance) */
-typedef struct _GGraphLayout GGraphLayout;
-
-/* Mise en disposition de blocs en graphique (classe) */
-typedef struct _GGraphLayoutClass GGraphLayoutClass;
-
-
-/* Indique le type définit par la GLib pour les mises en disposition graphique. */
-GType g_graph_layout_get_type(void);
-
-/* Construit un graphique à partir de blocs basiques. */
-GGraphLayout *g_graph_layout_new(GInstrBlock *, GtkBufferView **, size_t);
-
-/* Ajoute un lien entre deux noeuds au graphique. */
-void g_graph_layout_add_edge(GGraphLayout *, GGraphEdge *);
-
-/* Met à jour les positions des différents noeuds. */
-void g_graph_layout_refresh(GGraphLayout *);
-
-/* Dispose chaque noeud sur la surface de destination donnée. */
-void g_graph_layout_place(GGraphLayout *, GtkGraphView *);
-
-/* Fournit la taille requise pour un plein rendu du graphique. */
-void g_graph_layout_size_request(const GGraphLayout *, GtkRequisition *);
-
-/* Dessine les liens graphiques enregistrés dans le moteur. */
-void g_graph_layout_draw(const GGraphLayout *, cairo_t *, bool);
-
-
-
-#endif /* _GRAPH_LAYOUT_H */
diff --git a/src/gtkext/graph/node-int.h b/src/gtkext/graph/node-int.h
deleted file mode 100644
index c052e0d..0000000
--- a/src/gtkext/graph/node-int.h
+++ /dev/null
@@ -1,83 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * node-int.h - prototypes pour la gestion élémentaire des blocs sous forme de noeuds
- *
- * Copyright (C) 2013 Cyrille Bagard
- *
- * This file is part of Chrysalide.
- *
- * OpenIDA is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * OpenIDA is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#ifndef _GTKEXT_GRAPH_NODE_INT_H
-#define _GTKEXT_GRAPH_NODE_INT_H
-
-
-#include "node.h"
-
-
-
-/* Fournit le rang du noeud dans le graphique. */
-typedef unsigned int (* get_node_rank_fc) (const GGraphNode *);
-
-/* Réinitialise la position d'un noeud d'encapsulation. */
-typedef void (* node_reset_pos_fc) (GGraphNode *);
-
-/* Définit les abscisses relatives du contenu d'un noeud. */
-typedef void (* node_prepare_x_fc) (GGraphNode *, GGraphNode *);
-
-/* Applique une position finale au noeud. */
-typedef void (* node_apply_pos_fc) (GGraphNode *);
-
-/* Altère la position du noeud d'encapsulation. */
-typedef void (* node_set_pos_fc) (GGraphNode *, gint);
-
-/* Parcourt tous les noeuds graphiques dans un ordre donné. */
-typedef bool (* visit_flow_nodes_fc) (GGraphNode *, graph_node_visitor_cb, void *);
-
-/* Recherche le noeud contenant un autre noeud. */
-typedef GGraphNode * (* find_container_fc) (GGraphNode *, GGraphNode *);
-
-
-/* Intermédiaire entre le noeud dot et la bribe de code (instance) */
-struct _GGraphNode
-{
- GObject parent; /* A laisser en premier */
-
- GtkAllocation alloc; /* Emplacement du bloc rattaché*/
- PendingPositionFlags pending_flag; /* Cible le champ valide */
- pending_position pending_pos; /* Indication sur la position */
-
-};
-
-
-/* Intermédiaire entre le noeud dot et la bribe de code (classe) */
-struct _GGraphNodeClass
-{
- GObjectClass parent; /* A laisser en premier */
-
- get_node_rank_fc get_rank; /* Premier rang d'appartenance */
- node_reset_pos_fc reset_pos; /* Réinitialise l'emplacement */
- node_prepare_x_fc prepare_x; /* Préparation des abscisses */
- node_apply_pos_fc apply_pos; /* Applique une absisse finale */
- node_set_pos_fc set_pos; /* Définit l'emplacement */
- visit_flow_nodes_fc visit; /* Visite des noeuds d'exécut° */
- find_container_fc contain; /* Retrouve un conteneur */
-
-};
-
-
-
-#endif /* _GTKEXT_GRAPH_NODE_INT_H */
diff --git a/src/gtkext/graph/node.c b/src/gtkext/graph/node.c
deleted file mode 100644
index 08dd970..0000000
--- a/src/gtkext/graph/node.c
+++ /dev/null
@@ -1,634 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * node.c - éléments de graphiques chez dot
- *
- * Copyright (C) 2009-2013 Cyrille Bagard
- *
- * This file is part of Chrysalide.
- *
- * OpenIDA is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * OpenIDA is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#include "node.h"
-
-
-#include <assert.h>
-#include <malloc.h>
-#include <stdio.h>
-#include <string.h>
-
-
-#include "node-int.h"
-#include "nodes/flow.h"
-#include "nodes/virtual.h"
-#include "../../common/extstr.h"
-
-
-
-/* -------------------------- GESTION DES NOEUDS A L'UNITE -------------------------- */
-
-
-/* Initialise la classe des intermédiaires avec les noeuds dot. */
-static void g_graph_node_class_init(GGraphNodeClass *);
-
-/* Initialise la classe des intermédiaires avec les noeuds dot. */
-static void g_graph_node_init(GGraphNode *);
-
-/* Supprime toutes les références externes. */
-static void g_graph_node_dispose(GGraphNode *);
-
-/* Procède à la libération totale de la mémoire. */
-static void g_graph_node_finalize(GGraphNode *);
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* GESTION DES NOEUDS A L'UNITE */
-/* ---------------------------------------------------------------------------------- */
-
-
-/* Indique le type définit par la GLib pour le noeud. */
-G_DEFINE_TYPE(GGraphNode, g_graph_node, G_TYPE_OBJECT);
-
-
-/******************************************************************************
-* *
-* Paramètres : klass = classe à initialiser. *
-* *
-* Description : Initialise la classe des intermédiaires avec les noeuds dot. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_graph_node_class_init(GGraphNodeClass *klass)
-{
- GObjectClass *object; /* Autre version de la classe */
-
- object = G_OBJECT_CLASS(klass);
-
- object->dispose = (GObjectFinalizeFunc/* ! */)g_graph_node_dispose;
- object->finalize = (GObjectFinalizeFunc)g_graph_node_finalize;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : node = instance à initialiser. *
-* *
-* Description : Initialise la classe des intermédiaires avec les noeuds dot. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_graph_node_init(GGraphNode *node)
-{
- node->alloc.x = UNINITIALIZED_NODE_POS;
- node->alloc.y = UNINITIALIZED_NODE_POS;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : node = instance d'objet GLib à traiter. *
-* *
-* Description : Supprime toutes les références externes. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_graph_node_dispose(GGraphNode *node)
-{
- G_OBJECT_CLASS(g_graph_node_parent_class)->dispose(G_OBJECT(node));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : node = instance d'objet GLib à traiter. *
-* *
-* Description : Procède à la libération totale de la mémoire. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_graph_node_finalize(GGraphNode *node)
-{
- G_OBJECT_CLASS(g_graph_node_parent_class)->finalize(G_OBJECT(node));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : node = noeud graphique à consulter. *
-* *
-* Description : Fournit le rang du noeud dans le graphique. *
-* *
-* Retour : Indice supérieur ou égal à zéro. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-unsigned int g_graph_node_get_rank(const GGraphNode *node)
-{
- return G_GRAPH_NODE_GET_CLASS(node)->get_rank(node);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : node = noeud graphique à manipuler. *
-* *
-* Description : Réinitialise la position d'un noeud de graphique. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_graph_node_reset_position(GGraphNode *node)
-{
- node->alloc.x = UNINITIALIZED_NODE_POS;
- node->alloc.y = UNINITIALIZED_NODE_POS;
-
- node->pending_flag = PPF_NONE;
-
- if (G_GRAPH_NODE_GET_CLASS(node)->reset_pos != NULL)
- G_GRAPH_NODE_GET_CLASS(node)->reset_pos(node);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : node = noeud d'encapsulation à traiter. *
-* nodes = ensemble des noeuds en place. *
-* *
-* Description : Définit les abscisses relatives du contenu d'un noeud. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_graph_node_prepare_x_line(GGraphNode *node, GGraphNode *nodes)
-{
- G_GRAPH_NODE_GET_CLASS(node)->prepare_x(node, nodes);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : node = noeud graphique à manipuler. *
-* *
-* Description : Applique une position finale au noeud. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_graph_node_apply_position(GGraphNode *node)
-{
- gint x_pos; /* Position de référence */
- GGraphNode *ref; /* Accès rapide */
-
- if (G_GRAPH_NODE_GET_CLASS(node)->apply_pos != NULL)
- G_GRAPH_NODE_GET_CLASS(node)->apply_pos(node);
-
- switch (node->pending_flag)
- {
- case PPF_DIRECT_X:
- assert(g_graph_node_has_x_position(node->pending_pos.relative_ref));
- g_graph_node_get_position(node->pending_pos.relative_ref, &x_pos, NULL);
- x_pos += node->pending_pos.direct_x;
- g_graph_node_set_x_position(node, x_pos);
- break;
-
- case PPF_LEFT_MARGIN:
- assert(g_graph_node_has_x_position(node->pending_pos.relative_ref));
- g_graph_node_get_position(node->pending_pos.relative_ref, &x_pos, NULL);
- x_pos += EDGE_SLOT_HORIZ_MARGIN + node->pending_pos.left_margin;
- g_graph_node_set_x_position(node, x_pos);
- break;
-
- case PPF_RIGHT_MARGIN:
- assert(g_graph_node_has_x_position(node->pending_pos.relative_ref));
- g_graph_node_get_position(node->pending_pos.relative_ref, &x_pos, NULL);
- x_pos += node->pending_pos.right_margin;
- x_pos -= (EDGE_SLOT_HORIZ_MARGIN + node->alloc.width);
- g_graph_node_set_x_position(node, x_pos);
- break;
-
- case PPF_LEFT_NODE:
- ref = node->pending_pos.left_node;
- x_pos = ref->alloc.x - NODE_HORIZONTAL_MARGIN - node->alloc.width;
- g_graph_node_set_x_position(node, x_pos);
- break;
-
- case PPF_RIGHT_NODE:
- ref = node->pending_pos.right_node;
- x_pos = ref->alloc.x + ref->alloc.width - NODE_HORIZONTAL_MARGIN;
- g_graph_node_set_x_position(node, x_pos);
- break;
-
- default:
- /* Position traitée par l'appelant */
- break;
-
- }
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : node = noeud graphique à manipuler. *
-* Paramètres : node = noeud graphique à manipuler. *
-* x = abscisse à intégrer. *
-* direct = indique un tracé direct éventuel. *
-* *
-* Description : Altère la position du noeud d'encapsulation. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_graph_node_set_x_position(GGraphNode *node, gint x)
-{
- if (G_GRAPH_NODE_GET_CLASS(node)->set_pos != NULL && x != GRAPH_HORIZONTAL_MARGIN)
- G_GRAPH_NODE_GET_CLASS(node)->set_pos(node, x);
-
- node->alloc.x = x;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : node = noeud graphique à manipuler. *
-* flag = nature de l'indication à intégrer. *
-* pos = argument supplémentaire à venir chercher. *
-* *
-* Description : Prépare la position du noeud pour l'alignement des liens. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_graph_node_set_pending_position(GGraphNode *node, PendingPositionFlags flag, pending_position pos)
-{
- if (node->pending_flag != PPF_NONE && node->pending_flag != PPF_MIDDLE_OF)
- return;
-
- node->pending_flag = flag;
- node->pending_pos = pos;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : node = noeud graphique à manipuler. *
-* flag = nature de l'indication à intégrer. [OUT] *
-* pos = argument supplémentaire à venir chercher. [OUT] *
-* *
-* Description : Indique la position du noeud pour l'alignement des liens. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_graph_node_get_pending_position(GGraphNode *node, PendingPositionFlags *flag, pending_position *pos)
-{
- *flag = node->pending_flag;
-
- if (pos != NULL)
- *pos = node->pending_pos;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : node = noeud graphique à consulter. *
-* x = éventuelle abscisse à recevoir ou NULL. [OUT] *
-* y = éventuelle ordonnée à recevoir ou NULL. [OUT] *
-* *
-* Description : Fournit la position du noeud d'encapsulation. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_graph_node_get_position(const GGraphNode *node, gint *x, gint *y)
-{
- if (x != NULL) *x = node->alloc.x;
- if (y != NULL) *y = node->alloc.y;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : node = noeud graphique à consulter. *
-* *
-* Description : Indique l'espace requis pour un noeud d'encapsulation. *
-* *
-* Retour : Espace constitué, entièrement ou non. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GtkAllocation g_graph_node_get_allocation(const GGraphNode *node)
-{
- return node->alloc;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : node = noeud graphique démarrant la visite. *
-* callback = ensemble de blocs à parcourir. *
-* data = donnée utilisateur à associer au parcours. *
-* *
-* Description : Parcourt tous les noeuds graphiques dans un ordre donné. *
-* *
-* Retour : true si le parcours a été jusqu'à son terme, false sinon. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-bool g_graph_node_visit_nodes(GGraphNode *node, graph_node_visitor_cb callback, void *data)
-{
- return G_GRAPH_NODE_GET_CLASS(node)->visit(node, callback, data);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : nodes = noeud au sommet de la hiérarchie. *
-* target = élément à retrouver dans l'ensemble de noeuds. *
-* *
-* Description : Recherche le noeud contenant un autre noeud. *
-* *
-* Retour : Noeud trouvé ou NULL si aucun. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GGraphNode *g_graph_node_find_container(GGraphNode *nodes, GGraphNode *target)
-{
- GGraphNode *result; /* Trouvaille à retourner */
-
- result = NULL;
-
- if (G_GRAPH_NODE_GET_CLASS(nodes)->contain != NULL)
- result = G_GRAPH_NODE_GET_CLASS(nodes)->contain(nodes, target);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : nodes = noeud au sommet de la hiérarchie. *
-* ref = noeud indiquant le niveau de référence. *
-* target = élément à retrouver dans l'ensemble de noeuds. *
-* *
-* Description : Recherche le noeud contenant un autre noeud à un même niveau.*
-* *
-* Retour : Noeud trouvé ou NULL si aucun. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GGraphNode *g_graph_node_find_container_at_same_level(GGraphNode *nodes, GGraphNode *ref, GGraphNode *target)
-{
- GGraphNode *result; /* Trouvaille à retourner */
- GGraphNode *level; /* Niveau de référence */
- GGraphNode *container; /* Support de la cible */
-
- result = NULL;
-
- level = g_graph_node_find_container(nodes, ref);
-
- container = g_graph_node_find_container(nodes, target);
-
- if (container == level)
- result = target;
- else
- {
- if (container == NULL)
- result = NULL;
- else
- result = g_graph_node_find_container_at_same_level(nodes, ref, container);
- }
-
- return result;
-
-}
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* MANIPULATION D'ENSEMBLES DE NOEUDS */
-/* ---------------------------------------------------------------------------------- */
-
-
-/******************************************************************************
-* *
-* Paramètres : views = liste de vues à parcourir. *
-* count = taille de la liste. *
-* addrt = adresse de début du noeud recherché. *
-* *
-* Description : Recherche une vue donnée dans une série de vues. *
-* *
-* Retour : Vue trouvée ou NULL si aucun. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GtkBufferView *find_graph_view_by_start_address(GtkBufferView **views, size_t count, const vmpa2t *addr)
-{
- GtkBufferView *result; /* Trouvaille à remonter */
- size_t i; /* Boucle de parcours */
- GBufferView *buffer; /* Tampon d'une partie de code */
- vmpa2t start; /* Adresse de départ du tampon */
-
- result = NULL;
-
- for (i = 0; i < count && result == NULL; i++)
- {
- buffer = gtk_buffer_view_get_buffer(views[i]);
- g_buffer_view_get_restrictions(buffer, &start, NULL);
-
- if (cmp_vmpa(&start, addr) == 0)
- result = views[i];
-
- }
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : block = ensemble des blocs basiques déjà découpés. *
-* views = morceaux de code à afficher de façon organisée. *
-* count = quantité de ces morceaux de code. *
-* *
-* Description : Réalise une conversion de blocs en noeuds. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GGraphNode *convert_blocks_into_nodes(GInstrBlock *block, GtkBufferView **views, size_t count)
-{
- GGraphNode *result; /* Instance nouvelle à renvoyer*/
- vmpa2t start; /* Adresse de départ */
- GtkBufferView *view; /* Vue existante à retrouver */
- size_t max; /* Nombre de blocs à gérer */
- size_t i; /* Boucle de parcours */
- GInstrBlock *sub_block; /* Sous-bloc intégré */
- GGraphNode *child; /* Conversion à mémoriser */
-
- result = NULL;
-
- if (G_IS_FLOW_BLOCK(block))
- {
- g_flow_block_get_boundary_addresses(G_FLOW_BLOCK(block), &start, NULL);
- view = find_graph_view_by_start_address(views, count, &start);
-
- result = g_flow_node_new(G_FLOW_BLOCK(block), view);
-
- }
- else if (G_IS_VIRTUAL_BLOCK(block))
- {
- result = g_virtual_node_new(G_VIRTUAL_BLOCK(block));
-
- max = g_virtual_block_count_children(G_VIRTUAL_BLOCK(block));
-
- for (i = 0; i < max; i++)
- {
- sub_block = g_virtual_block_get_child(G_VIRTUAL_BLOCK(block), i);
- child = convert_blocks_into_nodes(sub_block, views, count);
-
- g_virtual_node_add_child(G_VIRTUAL_NODE(result), child);
-
- }
-
- }
- /*else BUG_ON(1); */
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : nodes = noeud au sommet de la hiérarchie. *
-* instr = instruction à retrouver. *
-* entry = position de cette instruction : première ou dernière.*
-* *
-* Description : Recherche le noeud contenant une instruction donnée. *
-* *
-* Retour : Noeud trouvé ou NULL. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GGraphNode *_find_node_for_instruction(GGraphNode *nodes, GArchInstruction *instr, bool entry)
-{
- GGraphNode *result; /* Trouvaille à retourner */
- struct visit_params {
- GArchInstruction *instr; /* Instruction recherchée */
- bool entry; /* Première ou dernière ? */
- GGraphNode *found; /* Remontée du noeud trouvé */
- } params; /* Paramètres pour le parcours */
-
- params.instr = instr;
- params.entry = entry;
- params.found = NULL;
-
- bool _find_node_cb(GFlowNode *node, GNodeVisitState state, struct visit_params *params)
- {
- bool result;
-
- if (state == GVS_NODE)
- {
- if ((params->entry && g_flow_node_start_with(node, params->instr))
- || (!params->entry && g_flow_node_end_with(node, params->instr)))
- {
- params->found = G_GRAPH_NODE(node);
- }
- result = (params->found == NULL);
- }
- else result = true;
-
- return result;
-
- }
-
- g_graph_node_visit_nodes(nodes, (graph_node_visitor_cb)_find_node_cb, &params);
-
- result = params.found;
-
- return result;
-
-}
diff --git a/src/gtkext/graph/node.h b/src/gtkext/graph/node.h
deleted file mode 100644
index 6d3589a..0000000
--- a/src/gtkext/graph/node.h
+++ /dev/null
@@ -1,174 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * node.h - prototypes pour les éléments de graphiques chez dot
- *
- * Copyright (C) 2009-2013 Cyrille Bagard
- *
- * This file is part of Chrysalide.
- *
- * OpenIDA is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * OpenIDA is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#ifndef _GTKEXT_GRAPH_NODE_H
-#define _GTKEXT_GRAPH_NODE_H
-
-
-#include "params.h"
-#include "ranks.h"
-#include "../gtkbufferview.h"
-#include "../gtkgraphview.h"
-#include "../../arch/instruction.h"
-#include "../../analysis/block.h"
-
-
-
-/* -------------------------- GESTION DES NOEUDS A L'UNITE -------------------------- */
-
-
-#define G_TYPE_GRAPH_NODE (g_graph_node_get_type())
-#define G_GRAPH_NODE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_GRAPH_NODE, GGraphNode))
-#define G_GRAPH_NODE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_GRAPH_NODE, GGraphNodeClass))
-#define G_IS_GRAPH_NODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_GRAPH_NODE))
-#define G_IS_GRAPH_NODE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_GRAPH_NODE))
-#define G_GRAPH_NODE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_GRAPH_NODE, GGraphNodeClass))
-
-
-/* Intermédiaire entre le noeud dot et la bribe de code (instance) */
-typedef struct _GGraphNode GGraphNode;
-
-/* Intermédiaire entre le noeud dot et la bribe de code (classe) */
-typedef struct _GGraphNodeClass GGraphNodeClass;
-
-
-/* Indications sur l'abscisse idéale à adopter */
-typedef union _pending_position
-{
- /* PPF_DIRECT_X, PPF_LEFT_MARGIN, PPF_RIGHT_MARGIN */
- struct
- {
- union
- {
- gint direct_x; /* Position strictement vert. */
- gint left_margin; /* Limite à ne pas dépasser #1 */
- gint right_margin; /* Limite à ne pas dépasser #2 */
- };
- GGraphNode *relative_ref; /* Eventuelle ref. relative */
- };
-
- /* PPF_LEFT_NODE, PPF_RIGHT_NODE, PPF_MIDDLE_OF */
- struct
- {
- GGraphNode *left_node; /* Noeud de référence à droite */
- GGraphNode *right_node; /* Noeud de référence à gauche */
- };
-
-} pending_position;
-
-/* Définition présente dans les indications */
-typedef enum _PendingPositionFlags
-{
- PPF_NONE, /* Aucune -> centrage */
- PPF_DIRECT_X, /* Position strictement vert. */
- PPF_LEFT_MARGIN, /* Limite à ne pas dépasser #1 */
- PPF_RIGHT_MARGIN, /* Limite à ne pas dépasser #2 */
- PPF_LEFT_NODE, /* Noeud de référence à droite */
- PPF_RIGHT_NODE, /* Noeud de référence à gauche */
- PPF_MIDDLE_OF /* Centré entre deux noeuds */
-
-} PendingPositionFlags;
-
-/* Détail sur une visite */
-typedef enum _GNodeVisitState
-{
- GVS_ENTER, /* Entrée dans un groupe */
- GVS_NODE, /* Traitement d'une feuille */
- GVS_EXIT /* Sortie d'un groupe */
-
-} GNodeVisitState;
-
-/* Rappel à chaque noeud visité */
-typedef bool (* graph_node_visitor_cb) (GGraphNode *, GNodeVisitState, void *);
-
-
-/* Indique le type définit par la GLib pour le noeud. */
-GType g_graph_node_get_type(void);
-
-/* Fournit le rang du noeud dans le graphique. */
-unsigned int g_graph_node_get_rank(const GGraphNode *);
-
-/* Réinitialise la position d'un noeud de graphique. */
-void g_graph_node_reset_position(GGraphNode *);
-
-/* Définit les abscisses relatives du contenu d'un noeud. */
-void g_graph_node_prepare_x_line(GGraphNode *node, GGraphNode *nodes);
-
-/* Applique une position finale au noeud. */
-void g_graph_node_apply_position(GGraphNode *);
-
-/* Altère la position du noeud d'encapsulation. */
-void g_graph_node_set_x_position(GGraphNode *, gint);
-
-/* Prépare la position du noeud pour l'alignement des liens. */
-void g_graph_node_set_pending_position(GGraphNode *, PendingPositionFlags, pending_position);
-
-/* Indique la position du noeud pour l'alignement des liens. */
-void g_graph_node_get_pending_position(GGraphNode *, PendingPositionFlags *, pending_position *);
-
-/* Fournit la position du noeud d'encapsulation. */
-void g_graph_node_get_position(const GGraphNode *, gint *, gint *);
-
-#define g_graph_node_has_x_position(node) \
- ({ \
- gint _x; \
- g_graph_node_get_position(node, &_x, NULL); \
- _x != UNINITIALIZED_NODE_POS; \
- })
-
-/* Espace constitué, entièrement ou non. */
-GtkAllocation g_graph_node_get_allocation(const GGraphNode *);
-
-/* Parcourt tous les noeuds graphiques dans un ordre donné. */
-bool g_graph_node_visit_nodes(GGraphNode *, graph_node_visitor_cb, void *);
-
-/* Recherche le noeud contenant un autre noeud. */
-GGraphNode *g_graph_node_find_container(GGraphNode *, GGraphNode *);
-
-/* Recherche le noeud contenant un autre noeud à un même niveau. */
-GGraphNode *g_graph_node_find_container_at_same_level(GGraphNode *, GGraphNode *, GGraphNode *);
-
-
-
-/* ----------------------- MANIPULATION D'ENSEMBLES DE NOEUDS ----------------------- */
-
-
-/* Recherche une vue donnée dans une série de vues. */
-GtkBufferView *find_graph_view_by_start_address(GtkBufferView **, size_t, const vmpa2t *);
-
-/* Réalise une conversion de blocs en noeuds. */
-GGraphNode *convert_blocks_into_nodes(GInstrBlock *, GtkBufferView **, size_t);
-
-/* Recherche le noeud contenant une instruction donnée. */
-GGraphNode *_find_node_for_instruction(GGraphNode *, GArchInstruction *, bool);
-
-
-#define find_node_for_first_instruction(nds, ins) \
- _find_node_for_instruction(nds, ins, true)
-
-#define find_node_for_last_instruction(nds, ins) \
- _find_node_for_instruction(nds, ins, false)
-
-
-
-#endif /* _GRAPH_NODE_H */
diff --git a/src/gtkext/graph/nodes/Makefile.am b/src/gtkext/graph/nodes/Makefile.am
deleted file mode 100755
index 50f26f1..0000000
--- a/src/gtkext/graph/nodes/Makefile.am
+++ /dev/null
@@ -1,15 +0,0 @@
-
-noinst_LTLIBRARIES = libgtkextgraphnodes.la
-
-libgtkextgraphnodes_la_SOURCES = \
- flow.h flow.c \
- virtual.h virtual.c
-
-libgtkextgraphnodes_la_LDFLAGS =
-
-
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS)
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
-
-SUBDIRS =
diff --git a/src/gtkext/graph/nodes/flow.c b/src/gtkext/graph/nodes/flow.c
deleted file mode 100644
index e19cacb..0000000
--- a/src/gtkext/graph/nodes/flow.c
+++ /dev/null
@@ -1,1329 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * flow.c - encapsulation graphique des blocs d'exécution
- *
- * Copyright (C) 2013 Cyrille Bagard
- *
- * This file is part of Chrysalide.
- *
- * OpenIDA is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * OpenIDA is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#include "flow.h"
-
-
-#include <assert.h>
-#include <malloc.h>
-#include <stdlib.h>
-
-
-#include "../layout.h"
-#include "../node-int.h"
-
-
-
-/* Type d'un accrochage pour lien */
-struct _node_slot_t
-{
- GArchInstruction *instr; /* Instruction liée */
- size_t group_index; /* Rang dans le grp d'origine */
-
- InstructionLinkType type; /* Type de lien à représenter */
- size_t slot_index; /* Position dans l'accroche */
- gint x; /* Abscisse graphique du rendu */
-
-};
-
-/* Encapsulation graphique d'un bloc d'exécution (instance) */
-struct _GFlowNode
-{
- GGraphNode parent; /* A laisser en premier */
-
- GFlowBlock *block; /* Bloc d'exécution associé */
- GtkBufferView *view; /* Représentation graphique */
-
- node_slot_t *entries; /* Positions des pts d'entrées */
- size_t entries_count; /* Nombre de ces points */
- node_slot_t *exits; /* Positions des pts de sorties*/
- size_t exits_count; /* Nombre de ces points */
-
-};
-
-/* Encapsulation graphique d'un bloc d'exécution (classe) */
-struct _GFlowNodeClass
-{
- GGraphNodeClass parent; /* A laisser en premier */
-
-};
-
-
-#define SPACE_BETWEEN_SLOT 15
-
-
-/* Initialise la classe des encapsulations de bloc d'exécution. */
-static void g_flow_node_class_init(GFlowNodeClass *);
-
-/* Initialise une encapsulation de bloc d'exécution. */
-static void g_flow_node_init(GFlowNode *);
-
-/* Supprime toutes les références externes. */
-static void g_flow_node_dispose(GFlowNode *);
-
-/* Procède à la libération totale de la mémoire. */
-static void g_flow_node_finalize(GFlowNode *);
-
-/* Fournit le rang du noeud dans le graphique. */
-static unsigned int g_flow_node_get_rank(const GFlowNode *);
-
-/* Organise le contenu du noeud selon l'axe des abscisses. */
-static void g_flow_node_prepare_x_line(GFlowNode *, GGraphNode *);
-
-/* Parcourt tous les blocs d'instructions dans un ordre donné. */
-static bool g_flow_node_visit_flow_nodes(GFlowNode *, graph_node_visitor_cb, void *);
-
-
-
-/* ------------------------ GESTION DES ACCROCHES D'UN NOEUD ------------------------ */
-
-
-/* Prépare les points d'entrées du noeud. */
-static void g_flow_node_setup_entry_slots(GFlowNode *);
-
-/* Prépare les points de sorties du noeud. */
-static void g_flow_node_setup_exit_slots(GFlowNode *);
-
-/* Etablit un lien entre deux noeuds graphiques. */
-static node_slot_t *g_flow_node_get_slot(const GFlowNode *, bool, GArchInstruction *, size_t);
-
-/* Localise un point d'accroche à un noeud graphique. */
-static gint g_flow_node_get_slot_offset(const GFlowNode *, bool, const node_slot_t *);
-
-
-
-
-/* Indique le type définit par la GLib pour l'encapsulation d'un bloc d'exécution. */
-G_DEFINE_TYPE(GFlowNode, g_flow_node, G_TYPE_GRAPH_NODE);
-
-
-/******************************************************************************
-* *
-* Paramètres : klass = classe à initialiser. *
-* *
-* Description : Initialise la classe des encapsulations de bloc d'exécution. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_flow_node_class_init(GFlowNodeClass *klass)
-{
- GObjectClass *object; /* Autre version de la classe */
- GGraphNodeClass *node_class; /* Version parente de la classe*/
-
- object = G_OBJECT_CLASS(klass);
- node_class = G_GRAPH_NODE_CLASS(klass);
-
- object->dispose = (GObjectFinalizeFunc/* ! */)g_flow_node_dispose;
- object->finalize = (GObjectFinalizeFunc)g_flow_node_finalize;
-
- node_class->get_rank = (get_node_rank_fc)g_flow_node_get_rank;
- node_class->prepare_x = (node_prepare_x_fc)g_flow_node_prepare_x_line;
- node_class->visit = (visit_flow_nodes_fc)g_flow_node_visit_flow_nodes;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : node = instance à initialiser. *
-* *
-* Description : Initialise une encapsulation de bloc d'exécution. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_flow_node_init(GFlowNode *node)
-{
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : node = instance d'objet GLib à traiter. *
-* *
-* Description : Supprime toutes les références externes. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_flow_node_dispose(GFlowNode *node)
-{
- size_t i; /* Boucle de parcours */
-
- g_object_unref(G_OBJECT(node->block));
- g_object_unref(G_OBJECT(node->view));
-
- for (i = 0; i < node->entries_count; i++)
- g_object_unref(G_OBJECT(node->entries[i].instr));
-
- for (i = 0; i < node->exits_count; i++)
- g_object_unref(G_OBJECT(node->exits[i].instr));
-
- G_OBJECT_CLASS(g_flow_node_parent_class)->dispose(G_OBJECT(node));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : node = instance d'objet GLib à traiter. *
-* *
-* Description : Procède à la libération totale de la mémoire. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_flow_node_finalize(GFlowNode *node)
-{
- if (node->entries != NULL)
- free(node->entries);
-
- if (node->exits != NULL)
- free(node->exits);
-
- G_OBJECT_CLASS(g_flow_node_parent_class)->finalize(G_OBJECT(node));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : block = bloc d'exécution représenté graphiquement. *
-* view = morceau d'affichage à représenter. *
-* *
-* Description : Encapsule graphiquement un bloc d'exécution. *
-* *
-* Retour : Adresse de la structure mise en place. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GGraphNode *g_flow_node_new(GFlowBlock *block, GtkBufferView *view)
-{
- GFlowNode *result; /* Structure à retourner */
- GtkRequisition requisition; /* Taille à l'écran actuelle */
-
- result = g_object_new(G_TYPE_FLOW_NODE, NULL);
-
- g_object_ref(G_OBJECT(block));
- g_object_ref(G_OBJECT(view));
-
- result->block = block;
- result->view = view;
-
- gtk_widget_show(GTK_WIDGET(result->view));
- gtk_widget_size_allocate(GTK_WIDGET(result->view), (GtkAllocation []) { { 0, 0, 100, 100 } });
-
- gtk_widget_get_preferred_size(GTK_WIDGET(result->view), NULL, &requisition);
-
- G_GRAPH_NODE(result)->alloc.width = requisition.width;
- G_GRAPH_NODE(result)->alloc.height = requisition.height;
-
- g_flow_node_setup_entry_slots(result);
- g_flow_node_setup_exit_slots(result);
-
- return G_GRAPH_NODE(result);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : node = noeud graphique à consulter. *
-* *
-* Description : Fournit le rang du noeud dans le graphique. *
-* *
-* Retour : Indice supérieur ou égal à zéro. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static unsigned int g_flow_node_get_rank(const GFlowNode *node)
-{
- return g_flow_block_get_rank(node->block);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : node = noeud d'encapsulation à traiter. *
-* nodes = ensemble des noeuds en place. *
-* *
-* Description : Organise le contenu du noeud selon l'axe des abscisses. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_flow_node_prepare_x_line(GFlowNode *node, GGraphNode *nodes)
-{
- GGraphNode *base; /* Autre vision de l'instance */
- GArchInstruction *last; /* Dernière instr. du noeud */
- size_t loop_index; /* Indice de sortie en boucle */
- GFlowNode *target; /* Bloc visé par le lien */
- node_slot_t *dest_slot; /* Accrochage d'arrivée */
- pending_position pos; /* Position à transmettre */
- GFlowNode *target_a; /* Bloc visé par le lien #a */
- GFlowNode *target_b; /* Bloc visé par le lien #b */
- unsigned int rank_a; /* Indice du rang associé #a */
- unsigned int rank_b; /* Indice du rang associé #b */
- GGraphNode *container; /* Conteneur à positionner */
-
- base = G_GRAPH_NODE(node);
-
- g_flow_block_get_boundary(node->block, NULL, &last);
-
- for (loop_index = 0; loop_index < node->exits_count; loop_index++)
- if (node->exits[loop_index].type == ILT_LOOP)
- break;
-
- switch (node->exits_count - (loop_index == node->exits_count ? 0 : 1))
- {
- case 0:
- break;
-
- case 1:
-
- if (loop_index == node->exits_count)
- {
- target = G_FLOW_NODE(find_node_for_first_instruction(nodes, node->exits[0].instr));
-
- /* Cf. commentaire de g_flow_node_link() */
- if (target == NULL) break;
-
- dest_slot = g_flow_node_get_slot(target, true,
- last, node->exits[0].group_index);
-
- }
- else
- {
- target = G_FLOW_NODE(find_node_for_first_instruction(nodes, node->exits[1].instr));
-
- /* Cf. commentaire de g_flow_node_link() */
- if (target == NULL) break;
-
- dest_slot = g_flow_node_get_slot(target, true,
- last, node->exits[1].group_index);
-
- }
-
- pos.direct_x = g_flow_node_get_slot_offset(target, true, dest_slot);
- pos.direct_x = (G_GRAPH_NODE(target)->alloc.width / 2) - pos.direct_x;
-
- pos.direct_x -= (G_GRAPH_NODE(target)->alloc.width - G_GRAPH_NODE(node)->alloc.width) / 2;
-
- pos.relative_ref = base;
-
- size_t count_and_skip_loop(GFlowNode *n)
- {
- size_t counter;
-
- for (counter = 0; counter < n->entries_count; counter++)
- if (n->entries[counter].type == ILT_LOOP)
- break;
-
- return counter < n->entries_count ? n->entries_count - 1 : n->entries_count;
-
- }
-
- if (count_and_skip_loop(target) == 1)
- g_graph_node_set_pending_position(G_GRAPH_NODE(target), PPF_DIRECT_X, pos);
-
- break;
-
- case 2:
-
- target_a = G_FLOW_NODE(find_node_for_first_instruction(nodes, node->exits[0].instr));
- target_b = G_FLOW_NODE(find_node_for_first_instruction(nodes, node->exits[1].instr));
-
- rank_a = g_flow_node_get_rank(target_a);
- rank_b = g_flow_node_get_rank(target_b);
-
- if (rank_a == rank_b)
- {
- /* On s'assure que le père est centré par rapport aux deux fils */
-
- pos.left_node = G_GRAPH_NODE(target_a);
- pos.right_node = G_GRAPH_NODE(target_b);
-
- /**
- * Un pré-condition pour pouvoir s'aligner est que les noeuds
- * de références soient traités au préalables pour les positions.
- * Sinon les assert() coincent dans g_virtual_node_apply_x_line().
- */
-
- if (g_graph_node_find_container_at_same_level(nodes, base, pos.left_node) != NULL
- && g_graph_node_find_container_at_same_level(nodes, base, pos.right_node) != NULL)
- {
- g_graph_node_set_pending_position(base, PPF_MIDDLE_OF, pos);
- }
-
- break;
-
- }
-
- /* Alignement d'un bloc lié */
-
- if (rank_a > rank_b)
- {
- /* Seuil vertical pour un côté */
-
- container = g_graph_node_find_container_at_same_level(nodes,
- G_GRAPH_NODE(node),
- G_GRAPH_NODE(target_b));
-
- if (container == NULL) container = G_GRAPH_NODE(target_b);
-
- pos.left_margin = g_flow_node_get_slot_offset(node, false, &node->exits[0]);
- pos.relative_ref = base;
- g_graph_node_set_pending_position(container, PPF_LEFT_MARGIN, pos);
-
- /* Trait vertical de l'autre côté... */
-
- pos.direct_x = pos.left_margin;
-
- dest_slot = g_flow_node_get_slot(target_a, true,
- last, node->exits[0].group_index);
-
- pos.direct_x -= g_flow_node_get_slot_offset(target_a, true, dest_slot);
-
- pos.relative_ref = base;
-
- g_graph_node_set_pending_position(G_GRAPH_NODE(target_a), PPF_DIRECT_X, pos);
-
- }
- else
- {
- /* Seuil vertical pour un côté */
-
- container = g_graph_node_find_container_at_same_level(nodes,
- G_GRAPH_NODE(node),
- G_GRAPH_NODE(target_a));
-
- if (container == NULL) container = G_GRAPH_NODE(target_a);
-
- pos.right_margin = g_flow_node_get_slot_offset(node, false, &node->exits[1]);
- pos.relative_ref = base;
- g_graph_node_set_pending_position(container, PPF_RIGHT_MARGIN, pos);
-
- /* Trait vertical de l'autre côté... */
-
- pos.direct_x = pos.right_margin;
-
- dest_slot = g_flow_node_get_slot(target_b, true,
- last, node->exits[1].group_index);
-
- pos.direct_x -= g_flow_node_get_slot_offset(target_b, true, dest_slot);
-
- pos.relative_ref = base;
-
- g_graph_node_set_pending_position(G_GRAPH_NODE(target_b), PPF_DIRECT_X, pos);
-
- }
-
- break;
-
- }
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : node = noeud graphique démarrant la visite. *
-* callback = ensemble de blocs à parcourir. *
-* data = donnée utilisateur à associer au parcours. *
-* *
-* Description : Parcourt tous les blocs d'instructions dans un ordre donné. *
-* *
-* Retour : true si le parcours a été jusqu'à son terme, false sinon. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static bool g_flow_node_visit_flow_nodes(GFlowNode *node, graph_node_visitor_cb callback, void *data)
-{
- return callback(G_GRAPH_NODE(node), GVS_NODE, data);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : node = noeud graphique à consulter. *
-* *
-* Description : Fournit le bloc basique à l'origine du bloc graphique. *
-* *
-* Retour : Bloc brut encapsulé. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GFlowBlock *g_flow_node_get_block(const GFlowNode *node)
-{
- return node->block;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : node = noeud graphique à consulter. *
-* instr = instruction à considérer. *
-* *
-* Description : Précise si le noeud a pour première instruction celle donnée.*
-* *
-* Retour : true si la première instruction du noeud est celle indiquée. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-bool g_flow_node_start_with(const GFlowNode *node, GArchInstruction *instr)
-{
- GArchInstruction *first; /* Première instr. du noeud */
-
- g_flow_block_get_boundary(node->block, &first, NULL);
-
- return (first == instr);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : node = noeud graphique à consulter. *
-* instr = instruction à considérer. *
-* *
-* Description : Précise si le noeud a pour dernière instruction celle donnée.*
-* *
-* Retour : true si la dernière instruction du noeud est celle indiquée. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-bool g_flow_node_end_with(const GFlowNode *node, GArchInstruction *instr)
-{
- GArchInstruction *last; /* Dernière instr. du noeud */
-
- g_flow_block_get_boundary(node->block, NULL, &last);
-
- return (last == instr);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : node = noeud graphique à consulter. *
-* ranks = classement à mettre à jour. *
-* *
-* Description : Précise la hauteur minimale requise pour un noeud. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_flow_node_register_rank(const GFlowNode *node, GGraphRanks *ranks)
-{
- unsigned int index; /* Indice du rang associé */
-
- index = g_flow_node_get_rank(node);
-
- g_graph_ranks_set_min_height(ranks, index, G_GRAPH_NODE(node)->alloc.height);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : node = noeud graphique à mettre à jour. *
-* ranks = classement à consulter. *
-* *
-* Description : Définit l'ordonnée de l'espace attribué à un noeud. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_flow_node_apply_rank(GFlowNode *node, GGraphRanks *ranks)
-{
- unsigned int index; /* Indice du rang associé */
-
- index = g_flow_node_get_rank(node);
-
- G_GRAPH_NODE(node)->alloc.y = g_graph_ranks_get_y_for_rank(ranks, index);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : node = noeud graphique à mettre à jour. *
-* layout = disposition globale du graphique. *
-* nodes = ensemble des noeuds en place. *
-* *
-* Description : Etablit les liaison entre un noeud et ses suivants. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_flow_node_link(GFlowNode *node, GGraphLayout *layout, GGraphNode *nodes)
-{
- GArchInstruction *last; /* Dernière instr. du noeud */
- size_t i; /* Boucle de parcours */
- GFlowNode *target; /* Bloc visé par le lien */
- node_slot_t *dest_slot; /* Accrochage d'arrivée */
- EdgeColor color; /* Couleur du lien à créer */
- GGraphEdge *edge; /* Lien à mettre en place */
-
- g_flow_block_get_boundary(node->block, NULL, &last);
-
- for (i = 0; i < node->exits_count; i++)
- {
- target = G_FLOW_NODE(find_node_for_first_instruction(nodes, node->exits[i].instr));
-
- /**
- * Il semblerait que l'adresse ciblée puisse ne correspondre à aucun bloc.
- * Ce serait le cas pour un saut avec __gmon_start__ sous ARM, à confirmer (TODO).
- * Référence. : http://stackoverflow.com/questions/12697081/what-is-gmon-start-symbol
- */
- if (target == NULL) continue;
-
- dest_slot = g_flow_node_get_slot(target, true,
- last, node->exits[i].group_index);
-
- switch (node->exits[i].type)
- {
- case ILT_JUMP_IF_TRUE:
- color = EGC_GREEN;
- break;
- case ILT_JUMP_IF_FALSE:
- color = EGC_RED;
- break;
- case ILT_LOOP:
- color = EGC_BLUE;
- break;
- case ILT_CATCH_EXCEPTION:
- color = EGC_DASHED_GRAY;
- break;
- default:
- color = EGC_DEFAULT;
- break;
-
- }
-
- edge = g_graph_edge_new(node, &node->exits[i], target, dest_slot, color);
- g_graph_layout_add_edge(layout, edge);
-
- }
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : node = intermédiaire à consulter. *
-* view = support de destination. *
-* *
-* Description : Place un noeud sur son support final. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_flow_node_place(const GFlowNode *node, GtkGraphView *view)
-{
- gtk_graph_view_put(view, GTK_WIDGET(node->view), &G_GRAPH_NODE(node)->alloc);
-
-}
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* GESTION DES ACCROCHES D'UN NOEUD */
-/* ---------------------------------------------------------------------------------- */
-
-
-/******************************************************************************
-* *
-* Paramètres : node = noeud graphique contenant les accrochées indiquées. *
-* a = première accroche à considérer. *
-* b = seconde accroche à considérer. *
-* *
-* Description : Compare deux accroches pour liens entre noeuds. *
-* *
-* Retour : Bilan de la comparaison : -1, 0 ou 1. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-int g_flow_node_compare_slots_for_edges(const GFlowNode *node, const node_slot_t *a, gint src_a, const node_slot_t *b, gint src_b)
-{
- int result; /* Bilan à retourner */
- GGraphNode *base; /* Accès rapides */
- gint middle; /* Milieu du noeud traité */
- gint diff_a; /* Distance A <-> centre */
- gint diff_b; /* Distance B <-> centre */
-
-
- /**
- * On place les extrémités en premier, afin de les traiter en premier.
- */
-
- int cmp_slot_indexes(const node_slot_t *a, const node_slot_t *b)
- {
- int result;
-
- if (a->slot_index < b->slot_index)
- result = 1;
-
- else if (a->slot_index > b->slot_index)
- result = -1;
-
- else
- result = 0;
-
- return result;
-
- }
-
-
- switch (node->entries_count)
- {
- case 0:
- case 1:
- assert(0);
- break;
-
- case 2:
-
- /**
- * Le tri se fait simplement : un accroche à gauche, l'autre à droite.
- */
-
- result = cmp_slot_indexes(a, b);
- break;
-
- default:
-
- /**
- * On donne plus de poids aux accroches éloignées du centre.
- * Facile quand les accroches sont distribuées d'un même côté, centre
- * à utiliser dans les calculs sinon.
- */
-
- base = G_GRAPH_NODE(node);
-
- middle = base->alloc.x + (base->alloc.width / 2);
-
-
- /* Les deux accroches sont à gauche */
- if (src_a <= middle && src_b <= middle)
- result = cmp_slot_indexes(b, a);
-
- /* Les deux accroches sont à droite */
- else if (src_a > middle && src_b > middle)
- result = cmp_slot_indexes(a, b);
-
- /* Les deux accroches sont de chaque côté */
- else
- {
- diff_a = (middle > src_a ? middle - src_a : src_a - middle);
- diff_b = (middle > src_b ? middle - src_b : src_b - middle);
-
- if (diff_a < diff_b)
- result = 1;
-
- else if (diff_a > diff_b)
- result = -1;
-
- else
- result = 0;
-
- }
-
- break;
-
- }
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : node = intermédiaire à compléter. *
-* *
-* Description : Prépare les points d'entrées du noeud. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_flow_node_setup_entry_slots(GFlowNode *node)
-{
- GArchInstruction *first; /* Première instr. du noeud */
- GArchInstruction **instrs; /* Instr. visée par une autre */
- InstructionLinkType *types; /* Type de lien entre lignes */
- size_t icount; /* Nombre de liens de dest. */
- size_t usable; /* Nombre de liens utiles ici */
- size_t i; /* Boucle de parcours */
- size_t used; /* Nombre de liens utilisés */
-
- g_flow_block_get_boundary(node->block, &first, NULL);
-
- g_arch_instruction_rlock_src(first);
- icount = g_arch_instruction_get_sources(first, &instrs, &types);
-
- usable = 0;
-
- for (i = 0; i < icount; i++)
- switch (types[i])
- {
- case ILT_EXEC_FLOW:
- case ILT_JUMP:
- case ILT_CASE_JUMP:
- case ILT_JUMP_IF_TRUE:
- case ILT_JUMP_IF_FALSE:
- case ILT_LOOP:
- case ILT_CATCH_EXCEPTION:
- usable++;
- break;
-
- default:
- break;
-
- }
-
- if (usable == 0)
- {
- node->entries = NULL;
- node->entries_count = 0;
- }
- else
- {
- node->entries = (node_slot_t *)calloc(usable, sizeof(node_slot_t));
- node->entries_count = usable;
- }
-
- used = 0;
-
- for (i = 0; i < icount; i++)
- switch (types[i])
- {
- case ILT_EXEC_FLOW:
- case ILT_JUMP:
- case ILT_CASE_JUMP:
- case ILT_JUMP_IF_TRUE:
- case ILT_JUMP_IF_FALSE:
- case ILT_LOOP:
- case ILT_CATCH_EXCEPTION:
-
- g_object_ref(instrs[i]);
- node->entries[used].instr = instrs[i];
-
- node->entries[used].type = types[i];
- node->entries[used].group_index = g_arch_instruction_compute_group_index(&instrs[i],
- instrs, icount);
- node->entries[used].slot_index = used;
-
- used++;
-
- break;
-
- default:
- break;
-
- }
-
- assert(used == usable);
-
- g_arch_instruction_runlock_src(first);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : node = intermédiaire à compléter. *
-* *
-* Description : Prépare les points de sorties du noeud. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_flow_node_setup_exit_slots(GFlowNode *node)
-{
- GArchInstruction *last; /* Dernière instr. du noeud */
- GArchInstruction **instrs; /* Instr. visée par une autre */
- InstructionLinkType *types; /* Type de lien entre lignes */
- size_t icount; /* Nombre de liens de dest. */
- size_t usable; /* Nombre de liens utiles ici */
- size_t i; /* Boucle de parcours */
- size_t used; /* Nombre de liens utilisés */
-
- g_flow_block_get_boundary(node->block, NULL, &last);
-
- g_arch_instruction_rlock_dest(last);
- icount = g_arch_instruction_get_destinations(last, &instrs, &types, NULL);
-
- usable = 0;
-
- for (i = 0; i < icount; i++)
- switch (types[i])
- {
- case ILT_EXEC_FLOW:
- case ILT_JUMP:
- case ILT_CASE_JUMP:
- case ILT_JUMP_IF_TRUE:
- case ILT_JUMP_IF_FALSE:
- case ILT_LOOP:
- case ILT_CATCH_EXCEPTION:
- usable++;
- break;
-
- default:
- break;
-
- }
-
- if (usable == 0)
- {
- node->exits = NULL;
- node->exits_count = 0;
- }
- else
- {
- node->exits = (node_slot_t *)calloc(usable, sizeof(node_slot_t));
- node->exits_count = usable;
- }
-
- used = 0;
-
- for (i = 0; i < icount; i++)
- switch (types[i])
- {
- case ILT_EXEC_FLOW:
- case ILT_JUMP:
- case ILT_CASE_JUMP:
- case ILT_JUMP_IF_TRUE:
- case ILT_JUMP_IF_FALSE:
- case ILT_LOOP:
- case ILT_CATCH_EXCEPTION:
-
- g_object_ref(instrs[i]);
- node->exits[used].instr = instrs[i];
-
- node->exits[used].type = types[i];
- node->exits[used].group_index = g_arch_instruction_compute_group_index(&instrs[i],
- instrs, icount);
- node->exits[used].slot_index = used;
-
- used++;
-
- break;
-
- default:
- break;
-
- }
-
- assert(used == usable);
-
- g_arch_instruction_runlock_dest(last);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : node = noeud graphique à consulter. *
-* entry = indique le type d'accrochage recherché. *
-* instr = instruction visée. *
-* index = indice de groupe pour départager au besoin. *
-* *
-* Description : Etablit un lien entre deux noeuds graphiques. *
-* *
-* Retour : Lien graphique mis en place. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static node_slot_t *g_flow_node_get_slot(const GFlowNode *node, bool entry, GArchInstruction *instr, size_t index)
-{
- node_slot_t *result; /* Emplacement à retourner */
- node_slot_t *list; /* Liste à parcourir */
- size_t count; /* Taille de cette liste */
- size_t i; /* Boucle de parcours */
-
- if (entry)
- {
- list = node->entries;
- count = node->entries_count;
- }
- else
- {
- list = node->exits;
- count = node->exits_count;
- }
-
- for (i = 0; i < count; i++)
- {
- result = list + i;
-
- if (result->instr == instr/* && result->group_index == index*/)
- break;
-
- }
-
- return (i == count ? NULL : result);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : node = noeud graphique à consulter. *
-* entry = indique le type d'accrochage recherché. *
-* slot = accroche dont l'emplacement est à définir. *
-* *
-* Description : Localise un point d'accroche à un noeud graphique. *
-* *
-* Retour : Décallage relatif pour l'accroche fournie. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static gint g_flow_node_get_slot_offset(const GFlowNode *node, bool entry, const node_slot_t *slot)
-{
- gint result; /* Valeur à retourner */
- node_slot_t *slots; /* Accroches à parcourir */
- size_t count; /* Nombre de ces points */
- gint slots_width; /* Largeur des accroches */
- gint slots_left; /* Abscisse de la première */
- size_t index; /* Indice de l'accroche visée */
-
- if (entry)
- {
- slots = node->entries;
- count = node->entries_count;
- }
- else
- {
- slots = node->exits;
- count = node->exits_count;
- }
-
- slots_width = (count - 1) * SPACE_BETWEEN_SLOT;
- slots_left = (G_GRAPH_NODE(node)->alloc.width - slots_width) / 2;
-
- index = (slot - slots);
- /* BUG_ON(index >= count); */
-
- index = slot->slot_index;
-
- result = slots_left + index * SPACE_BETWEEN_SLOT;
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : node = intermédiaire à consulter. *
-* nodes = ensemble des noeuds en place. *
-* *
-* Description : Réorganise au mieux les points d'accroche d'un noeud. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-#include "../../../arch/instruction-int.h"
-void g_flow_node_reorder_slots(const GFlowNode *node, GGraphNode *nodes)
-{
-
- typedef struct _reordering_params
- {
- GdkPoint middle; /* Milieu du noeud traité */
- bool down_first; /* Liens descendants aux bords */
-
- bool entry; /* Zone d'accrochage aux bouts */
- GArchInstruction *instr; /* Instruction du bloc courant */
-
- } reordering_params;
-
- typedef struct _reordered_slot
- {
- const reordering_params *params; /* Informations partagées */
-
- GdkPoint dest; /* Position à l'extrémité */
-
- size_t orig_index; /* Indice d'accroche d'origine */
-
- } reordered_slot;
-
-
- GGraphNode *base; /* Accès rapides */
- reordering_params params; /* Directives générales */
-
-
- int cmp_slots_for_reordering(const reordered_slot *a, const reordered_slot *b)
- {
- const reordering_params *params; /* Informations partagées */
- bool on_left_a; /* Lien A vers la gauche ? */
- bool on_left_b; /* Lien B vers la gauche ? */
- bool go_down_a; /* Lien A vers le bas ? */
- bool go_down_b; /* Lien B vers le bas ? */
-
- params = a->params;
-
- /* Première distinction : côté par rapport au centre */
-
- on_left_a = (a->dest.x <= params->middle.x);
- on_left_b = (b->dest.x <= params->middle.x);
-
- if (on_left_a && !on_left_b) return -1;
- else if (!on_left_a && on_left_b) return 1;
-
- /* On évite les recoupements entre montées et descentes */
-
- go_down_a = (a->dest.y >= params->middle.y);
- go_down_b = (b->dest.y >= params->middle.y);
-
- if (go_down_a && !go_down_b) return (params->down_first ? -1 : 1);
- else if (!go_down_a && go_down_b) return (params->down_first ? -1 : 1);
-
- /* Au sein d'une même catégorie, on se base uniquement sur la position */
-
- return (a->dest.x <= b->dest.x ? -1 : 1);
-
- }
-
- void reorder_slots(node_slot_t *slots, size_t count, __compar_fn_t cmp, const reordering_params *params, GGraphNode *nodes)
- {
- reordered_slot *rslots; /* Créneaux réorganisés */
- reordered_slot *iter; /* Boucle de parcours #1 */
- size_t used; /* Nombre de liens valides */
- size_t i; /* Boucle de parcours #2 */
- GFlowNode *target; /* Bloc visé par le lien */
- node_slot_t *dest_slot; /* Accrochage associé */
-
- rslots = (reordered_slot *)calloc(count, sizeof(reordered_slot));
-
- /* Constitution d'une liste triée */
-
- iter = rslots;
- used = 0;
-
- for (i = 0; i < count; i++)
- {
- iter->params = params;
-
- target = G_FLOW_NODE(_find_node_for_instruction(nodes, slots[i].instr, params->entry));
-
- /* Cf. commentaire de g_flow_node_link() */
- if (target == NULL) continue;
-
- dest_slot = g_flow_node_get_slot(target, params->entry,
- params->instr, slots[i].group_index);
-
- iter->dest = g_flow_node_get_point_from_slot(target, params->entry, dest_slot);
-
- iter->orig_index = i;
-
- iter++;
- used++;
-
- }
-
- /* TODO : utiliser qsort_r, avec params en argument ? */
- qsort(rslots, used, sizeof(reordered_slot), cmp);
-
-
-
-
- for (i = 0; i < used; i++)
- {
-
-
- if (rslots[i].orig_index != i)
- printf("Could reorder %zu -> %zu\n", rslots[i].orig_index, i);
-
- if (rslots[i].orig_index != i)
- slots[rslots[i].orig_index].slot_index = i;
-
-
-
- }
-
- free(rslots);
-
- }
-
-
- base = G_GRAPH_NODE(node);
-
- /* Régorganise les accroches d'entrée */
-
- if (node->entries_count > 1)
- {
- params.middle.x = base->alloc.x + (base->alloc.width / 2);
- params.middle.y = base->alloc.y;
-
- params.down_first = true;
-
- params.entry = false;
- g_flow_block_get_boundary(node->block, &params.instr, NULL);
-
- printf(" ### REORDERING ENTRIES OF 0x%08x\n", (unsigned int)params.instr->range.addr.virtual);
-
- reorder_slots(node->entries, node->entries_count, (__compar_fn_t)cmp_slots_for_reordering, &params, nodes);
-
- }
-
- /* Régorganise les accroches de sortie */
-
- if (node->exits_count > 1)
- {
- params.middle.x = base->alloc.x + (base->alloc.width / 2);
- params.middle.y = base->alloc.y + base->alloc.height;
-
- params.down_first = false;
-
- params.entry = true;
- g_flow_block_get_boundary(node->block, NULL, &params.instr);
-
- printf(" ### REORDERING EXITS OF 0x%08x\n", (unsigned int)params.instr->range.addr.virtual);
-
- reorder_slots(node->exits, node->exits_count, (__compar_fn_t)cmp_slots_for_reordering, &params, nodes);
-
- }
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : node = noeud graphique à consulter. *
-* entry = indique le type d'accrochage recherché. *
-* slot = accroche dont l'emplacement est à définir. *
-* *
-* Description : Localise un point d'accroche à un noeud graphique. *
-* *
-* Retour : Emplacement réservé pour l'accroche fournie. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GdkPoint g_flow_node_get_point_from_slot(const GFlowNode *node, bool entry, const node_slot_t *slot)
-{
- GGraphNode *base; /* Accès rapides */
- GdkPoint result; /* Position à retourner */
- node_slot_t *slots; /* Accroches à parcourir */
- size_t count; /* Nombre de ces points */
- gint slots_width; /* Largeur des accroches */
- gint slots_left; /* Abscisse de la première */
- size_t index; /* Indice de l'accroche visée */
-
- base = G_GRAPH_NODE(node);
-
- if (entry)
- {
- result.y = base->alloc.y;
-
- slots = node->entries;
- count = node->entries_count;
-
- }
- else
- {
- result.y = base->alloc.y + base->alloc.height;
-
- slots = node->exits;
- count = node->exits_count;
-
- }
-
- slots_width = (count - 1) * SPACE_BETWEEN_SLOT;
- slots_left = base->alloc.x + (base->alloc.width - slots_width) / 2;
-
- index = (slot - slots)/* / sizeof(node_slot_t)*/;
- /* BUG_ON(index >= count); */
-
-
- if (count > 1 && entry)
- printf(" -->> index = %zu vs %zu (max = %zu)\n", index, slot->slot_index, count);
-
- index = slot->slot_index;
-
-
- result.x = slots_left + index * SPACE_BETWEEN_SLOT;
-
- return result;
-
-}
diff --git a/src/gtkext/graph/nodes/flow.h b/src/gtkext/graph/nodes/flow.h
deleted file mode 100644
index 76d0a03..0000000
--- a/src/gtkext/graph/nodes/flow.h
+++ /dev/null
@@ -1,99 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * flow.h - prototypes pour l'encapsulation graphique des blocs d'exécution
- *
- * Copyright (C) 2013 Cyrille Bagard
- *
- * This file is part of Chrysalide.
- *
- * OpenIDA is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * OpenIDA is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#ifndef _GTKEXT_GRAPH_NODES_FLOW_H
-#define _GTKEXT_GRAPH_NODES_FLOW_H
-
-
-#include "../node.h"
-#include "../../../analysis/blocks/flow.h"
-
-
-
-/* Redéfinition depuis layout.h pour contourner une boucle. */
-typedef struct _GGraphLayout GGraphLayout;
-
-
-
-#define G_TYPE_FLOW_NODE (g_flow_node_get_type())
-#define G_FLOW_NODE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_FLOW_NODE, GFlowNode))
-#define G_FLOW_NODE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_FLOW_NODE, GFlowNodeClass))
-#define G_IS_FLOW_NODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_FLOW_NODE))
-#define G_IS_FLOW_NODE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_FLOW_NODE))
-#define G_FLOW_NODE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_FLOW_NODE, GFlowNodeClass))
-
-
-/* Type d'un accrochage pour lien */
-typedef struct _node_slot_t node_slot_t;
-
-/* Encapsulation graphique d'un bloc d'exécution (instance) */
-typedef struct _GFlowNode GFlowNode;
-
-/* Encapsulation graphique d'un bloc d'exécution (classe) */
-typedef struct _GFlowNodeClass GFlowNodeClass;
-
-
-/* Indique le type définit par la GLib pour l'encapsulation d'un bloc d'exécution. */
-GType g_flow_node_get_type(void);
-
-/* Encapsule graphiquement un bloc d'exécution. */
-GGraphNode *g_flow_node_new(GFlowBlock *, GtkBufferView *);
-
-/* Fournit le bloc basique à l'origine du bloc graphique. */
-GFlowBlock *g_flow_node_get_block(const GFlowNode *);
-
-/* Précise si le noeud a pour première instruction celle donnée. */
-bool g_flow_node_start_with(const GFlowNode *, GArchInstruction *);
-
-/* Précise si le noeud a pour dernière instruction celle donnée. */
-bool g_flow_node_end_with(const GFlowNode *, GArchInstruction *);
-
-/* Précise la hauteur minimale requise pour un noeud. */
-void g_flow_node_register_rank(const GFlowNode *, GGraphRanks *);
-
-/* Définit l'ordonnée de l'espace attribué à un noeud. */
-void g_flow_node_apply_rank(GFlowNode *, GGraphRanks *);
-
-/* Etablit les liaison entre un noeud et ses suivants. */
-void g_flow_node_link(GFlowNode *, GGraphLayout *, GGraphNode *);
-
-/* Place un noeud sur son support final. */
-void g_flow_node_place(const GFlowNode *, GtkGraphView *);
-
-
-
-/* ------------------------ GESTION DES ACCROCHES D'UN NOEUD ------------------------ */
-
-
-/* Compare deux accroches pour liens entre noeuds. */
-int g_flow_node_compare_slots_for_edges(const GFlowNode *, const node_slot_t *, gint, const node_slot_t *, gint);
-
-/* Réorganise au mieux les points d'accroche d'un noeud. */
-void g_flow_node_reorder_slots(const GFlowNode *, GGraphNode *);
-
-/* Localise un point d'accroche à un noeud graphique. */
-GdkPoint g_flow_node_get_point_from_slot(const GFlowNode *, bool, const node_slot_t *);
-
-
-
-#endif /* _GTKEXT_GRAPH_NODES_FLOW_H */
diff --git a/src/gtkext/graph/nodes/virtual.c b/src/gtkext/graph/nodes/virtual.c
deleted file mode 100644
index 62f5b42..0000000
--- a/src/gtkext/graph/nodes/virtual.c
+++ /dev/null
@@ -1,990 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * virtual.c - encapsulation graphique des blocs virtuels
- *
- * Copyright (C) 2013 Cyrille Bagard
- *
- * This file is part of Chrysalide.
- *
- * OpenIDA is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * OpenIDA is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#include "virtual.h"
-
-
-#include <assert.h>
-#include <malloc.h>
-#include <sys/param.h>
-
-
-#include "flow.h"
-#include "../node-int.h"
-
-
-
-/* ----------------------- MANIPULATION DES PORTES VERTICALES ----------------------- */
-
-
-/* Etendue verticale d'un lien */
-typedef struct _reserved_vspan
-{
- unsigned int r1; /* Départ d'une ligne */
- unsigned int r2; /* Arrivée de cette même ligne */
-
-} reserved_vspan;
-
-/* Lignes de liens verticales au sein d'un même groupe */
-typedef struct _vert_links
-{
- reserved_vspan *vspans; /* Lignes sans chevauchement */
- size_t count; /* Nombre de ces lignes */
-
-} vert_links;
-
-
-/* Initialise les futures portées d'un même niveau. */
-static void init_vertical_links(vert_links *);
-
-/* Regarde si des portées verticales se chevauchent ou non. */
-static bool is_intersection_with_vertical_spans(const vert_links *, const reserved_vspan *);
-
-/* Ajoute une réservation à un ensemble de portées verticales. */
-static void extend_vertical_links_spans(vert_links *, const reserved_vspan *);
-
-
-
-/* ---------------------- REPRESENTATIONS DES GROUPES LOGIQUES ---------------------- */
-
-
-/* Représentation d'un étage */
-typedef struct _virtual_level
-{
- unsigned int rank; /* Rang associé à l'étage */
-
- GGraphNode **children; /* Noeuds englobés */
- size_t count; /* Quantité de ces noeuds */
-
-} virtual_level;
-
-/* Encapsulation graphique d'un bloc virtuel (instance) */
-struct _GVirtualNode
-{
- GGraphNode parent; /* A laisser en premier */
-
- GVirtualBlock *block; /* Bloc virtuel associé */
-
- GGraphNode **children; /* Noeuds englobés */
- size_t count; /* Quantité de ces noeuds */
- virtual_level *levels; /* Différents étages de noeuds */
- size_t lcount; /* Nombre de ces étages */
-
- vert_links *left_padding; /* Espace à gauche pour liens */
- vspan_slot_t left_count; /* Nombre de largeurs réservées*/
- vert_links *right_padding; /* Espace à droite pour liens */
- vspan_slot_t right_count; /* Nombre de largeurs réservées*/
-
-};
-
-/* Encapsulation graphique d'un bloc virtuel (classe) */
-struct _GVirtualNodeClass
-{
- GGraphNodeClass parent; /* A laisser en premier */
-
-};
-
-
-/* Initialise la classe des encapsulations de blocs virtuels. */
-static void g_virtual_node_class_init(GVirtualNodeClass *);
-
-/* Initialise une encapsulation de bloc virtuel. */
-static void g_virtual_node_init(GVirtualNode *);
-
-/* Supprime toutes les références externes. */
-static void g_virtual_node_dispose(GVirtualNode *);
-
-/* Procède à la libération totale de la mémoire. */
-static void g_virtual_node_finalize(GVirtualNode *);
-
-/* Fournit le rang du noeud dans le graphique. */
-static unsigned int g_virtual_node_get_rank(const GVirtualNode *);
-
-/* Réinitialise la position d'un noeud d'encapsulation. */
-static void g_virtual_node_reset_position(GVirtualNode *);
-
-/* Définit les abscisses relatives du contenu d'un noeud. */
-static void g_virtual_node_prepare_x_line(GVirtualNode *, GGraphNode *);
-
-/* Applique une position finale au noeud. */
-static void g_virtual_node_apply_position(GVirtualNode *);
-
-/* Définit les abscisses relatives du contenu d'un noeud. */
-static void g_virtual_node_apply_x_line(GVirtualNode *);
-
-/* Met à jour la largeur interne du noeud. */
-static void g_virtual_node_compute_width(GVirtualNode *);
-
-/* Altère la position du noeud d'encapsulation. */
-static void g_virtual_node_set_position(GVirtualNode *, gint);
-
-/* Parcourt tous les blocs d'instructions dans un ordre donné. */
-static bool g_virtual_node_visit_flow_nodes(GVirtualNode *, graph_node_visitor_cb, void *);
-
-/* Recherche le noeud contenant un autre noeud. */
-static GGraphNode *g_virtual_node_find_container(GVirtualNode *, GGraphNode *);
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* MANIPULATION DES PORTES VERTICALES */
-/* ---------------------------------------------------------------------------------- */
-
-
-/******************************************************************************
-* *
-* Paramètres : links = liste à initialiser. *
-* *
-* Description : Initialise les futures portées d'un même niveau. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void init_vertical_links(vert_links *links)
-{
- links->vspans = NULL;
- links->count = 0;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : links = liste de portées déjà en place. *
-* vspan = nouvelle portée à insérer quelque part. *
-* *
-* Description : Regarde si des portées verticales se chevauchent ou non. *
-* *
-* Retour : true si les portées peuvent cohabiter, false sinon. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static bool is_intersection_with_vertical_spans(const vert_links *links, const reserved_vspan *vspan)
-{
- bool result; /* Bilan d'analyse à retourner */
- size_t i; /* Boucle de parcours */
-
- result = false;
-
- for (i = 0; i < links->count && !result; i++)
- {
- if (vspan->r1 < links->vspans[i].r1)
- result = vspan->r2 >= links->vspans[i].r1;
-
- else if (vspan->r1 > links->vspans[i].r2)
- result = vspan->r2 <= links->vspans[i].r2;
-
- else
- {
- result = links->vspans[i].r1 < vspan->r1 && vspan->r1 < links->vspans[i].r2;
- result |= links->vspans[i].r1 < vspan->r2 && vspan->r2 < links->vspans[i].r2;
- }
-
- }
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : spans = liste de portées déjà en place. *
-* vspan = nouvelle portée à insérer quelque part. *
-* *
-* Description : Ajoute une réservation à un ensemble de portées verticales. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void extend_vertical_links_spans(vert_links *links, const reserved_vspan *new)
-{
- links->vspans = (reserved_vspan *)realloc(links->vspans,
- ++links->count * sizeof(reserved_vspan));
-
- if (new->r1 <= new->r2)
- links->vspans[links->count - 1] = *new;
- else
- {
- links->vspans[links->count - 1].r1 = new->r2;
- links->vspans[links->count - 1].r2 = new->r1;
- }
-
-}
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* REPRESENTATIONS DES GROUPES LOGIQUES */
-/* ---------------------------------------------------------------------------------- */
-
-
-/* Indique le type définit par la GLib pour l'encapsulation d'un bloc virtuel. */
-G_DEFINE_TYPE(GVirtualNode, g_virtual_node, G_TYPE_GRAPH_NODE);
-
-
-/******************************************************************************
-* *
-* Paramètres : klass = classe à initialiser. *
-* *
-* Description : Initialise la classe des encapsulations de blocs virtuels. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_virtual_node_class_init(GVirtualNodeClass *klass)
-{
- GObjectClass *object; /* Autre version de la classe */
- GGraphNodeClass *node_class; /* Version parente de la classe*/
-
- object = G_OBJECT_CLASS(klass);
- node_class = G_GRAPH_NODE_CLASS(klass);
-
- object->dispose = (GObjectFinalizeFunc/* ! */)g_virtual_node_dispose;
- object->finalize = (GObjectFinalizeFunc)g_virtual_node_finalize;
-
- node_class->get_rank = (get_node_rank_fc)g_virtual_node_get_rank;
- node_class->reset_pos = (node_reset_pos_fc)g_virtual_node_reset_position;
- node_class->prepare_x = (node_prepare_x_fc)g_virtual_node_prepare_x_line;
- node_class->apply_pos = (node_apply_pos_fc)g_virtual_node_apply_position;
- node_class->set_pos = (node_set_pos_fc)g_virtual_node_set_position;
- node_class->visit = (visit_flow_nodes_fc)g_virtual_node_visit_flow_nodes;
- node_class->contain = (find_container_fc)g_virtual_node_find_container;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : node = instance à initialiser. *
-* *
-* Description : Initialise une encapsulation de bloc virtuel. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_virtual_node_init(GVirtualNode *node)
-{
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : node = instance d'objet GLib à traiter. *
-* *
-* Description : Supprime toutes les références externes. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_virtual_node_dispose(GVirtualNode *node)
-{
- size_t i; /* Boucle de parcours */
-
- g_object_unref(G_OBJECT(node->block));
-
- for (i = 0; i < node->count; i++)
- g_object_unref(G_OBJECT(node->children[i]));
-
- if (node->children != NULL)
- free(node->children);
-
- G_OBJECT_CLASS(g_virtual_node_parent_class)->dispose(G_OBJECT(node));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : node = instance d'objet GLib à traiter. *
-* *
-* Description : Procède à la libération totale de la mémoire. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_virtual_node_finalize(GVirtualNode *node)
-{
- G_OBJECT_CLASS(g_virtual_node_parent_class)->finalize(G_OBJECT(node));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : block = bloc virtuel représenté graphiquement. *
-* *
-* Description : Encapsule graphiquement un bloc virtuel. *
-* *
-* Retour : Adresse de la structure mise en place. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GGraphNode *g_virtual_node_new(GVirtualBlock *block)
-{
- GVirtualNode *result; /* Structure à retourner */
-
- result = g_object_new(G_TYPE_VIRTUAL_NODE, NULL);
-
- g_object_ref(G_OBJECT(block));
-
- result->block = block;
-
- return G_GRAPH_NODE(result);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : node = noeud graphique à consulter. *
-* *
-* Description : Fournit le rang du noeud dans le graphique. *
-* *
-* Retour : Indice supérieur ou égal à zéro. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static unsigned int g_virtual_node_get_rank(const GVirtualNode *node)
-{
- /* BUG_ON(node->count == 0) */
-
- return g_graph_node_get_rank(node->children[0]);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : node = noeud graphique à manipuler. *
-* *
-* Description : Réinitialise la position d'un noeud d'encapsulation. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_virtual_node_reset_position(GVirtualNode *node)
-{
- size_t i; /* Boucle de parcours */
-
- for (i = 0; i < node->count; i++)
- g_graph_node_reset_position(node->children[i]);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : node = noeud d'encapsulation à traiter. *
-* nodes = ensemble des noeuds en place. *
-* *
-* Description : Définit les abscisses relatives du contenu d'un noeud. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_virtual_node_prepare_x_line(GVirtualNode *node, GGraphNode *nodes)
-{
- size_t i; /* Boucle de parcours */
-
- for (i = 0; i < node->count; i++)
- g_graph_node_prepare_x_line(node->children[i], nodes);
-
-}
-
-
-
-/******************************************************************************
-* *
-* Paramètres : node = noeud d'encapsulation à traiter. *
-* *
-* Description : Applique une position finale au noeud. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_virtual_node_apply_position(GVirtualNode *node)
-{
- gint min; /* Valeur minimale rencontrée */
- size_t i; /* Boucle de parcours */
- gint x_pos; /* Nouvelle position #1 */
- gint offset; /* Décallage à faire suivre */
-
- g_virtual_node_apply_x_line(node);
-
- /* Collecte de l'ensemble des positions */
-
- min = 0;
-
- for (i = 0; i < node->count; i++)
- {
- g_graph_node_get_position(node->children[i], &x_pos, NULL);
- min = MIN(min, x_pos);
- }
-
- /* Espace pour les liens remontants */
-
- if (node->left_count > 0)
- offset = EDGE_SLOT_HORIZ_MARGIN + EDGE_HORIZONTAL_MIN_SEP * (node->left_count - 1);
- else
- offset = 0;
-
- /* Ajout du décallage le plus grand */
-
- offset += -min;
-
- /* Traitement des sous-noeuds */
-
- for (i = 0; i < node->count; i++)
- {
- /* BUG_ON(node->children[i]->alloc.x != UNINITIALIZED_NODE_POS); */
-
- g_graph_node_get_position(node->children[i], &x_pos, NULL);
-
- printf(" == vapply == %p : %d + %d -> %d\n",
- node->children[i], x_pos, offset, (int)(x_pos + offset));
-
- x_pos += offset;
-
- g_graph_node_set_x_position(node->children[i], x_pos);
-
- }
-
- g_virtual_node_compute_width(node);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : node = noeud d'encapsulation à traiter. *
-* *
-* Description : Définit les abscisses relatives du contenu d'un noeud. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_virtual_node_apply_x_line(GVirtualNode *node)
-{
- size_t i; /* Boucle de parcours #1 */
- virtual_level *level; /* Accès rapide */
- size_t j; /* Boucle de parcours #2 */
- gint width_sum; /* Largeur d'un étage traité */
- gint x_pos; /* Abscisse à attribuer */
- GGraphNode *ref_a; /* Accès rapide #1 */
- GGraphNode *ref_b; /* Accès rapide #2 */
-
- for (i = 0; i < node->lcount; i++)
- {
- level = &node->levels[i];
-
- /* Si l'ensemble de l'étage doit être centré */
- if (level->children[0]->pending_flag == PPF_NONE)
- {
- width_sum = 0;
-
- for (j = 0; j < level->count; j++)
- {
- assert(level->children[j]->pending_flag == PPF_NONE);
-
- g_graph_node_apply_position(level->children[j]);
- width_sum += level->children[j]->alloc.width;
-
- }
-
- width_sum += NODE_HORIZONTAL_MARGIN * (level->count - 1);
-
- x_pos = - width_sum / 2;
-
- for (j = 0; j < level->count; j++)
- {
- g_graph_node_set_x_position(level->children[j], x_pos);
- x_pos += level->children[j]->alloc.width + NODE_HORIZONTAL_MARGIN;
- }
-
- }
-
- else if (level->children[0]->pending_flag == PPF_MIDDLE_OF)
- continue;
-
- /* On traite les noeuds individuellement */
- else
- {
- void _apply_rel_position(GGraphNode *child)
- {
- switch (node->children[0]->pending_flag)
- {
- case PPF_LEFT_NODE:
- if (!g_graph_node_has_x_position(child->pending_pos.left_node))
- _apply_rel_position(child->pending_pos.left_node);
- break;
-
- case PPF_RIGHT_NODE:
- if (!g_graph_node_has_x_position(child->pending_pos.right_node))
- _apply_rel_position(child->pending_pos.right_node);
- break;
-
- default:
- break;
-
- }
-
- g_graph_node_apply_position(child);
-
- }
-
- for (j = 0; j < level->count; j++)
- if (!g_graph_node_has_x_position(level->children[j]))
- _apply_rel_position(level->children[j]);
-
- }
-
- }
-
- for (i = 0; i < node->lcount; i++)
- {
- level = &node->levels[i];
-
- /* Si l'ensemble de l'étage doit être centré */
- if (level->children[0]->pending_flag == PPF_MIDDLE_OF)
- {
- ref_a = level->children[0]->pending_pos.left_node;
- ref_b = level->children[0]->pending_pos.right_node;
-
- assert(g_graph_node_has_x_position(ref_a));
- assert(g_graph_node_has_x_position(ref_b));
-
- if (ref_a->alloc.x < ref_b->alloc.x)
- {
- ref_b = level->children[0]->pending_pos.left_node;
- ref_a = level->children[0]->pending_pos.right_node;
- }
-
- x_pos = ref_a->alloc.x;
- x_pos += (ref_b->alloc.x + ref_b->alloc.width - ref_a->alloc.x) / 2;
- x_pos -= level->children[0]->alloc.width / 2;
-
- g_graph_node_set_x_position(level->children[0], x_pos);
-
- }
-
- }
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : node = noeud graphique à mettre à jour. *
-* *
-* Description : Met à jour la largeur interne du noeud. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_virtual_node_compute_width(GVirtualNode *node)
-{
- GGraphNode *base; /* Accès rapides */
- size_t i; /* Boucle de parcours */
- GGraphNode *child; /* Raccourci confortable */
-
- base = G_GRAPH_NODE(node);
-
- /* Largeur maximale des niveaux */
-
- base->alloc.width = 0;
-
- for (i = 0; i < node->lcount; i++)
- {
- child = node->levels[i].children[node->levels[i].count - 1];
-
- base->alloc.width = MAX(base->alloc.width, child->alloc.x + child->alloc.width);
-
- }
-
- /* Bordures gauche et droite */
-
- if (node->left_count > 0)
- {
- base->alloc.width += EDGE_SLOT_HORIZ_MARGIN;
- base->alloc.width += (node->left_count - 1) * EDGE_HORIZONTAL_MIN_SEP;
- }
-
- if (node->right_count > 0)
- {
- base->alloc.width += EDGE_SLOT_HORIZ_MARGIN;
- base->alloc.width += (node->right_count - 1) * EDGE_HORIZONTAL_MIN_SEP;
- }
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : node = noeud graphique à manipuler. *
-* x = éventuelle abscisse à intégrer. *
-* *
-* Description : Altère la position du noeud d'encapsulation. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_virtual_node_set_position(GVirtualNode *node, gint x)
-{
- GGraphNode *base; /* Autre version de l'instance */
- gint offset; /* Décallage à faire suivre */
- size_t i; /* Boucle de parcours */
- gint x_pos; /* Nouvelle position #1 */
-
- base = G_GRAPH_NODE(node);
-
- if (base->alloc.x == UNINITIALIZED_NODE_POS)
- offset = x;
- else
- offset = x - base->alloc.x;
-
- for (i = 0; i < node->count; i++)
- {
- /* BUG_ON(node->children[i]->alloc.x != UNINITIALIZED_NODE_POS); */
-
- g_graph_node_get_position(node->children[i], &x_pos, NULL);
- x_pos += offset;
-
- g_graph_node_set_x_position(node->children[i], x_pos);
-
- }
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : node = noeud graphique démarrant la visite. *
-* callback = ensemble de blocs à parcourir. *
-* data = donnée utilisateur à associer au parcours. *
-* *
-* Description : Parcourt tous les blocs d'instructions dans un ordre donné. *
-* *
-* Retour : true si le parcours a été jusqu'à son terme, false sinon. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static bool g_virtual_node_visit_flow_nodes(GVirtualNode *node, graph_node_visitor_cb callback, void *data)
-{
- bool result; /* Bilan à retourner */
- size_t i; /* Boucle de parcours */
-
- result = callback(G_GRAPH_NODE(node), GVS_ENTER, data);
-
- for (i = 0; i < node->count && result; i++)
- result = g_graph_node_visit_nodes(node->children[i], callback, data);
-
- if (result)
- result = callback(G_GRAPH_NODE(node), GVS_EXIT, data);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : nodes = noeud à consulter. *
-* target = élément à retrouver dans l'ensemble de noeuds. *
-* *
-* Description : Recherche le noeud contenant un autre noeud. *
-* *
-* Retour : Noeud trouvé ou NULL si aucun. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static GGraphNode *g_virtual_node_find_container(GVirtualNode *node, GGraphNode *target)
-{
- GGraphNode *result; /* Trouvaille à retourner */
- size_t i; /* Boucle de parcours */
-
- result = NULL;
-
- for (i = 0; i < node->count && result == NULL; i++)
- {
- if (node->children[i] == target)
- result = G_GRAPH_NODE(node);
- else
- result = g_graph_node_find_container(node->children[i], target);
- }
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : node = noeud d'encapsulation à compléter. *
-* child = sous-noeud à insérer. *
-* *
-* Description : Ajoute un noeud au groupe courant. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_virtual_node_add_child(GVirtualNode *node, GGraphNode *child)
-{
- unsigned int rank; /* Rang de l'enfant */
- virtual_level *level; /* Niveau d'intégration */
- size_t i; /* Boucle de parcours */
-
- /* Liste globale */
-
- node->children = (GGraphNode **)realloc(node->children,
- ++node->count * sizeof(GGraphNode *));
-
- node->children[node->count - 1] = child;
-
- g_object_ref(G_OBJECT(child));
-
- /* Intégration dans l'étage correspondant */
-
- rank = g_graph_node_get_rank(child);
-
- level = NULL;
-
- for (i = 0; i < node->lcount && level == NULL; i++)
- if (node->levels[i].rank == rank)
- level = &node->levels[i];
-
- if (level == NULL)
- {
- node->levels = (virtual_level *)realloc(node->levels,
- ++node->lcount * sizeof(virtual_level));
- level = &node->levels[node->lcount - 1];
-
- level->rank = rank;
- level->children = NULL;
- level->count = 0;
-
- }
-
- level->children = (GGraphNode **)realloc(level->children,
- ++level->count * sizeof(GGraphNode *));
-
- level->children[level->count - 1] = child;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : node = noeud d'encapsulation à consulter. *
-* *
-* Description : Compte le nombre de noeuds contenus dans le groupe courant. *
-* *
-* Retour : Quantité normalement non nulle. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-size_t g_virtual_node_count_children(const GVirtualNode *node)
-{
- return node->count;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : node = noeud d'encapsulation à consulter. *
-* index = indice du sous-bloc recherché. *
-* *
-* Description : Renvoie un des noeuds contenus dans le groupe courant. *
-* *
-* Retour : Un des blocs du groupe. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GGraphNode *g_virtual_node_get_child(const GVirtualNode *node, size_t index)
-{
- if (index >= node->count)
- return NULL;
-
- else
- return node->children[index];
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : node = groupe de noeuds à mettre à jour. *
-* r1 = début de la portée à réserver. *
-* r2 = fin de la portée à réserver. *
-* left = désignation de la zone à traiter. *
-* *
-* Description : Réserve une portion de largeur pour un lien. *
-* *
-* Retour : Indice de la largeur adaptée et réservée. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-vspan_slot_t g_virtual_node_reserve_span(GVirtualNode *node, unsigned int r1, unsigned int r2, bool left)
-{
- vspan_slot_t result; /* Identifiant à retourner */
- reserved_vspan vspan; /* Portée à constituer */
- vert_links **list; /* Liste à parcourir */
- vspan_slot_t *count; /* Taille de cette liste */
-
- vspan.r1 = r1;
- vspan.r2 = r2;
-
- if (left)
- {
- list = &node->left_padding;
- count = &node->left_count;
- }
- else
- {
- list = &node->right_padding;
- count = &node->right_count;
- }
-
- for (result = 0; result < *count; result++)
- if (!is_intersection_with_vertical_spans(&(*list)[result], &vspan))
- break;
-
- if (result == *count)
- {
- *list = (vert_links *)realloc(*list, ++(*count) * sizeof(vert_links));
- init_vertical_links(&(*list)[result]);
- }
-
- extend_vertical_links_spans(&(*list)[result], &vspan);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : node = conteneur de noeuds à consulter. *
-* slot = numérod de la réservation. *
-* left = désignation de la zone à traiter. *
-* *
-* Description : Fournit la position horizontale obtenue par réservation. *
-* *
-* Retour : Abscisse à utiliser. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-gint g_virtual_node_get_x_for_vspan_slot(const GVirtualNode *node, vspan_slot_t slot, bool left)
-{
- gint result; /* Position à retourner */
- GtkAllocation alloc; /* Taille totale requise */
-
- alloc = G_GRAPH_NODE(node)->alloc;
-
- if (left)
- {
- /*BUG_ON(slot >= node->left_count) */
-
- result = -(node->left_count - 1) * EDGE_HORIZONTAL_MIN_SEP/* + EDGE_SLOT_HORIZ_MARGIN*/;
- result += (slot * EDGE_HORIZONTAL_MIN_SEP/* + EDGE_SLOT_HORIZ_MARGIN*/);
-
- result += alloc.x;
-
- }
- else
- {
- /*BUG_ON(slot >= node->right_count) */
-
- result = /*EDGE_SLOT_HORIZ_MARGIN + */slot * EDGE_HORIZONTAL_MIN_SEP;
-
- result += alloc.x + alloc.width/* - EDGE_SLOT_HORIZ_MARGIN*/;
- if (node->right_count > 0)
- result -= (node->right_count - 1) * EDGE_HORIZONTAL_MIN_SEP;
-
- /* On pense à la largeur du trait... */
- result -= 2;
-
- }
-
- return result;
-
-}
diff --git a/src/gtkext/graph/nodes/virtual.h b/src/gtkext/graph/nodes/virtual.h
deleted file mode 100644
index 7f32591..0000000
--- a/src/gtkext/graph/nodes/virtual.h
+++ /dev/null
@@ -1,77 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * virtual.h - prototypes pour l'encapsulation graphique des blocs virtuels
- *
- * Copyright (C) 2013 Cyrille Bagard
- *
- * This file is part of Chrysalide.
- *
- * OpenIDA is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * OpenIDA is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#ifndef _GTKEXT_GRAPH_NODES_VIRTUAL_H
-#define _GTKEXT_GRAPH_NODES_VIRTUAL_H
-
-
-#include "../node.h"
-#include "../../../analysis/blocks/virtual.h"
-
-
-/* Indice d'une hauteur au sein des rangs */
-typedef size_t vspan_slot_t;
-
-/* Indice non initilisé */
-#define UNINITIALIZED_VSPAN_SLOT (~((vspan_slot_t)0))
-
-
-#define G_TYPE_VIRTUAL_NODE (g_virtual_node_get_type())
-#define G_VIRTUAL_NODE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_VIRTUAL_NODE, GVirtualNode))
-#define G_VIRTUAL_NODE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_VIRTUAL_NODE, GVirtualNodeClass))
-#define G_IS_VIRTUAL_NODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_VIRTUAL_NODE))
-#define G_IS_VIRTUAL_NODE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_VIRTUAL_NODE))
-#define G_VIRTUAL_NODE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_VIRTUAL_NODE, GVirtualNodeClass))
-
-
-/* Encapsulation graphique d'un bloc virtuel (instance) */
-typedef struct _GVirtualNode GVirtualNode;
-
-/* Encapsulation graphique d'un bloc virtuel (classe) */
-typedef struct _GVirtualNodeClass GVirtualNodeClass;
-
-
-/* Indique le type définit par la GLib pour l'encapsulation d'un bloc virtuel. */
-GType g_virtual_node_get_type(void);
-
-/* Encapsule graphiquement un bloc virtuel. */
-GGraphNode *g_virtual_node_new(GVirtualBlock *);
-
-/* Ajoute un noeud au groupe courant. */
-void g_virtual_node_add_child(GVirtualNode *, GGraphNode *);
-
-/* Compte le nombre de noeuds contenus dans le groupe courant. */
-size_t g_virtual_node_count_children(const GVirtualNode *);
-
-/* Renvoie un des noeuds contenus dans le groupe courant. */
-GGraphNode *g_virtual_node_get_child(const GVirtualNode *, size_t);
-
-/* Réserve une portion de largeur pour un lien. */
-vspan_slot_t g_virtual_node_reserve_span(GVirtualNode *, unsigned int, unsigned int, bool);
-
-/* Fournit la position horizontale obtenue par réservation. */
-gint g_virtual_node_get_x_for_vspan_slot(const GVirtualNode *, vspan_slot_t, bool);
-
-
-
-#endif /* _GTKEXT_GRAPH_NODES_VIRTUAL_H */
diff --git a/src/gtkext/graph/params.h b/src/gtkext/graph/params.h
deleted file mode 100644
index 9d26426..0000000
--- a/src/gtkext/graph/params.h
+++ /dev/null
@@ -1,84 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * params.h - prototypes pour la modulation des paramètres de rendu
- *
- * Copyright (C) 2013 Cyrille Bagard
- *
- * This file is part of Chrysalide.
- *
- * OpenIDA is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * OpenIDA is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#ifndef _GTKEXT_GRAPH_PARAMS_H
-#define _GTKEXT_GRAPH_PARAMS_H
-
-
-
-
-/* Coordonnés d'un noeud non initialisées */
-#define UNINITIALIZED_NODE_POS G_MININT
-
-
-/**
- * Paramètres à l'échelle du graphique.
- */
-
-/* Bordures supérieure et inférieure des graphiques */
-#define GRAPH_VERTICAL_MARGIN 15
-
-/* Bordures gauche et droite des graphiques */
-#define GRAPH_HORIZONTAL_MARGIN 15
-
-
-/**
- * Paramètres à l'échelle du noeud.
- */
-
-
-
-
-
-#define NODE_LEFT_MARGIN 25
-#define NODE_TOP_MARGIN 55 /* TODO : supprimer */
-
-
-
-
-
-
-/* Séparations minimales entre deux liens */
-#define EDGE_HORIZONTAL_MIN_SEP 10
-#define EDGE_VERTICAL_MIN_SEP 10
-
-/* Séparations minimales entre un lien et un noeud */
-#define EDGE_SLOT_HORIZ_MARGIN 20
-#define EDGE_SLOT_VERT_MARGIN 20
-
-/* Séparations minimales entre un noeud et un autre */
-#define NODE_HORIZONTAL_MARGIN 20
-#define NODE_VERTICAL_MARGIN 35
-
-
-
-
-#define SLOT_VERT_SEP EDGE_SLOT_VERT_MARGIN /* TODO : remplacer */
-
-#define ARROW_LENGHT 10
-#define ARROW_DEGREES 10
-
-
-
-
-#endif /* _GTKEXT_GRAPH_PARAMS_H */
diff --git a/src/gtkext/graph/ranks.c b/src/gtkext/graph/ranks.c
deleted file mode 100644
index e1f6688..0000000
--- a/src/gtkext/graph/ranks.c
+++ /dev/null
@@ -1,695 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * ranks.c - calcul de l'ordonnée des différents classements
- *
- * Copyright (C) 2013 Cyrille Bagard
- *
- * This file is part of Chrysalide.
- *
- * OpenIDA is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * OpenIDA is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#include "ranks.h"
-
-
-#include <malloc.h>
-#include <sys/param.h>
-
-
-#include "params.h"
-
-
-
-/* ---------------------- MANIPULATION DES PORTES HORIZONTALES ---------------------- */
-
-
-/* Etendue horizontale d'un lien */
-typedef struct _reserved_hspan
-{
- gint x1; /* Départ d'une ligne */
- gint x2; /* Arrivée de cette même ligne */
-
-} reserved_hspan;
-
-/* Lignes de liens d'un même niveau */
-typedef struct _links_spans
-{
- reserved_hspan *hspans; /* Lignes sans chevauchement */
- size_t count; /* Nombre de ces lignes */
-
-} links_spans;
-
-
-/* Initialise les futures portées d'un même niveau. */
-static void init_links_spans(links_spans *);
-
-/* Regarde si des portées horizontales se chevauchent ou non. */
-static bool is_intersection_with_spans(const links_spans *, const reserved_hspan *);
-
-/* Ajoute une réservation à un ensemble de portées horizontales. */
-static void extend_links_spans(links_spans *, const reserved_hspan *);
-
-
-
-/* ------------------------ GESTION D'UN ETAGE DE CLASSEMENT ------------------------ */
-
-
-/* Information relatives à un rang de classement */
-typedef struct _rank_props
-{
- links_spans *top_spans; /* Niveaux de lignes supérieurs*/
- hspan_slot_t top_count; /* Nbre des niveaux de lignes */
- links_spans *bottom_spans; /* Niveaux de lignes inférieurs*/
- hspan_slot_t bottom_count; /* Nbre des niveaux de lignes */
-
- gint height; /* Hauteur minimale */
- gint y; /* Ordonnée finale */
-
-} rank_props;
-
-
-/* Réserve une portion de hauteur pour un lien. */
-static hspan_slot_t reserve_span_in_rank_props(rank_props *, gint, gint, bool);
-
-/* Calcule la position verticale du rang de classement. */
-static gint compute_rank_props_y_pos(rank_props *, gint *, gint);
-
-/* Fournit la position verticale obtenue par réservation. */
-static gint get_y_for_rank_props_hspan_slot(const rank_props *, hspan_slot_t, bool);
-
-
-
-/* ------------------------- CLASSEMENT VERTICAL DES NOEUDS ------------------------- */
-
-
-/* Calcul de l'ordonnée des différents classements (instance) */
-struct _GGraphRanks
-{
- GObject parent; /* A laisser en premier */
-
- rank_props *props; /* Propriétés des rangs */
- unsigned int count; /* Nombre de rangs présents */
-
- gint height; /* Hauteur totale du graphique */
-
-};
-
-/* Calcul de l'ordonnée des différents classements (classe) */
-struct _GGraphRanksClass
-{
- GObjectClass parent; /* A laisser en premier */
-
-};
-
-
-/* Initialise la classe de calcul de l'ordonnée des classements. */
-static void g_graph_ranks_class_init(GGraphRanksClass *);
-
-/* Initialise un calcul de l'ordonnée des classements. */
-static void g_graph_ranks_init(GGraphRanks *);
-
-/* Supprime toutes les références externes. */
-static void g_graph_ranks_dispose(GGraphRanks *);
-
-/* Procède à la libération totale de la mémoire. */
-static void g_graph_ranks_finalize(GGraphRanks *);
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* MANIPULATION DES PORTES HORIZONTALES */
-/* ---------------------------------------------------------------------------------- */
-
-
-/******************************************************************************
-* *
-* Paramètres : spans = liste à initialiser. *
-* *
-* Description : Initialise les futures portées d'un même niveau. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void init_links_spans(links_spans *spans)
-{
- spans->hspans = NULL;
- spans->count = 0;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : spans = liste de portées déjà en place. *
-* hspan = nouvelle portée à insérer quelque part. *
-* *
-* Description : Regarde si des portées horizontales se chevauchent ou non. *
-* *
-* Retour : true si les portées peuvent cohabiter, false sinon. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static bool is_intersection_with_spans(const links_spans *spans, const reserved_hspan *hspan)
-{
- bool result; /* Bilan d'analyse à retourner */
- size_t i; /* Boucle de parcours */
-
- result = false;
-
- for (i = 0; i < spans->count && !result; i++)
- {
- if (hspan->x1 < spans->hspans[i].x1)
- result = hspan->x2 >= spans->hspans[i].x1;
-
- else if (hspan->x1 > spans->hspans[i].x2)
- result = hspan->x2 <= spans->hspans[i].x2;
-
- else
- {
- result = spans->hspans[i].x1 < hspan->x1 && hspan->x1 < spans->hspans[i].x2;
- result |= spans->hspans[i].x1 < hspan->x2 && hspan->x2 < spans->hspans[i].x2;
- }
-
- }
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : spans = liste de portées déjà en place. *
-* hspan = nouvelle portée à insérer quelque part. *
-* *
-* Description : Ajoute une réservation à un ensemble de portées horizontales.*
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void extend_links_spans(links_spans *spans, const reserved_hspan *new)
-{
- spans->hspans = (reserved_hspan *)realloc(spans->hspans,
- ++spans->count * sizeof(reserved_hspan));
-
- if (new->x1 <= new->x2)
- spans->hspans[spans->count - 1] = *new;
- else
- {
- spans->hspans[spans->count - 1].x1 = new->x2;
- spans->hspans[spans->count - 1].x2 = new->x1;
- }
-
-}
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* GESTION D'UN ETAGE DE CLASSEMENT */
-/* ---------------------------------------------------------------------------------- */
-
-
-/******************************************************************************
-* *
-* Paramètres : props = propriétés de rang à mettre à jour. *
-* *
-* Description : Supprime les portions de hauteur pour un lien. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void reset_spans_in_rank_props(rank_props *props)
-{
- hspan_slot_t i; /* Boucle de parcours */
-
- for (i = 0; i < props->top_count; i++)
- if (props->top_spans[i].hspans != NULL)
- free(props->top_spans[i].hspans);
-
- if (props->top_spans != NULL)
- {
- free(props->top_spans);
- props->top_spans = NULL;
- props->top_count = 0;
- }
-
- for (i = 0; i < props->bottom_count; i++)
- if (props->bottom_spans[i].hspans != NULL)
- free(props->bottom_spans[i].hspans);
-
- if (props->bottom_spans != NULL)
- {
- free(props->bottom_spans);
- props->bottom_spans = NULL;
- props->bottom_count = 0;
- }
-
- props->y = 0;
- props->height = 0;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : props = propriétés de rang à mettre à jour. *
-* x1 = début de la portée à réserver. *
-* x2 = fin de la portée à réserver. *
-* top = désignation de la zone à traiter. *
-* *
-* Description : Réserve une portion de hauteur pour un lien. *
-* *
-* Retour : Indice de la hauteur adaptée et réservée. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static hspan_slot_t reserve_span_in_rank_props(rank_props *props, gint x1, gint x2, bool top)
-{
- hspan_slot_t result; /* Indice à retourner */
- reserved_hspan hspan; /* Portée à constituer */
- links_spans **list; /* Liste à parcourir */
- hspan_slot_t *count; /* Taille de cette liste */
-
- hspan.x1 = x1;
- hspan.x2 = x2;
-
- if (top)
- {
- list = &props->top_spans;
- count = &props->top_count;
- }
- else
- {
- list = &props->bottom_spans;
- count = &props->bottom_count;
- }
-
- for (result = 0; result < *count; result++)
- if (!is_intersection_with_spans(&(*list)[result], &hspan))
- break;
-
- if (result == *count)
- {
- *list = (links_spans *)realloc(*list, ++(*count) * sizeof(links_spans));
- init_links_spans(&(*list)[result]);
- }
-
- extend_links_spans(&(*list)[result], &hspan);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : props = propriétés de rang à mettre à jour. *
-* y = ordonnée courante à faire évoluer. *
-* last_bottom = espace inférieur requis du niveau précédent. *
-* *
-* Description : Calcule la position verticale du rang de classement. *
-* *
-* Retour : Espace inférieur nécessaire au niveau de classement. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static gint compute_rank_props_y_pos(rank_props *props, gint *y, gint last_bottom)
-{
- gint result; /* Espace Sud à retourner */
- gint top_margin; /* Espace Nord nécessaire */
-
- /* Espace supérieur pour les liens */
-
- top_margin = last_bottom;
-
- if (props->top_count > 0)
- {
- top_margin += props->top_count * EDGE_VERTICAL_MIN_SEP;
- top_margin += EDGE_SLOT_VERT_MARGIN;
- }
-
- /**
- * L'espace vertical entre les noeuds n'a lieu d'être qu'en présence de noeuds !
- */
- top_margin = MAX(top_margin, (*y > 0 && props->height > 0 ? NODE_VERTICAL_MARGIN : 0));
-
- /* Position des noeuds */
-
- props->y = *y + top_margin;
- *y = props->y + props->height;
-
- /* Espace inférieur pour les liens */
-
- /**
- * Fournit une marge minimum : si des liens autres que boucles partent de ce rang,
- * il ne sont pas enregistrés à ce niveau, mais ont besoin d'espace quand même.
- * On prend néanmoins garde aux rangs terminaux, potentiellement vides.
- */
- result = (props->height > 0 ? EDGE_SLOT_VERT_MARGIN : 0);
-
- if (props->bottom_count > 0)
- result += props->bottom_count * EDGE_VERTICAL_MIN_SEP;
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : props = propriétés de rang à consulter. *
-* slot = numérod de la réservation. *
-* top = désignation de la zone à traiter. *
-* *
-* Description : Fournit la position verticale obtenue par réservation. *
-* *
-* Retour : Ordonnée à utiliser. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static gint get_y_for_rank_props_hspan_slot(const rank_props *props, hspan_slot_t slot, bool top)
-{
- gint result; /* Ordonnée à retourner */
-
- result = EDGE_SLOT_VERT_MARGIN + slot * EDGE_VERTICAL_MIN_SEP;
-
- if (top)
- result = props->y - result;
- else
- result += props->y + props->height;
-
- return result;
-
-}
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* CLASSEMENT VERTICAL DES NOEUDS */
-/* ---------------------------------------------------------------------------------- */
-
-
-/* Indique le type définit par la GLib pour le calcul de l'ordonnée des classements. */
-G_DEFINE_TYPE(GGraphRanks, g_graph_ranks, G_TYPE_OBJECT);
-
-
-/******************************************************************************
-* *
-* Paramètres : klass = classe à initialiser. *
-* *
-* Description : Initialise la classe de calcul de l'ordonnée des classements.*
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_graph_ranks_class_init(GGraphRanksClass *klass)
-{
- GObjectClass *object; /* Autre version de la classe */
-
- object = G_OBJECT_CLASS(klass);
-
- object->dispose = (GObjectFinalizeFunc/* ! */)g_graph_ranks_dispose;
- object->finalize = (GObjectFinalizeFunc)g_graph_ranks_finalize;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : ranks = instance à initialiser. *
-* *
-* Description : Initialise un calcul de l'ordonnée des classements. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_graph_ranks_init(GGraphRanks *ranks)
-{
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : node = instance d'objet GLib à traiter. *
-* *
-* Description : Supprime toutes les références externes. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_graph_ranks_dispose(GGraphRanks *ranks)
-{
- G_OBJECT_CLASS(g_graph_ranks_parent_class)->dispose(G_OBJECT(ranks));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : ranks = instance d'objet GLib à traiter. *
-* *
-* Description : Procède à la libération totale de la mémoire. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_graph_ranks_finalize(GGraphRanks *ranks)
-{
- if (ranks->props != NULL)
- free(ranks->props);
-
- G_OBJECT_CLASS(g_graph_ranks_parent_class)->finalize(G_OBJECT(ranks));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : count = nombre de rangs dans le classement au total. *
-* *
-* Description : Prépare de quoi se définir au mieux les ordonnées des noeuds.*
-* *
-* Retour : Adresse de la structure mise en place. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GGraphRanks *g_graph_ranks_new(unsigned int count)
-{
- GGraphRanks *result; /* Structure à retourner */
-
- result = g_object_new(G_TYPE_GRAPH_RANKS, NULL);
-
- result->count = count;
- result->props = (rank_props *)calloc(count, sizeof(rank_props));
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : ranks = ensemble des rangs de classement à manipuler. *
-* index = indice du rang visé. *
-* height = hauteur minimale requise pour le rang donné. *
-* *
-* Description : Note une hauteur minimale requise pour un rang du classement.*
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_graph_ranks_set_min_height(GGraphRanks *ranks, unsigned int index, gint height)
-{
- /*BUG_ON(index >= ranks->count) */
-
- ranks->props[index].height = MAX(ranks->props[index].height, height);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : ranks = ensemble des rangs de classement à consulter. *
-* *
-* Description : Fournit la hauteur requise pour l'affichage des rangs. *
-* *
-* Retour : Hauteur nécessaire en pixel. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-gint g_graph_ranks_get_height(const GGraphRanks *ranks)
-{
- return ranks->height;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : ranks = ensemble des rangs à mettre à jour. *
-* *
-* Description : Supprime toutes les réservations faites pour les liens. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_graph_ranks_reset_reservations(GGraphRanks *ranks)
-{
- unsigned int i; /* Boucle de parcours */
-
- for (i = 0; i < ranks->count; i++)
- reset_spans_in_rank_props(&ranks->props[i]);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : ranks = ensemble des rangs à mettre à jour. *
-* index = indice du rang visé. *
-* x1 = début de la portée à réserver. *
-* x2 = fin de la portée à réserver. *
-* top = désignation de la zone à traiter. *
-* *
-* Description : Réserve une portion de hauteur pour un lien. *
-* *
-* Retour : Indice de la hauteur adaptée et réservée. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-hspan_slot_t g_graph_ranks_reserve_span(GGraphRanks *ranks, unsigned int index, gint x1, gint x2, bool top)
-{
- /*BUG_ON(index >= ranks->count) */
-
- return reserve_span_in_rank_props(&ranks->props[index], x1, x2, top);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : ranks = ensemble des rangs de classement à manipuler. *
-* *
-* Description : Calcule l'ordonnée finale de chaque rang du classement. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_graph_ranks_compute_y_line(GGraphRanks *ranks)
-{
- gint last_bottom; /* Espace minimal à transmettre*/
- gint y; /* Ordonnée courante à proposer*/
- size_t i; /* Boucle de parcours */
-
- last_bottom = GRAPH_VERTICAL_MARGIN;
- y = 0;
-
- for (i = 0; i < ranks->count; i++)
- last_bottom = compute_rank_props_y_pos(&ranks->props[i], &y, last_bottom);
-
- ranks->height = y + last_bottom + GRAPH_VERTICAL_MARGIN;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : ranks = ensemble des rangs de classement à consulter. *
-* index = indice du rang visé. *
-* *
-* Description : Fournit la position verticale correspondant à un rang donné. *
-* *
-* Retour : Ordonnée à utiliser. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-gint g_graph_ranks_get_y_for_rank(const GGraphRanks *ranks, unsigned int index)
-{
- /*BUG_ON(index >= ranks->count) */
-
- return ranks->props[index].y;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : ranks = ensemble des rangs de classement à consulter. *
-* index = indice du rang visé. *
-* slot = numérod de la réservation. *
-* top = désignation de la zone à traiter. *
-* *
-* Description : Fournit la position verticale obtenue par réservation. *
-* *
-* Retour : Ordonnée à utiliser. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-gint g_graph_ranks_get_y_for_hspan_slot(const GGraphRanks *ranks, unsigned int index, hspan_slot_t slot, bool top)
-{
- /*BUG_ON(index >= ranks->count) */
-
- return get_y_for_rank_props_hspan_slot(&ranks->props[index], slot, top);
-
-}
diff --git a/src/gtkext/graph/ranks.h b/src/gtkext/graph/ranks.h
deleted file mode 100644
index da7e54f..0000000
--- a/src/gtkext/graph/ranks.h
+++ /dev/null
@@ -1,82 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * ranks.h - prototypes pour le calcul de l'ordonnée des différents classements
- *
- * Copyright (C) 2013 Cyrille Bagard
- *
- * This file is part of Chrysalide.
- *
- * OpenIDA is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * OpenIDA is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#ifndef _GTKEXT_GRAPH_RANKS_H
-#define _GTKEXT_GRAPH_RANKS_H
-
-
-#include <glib-object.h>
-#include <stdbool.h>
-
-
-/* Indice d'une hauteur au sein des rangs */
-typedef size_t hspan_slot_t;
-
-/* Indice non initilisé */
-#define UNINITIALIZED_HSPAN_SLOT (~((hspan_slot_t)0))
-
-
-#define G_TYPE_GRAPH_RANKS g_graph_ranks_get_type()
-#define G_GRAPH_RANKS(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_graph_ranks_get_type(), GGraphRanks))
-#define G_IS_GRAPH_RANKS(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_graph_ranks_get_type()))
-#define G_GRAPH_RANKS_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), g_graph_ranks_get_type(), GGraphRanksIface))
-#define G_GRAPH_RANKS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_GRAPH_RANKS, GGraphRanksClass))
-
-
-/* Calcul de l'ordonnée des différents classements (instance) */
-typedef struct _GGraphRanks GGraphRanks;
-
-/* Calcul de l'ordonnée des différents classements (classe) */
-typedef struct _GGraphRanksClass GGraphRanksClass;
-
-
-/* Indique le type définit par la GLib pour le calcul de l'ordonnée des classements. */
-GType g_graph_ranks_get_type(void);
-
-/* Prépare de quoi se définir au mieux les ordonnées des noeuds. */
-GGraphRanks *g_graph_ranks_new(unsigned int);
-
-/* Note une hauteur minimale requise pour un rang du classement. */
-void g_graph_ranks_set_min_height(GGraphRanks *, unsigned int, gint);
-
-/* Fournit la hauteur requise pour l'affichage des rangs. */
-gint g_graph_ranks_get_height(const GGraphRanks *);
-
-/* Supprime toutes les réservations faites pour les liens. */
-void g_graph_ranks_reset_reservations(GGraphRanks *);
-
-/* Réserve une portion de hauteur pour un lien. */
-hspan_slot_t g_graph_ranks_reserve_span(GGraphRanks *, unsigned int, gint, gint, bool);
-
-/* Calcule l'ordonnée finale de chaque rang du classement. */
-void g_graph_ranks_compute_y_line(GGraphRanks *);
-
-/* Fournit la position verticale correspondant à un rang donné. */
-gint g_graph_ranks_get_y_for_rank(const GGraphRanks *, unsigned int);
-
-/* Fournit la position verticale obtenue par réservation. */
-gint g_graph_ranks_get_y_for_hspan_slot(const GGraphRanks *, unsigned int, hspan_slot_t, bool);
-
-
-
-#endif /* _GTKEXT_GRAPH_RANKS_H */
diff --git a/src/gtkext/gtkgraphview.c b/src/gtkext/gtkgraphview.c
index 368792b..6255602 100644
--- a/src/gtkext/gtkgraphview.c
+++ b/src/gtkext/gtkgraphview.c
@@ -30,7 +30,7 @@
#include "gtkblockview.h"
#include "gtkbufferview.h"
#include "gtkviewpanel-int.h"
-#include "graph/layout.h"
+#include "graph/cluster.h"
#include "../analysis/blocks/flow.h"
#include "../gui/editem.h"
@@ -49,7 +49,11 @@ struct _GtkGraphView
GtkAllocation *allocs; /* Emplacements prévisibles */
size_t children_count; /* Taille de cette liste */
- GGraphLayout *layout; /* Disposition en graphique */
+ //GGraphLayout *layout; /* Disposition en graphique */
+ GGraphCluster *cluster; /* Disposition en graphique */
+
+ GGraphEdge **edges; /* Liens entre les noeuds */
+ size_t edges_count; /* Quantité de ces liens */
gdouble start_x; /* Abscisse du point de souris */
gdouble start_y; /* Ordonnée du point de souris */
@@ -74,6 +78,12 @@ static void gtk_graph_view_class_init(GtkGraphViewClass *);
/* Initialise une instance d'afficheur de code en graphique. */
static void gtk_graph_view_init(GtkGraphView *);
+/* Supprime toutes les références externes. */
+static void gtk_graph_view_dispose(GtkGraphView *);
+
+/* Procède à la libération totale de la mémoire. */
+static void gtk_graph_view_finalize(GtkGraphView *);
+
/* Indique les dimensions de travail du composant d'affichage. */
static void gtk_graph_view_compute_requested_size(GtkGraphView *, gint *, gint *);
@@ -210,9 +220,66 @@ static void gtk_graph_view_init(GtkGraphView *view)
//view->mutex = g_mutex_new();
//view->cond = g_cond_new();
+
+
+ view->cluster = NULL;
+
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : view = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_graph_view_dispose(GtkGraphView *view)
+{
+ if (view->cluster != NULL)
+ {
+ g_object_unref(G_OBJECT(view->cluster));
+ view->cluster = NULL;
+ }
+
+ G_OBJECT_CLASS(gtk_graph_view_parent_class)->dispose(G_OBJECT(view));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : view = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_graph_view_finalize(GtkGraphView *view)
+{
+ G_OBJECT_CLASS(gtk_graph_view_parent_class)->finalize(G_OBJECT(view));
+
}
+
+
+
+
+
+
+
+
/******************************************************************************
* *
* Paramètres : view = composant GTK à consulter. *
@@ -229,30 +296,27 @@ static void gtk_graph_view_init(GtkGraphView *view)
static void gtk_graph_view_compute_requested_size(GtkGraphView *view, gint *width, gint *height)
{
- GtkRequisition requisition; /* Taille requise */
+ GtkAllocation needed; /* Taille requise */
+ gint rwidth; /* Largeur demandée */
+ gint rheight; /* Hauteur demandée */
- if (width != NULL)
+ if (view->cluster != NULL)
{
- if (view->layout != NULL)
- {
- g_graph_layout_size_request(view->layout, &requisition);
- *width = requisition.width;
- }
- else
- *width = 0;
- }
+ g_graph_cluster_compute_needed_alloc(view->cluster, &needed);
+ assert(needed.x == 0 && needed.y == 0);
- if (height != NULL)
+ /* TODO : marges ou centrage */
+
+ }
+ else
{
- if (view->layout != NULL)
- {
- g_graph_layout_size_request(view->layout, &requisition);
- *height = requisition.height;
- }
- else
- *height = 0;
+ needed.width = 0;
+ needed.height = 0;
}
+ if (width != NULL) *width = needed.width;
+ if (height != NULL) *height = needed.height;
+
}
@@ -300,8 +364,16 @@ static void gtk_graph_view_adjust_scroll_value(GtkGraphView *view, GtkAdjustment
static gboolean gtk_graph_view_draw(GtkWidget *widget, cairo_t *cr, GtkGraphView *view)
{
+ size_t i; /* Boucle de parcours */
+
+ for (i = 0; i < view->edges_count; i++)
+ g_graph_edge_draw(view->edges[i], cr, true);
+
+
+ /*
if (view->layout != NULL)
g_graph_layout_draw(view->layout, cr, true);
+ */
return FALSE;
@@ -458,8 +530,10 @@ static void gtk_graph_view_prepare_resize(GtkGraphView *view)
for (i = 0; i < view->children_count; i++)
gtk_widget_queue_resize(GTK_WIDGET(view->children[i]));
+ /*
g_graph_layout_refresh(view->layout);
g_graph_layout_place(view->layout, view);
+ */
change_editor_items_current_view_content(GTK_VIEW_PANEL(view));
@@ -518,6 +592,7 @@ static void gtk_graph_view_define_main_address(GtkGraphView *view, const vmpa2t
view->highlighted = init_segment_content_list();
+ /*
view->children = gtk_graph_view_load_nodes(view, GTK_VIEW_PANEL(view)->binary,
routines[i]);
@@ -528,6 +603,33 @@ static void gtk_graph_view_define_main_address(GtkGraphView *view, const vmpa2t
view->children, view->children_count);
g_graph_layout_place(view->layout, view);
+ */
+
+ do
+ {
+
+ GBlockList *list;
+
+ list = g_binary_routine_get_basic_blocks(routines[i]);
+
+#if 0
+ view->cluster = g_graph_cluster_new(GTK_VIEW_PANEL(view)->binary,
+ list, 0/* FIXME */, view->highlighted);
+#endif
+
+
+ view->cluster = bootstrap_graph_cluster(GTK_VIEW_PANEL(view)->binary,
+ list, view->highlighted);
+
+
+
+ g_graph_cluster_place(view->cluster, view);
+
+
+ }
+ while (0);
+
+
break;
@@ -668,8 +770,10 @@ static void gtk_graph_view_cache_glance(GtkGraphView *view, cairo_t *cairo, cons
cairo_scale(cairo, scale, scale);
+ /*
if (view->layout != NULL)
g_graph_layout_draw(view->layout, cairo, false);
+ */
}
@@ -714,6 +818,7 @@ void gtk_graph_view_put(GtkGraphView *view, GtkWidget *widget, const GtkAllocati
size_t i; /* Boucle de parcours */
GtkWidget *parent; /* Parent en cas de réajustemt.*/
+ /*
for (i = 0; i < view->children_count; i++)
if (GTK_WIDGET(view->children[i]) == widget)
{
@@ -728,11 +833,38 @@ void gtk_graph_view_put(GtkGraphView *view, GtkWidget *widget, const GtkAllocati
g_object_ref(G_OBJECT(widget));
gtk_container_remove(GTK_CONTAINER(parent), widget);
}
+ */
gtk_fixed_put(GTK_FIXED(view->support), widget, alloc->x, alloc->y);
+ /*
if (parent != NULL)
g_object_unref(G_OBJECT(widget));
+ */
+
+}
+
+
+
+/******************************************************************************
+* *
+* Paramètres : view = composant GTK à mettre à jour. *
+* edge = lien entre noeuds à conserver. *
+* *
+* Description : Intègre un lien entre blocs graphiques dans l'afficheur. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void gtk_graph_view_add_edge(GtkGraphView *view, GGraphEdge *edge)
+{
+ view->edges = (GGraphEdge **)realloc(view->edges,
+ ++view->edges_count * sizeof(GGraphEdge *));
+
+ view->edges[view->edges_count - 1] = edge;
}
@@ -753,6 +885,40 @@ static void gtk_graph_view_reset(GtkGraphView *view)
{
size_t i; /* Boucle de parcours */
+
+ void detach_all_blocks(GtkWidget *widget, GtkContainer *container)
+ {
+
+
+
+ gtk_container_remove(container, widget);
+
+
+ }
+
+
+ gtk_container_foreach(GTK_CONTAINER(view->support), (GtkCallback)detach_all_blocks, view->support);
+
+
+ if (view->cluster != NULL)
+ {
+ g_object_unref(G_OBJECT(view->cluster));
+ view->cluster = NULL;
+ }
+
+ for (i = 0; i < view->edges_count; i++)
+ g_object_unref(G_OBJECT(view->edges[i]));
+
+ if (view->edges_count > 0)
+ {
+ free(view->edges);
+ view->edges = NULL;
+
+ view->edges_count = 0;
+
+ }
+
+
/*
for (i = 0; i < view->links_count; i++)
gtk_object_destroy(GTK_OBJECT(view->links[i]));
diff --git a/src/gtkext/gtkgraphview.h b/src/gtkext/gtkgraphview.h
index 7f841be..5e0f994 100644
--- a/src/gtkext/gtkgraphview.h
+++ b/src/gtkext/gtkgraphview.h
@@ -28,6 +28,9 @@
#include <gtk/gtk.h>
+#include "graph/edge.h"
+
+
#define GTK_TYPE_GRAPH_VIEW (gtk_graph_view_get_type())
#define GTK_GRAPH_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_GRAPH_VIEW, GtkGraphView))
@@ -53,6 +56,9 @@ GtkWidget *gtk_graph_view_new(void);
/* Place une vue sous forme de bloc dans le graphique. */
void gtk_graph_view_put(GtkGraphView *, GtkWidget *, const GtkAllocation *);
+/* Intègre un lien entre blocs graphiques dans l'afficheur. */
+void gtk_graph_view_add_edge(GtkGraphView *, GGraphEdge *);
+
#endif /* _GTKEXT_GTKGRAPHVIEW_H */