From 25811bc506ecca92d6b36fe739734121a872af4d Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Tue, 5 Mar 2019 22:15:36 +0100
Subject: Split the graph code into several files.

---
 src/gtkext/graph/Makefile.am   |    8 +-
 src/gtkext/graph/cluster-int.h |  102 +++
 src/gtkext/graph/cluster.c     | 1892 +---------------------------------------
 src/gtkext/graph/hspace.c      |  125 +++
 src/gtkext/graph/hspace.h      |   52 ++
 src/gtkext/graph/incoming.c    |  184 ++++
 src/gtkext/graph/incoming.h    |   67 ++
 src/gtkext/graph/leaving.c     |  107 +++
 src/gtkext/graph/leaving.h     |   66 ++
 src/gtkext/graph/rank.c        |  914 +++++++++++++++++++
 src/gtkext/graph/rank.h        |  126 +++
 src/gtkext/graph/vspace.c      |  374 ++++++++
 src/gtkext/graph/vspace.h      |   86 ++
 13 files changed, 2242 insertions(+), 1861 deletions(-)
 create mode 100644 src/gtkext/graph/cluster-int.h
 create mode 100644 src/gtkext/graph/hspace.c
 create mode 100644 src/gtkext/graph/hspace.h
 create mode 100644 src/gtkext/graph/incoming.c
 create mode 100644 src/gtkext/graph/incoming.h
 create mode 100644 src/gtkext/graph/leaving.c
 create mode 100644 src/gtkext/graph/leaving.h
 create mode 100644 src/gtkext/graph/rank.c
 create mode 100644 src/gtkext/graph/rank.h
 create mode 100644 src/gtkext/graph/vspace.c
 create mode 100644 src/gtkext/graph/vspace.h

diff --git a/src/gtkext/graph/Makefile.am b/src/gtkext/graph/Makefile.am
index 310c13c..ee5eb19 100644
--- a/src/gtkext/graph/Makefile.am
+++ b/src/gtkext/graph/Makefile.am
@@ -2,8 +2,14 @@
 noinst_LTLIBRARIES  = libgtkextgraph.la
 
 libgtkextgraph_la_SOURCES =				\
+	cluster-int.h						\
 	cluster.h cluster.c					\
-	edge.h edge.c
+	edge.h edge.c						\
+	hspace.h hspace.c					\
+	incoming.h incoming.c				\
+	leaving.h leaving.c					\
+	rank.h rank.c						\
+	vspace.h vspace.c
 
 libgtkextgraph_la_LIBADD =
 
diff --git a/src/gtkext/graph/cluster-int.h b/src/gtkext/graph/cluster-int.h
new file mode 100644
index 0000000..881a60a
--- /dev/null
+++ b/src/gtkext/graph/cluster-int.h
@@ -0,0 +1,102 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * cluster-int.h - prototypes pour les définitions internes de mise en place de graphiques
+ *
+ * Copyright (C) 2019 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide 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.
+ *
+ *  Chrysalide 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 Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GTKEXT_GRAPH_CLUSTER_INT_H
+#define _GTKEXT_GRAPH_CLUSTER_INT_H
+
+
+#include "cluster.h"
+#include "leaving.h"
+
+
+
+/* Espace minimal horizontal entre les blocs */
+#define HORIZONTAL_MARGIN 20
+
+/* Espace minimal vertical entre les blocs */
+#define VERTICAL_MARGIN 15
+
+
+/* Assigne à un bloc et son ensemble un emplacement initial. */
+void g_graph_cluster_reset_allocation(GGraphCluster *);
+
+/* Met en place les embryons de liens nécessaires. */
+void g_graph_cluster_define_links(GGraphCluster *, GHashTable *);
+
+/* Repère les liens marquants à destination d'autres blocs. */
+void g_graph_cluster_setup_links(GGraphCluster *);
+
+/* Organise la disposition d'un ensemble de blocs basiques. */
+void g_graph_cluster_dispatch_x(GGraphCluster *);
+
+/* Réorganise au besoin les liens entrants d'un bloc. */
+void g_graph_cluster_sort_incoming_links(GGraphCluster *);
+
+/* Retrouve l'indice d'un lien entrant donné pour un bloc. */
+size_t g_graph_cluster_find_incoming_link(const GGraphCluster *, const leaving_link_t *);
+
+/* Détermine si un cluster possède un lien sortant. */
+bool g_graph_cluster_has_exit_link(GGraphCluster *, bool *);
+
+/* Compare deux clusters avec lien sortant. */
+int g_graph_cluster_compare_by_exit(const GGraphCluster **, const GGraphCluster **, const bool *);
+
+/* Réordonne les blocs sortant du cluster au mieux. */
+void g_graph_cluster_reorder_exit_blocks(GGraphCluster *);
+
+/* Réordonne les blocs de départ de boucle au mieux. */
+void g_graph_cluster_reorder_loop_blocks(GGraphCluster *);
+
+/* Réordonne le départ des liens en entrée de bloc. */
+void g_graph_cluster_reorder_link_origins(GGraphCluster *, bool);
+
+/* Décale vers la droite un ensemble de blocs basiques. */
+void g_graph_cluster_offset_x(GGraphCluster *, gint);
+
+/* Décale vers le bas un ensemble de blocs basiques. */
+void g_graph_cluster_set_y(GGraphCluster *, gint);
+
+/* Calcule l'abscisse d'un lien pour un bloc. */
+gint _g_graph_cluster_compute_link_position(const GGraphCluster *, size_t, size_t, bool);
+
+/* Calcule l'abscisse d'un lien à son départ d'un bloc. */
+gint g_graph_cluster_compute_leaving_link_position(const GGraphCluster *, size_t);
+
+/* Calcule l'abscisse d'un lien à son arrivée à un bloc. */
+gint g_graph_cluster_compute_incoming_link_position(const GGraphCluster *, size_t);
+
+/* Détermine les abscisses des liens de boucle en place. */
+void g_graph_cluster_compute_loop_link_x_positions(GGraphCluster *);
+
+/* Détermine les ordonnées de tous les liens en place. */
+void g_graph_cluster_compute_link_y_positions(GGraphCluster *);
+
+/* Collecte tous les chefs de file de blocs de code. */
+GGraphCluster **g_graph_cluster_collect(GGraphCluster *, GGraphCluster **, size_t *);
+
+/* Collecte tous les liens de chefs de file de blocs de code. */
+GGraphEdge **g_graph_cluster_collect_edges(GGraphCluster *, GGraphEdge **, size_t *);
+
+
+
+#endif
diff --git a/src/gtkext/graph/cluster.c b/src/gtkext/graph/cluster.c
index 6284029..41392a2 100644
--- a/src/gtkext/graph/cluster.c
+++ b/src/gtkext/graph/cluster.c
@@ -31,6 +31,12 @@
 #include <string.h>
 
 
+#include "cluster-int.h"
+#include "hspace.h"
+#include "incoming.h"
+#include "leaving.h"
+#include "rank.h"
+#include "vspace.h"
 #include "../gtkblockdisplay.h"
 #include "../gtkbufferdisplay.h"
 #include "../gtkdisplaypanel.h"
@@ -39,248 +45,6 @@
 
 
 
-/* Définition du tracé d'un lien */
-typedef struct _incoming_link_t incoming_link_t;
-
-
-/* ------------------------- LIEN SORTANT D'UN BLOC DE CODE ------------------------- */
-
-
-/* Détails sur le départ d'un lien */
-typedef struct _leaving_link_t
-{
-    GGraphCluster *owner;                   /* Propriétaire du lien        */
-
-    GdkPoint start[2];                      /* Point de départ d'un lien   */
-    size_t index;                           /* Indice sur ligne de départ  */
-
-    bool straight;                          /* Présence d'une ligne droite */
-    bool forced_straight;                   /* Forçage de verticalité      */
-    size_t straight_level;                  /* Rang atteint en ligne droite*/
-    bool cluster_exit;                      /* Sortie du cluster d'origine */
-
-    incoming_link_t *other;                 /* Autre extrémité du lien     */
-
-} leaving_link_t;
-
-
-#define SHOULD_BE_VERTICAL(l) ((l)->straight || (l)->forced_straight || (l)->cluster_exit)
-
-
-/* Crée un point d'attache pour un lien sortant. */
-static leaving_link_t *create_leaving_link(GGraphCluster *, size_t);
-
-/* Détruit un point d'attache pour un lien sortant. */
-static void delete_leaving_link(leaving_link_t *);
-
-/* Calcule l'abscisse d'un lien à son départ d'un bloc. */
-static gint compute_leaving_link_position(const leaving_link_t *);
-
-
-
-/* ------------------------- LIEN ENTRANT D'UN BLOC DE CODE ------------------------- */
-
-
-/* Définition du tracé d'un lien */
-struct _incoming_link_t
-{
-    GGraphCluster *owner;                   /* Propriétaire du lien        */
-
-    InstructionLinkType type;               /* Complexité du tracé         */
-
-    const size_t *hslot;                    /* Couche horizontale réservée */
-    GdkPoint end[2];                        /* Point d'arrivée final       */
-
-    GGraphEdge *edge;                       /* Lien complet en préparation */
-
-    leaving_link_t *other;                  /* Autre extrémité du lien     */
-
-};
-
-
-/* Crée un point d'attache pour un lien entrant simple. */
-static incoming_link_t *create_incoming_link(GGraphCluster *, InstructionLinkType, leaving_link_t *);
-
-/* Crée un point d'attache pour un lien entrant de boucle. */
-static incoming_link_t *create_incoming_loop_link(GGraphCluster *, const GdkPoint *, leaving_link_t *);
-
-/* Détruit un point d'attache pour un lien entrant. */
-static void delete_incoming_link(incoming_link_t *);
-
-/* Compare deux liens entrants. */
-static int cmp_incoming_links(const incoming_link_t **, const incoming_link_t **);
-
-
-
-/* ------------------------ ENCADREMENTS D'ESPACES VERTICAUX ------------------------ */
-
-
-/* Réservations d'espaces latéraux */
-typedef struct _vspace_booking_t
-{
-    leaving_link_t *from;                   /* Bloc de départ du lien      */
-    incoming_link_t *to;                    /* Bloc d'arrivée du lien      */
-
-    GdkPoint *pts;                          /* Coordonnées des points      */
-
-    bool external;                          /* Lien vers un cluster parent */
-
-} vspace_booking_t;
-
-/* Réservations d'espaces latéraux */
-typedef struct _vspace_manager_t
-{
-    vspace_booking_t *pending;              /* Besoins exprimés            */
-    size_t pending_count;                   /* Nombre de ces besoins       */
-
-    vspace_booking_t **left;                /* Lignes disposées à gauche   */
-    size_t left_count;                      /* Quantité de ces lignes      */
-
-    vspace_booking_t **right;               /* Lignes disposées à droite  */
-    size_t right_count;                     /* Quantité de ces lignes      */
-
-} vspace_manager_t;
-
-
-/* Initialise les réservations liens verticaux. */
-static void init_vspace_manager(vspace_manager_t *);
-
-/* Termine les réservations liens verticaux. */
-static void exit_vspace_manager(vspace_manager_t *);
-
-/* Inscrit une nouvelle réservation d'espace latéral. */
-static void extend_vspace_manager(vspace_manager_t *, leaving_link_t *, incoming_link_t *, GdkPoint *, bool);
-
-/* Détermine l'emplacement requis pour les espaces latéraux. */
-static void compute_vspace_manager_needed_alloc(const vspace_manager_t *, bool, GtkAllocation *);
-
-/* Réorganise au besoin les liens de boucle entre blocs. */
-static void sort_incoming_links_for_vspace_manager(vspace_manager_t *);
-
-/* Décale vers la droite un ensemble de points. */
-static void offset_x_vspace_manager(vspace_manager_t *, gint);
-
-/* Détermine les abscisses de tous les liens en place. */
-static gint compute_loop_link_x_with_vspace_manager(const vspace_manager_t *, const GtkAllocation *, bool);
-
-/* Détermine les ordonnées de tous les liens en place. */
-static void compute_loop_link_y_with_vspace_manager(const vspace_manager_t *, const GtkAllocation *);
-
-
-
-/* ---------------------- DESCENDANTS DIRECTS CLASSES PAR RANG ---------------------- */
-
-
-/* Réservation pour les lignes horizontales */
-typedef struct _hspace_booking
-{
-    gint start;                             /* Abscisse de départ de ligne */
-    size_t index;                           /* Indice de rangée verticale  */
-
-} hspace_booking;
-
-
-/* Prépare une réservation d'espace pour ligne horizontale. */
-static hspace_booking *create_hspace_booking(gint);
-
-/* Compare deux réservations d'espace. */
-static int cmp_hspace_booking_r2l(const hspace_booking **, const hspace_booking **);
-
-/* Compare deux réservations d'espace. */
-static int cmp_hspace_booking_l2r(const hspace_booking **, const hspace_booking **);
-
-
-/* Découpage vertical */
-typedef struct _graph_rank_t
-{
-    hspace_booking **right2left;            /* Réservations de D -> G      */
-    size_t r2l_count;                       /* Quantité de ces réservations*/
-
-    hspace_booking **left2right;            /* Réservations de G -> D      */
-    size_t l2r_count;                       /* Quantité de ces réservations*/
-
-    GGraphCluster **clusters;               /* Ensembles de blocs          */
-    size_t count;                           /* Nombre de ces ensembles     */
-
-    vspace_manager_t vspaces;               /* Gestion des liens latéraux  */
-
-} graph_rank_t;
-
-
-/* Initialise la gestion d'un ensemble de blocs de même rang. */
-static void init_graph_rank(graph_rank_t *, GGraphCluster *);
-
-/* Termine la gestion d'un ensemble de blocs de même rang. */
-static void exit_graph_rank(graph_rank_t *);
-
-/* Assigne à un ensemble de blocs un emplacement initial. */
-static void reset_graph_rank_allocation(const graph_rank_t *);
-
-/* Fournit le rang d'un ensemble de blocs. */
-static size_t get_graph_rank(const graph_rank_t *);
-
-/* Compare deux rangées de blocs de code. */
-static int cmp_graph_rank(const graph_rank_t *, const graph_rank_t *);
-
-/* Etend un ensemble de blocs de même rang. */
-static void extend_graph_rank(graph_rank_t *, GGraphCluster *);
-
-/* Détermine si un groupe de blocs contient un bloc particulier. */
-static bool has_graph_rank_cluster(const graph_rank_t *, GGraphCluster *);
-
-/* Inscrit à l'endroit idéal une réservation d'espace latéral. */
-static bool extend_graph_rank_vspace_manager(graph_rank_t *, leaving_link_t *, incoming_link_t *, GdkPoint *, bool);
-
-/* Met en place les embryons de liens nécessaires. */
-static void define_graph_rank_links(const graph_rank_t *, GHashTable *);
-
-/* Repère les liens marquants à destination d'autres blocs. */
-static void setup_graph_rank_links(const graph_rank_t *);
-
-/* Détermine l'emplacement requis d'un ensemble de blocs. */
-static void compute_graph_rank_needed_alloc(const graph_rank_t *, bool, GtkAllocation *);
-
-/* Affine l'abscisse d'un ensemble de blocs de même rang. */
-static void _place_graph_rank_clusters(GGraphCluster **, size_t, gint, int);
-
-/* Organise la disposition d'un ensemble de blocs basiques. */
-static void dispatch_x_graph_rank(const graph_rank_t *);
-
-/* Réorganise au besoin les liens entrants un ensemble de blocs. */
-static void sort_graph_rank_incoming_links(graph_rank_t *);
-
-/* Réordonne les blocs sortant d'un ensemble. */
-static void reorder_graph_rank_exit_blocks(graph_rank_t *);
-
-/* Réordonne les blocs de départ de boucle d'un ensemble. */
-static void reorder_graph_rank_loop_blocks(graph_rank_t *);
-
-/* Décale vers la droite un ensemble de blocs basiques. */
-static void offset_x_graph_rank(graph_rank_t *, gint);
-
-/* Détermine les abscisses des liens de boucle en place. */
-static gint compute_loop_link_x_positions_with_graph_rank(const graph_rank_t *, const GtkAllocation *);
-
-/* Décale vers le bas un ensemble de blocs basiques. */
-static void set_y_for_graph_rank(const graph_rank_t *, gint *);
-
-/* Détermine les ordonnées de tous les liens en place. */
-static void compute_loop_link_with_graph_rank(const graph_rank_t *, const GtkAllocation *);
-
-/* Recherche le groupe de blocs avec un bloc donné comme chef. */
-static GGraphCluster *find_cluster_by_block_in_graph_rank(const graph_rank_t *, GCodeBlock *);
-
-/* Recherche le groupe de blocs avec un composant comme chef. */
-static GGraphCluster *find_cluster_by_widget_in_graph_rank(const graph_rank_t *, GtkWidget *);
-
-/* Collecte tous les chefs de file de blocs de code. */
-static GGraphCluster **collect_graph_ranks_clusters(const graph_rank_t *, GGraphCluster **, size_t *);
-
-/* Collecte tous les liens de chefs de file de blocs de code. */
-static GGraphEdge **collect_graph_ranks_cluster_edges(const graph_rank_t *, GGraphEdge **, size_t *);
-
-
-
 /* -------------------------- DEFINITION D'UN CHEF DE FILE -------------------------- */
 
 
@@ -330,12 +94,6 @@ struct _GGraphClusterClass
 };
 
 
-/* Espace minimal horizontal entre les blocs */
-#define HORIZONTAL_MARGIN 20
-
-/* Espace minimal vertical entre les blocs */
-#define VERTICAL_MARGIN 15
-
 
 /* Initialise la classe des mises en disposition graphique. */
 static void g_graph_cluster_class_init(GGraphClusterClass *);
@@ -349,9 +107,6 @@ static void g_graph_cluster_dispose(GGraphCluster *);
 /* Procède à la libération totale de la mémoire. */
 static void g_graph_cluster_finalize(GGraphCluster *);
 
-/* Assigne à un bloc et son ensemble un emplacement initial. */
-static void g_graph_cluster_reset_allocation(GGraphCluster *);
-
 /* Complète un graphique avec un sous-ensemble de blocs. */
 static void g_graph_cluster_add_sub(GGraphCluster *, GGraphCluster *);
 
@@ -361,75 +116,18 @@ static void g_graph_cluster_setup_link_for_target(GGraphCluster *, GGraphCluster
 /* Inscrit à l'endroit idéal une réservation d'espace latéral. */
 static void g_graph_cluster_extend_vspace_manager(GGraphCluster *, leaving_link_t *, incoming_link_t *, GdkPoint *);
 
-/* Met en place les embryons de liens nécessaires. */
-static void g_graph_cluster_define_links(GGraphCluster *, GHashTable *);
-
-/* Repère les liens marquants à destination d'autres blocs. */
-static void g_graph_cluster_setup_links(GGraphCluster *);
-
-/* Organise la disposition d'un ensemble de blocs basiques. */
-static void g_graph_cluster_dispatch_x(GGraphCluster *);
-
-/* Réorganise au besoin les liens entrants d'un bloc. */
-static void g_graph_cluster_sort_incoming_links(GGraphCluster *);
-
-/* Retrouve l'indice d'un lien entrant donné pour un bloc. */
-static size_t g_graph_cluster_find_incoming_link(const GGraphCluster *, const leaving_link_t *);
-
-/* Détermine si un cluster possède un lien sortant. */
-static bool g_graph_cluster_has_exit_link(GGraphCluster *, bool *);
-
-/* Compare deux clusters avec lien sortant. */
-static int g_graph_cluster_compare_by_exit(const GGraphCluster **, const GGraphCluster **, const bool *);
-
-/* Réordonne les blocs sortant du cluster au mieux. */
-static void g_graph_cluster_reorder_exit_blocks(GGraphCluster *);
-
-/* Réordonne les blocs de départ de boucle au mieux. */
-static void g_graph_cluster_reorder_loop_blocks(GGraphCluster *);
-
-/* Réordonne le départ des liens en entrée de bloc. */
-static void g_graph_cluster_reorder_link_origins(GGraphCluster *, bool);
-
-/* Décale vers la droite un ensemble de blocs basiques. */
-static void g_graph_cluster_offset_x(GGraphCluster *, gint);
-
-/* Décale vers le bas un ensemble de blocs basiques. */
-static void g_graph_cluster_set_y(GGraphCluster *, gint);
-
-/* Calcule l'abscisse d'un lien pour un bloc. */
-static gint _g_graph_cluster_compute_link_position(const GGraphCluster *, size_t, size_t, bool);
-
-/* Calcule l'abscisse d'un lien à son départ d'un bloc. */
-static gint g_graph_cluster_compute_leaving_link_position(const GGraphCluster *, size_t);
-
-/* Calcule l'abscisse d'un lien à son arrivée à un bloc. */
-static gint g_graph_cluster_compute_incoming_link_position(const GGraphCluster *, size_t);
-
 /* Ajoute une marge à gauche pour les liens remontants. */
 static void g_graph_cluster_insert_left_margin(GGraphCluster *, gint);
 
-/* Détermine les abscisses des liens de boucle en place. */
-static void g_graph_cluster_compute_loop_link_x_positions(GGraphCluster *);
-
 /* Détermine les abscisses de tous les liens en place. */
 static void g_graph_cluster_compute_link_x_positions(GGraphCluster *);
 
 /* Réserve de l'espace vertical pour les lignes horizontales. */
 static void g_graph_cluster_book_hspace_for_links(GGraphCluster *);
 
-/* Détermine les ordonnées de tous les liens en place. */
-static void g_graph_cluster_compute_link_y_positions(GGraphCluster *);
-
 /* Applique les positions calculées pour chaque lien graphique. */
 static void g_graph_cluster_resolve_links(const GGraphCluster *);
 
-/* Collecte tous les chefs de file de blocs de code. */
-static GGraphCluster **g_graph_cluster_collect(GGraphCluster *, GGraphCluster **, size_t *);
-
-/* Collecte tous les liens de chefs de file de blocs de code. */
-static GGraphEdge **g_graph_cluster_collect_edges(GGraphCluster *, GGraphEdge **, size_t *);
-
 
 
 /* ------------------------- CALCUL DE REPARTITION DE BLOCS ------------------------- */
@@ -454,80 +152,6 @@ static GGraphCluster *setup_graph_clusters(GLoadedBinary *, const GBlockList *,
 /* ---------------------------------------------------------------------------------- */
 
 
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : owner = propriétaire du bloc de rattachement.                *
-*                index = indice dans les liens de sortie.                     *
-*                                                                             *
-*  Description : Crée un point d'attache pour un lien sortant.                *
-*                                                                             *
-*  Retour      : Structure mise en place.                                     *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static leaving_link_t *create_leaving_link(GGraphCluster *owner, size_t index)
-{
-    leaving_link_t *result;                 /* Structure à retourner       */
-
-    result = malloc(sizeof(leaving_link_t));
-
-    result->owner = owner;
-
-    result->index = index;
-
-    result->straight = false;
-    result->forced_straight = false;
-    result->straight_level = SIZE_MAX;
-    result->cluster_exit = false;
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : link = structure à libérer de la mémoire.                    *
-*                                                                             *
-*  Description : Détruit un point d'attache pour un lien sortant.             *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void delete_leaving_link(leaving_link_t *link)
-{
-    free(link);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : link = information sur un lien à consulter.                  *
-*                                                                             *
-*  Description : Calcule l'abscisse d'un lien à son départ d'un bloc.         *
-*                                                                             *
-*  Retour      : Abscisse à attribuer à un départ de lien.                    *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static gint compute_leaving_link_position(const leaving_link_t *link)
-{
-    gint result;                            /* Position à retourner        */
-
-    result = g_graph_cluster_compute_leaving_link_position(link->owner, link->index);
-
-    return result;
-
-}
-
 
 
 /* ---------------------------------------------------------------------------------- */
@@ -535,1473 +159,21 @@ static gint compute_leaving_link_position(const leaving_link_t *link)
 /* ---------------------------------------------------------------------------------- */
 
 
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : owner = propriétaire du bloc de rattachement.                *
-*                type  = type de lien simple attendu.                         *
-*                other = point de départ du lien formé.                       *
-*                                                                             *
-*  Description : Crée un point d'attache pour un lien entrant simple.         *
-*                                                                             *
-*  Retour      : Structure mise en place.                                     *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static incoming_link_t *create_incoming_link(GGraphCluster *owner, InstructionLinkType type, leaving_link_t *other)
-{
-    incoming_link_t *result;                /* Structure à retourner       */
-    GCodeBlock *src;                        /* Bloc d'origine du lien      */
-    GCodeBlock *dst;                        /* Bloc de destination du lien */
-
-    result = malloc(sizeof(incoming_link_t));
-
-    result->owner = owner;
-
-    result->type = type;
-
-    src = other->owner->block;
-    dst = owner->block;
-
-    if (type == ILT_JUMP_IF_TRUE)
-        result->edge = g_graph_edge_new_true(src, dst,
-                                             &other->start[0], &other->start[1],
-                                             &result->end[0], &result->end[1]);
-
-    else if (type == ILT_JUMP_IF_FALSE)
-        result->edge = g_graph_edge_new_false(src, dst,
-                                              &other->start[0], &other->start[1],
-                                              &result->end[0], &result->end[1]);
-
-    else
-        result->edge = g_graph_edge_new(src, dst,
-                                        &other->start[0], &other->start[1],
-                                        &result->end[0], &result->end[1]);
-
-    result->other = other;
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : owner = propriétaire du bloc de rattachement.                *
-*                other = point de départ du lien formé.                       *
-*                                                                             *
-*  Description : Crée un point d'attache pour un lien entrant de boucle.      *
-*                                                                             *
-*  Retour      : Structure mise en place.                                     *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static incoming_link_t *create_incoming_loop_link(GGraphCluster *owner, const GdkPoint *midpts, leaving_link_t *other)
-{
-    incoming_link_t *result;                /* Structure à retourner       */
-    GCodeBlock *src;                        /* Bloc d'origine du lien      */
-    GCodeBlock *dst;                        /* Bloc de destination du lien */
-
-    result = malloc(sizeof(incoming_link_t));
-
-    result->owner = owner;
-
-    result->type = ILT_LOOP;
-
-    src = other->owner->block;
-    dst = owner->block;
-
-    result->edge = g_graph_edge_new_loop(src, dst,
-                                         &other->start[0], &other->start[1],
-                                         &midpts[0], &midpts[1],
-                                         &result->end[0], &result->end[1]);
-
-    result->other = other;
 
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : link = structure à libérer de la mémoire.                    *
-*                                                                             *
-*  Description : Détruit un point d'attache pour un lien entrant.             *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
 
-static void delete_incoming_link(incoming_link_t *link)
-{
-    free(link);
+/* ---------------------------------------------------------------------------------- */
+/*                          ENCADREMENTS D'ESPACES VERTICAUX                          */
+/* ---------------------------------------------------------------------------------- */
 
-}
 
 
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : a = premier lien entrant à comparer.                         *
-*                b = second lien entrant à comparer.                          *
-*                                                                             *
-*  Description : Compare deux liens entrants.                                 *
-*                                                                             *
-*  Retour      : Bilan de comparaison.                                        *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
 
-static int cmp_incoming_links(const incoming_link_t **a, const incoming_link_t **b)
-{
-    int result;                             /* Bilan à retourner           */
-    gint pos_a;                             /* Point de départ pour A      */
-    gint pos_b;                             /* Point de départ pour B      */
 
-    pos_a = compute_leaving_link_position((*a)->other);
+/* ---------------------------------------------------------------------------------- */
+/*                        DESCENDANTS DIRECTS CLASSES PAR RANG                        */
+/* ---------------------------------------------------------------------------------- */
 
-    pos_b = compute_leaving_link_position((*b)->other);
 
-    if (pos_a < pos_b)
-        result = -1;
-
-    else if (pos_a > pos_b)
-        result = 1;
-
-    else
-        result = 0;
-
-    return result;
-
-}
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/*                          ENCADREMENTS D'ESPACES VERTICAUX                          */
-/* ---------------------------------------------------------------------------------- */
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : manager = structure à initialiser.                           *
-*                                                                             *
-*  Description : Initialise les réservations liens verticaux.                 *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void init_vspace_manager(vspace_manager_t *manager)
-{
-    manager->pending = NULL;
-    manager->pending_count = 0;
-
-    manager->left = NULL;
-    manager->left_count = 0;
-
-    manager->right = NULL;
-    manager->right_count = 0;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : manager = structure à vider.                                 *
-*                                                                             *
-*  Description : Termine les réservations liens verticaux.                    *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void exit_vspace_manager(vspace_manager_t *manager)
-{
-    size_t i;                               /* Boucle de parcours          */
-
-    for (i = 0; i < manager->pending_count; i++)
-        free(manager->pending[i].pts);
-
-    if (manager->pending != NULL)
-        free(manager->pending);
-
-    if (manager->left != NULL)
-        free(manager->left);
-
-    if (manager->right != NULL)
-        free(manager->right);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : manager  = structure à compléter.                            *
-*                from     = point de départ du lien concerné.                 *
-*                to       = point d'arrivée du lien concerné.                 *
-*                pts      = points intermédiaires du tracé complet final.     *
-*                external = précise une sortie du cadre du cluster premier.   *
-*                                                                             *
-*  Description : Inscrit une nouvelle réservation d'espace latéral.           *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void extend_vspace_manager(vspace_manager_t *manager, leaving_link_t *from, incoming_link_t *to, GdkPoint *pts, bool external)
-{
-    vspace_booking_t *new;                  /* Réservation à constituer    */
-
-    manager->pending = realloc(manager->pending, ++manager->pending_count * sizeof(vspace_booking_t));
-
-    new = &manager->pending[manager->pending_count - 1];
-
-    new->from = from;
-    new->to = to;
-
-    new->pts = pts;
-
-    new->external = external;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : manager  = gestion des espaces latéraux à consulter.         *
-*                external = précise une sortie du cadre du cluster premier.   *
-*                alloc    = emplacement idéal pour l'affichage. [OUT]         *
-*                                                                             *
-*  Description : Détermine l'emplacement requis pour les espaces latéraux.    *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void compute_vspace_manager_needed_alloc(const vspace_manager_t *manager, bool external, GtkAllocation *alloc)
-{
-    gint width;                             /* Largeur supplémentaire      */
-    size_t count;                           /* Nombre de liens retenus     */
-    size_t i;                               /* Boucle de parcours          */
-
-    width = 0;
-
-    /* Extension de la largeur, à gauche */
-
-    count = 0;
-
-    for (i = 0; i < manager->left_count; i++)
-        if (manager->left[i]->external == external)
-            count++;
-
-    width += count * LINK_MARGIN;
-
-    alloc->x -= width;
-
-    /* Extension de la largeur, à droite */
-
-    count = 0;
-
-    for (i = 0; i < manager->right_count; i++)
-        if (manager->right[i]->external == external)
-            count++;
-
-    width += count * LINK_MARGIN;
-
-    alloc->width += width;
-
-    /* Extension de la hauteur */
-
-    if (!external)
-        alloc->height += manager->pending_count * VERTICAL_MARGIN;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : manager = gestion d'espaces latéraux à manipuler.            *
-*                                                                             *
-*  Description : Réorganise au besoin les liens de boucle entre blocs.        *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void sort_incoming_links_for_vspace_manager(vspace_manager_t *manager)
-{
-    size_t i;                               /* Boucle de parcours          */
-    vspace_booking_t *pending;              /* Elément traité              */
-    gint x1;                                /* Abscisse de départ de lien  */
-    size_t idx;                             /* Indice du lien entrant      */
-    gint x2;                                /* Abscisse d'arrivée de lien  */
-    bool for_left;                          /* Répartition par la gauche ? */
-
-    for (i = 0; i < manager->pending_count; i++)
-    {
-        pending = &manager->pending[i];
-
-        x1 = g_graph_cluster_compute_leaving_link_position(pending->from->owner, pending->from->index);
-
-        idx = g_graph_cluster_find_incoming_link(pending->to->owner, pending->from);
-
-        x2 = g_graph_cluster_compute_incoming_link_position(pending->to->owner, idx);
-
-        /**
-         * Prise en compte d'une boucle while (1);
-         */
-        if (pending->from->owner == pending->to->owner)
-            for_left = (x2 < x1);
-        else
-            for_left = (x1 < x2);
-
-        if (for_left)
-        {
-            manager->left = realloc(manager->left, ++manager->left_count * sizeof(vspace_booking_t *));
-            manager->left[manager->left_count - 1] = pending;
-        }
-        else
-        {
-            manager->right = realloc(manager->right, ++manager->right_count * sizeof(vspace_booking_t *));
-            manager->right[manager->right_count - 1] = pending;
-        }
-
-    }
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : manager = structure à actualiser.                            *
-*                offset = décalage à appliquer.                               *
-*                                                                             *
-*  Description : Décale vers la droite un ensemble de points.                 *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void offset_x_vspace_manager(vspace_manager_t *manager, gint offset)
-{
-    size_t i;                               /* Boucle de parcours          */
-    vspace_booking_t *booking;              /* Réservation à traiter       */
-
-    for (i = 0; i < manager->left_count; i++)
-    {
-        booking = manager->left[i];
-
-        booking->pts[0].x += offset;
-        booking->pts[1].x += offset;
-
-    }
-
-    for (i = 0; i < manager->right_count; i++)
-    {
-        booking = manager->right[i];
-
-        booking->pts[0].x += offset;
-        booking->pts[1].x += offset;
-
-    }
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : manager  = structure à consulter.                            *
-*                needed   = espace nécessaire et alloué pour les blocs.       *
-*                external = précise une sortie du cadre du cluster premier.   *
-*                                                                             *
-*  Description : Détermine les abscisses de tous les liens en place.          *
-*                                                                             *
-*  Retour      : Eventuelle marge à gauche devenue nécessaire.                *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static gint compute_loop_link_x_with_vspace_manager(const vspace_manager_t *manager, const GtkAllocation *needed, bool external)
-{
-    gint result;                            /* Eventuelle marge à renvoyer */
-    size_t count;                           /* Quantité de liens traités   */
-    size_t i;                               /* Boucle de parcours          */
-    vspace_booking_t *booking;              /* Réservation à traiter       */
-    gint x;                                 /* Position à appliquer        */
-
-    count = 0;
-
-    for (i = 0; i < manager->left_count; i++)
-    {
-        booking = manager->left[i];
-
-        if (booking->external != external)
-            continue;
-
-        x = ++count * LINK_MARGIN;
-
-        booking->pts[0].x = needed->x - x;
-        booking->pts[1].x = needed->x - x;
-
-    }
-
-    result = count * LINK_MARGIN;
-
-    count = 0;
-
-    for (i = 0; i < manager->right_count; i++)
-    {
-        booking = manager->right[i];
-
-        if (booking->external != external)
-            continue;
-
-        x = ++count * LINK_MARGIN;
-
-        booking->pts[0].x = needed->x + needed->width + x;
-        booking->pts[1].x = needed->x + needed->width + x;
-
-    }
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : manager = structure à consulter.                             *
-*                needed  = espace nécessaire et alloué pour les blocs.        *
-*                                                                             *
-*  Description : Détermine les ordonnées de tous les liens en place.          *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void compute_loop_link_y_with_vspace_manager(const vspace_manager_t *manager, const GtkAllocation *needed)
-{
-    gint real_bottom;                       /* Point de départ réel        */
-    size_t i;                               /* Boucle de parcours          */
-    vspace_booking_t *booking;              /* Réservation à traiter       */
-
-    real_bottom = needed->y + needed->height - manager->pending_count * VERTICAL_MARGIN;
-
-    for (i = 0; i < manager->pending_count; i++)
-    {
-        booking = &manager->pending[i];
-
-        /**
-         * On corrige le raccourci pris sans distinction de type de lien dans
-         * la fonction g_graph_cluster_compute_link_y_positions().
-         */
-
-        booking->from->start[1].y = real_bottom +  (i + 1) * VERTICAL_MARGIN;
-
-        /* Définition de l'ordonnée des points du lien */
-
-        booking->pts[0].y = booking->from->start[1].y;
-
-        booking->pts[1].y = booking->to->end[0].y;
-
-    }
-
-}
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/*                        DESCENDANTS DIRECTS CLASSES PAR RANG                        */
-/* ---------------------------------------------------------------------------------- */
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : start = abscisse de départ de ligne.                         *
-*                                                                             *
-*  Description : Prépare une réservation d'espace pour ligne horizontale.     *
-*                                                                             *
-*  Retour      : Structure mise en place pour la conservation d'informations. *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static hspace_booking *create_hspace_booking(gint start)
-{
-    hspace_booking *result;                 /* Structure à retourner       */
-
-    result = malloc(sizeof(hspace_booking));
-
-    result->start = start;
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : a = première réservation d'espace à comparer.                *
-*                b = seconde réservation d'espace à comparer.                 *
-*                                                                             *
-*  Description : Compare deux réservations d'espace.                          *
-*                                                                             *
-*  Retour      : Bilan de comparaison.                                        *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static int cmp_hspace_booking_r2l(const hspace_booking **a, const hspace_booking **b)
-{
-    int result;                             /* Bilan à retourner           */
-
-    if ((*a)->start > (*b)->start)
-        result = -1;
-
-    else if ((*a)->start < (*b)->start)
-        result = 1;
-
-    else
-    {
-        assert(false);
-        result = 0;
-    }
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : a = première réservation d'espace à comparer.                *
-*                b = seconde réservation d'espace à comparer.                 *
-*                                                                             *
-*  Description : Compare deux réservations d'espace.                          *
-*                                                                             *
-*  Retour      : Bilan de comparaison.                                        *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static int cmp_hspace_booking_l2r(const hspace_booking **a, const hspace_booking **b)
-{
-    int result;                             /* Bilan à retourner           */
-
-    if ((*a)->start < (*b)->start)
-        result = -1;
-
-    else if ((*a)->start > (*b)->start)
-        result = 1;
-
-    else
-    {
-        assert(false);
-        result = 0;
-    }
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : grank   = structure à initialiser. [OUT]                     *
-*                cluster = chef de file d'un ensemble de blocs.               *
-*                                                                             *
-*  Description : Initialise la gestion d'un ensemble de blocs de même rang.   *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void init_graph_rank(graph_rank_t *grank, GGraphCluster *cluster)
-{
-    grank->right2left = NULL;
-    grank->r2l_count = 0;
-
-    grank->left2right = NULL;
-    grank->l2r_count = 0;
-
-    grank->clusters = malloc(sizeof(GGraphCluster *));
-    grank->count = 1;
-
-    grank->clusters[0] = cluster;
-
-    init_vspace_manager(&grank->vspaces);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : grank = structure à vider.                                   *
-*                                                                             *
-*  Description : Termine la gestion d'un ensemble de blocs de même rang.      *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void exit_graph_rank(graph_rank_t *grank)
-{
-    size_t i;                               /* Boucle de parcours          */
-
-    for (i = 0; i < grank->r2l_count; i++)
-        free(grank->right2left[i]);
-
-    if (grank->right2left != NULL)
-        free(grank->right2left);
-
-    for (i = 0; i < grank->l2r_count; i++)
-        free(grank->left2right[i]);
-
-    if (grank->left2right != NULL)
-        free(grank->left2right);
-
-    assert(grank->clusters != NULL);
-
-    free(grank->clusters);
-
-    exit_vspace_manager(&grank->vspaces);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : grank = ensemble de même rang à consulter.                   *
-*                                                                             *
-*  Description : Assigne à un ensemble de blocs un emplacement initial.       *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void reset_graph_rank_allocation(const graph_rank_t *grank)
-{
-    size_t i;                               /* Boucle de parcours          */
-
-    for (i = 0; i < grank->count; i++)
-        g_graph_cluster_reset_allocation(grank->clusters[i]);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : grank = ensemble de même rang à consulter.                   *
-*                                                                             *
-*  Description : Fournit le rang d'un ensemble de blocs.                      *
-*                                                                             *
-*  Retour      : Rang d'un ensemble de blocs de même rang.                    *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static size_t get_graph_rank(const graph_rank_t *grank)
-{
-    size_t result;                          /* Rang à retourner            */
-
-    result = g_code_block_get_rank(grank->clusters[0]->block);
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : a = premier ensemble de même rang à comparer.                *
-*                b = second ensemble de même rang à comparer.                 *
-*                                                                             *
-*  Description : Compare deux rangées de blocs de code.                       *
-*                                                                             *
-*  Retour      : Bilan de comparaison.                                        *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static int cmp_graph_rank(const graph_rank_t *a, const graph_rank_t *b)
-{
-    int result;                             /* Bilan à retourner           */
-    size_t level_a;                         /* Niveau de l'ensemble A      */
-    size_t level_b;                         /* Niveau de l'ensemble B      */
-
-    level_a = get_graph_rank(a);
-    level_b = get_graph_rank(b);
-
-    if (level_a < level_b)
-        result = -1;
-
-    else if (level_a > level_b)
-        result = 1;
-
-    else
-        result = 0;
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : grank   = structure à compléter.                             *
-*                cluster = chef de file d'un ensemble de blocs.               *
-*                                                                             *
-*  Description : Etend un ensemble de blocs de même rang.                     *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void extend_graph_rank(graph_rank_t *grank, GGraphCluster *cluster)
-{
-    grank->count++;
-    grank->clusters = realloc(grank->clusters, sizeof(GGraphCluster *) * grank->count);
-
-    grank->clusters[grank->count - 1] = cluster;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : grank   = structure à compléter.                             *
-*                cluster = chef de file d'un ensemble de blocs.               *
-*                                                                             *
-*  Description : Détermine si un groupe de blocs contient un bloc particulier.*
-*                                                                             *
-*  Retour      : true si le chef est bien contenu, false sinon.               *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static bool has_graph_rank_cluster(const graph_rank_t *grank, GGraphCluster *cluster)
-{
-    bool result;                            /* Bilan à renvoyer            */
-    size_t i;                               /* Boucle de parcours          */
-
-    result = false;
-
-    for (i = 0; i < grank->count && !result; i++)
-        result = (grank->clusters[i] == cluster);
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : grank    = ensemble de descendants d'un même rang.           *
-*                from     = point de départ du lien concerné.                 *
-*                to       = point d'arrivée du lien concerné.                 *
-*                pts      = points intermédiaires du tracé complet final.     *
-*                external = précise une sortie du cadre du cluster premier.   *
-*                                                                             *
-*  Description : Inscrit à l'endroit idéal une réservation d'espace latéral.  *
-*                                                                             *
-*  Retour      : true si la demande a bien été traitée.                       *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static bool extend_graph_rank_vspace_manager(graph_rank_t *grank, leaving_link_t *from, incoming_link_t *to, GdkPoint *pts, bool external)
-{
-    bool result;                            /* Bilan à renvoyer            */
-
-    result = has_graph_rank_cluster(grank, from->owner);
-
-    if (result)
-        extend_vspace_manager(&grank->vspaces, from, to, pts, external);
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : grank = ensemble de descendants d'un même rang.              *
-*                all   = table regroupant tous les groupes créés.             *
-*                                                                             *
-*  Description : Met en place les embryons de liens nécessaires.              *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void define_graph_rank_links(const graph_rank_t *grank, GHashTable *all)
-{
-    size_t i;                               /* Boucle de parcours          */
-
-    for (i = 0; i < grank->count; i++)
-        g_graph_cluster_define_links(grank->clusters[i], all);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : grank = ensemble de descendants d'un même rang.              *
-*                                                                             *
-*  Description : Repère les liens marquants à destination d'autres blocs.     *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void setup_graph_rank_links(const graph_rank_t *grank)
-{
-    size_t i;                               /* Boucle de parcours          */
-
-    for (i = 0; i < grank->count; i++)
-        g_graph_cluster_setup_links(grank->clusters[i]);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : grank = ensemble de descendants d'un même rang.              *
-*                last  = indique s'il s'agit du dernier étage de l'ensemble.  *
-*                alloc = emplacement idéal pour l'affichage. [OUT]            *
-*                                                                             *
-*  Description : Détermine l'emplacement requis d'un ensemble de blocs.       *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void compute_graph_rank_needed_alloc(const graph_rank_t *grank, bool last, GtkAllocation *alloc)
-{
-    GtkAllocation needed;                   /* Taille requise              */
-
-    switch (grank->count)
-    {
-        case 1:
-
-            g_graph_cluster_compute_needed_alloc(grank->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 (last)
-            {
-                if ((needed.y + needed.height) > (alloc->y + alloc->height))
-                    alloc->height += needed.y + needed.height - alloc->y - alloc->height;
-            }
-
-            break;
-
-        default:
-
-            assert(grank->count >= 2);
-
-            g_graph_cluster_compute_needed_alloc(grank->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 (last)
-            {
-                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(grank->clusters[grank->count - 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 (last)
-            {
-                if ((needed.y + needed.height) > (alloc->y + alloc->height))
-                    alloc->height += needed.y + needed.height - alloc->y - alloc->height;
-            }
-
-            break;
-
-    }
-
-    compute_vspace_manager_needed_alloc(&grank->vspaces, false, alloc);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : iter = début de la boucle de parcours.                       *
-*                loop = nombre d'itérations à mener.                          *
-*                base = position de base sur l'axe des abscisses.             *
-*                dir  = direction du parcours.                                *
-*                                                                             *
-*  Description : Affine l'abscisse d'un ensemble de blocs de même rang.       *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void _place_graph_rank_clusters(GGraphCluster **iter, size_t loop, gint base, int dir)
-{
-    size_t i;                               /* Boucle de parcours          */
-    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);
-
-    }
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : grank = ensemble de blocs de même rang à manipuler.          *
-*                                                                             *
-*  Description : Organise la disposition d'un ensemble de blocs basiques.     *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void dispatch_x_graph_rank(const graph_rank_t *grank)
-{
-    size_t mid;                             /* Position centrale de départ */
-    gint start;                             /* Position initiale de départ */
-
-    if (grank->count % 2 == 1)
-    {
-        if (grank->count > 1)
-        {
-            mid = grank->count / 2;
-
-            start = grank->clusters[mid]->alloc.x - HORIZONTAL_MARGIN;
-
-            _place_graph_rank_clusters(grank->clusters + mid - 1, mid, start, -1);
-
-            start *= -1;
-
-            _place_graph_rank_clusters(grank->clusters + mid + 1, mid, start, 1);
-
-        }
-
-        else
-            g_graph_cluster_dispatch_x(grank->clusters[0]);
-
-    }
-
-    else
-    {
-        mid = grank->count / 2 - 1;
-
-        start = - HORIZONTAL_MARGIN / 2;
-
-        _place_graph_rank_clusters(grank->clusters + mid, mid + 1, start, -1);
-
-        start *= -1;
-
-        _place_graph_rank_clusters(grank->clusters + mid + 1, mid + 1, start, 1);
-
-    }
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : grank  = ensemble de blocs de même rang à actualiser.        *
-*                                                                             *
-*  Description : Réorganise au besoin les liens entrants un ensemble de blocs.*
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void sort_graph_rank_incoming_links(graph_rank_t *grank)
-{
-    size_t i;                               /* Boucle de parcours          */
-
-    for (i = 0; i < grank->count; i++)
-        g_graph_cluster_sort_incoming_links(grank->clusters[i]);
-
-    sort_incoming_links_for_vspace_manager(&grank->vspaces);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : grank = ensemble de blocs de même rang à actualiser.         *
-*                                                                             *
-*  Description : Réordonne les blocs sortant d'un ensemble.                   *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void reorder_graph_rank_exit_blocks(graph_rank_t *grank)
-{
-    GGraphCluster **exit_2_left;            /* Liste avec sortie à gauche  */
-    GGraphCluster **exit_2_right;           /* Liste avec sortie à droite  */
-    GGraphCluster **no_exit;                /* Liste sans sortie           */
-    size_t count_2_left;                    /* Quantité de présents        */
-    size_t count_2_right;                   /* Quantité de présents        */
-    size_t count_no;                        /* Quantité de présents        */
-    size_t i;                               /* Boucle de parcours          */
-    bool l2r;                               /* Détermination de catégorie  */
-
-    if (grank->count > 1)
-    {
-        exit_2_left = malloc(grank->count * sizeof(GGraphCluster *));
-        exit_2_right = malloc(grank->count * sizeof(GGraphCluster *));
-        no_exit = malloc(grank->count * sizeof(GGraphCluster *));
-
-        count_2_left = 0;
-        count_2_right = 0;
-        count_no = 0;
-
-        for (i = 0; i < grank->count; i++)
-        {
-            if (g_graph_cluster_has_exit_link(grank->clusters[i], &l2r))
-            {
-                if (l2r)
-                    exit_2_right[count_2_right++] = grank->clusters[i];
-                else
-                    exit_2_left[count_2_left++] = grank->clusters[i];
-            }
-            else
-                no_exit[count_no++] = grank->clusters[i];
-
-        }
-
-        assert((count_2_left + count_2_right + count_no) == grank->count);
-
-        qsort_r(exit_2_left, count_2_left, sizeof(GGraphCluster *),
-                (__compar_d_fn_t)g_graph_cluster_compare_by_exit, (bool []){ false });
-
-        qsort_r(exit_2_right, count_2_right, sizeof(GGraphCluster *),
-                (__compar_d_fn_t)g_graph_cluster_compare_by_exit, (bool []){ true });
-
-        grank->count = 0;
-
-        for (i = 0; i < count_2_left; i++)
-            grank->clusters[grank->count++] = exit_2_left[i];
-
-        for (i = 0; i < count_no; i++)
-            grank->clusters[grank->count++] = no_exit[i];
-
-        for (i = 0; i < count_2_right; i++)
-            grank->clusters[grank->count++] = exit_2_right[i];
-
-    }
-
-    for (i = 0; i < grank->count; i++)
-        g_graph_cluster_reorder_exit_blocks(grank->clusters[i]);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : grank = ensemble de blocs de même rang à actualiser.         *
-*                                                                             *
-*  Description : Réordonne les blocs de départ de boucle d'un ensemble.       *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void reorder_graph_rank_loop_blocks(graph_rank_t *grank)
-{
-    size_t i;                               /* Boucle de parcours #1       */
-    size_t k;                               /* Boucle de parcours #2       */
-    GGraphCluster *tmp;                     /* Stockage temporaire         */
-
-    for (i = 0; i < grank->count; i++)
-        g_graph_cluster_reorder_loop_blocks(grank->clusters[i]);
-
-    if (grank->count > 1)
-    {
-        /* Placement des départs de boucle à gauche ! */
-
-        for (i = 0; i < grank->vspaces.left_count; i++)
-        {
-            tmp = grank->vspaces.left[i]->from->owner;
-
-            for (k = 0; k < grank->count; k++)
-                if (grank->clusters[k] == tmp)
-                    break;
-
-            assert(k < grank->count);
-
-            memmove(&grank->clusters[1], &grank->clusters[0],
-                    k * sizeof(GGraphCluster *));
-
-            grank->clusters[0] = tmp;
-
-            g_graph_cluster_reorder_link_origins(tmp, true);
-
-        }
-
-        /* Placement des départs de boucle à droite ! */
-
-        for (i = 0; i < grank->vspaces.right_count; i++)
-        {
-            tmp = grank->vspaces.right[i]->from->owner;
-
-            for (k = 0; k < grank->count; k++)
-                if (grank->clusters[k] == tmp)
-                    break;
-
-            assert(k < grank->count);
-
-            memmove(&grank->clusters[k], &grank->clusters[k + 1],
-                    (grank->count - k - 1) * sizeof(GGraphCluster *));
-
-            grank->clusters[grank->count - 1] = tmp;
-
-            g_graph_cluster_reorder_link_origins(tmp, false);
-
-        }
-
-    }
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : grank  = ensemble de blocs de même rang à actualiser.        *
-*                offset = décalage à appliquer.                               *
-*                                                                             *
-*  Description : Décale vers la droite un ensemble de blocs basiques.         *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void offset_x_graph_rank(graph_rank_t *grank, gint offset)
-{
-    size_t i;                               /* Boucle de parcours          */
-
-    for (i = 0; i < grank->count; i++)
-        g_graph_cluster_offset_x(grank->clusters[i], offset);
-
-    offset_x_vspace_manager(&grank->vspaces, offset);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : grank  = ensemble de blocs de même rang à actualiser.        *
-*                needed = espace nécessaire et alloué pour les blocs.         *
-*                                                                             *
-*  Description : Détermine les abscisses des liens de boucle en place.        *
-*                                                                             *
-*  Retour      : Eventuelle marge à gauche devenue nécessaire.                *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static gint compute_loop_link_x_positions_with_graph_rank(const graph_rank_t *grank, const GtkAllocation *needed)
-{
-    gint result;                            /* Eventuelle marge à renvoyer */
-    size_t i;                               /* Boucle de parcours          */
-
-    for (i = 0; i < grank->count; i++)
-        g_graph_cluster_compute_loop_link_x_positions(grank->clusters[i]);
-
-    result = compute_loop_link_x_with_vspace_manager(&grank->vspaces, needed, false);
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : grank = ensemble de blocs de même rang à actualiser.         *
-*                base  = position ordonnée à appliquer.                       *
-*                                                                             *
-*  Description : Décale vers le bas un ensemble de blocs basiques.            *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void set_y_for_graph_rank(const graph_rank_t *grank, gint *base)
-{
-    gint max;                               /* Hauteur maximale rencontrée */
-    size_t i;                               /* Boucle de parcours          */
-    GGraphCluster *sub;                     /* Sous-ensemble traité        */
-    GtkAllocation alloc;                    /* Allocation courante         */
-
-    /* On ajoute l'espace vertical pour les lignes horizontales */
-
-    if (grank->r2l_count > grank->l2r_count)
-        max = grank->r2l_count;
-    else
-        max = grank->l2r_count;
-
-    *base += VERTICAL_MARGIN;
-
-    /**
-     * Comme les liens purement verticaux n'entrainent pas de réservation,
-     * il n'y a potentiellement pas toujours d'espace à ajouter.
-     */
-
-    if (max > 0)
-    {
-        *base += ((max - 1) * LINK_MARGIN);
-        *base += VERTICAL_MARGIN;
-    }
-
-    /* On ajoute l'espace requis pour l'affichage des blocs */
-
-    max = 0;
-
-    for (i = 0; i < grank->count; i++)
-    {
-        sub = grank->clusters[i];
-
-        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  : grank = ensemble de blocs de même rang à actualiser.         *
-*                needed  = espace nécessaire et alloué pour les blocs.        *
-*                                                                             *
-*  Description : Détermine les ordonnées de tous les liens en place.          *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void compute_loop_link_with_graph_rank(const graph_rank_t *grank, const GtkAllocation *needed)
-{
-    size_t i;                               /* Boucle de parcours          */
-
-    for (i = 0; i < grank->count; i++)
-        g_graph_cluster_compute_link_y_positions(grank->clusters[i]);
-
-    compute_loop_link_y_with_vspace_manager(&grank->vspaces, needed);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : grank = ensemble de blocs de même rang à analyser.           *
-*                block = bloc de code à retrouver.                            *
-*                                                                             *
-*  Description : Recherche le groupe de blocs avec un bloc donné comme chef.  *
-*                                                                             *
-*  Retour      : Groupe trouvé ou NULL en cas d'échec.                        *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static GGraphCluster *find_cluster_by_block_in_graph_rank(const graph_rank_t *grank, GCodeBlock *block)
-{
-    GGraphCluster *result;                  /* Trouvaille à retourner      */
-    size_t i;                               /* Boucle de parcours          */
-
-    result = NULL;
-
-    for (i = 0; i < grank->count && result == NULL; i++)
-        result = g_graph_cluster_find_by_block(grank->clusters[i], block);
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : grank  = ensemble de blocs de même rang à analyser.          *
-*                widget = composant graphique à retrouver.                    *
-*                                                                             *
-*  Description : Recherche le groupe de blocs avec un composant comme chef.   *
-*                                                                             *
-*  Retour      : Groupe trouvé ou NULL en cas d'échec.                        *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static GGraphCluster *find_cluster_by_widget_in_graph_rank(const graph_rank_t *grank, GtkWidget *widget)
-{
-    GGraphCluster *result;                  /* Trouvaille à retourner      */
-    size_t i;                               /* Boucle de parcours          */
-
-    result = NULL;
-
-    for (i = 0; i < grank->count && result == NULL; i++)
-        result = g_graph_cluster_find_by_widget(grank->clusters[i], widget);
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : grank = ensemble de blocs de même rang à analyser.           *
-*                list  = liste en cours de constitution. [OUT]                *
-*                count = taille de cette liste. [OUT]                         *
-*                                                                             *
-*  Description : Collecte tous les chefs de file de blocs de code.            *
-*                                                                             *
-*  Retour      : Liste de graphiques de blocs rassemblés.                     *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static GGraphCluster **collect_graph_ranks_clusters(const graph_rank_t *grank, GGraphCluster **list, size_t *count)
-{
-    GGraphCluster **result;                 /* Liste complétée à renvoyer  */
-    size_t i;                               /* Boucle de parcours          */
-
-    result = list;
-
-    for (i = 0; i < grank->count; i++)
-        result = g_graph_cluster_collect(grank->clusters[i], result, count);
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : grank = ensemble de blocs de même rang à analyser.           *
-*                list  = liste en cours de constitution. [OUT]                *
-*                count = taille de cette liste. [OUT]                         *
-*                                                                             *
-*  Description : Collecte tous les liens de chefs de file de blocs de code.   *
-*                                                                             *
-*  Retour      : Liste de liens graphiques de blocs rassemblés.               *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static GGraphEdge **collect_graph_ranks_cluster_edges(const graph_rank_t *grank, GGraphEdge **list, size_t *count)
-{
-    GGraphEdge **result;                    /* Liste complétée à renvoyer  */
-    size_t i;                               /* Boucle de parcours          */
-
-    result = list;
-
-    for (i = 0; i < grank->count; i++)
-        result = g_graph_cluster_collect_edges(grank->clusters[i], result, count);
-
-    return result;
-
-}
 
 
 
@@ -2178,7 +350,7 @@ GGraphCluster *g_graph_cluster_new(GCodeBlock *block, segcnt_list *highlighted,
 *                                                                             *
 ******************************************************************************/
 
-static void g_graph_cluster_reset_allocation(GGraphCluster *cluster)
+void g_graph_cluster_reset_allocation(GGraphCluster *cluster)
 {
     GtkRequisition requisition;             /* Taille à l'écran actuelle   */
     size_t i;                               /* Boucle de parcours          */
@@ -2344,7 +516,7 @@ static void g_graph_cluster_extend_vspace_manager(GGraphCluster *target, leaving
 *                                                                             *
 ******************************************************************************/
 
-static void g_graph_cluster_define_links(GGraphCluster *cluster, GHashTable *all)
+void g_graph_cluster_define_links(GGraphCluster *cluster, GHashTable *all)
 {
     size_t dcount;                          /* Nombre de liens de dest.    */
     block_link_t *links;                    /* Liens associés au bloc      */
@@ -2539,7 +711,7 @@ static void g_graph_cluster_define_links(GGraphCluster *cluster, GHashTable *all
 *                                                                             *
 ******************************************************************************/
 
-static void g_graph_cluster_setup_links(GGraphCluster *cluster)
+void g_graph_cluster_setup_links(GGraphCluster *cluster)
 {
     size_t i;                               /* Boucle de parcours #1       */
     leaving_link_t *leaving;                /* Départ de lien              */
@@ -2633,7 +805,7 @@ static void g_graph_cluster_setup_links(GGraphCluster *cluster)
 *                                                                             *
 ******************************************************************************/
 
-static void g_graph_cluster_dispatch_x(GGraphCluster *cluster)
+void g_graph_cluster_dispatch_x(GGraphCluster *cluster)
 {
     size_t i;                               /* Boucle de parcours #1       */
     leaving_link_t *straight_leaving;       /* Lien à présenter vertical   */
@@ -2786,7 +958,7 @@ static void g_graph_cluster_dispatch_x(GGraphCluster *cluster)
 *                                                                             *
 ******************************************************************************/
 
-static void g_graph_cluster_sort_incoming_links(GGraphCluster *cluster)
+void g_graph_cluster_sort_incoming_links(GGraphCluster *cluster)
 {
     size_t i;                               /* Boucle de parcours          */
 
@@ -2813,7 +985,7 @@ static void g_graph_cluster_sort_incoming_links(GGraphCluster *cluster)
 *                                                                             *
 ******************************************************************************/
 
-static size_t g_graph_cluster_find_incoming_link(const GGraphCluster *cluster, const leaving_link_t *leaving)
+size_t g_graph_cluster_find_incoming_link(const GGraphCluster *cluster, const leaving_link_t *leaving)
 {
     size_t result;                          /* Indice à retourner          */
 
@@ -2841,7 +1013,7 @@ static size_t g_graph_cluster_find_incoming_link(const GGraphCluster *cluster, c
 *                                                                             *
 ******************************************************************************/
 
-static bool g_graph_cluster_has_exit_link(GGraphCluster *cluster, bool *l2r)
+bool g_graph_cluster_has_exit_link(GGraphCluster *cluster, bool *l2r)
 {
     bool result;                            /* Bilan à retourner           */
     size_t i;                               /* Boucle de parcours          */
@@ -2891,7 +1063,7 @@ static bool g_graph_cluster_has_exit_link(GGraphCluster *cluster, bool *l2r)
 *                                                                             *
 ******************************************************************************/
 
-static int g_graph_cluster_compare_by_exit(const GGraphCluster **cluster, const GGraphCluster **other, const bool *l2r)
+int g_graph_cluster_compare_by_exit(const GGraphCluster **cluster, const GGraphCluster **other, const bool *l2r)
 {
     int result;                             /* Bilan à renvoyer            */
     size_t i;                               /* Boucle de parcours          */
@@ -2959,7 +1131,7 @@ static int g_graph_cluster_compare_by_exit(const GGraphCluster **cluster, const
 *                                                                             *
 ******************************************************************************/
 
-static void g_graph_cluster_reorder_exit_blocks(GGraphCluster *cluster)
+void g_graph_cluster_reorder_exit_blocks(GGraphCluster *cluster)
 {
     size_t i;                               /* Boucle de parcours          */
 
@@ -2981,7 +1153,7 @@ static void g_graph_cluster_reorder_exit_blocks(GGraphCluster *cluster)
 *                                                                             *
 ******************************************************************************/
 
-static void g_graph_cluster_reorder_loop_blocks(GGraphCluster *cluster)
+void g_graph_cluster_reorder_loop_blocks(GGraphCluster *cluster)
 {
     size_t i;                               /* Boucle de parcours          */
 
@@ -3005,7 +1177,7 @@ static void g_graph_cluster_reorder_loop_blocks(GGraphCluster *cluster)
 *                                                                             *
 ******************************************************************************/
 
-static void g_graph_cluster_reorder_link_origins(GGraphCluster *cluster, bool left)
+void g_graph_cluster_reorder_link_origins(GGraphCluster *cluster, bool left)
 {
     size_t i;                               /* Boucle de parcours #1       */
     leaving_link_t *origin;                 /* Autre extrémité du lien     */
@@ -3058,7 +1230,7 @@ static void g_graph_cluster_reorder_link_origins(GGraphCluster *cluster, bool le
 *                                                                             *
 ******************************************************************************/
 
-static void g_graph_cluster_offset_x(GGraphCluster *cluster, gint offset)
+void g_graph_cluster_offset_x(GGraphCluster *cluster, gint offset)
 {
     size_t i;                               /* Boucle de parcours          */
 
@@ -3085,7 +1257,7 @@ static void g_graph_cluster_offset_x(GGraphCluster *cluster, gint offset)
 *                                                                             *
 ******************************************************************************/
 
-static void g_graph_cluster_set_y(GGraphCluster *cluster, gint base)
+void g_graph_cluster_set_y(GGraphCluster *cluster, gint base)
 {
     size_t i;                               /* Boucle de parcours          */
 
@@ -3265,7 +1437,7 @@ void g_graph_cluster_place(GGraphCluster *cluster, GtkGraphDisplay *display)
 *                                                                             *
 ******************************************************************************/
 
-static gint _g_graph_cluster_compute_link_position(const GGraphCluster *cluster, size_t index, size_t half, bool odd)
+gint _g_graph_cluster_compute_link_position(const GGraphCluster *cluster, size_t index, size_t half, bool odd)
 {
     gint result;                            /* Position à retourner        */
     gint mid_x;                             /* Abscisse centrale           */
@@ -3313,7 +1485,7 @@ static gint _g_graph_cluster_compute_link_position(const GGraphCluster *cluster,
 *                                                                             *
 ******************************************************************************/
 
-static gint g_graph_cluster_compute_leaving_link_position(const GGraphCluster *cluster, size_t index)
+gint g_graph_cluster_compute_leaving_link_position(const GGraphCluster *cluster, size_t index)
 {
     gint result;                            /* Position à retourner        */
     size_t half;                            /* Indice de répartition égale */
@@ -3345,7 +1517,7 @@ static gint g_graph_cluster_compute_leaving_link_position(const GGraphCluster *c
 *                                                                             *
 ******************************************************************************/
 
-static gint g_graph_cluster_compute_incoming_link_position(const GGraphCluster *cluster, size_t index)
+gint g_graph_cluster_compute_incoming_link_position(const GGraphCluster *cluster, size_t index)
 {
     gint result;                            /* Position à retourner        */
     size_t half;                            /* Indice de répartition égale */
@@ -3441,7 +1613,7 @@ static void g_graph_cluster_insert_left_margin(GGraphCluster *cluster, gint marg
 *                                                                             *
 ******************************************************************************/
 
-static void g_graph_cluster_compute_loop_link_x_positions(GGraphCluster *cluster)
+void g_graph_cluster_compute_loop_link_x_positions(GGraphCluster *cluster)
 {
     GtkAllocation alloc;                    /* Emplacement à faire évoluer */
     gint margin;                            /* Marge à gauche éventuelle   */
@@ -3680,7 +1852,7 @@ static void g_graph_cluster_book_hspace_for_links(GGraphCluster *cluster)
 *                                                                             *
 ******************************************************************************/
 
-static void g_graph_cluster_compute_link_y_positions(GGraphCluster *cluster)
+void g_graph_cluster_compute_link_y_positions(GGraphCluster *cluster)
 {
     gint y;                                 /* Ordonnée d'application      */
     size_t i;                               /* Boucle de parcours          */
@@ -3855,7 +2027,7 @@ GGraphCluster *g_graph_cluster_find_by_widget(GGraphCluster *cluster, GtkWidget
 *                                                                             *
 ******************************************************************************/
 
-static GGraphCluster **g_graph_cluster_collect(GGraphCluster *cluster, GGraphCluster **list, size_t *count)
+GGraphCluster **g_graph_cluster_collect(GGraphCluster *cluster, GGraphCluster **list, size_t *count)
 {
     GGraphCluster **result;                 /* Liste complétée à renvoyer  */
     size_t i;                               /* Boucle de parcours          */
@@ -3887,7 +2059,7 @@ static GGraphCluster **g_graph_cluster_collect(GGraphCluster *cluster, GGraphClu
 *                                                                             *
 ******************************************************************************/
 
-static GGraphEdge **g_graph_cluster_collect_edges(GGraphCluster *cluster, GGraphEdge **list, size_t *count)
+GGraphEdge **g_graph_cluster_collect_edges(GGraphCluster *cluster, GGraphEdge **list, size_t *count)
 {
     GGraphEdge **result;                    /* Liste complétée à renvoyer  */
     size_t i;                               /* Boucle de parcours          */
diff --git a/src/gtkext/graph/hspace.c b/src/gtkext/graph/hspace.c
new file mode 100644
index 0000000..4294050
--- /dev/null
+++ b/src/gtkext/graph/hspace.c
@@ -0,0 +1,125 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * hspace.c - encadrement des espaces horizontaux réservés
+ *
+ * Copyright (C) 2019 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide 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.
+ *
+ *  Chrysalide 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 Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "hspace.h"
+
+
+#include <assert.h>
+#include <malloc.h>
+#ifndef NDEBUG
+#   include <stdbool.h>
+#endif
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : start = abscisse de départ de ligne.                         *
+*                                                                             *
+*  Description : Prépare une réservation d'espace pour ligne horizontale.     *
+*                                                                             *
+*  Retour      : Structure mise en place pour la conservation d'informations. *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+hspace_booking *create_hspace_booking(gint start)
+{
+    hspace_booking *result;                 /* Structure à retourner       */
+
+    result = malloc(sizeof(hspace_booking));
+
+    result->start = start;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : a = première réservation d'espace à comparer.                *
+*                b = seconde réservation d'espace à comparer.                 *
+*                                                                             *
+*  Description : Compare deux réservations d'espace.                          *
+*                                                                             *
+*  Retour      : Bilan de comparaison.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+int cmp_hspace_booking_r2l(const hspace_booking **a, const hspace_booking **b)
+{
+    int result;                             /* Bilan à retourner           */
+
+    if ((*a)->start > (*b)->start)
+        result = -1;
+
+    else if ((*a)->start < (*b)->start)
+        result = 1;
+
+    else
+    {
+        assert(false);
+        result = 0;
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : a = première réservation d'espace à comparer.                *
+*                b = seconde réservation d'espace à comparer.                 *
+*                                                                             *
+*  Description : Compare deux réservations d'espace.                          *
+*                                                                             *
+*  Retour      : Bilan de comparaison.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+int cmp_hspace_booking_l2r(const hspace_booking **a, const hspace_booking **b)
+{
+    int result;                             /* Bilan à retourner           */
+
+    if ((*a)->start < (*b)->start)
+        result = -1;
+
+    else if ((*a)->start > (*b)->start)
+        result = 1;
+
+    else
+    {
+        assert(false);
+        result = 0;
+    }
+
+    return result;
+
+}
diff --git a/src/gtkext/graph/hspace.h b/src/gtkext/graph/hspace.h
new file mode 100644
index 0000000..ee0b778
--- /dev/null
+++ b/src/gtkext/graph/hspace.h
@@ -0,0 +1,52 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * hspace.h - prototypes pour l'encadrement des espaces horizontaux réservés
+ *
+ * Copyright (C) 2019 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide 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.
+ *
+ *  Chrysalide 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 Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GTKEXT_GRAPH_HSPACE_H
+#define _GTKEXT_GRAPH_HSPACE_H
+
+
+#include <glib.h>
+
+
+
+/* Réservation pour les lignes horizontales */
+typedef struct _hspace_booking
+{
+    gint start;                             /* Abscisse de départ de ligne */
+    size_t index;                           /* Indice de rangée verticale  */
+
+} hspace_booking;
+
+
+/* Prépare une réservation d'espace pour ligne horizontale. */
+hspace_booking *create_hspace_booking(gint);
+
+/* Compare deux réservations d'espace. */
+int cmp_hspace_booking_r2l(const hspace_booking **, const hspace_booking **);
+
+/* Compare deux réservations d'espace. */
+int cmp_hspace_booking_l2r(const hspace_booking **, const hspace_booking **);
+
+
+
+#endif  /* _GTKEXT_GRAPH_HSPACE_H */
diff --git a/src/gtkext/graph/incoming.c b/src/gtkext/graph/incoming.c
new file mode 100644
index 0000000..8e25b8d
--- /dev/null
+++ b/src/gtkext/graph/incoming.c
@@ -0,0 +1,184 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * incoming.c - liens entrants d'un bloc de code dans une représentation graphique
+ *
+ * Copyright (C) 2019 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide 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.
+ *
+ *  Chrysalide 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 Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "incoming.h"
+
+
+#include <malloc.h>
+
+
+#include "leaving.h"
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : owner = propriétaire du bloc de rattachement.                *
+*                type  = type de lien simple attendu.                         *
+*                other = point de départ du lien formé.                       *
+*                                                                             *
+*  Description : Crée un point d'attache pour un lien entrant simple.         *
+*                                                                             *
+*  Retour      : Structure mise en place.                                     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+incoming_link_t *create_incoming_link(GGraphCluster *owner, InstructionLinkType type, leaving_link_t *other)
+{
+    incoming_link_t *result;                /* Structure à retourner       */
+    GCodeBlock *src;                        /* Bloc d'origine du lien      */
+    GCodeBlock *dst;                        /* Bloc de destination du lien */
+
+    result = malloc(sizeof(incoming_link_t));
+
+    result->owner = owner;
+
+    result->type = type;
+
+    src = g_graph_cluster_get_block(other->owner);
+    dst = g_graph_cluster_get_block(owner);
+
+    if (type == ILT_JUMP_IF_TRUE)
+        result->edge = g_graph_edge_new_true(src, dst,
+                                             &other->start[0], &other->start[1],
+                                             &result->end[0], &result->end[1]);
+
+    else if (type == ILT_JUMP_IF_FALSE)
+        result->edge = g_graph_edge_new_false(src, dst,
+                                              &other->start[0], &other->start[1],
+                                              &result->end[0], &result->end[1]);
+
+    else
+        result->edge = g_graph_edge_new(src, dst,
+                                        &other->start[0], &other->start[1],
+                                        &result->end[0], &result->end[1]);
+
+    g_object_unref(G_OBJECT(src));
+    g_object_unref(G_OBJECT(dst));
+
+    result->other = other;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : owner = propriétaire du bloc de rattachement.                *
+*                other = point de départ du lien formé.                       *
+*                                                                             *
+*  Description : Crée un point d'attache pour un lien entrant de boucle.      *
+*                                                                             *
+*  Retour      : Structure mise en place.                                     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+incoming_link_t *create_incoming_loop_link(GGraphCluster *owner, const GdkPoint *midpts, leaving_link_t *other)
+{
+    incoming_link_t *result;                /* Structure à retourner       */
+    GCodeBlock *src;                        /* Bloc d'origine du lien      */
+    GCodeBlock *dst;                        /* Bloc de destination du lien */
+
+    result = malloc(sizeof(incoming_link_t));
+
+    result->owner = owner;
+
+    result->type = ILT_LOOP;
+
+    src = g_graph_cluster_get_block(other->owner);
+    dst = g_graph_cluster_get_block(owner);
+
+    result->edge = g_graph_edge_new_loop(src, dst,
+                                         &other->start[0], &other->start[1],
+                                         &midpts[0], &midpts[1],
+                                         &result->end[0], &result->end[1]);
+
+    g_object_unref(G_OBJECT(src));
+    g_object_unref(G_OBJECT(dst));
+
+    result->other = other;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : link = structure à libérer de la mémoire.                    *
+*                                                                             *
+*  Description : Détruit un point d'attache pour un lien entrant.             *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void delete_incoming_link(incoming_link_t *link)
+{
+    free(link);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : a = premier lien entrant à comparer.                         *
+*                b = second lien entrant à comparer.                          *
+*                                                                             *
+*  Description : Compare deux liens entrants.                                 *
+*                                                                             *
+*  Retour      : Bilan de comparaison.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+int cmp_incoming_links(const incoming_link_t **a, const incoming_link_t **b)
+{
+    int result;                             /* Bilan à retourner           */
+    gint pos_a;                             /* Point de départ pour A      */
+    gint pos_b;                             /* Point de départ pour B      */
+
+    pos_a = compute_leaving_link_position((*a)->other);
+
+    pos_b = compute_leaving_link_position((*b)->other);
+
+    if (pos_a < pos_b)
+        result = -1;
+
+    else if (pos_a > pos_b)
+        result = 1;
+
+    else
+        result = 0;
+
+    return result;
+
+}
diff --git a/src/gtkext/graph/incoming.h b/src/gtkext/graph/incoming.h
new file mode 100644
index 0000000..d08eb46
--- /dev/null
+++ b/src/gtkext/graph/incoming.h
@@ -0,0 +1,67 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * incoming.h - prototypes pour les liens entrants d'un bloc de code dans une représentation graphique
+ *
+ * Copyright (C) 2019 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide 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.
+ *
+ *  Chrysalide 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 Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GTKEXT_GRAPH_INCOMING_H
+#define _GTKEXT_GRAPH_INCOMING_H
+
+
+#include "cluster.h"
+#include "edge.h"
+
+
+
+/* Depuis leaving.h : détails sur le départ d'un lien */
+typedef struct _leaving_link_t leaving_link_t;
+
+/* Définition du tracé d'un lien */
+typedef struct _incoming_link_t
+{
+    GGraphCluster *owner;                   /* Propriétaire du lien        */
+
+    InstructionLinkType type;               /* Complexité du tracé         */
+
+    const size_t *hslot;                    /* Couche horizontale réservée */
+    GdkPoint end[2];                        /* Point d'arrivée final       */
+
+    GGraphEdge *edge;                       /* Lien complet en préparation */
+
+    leaving_link_t *other;                  /* Autre extrémité du lien     */
+
+} incoming_link_t;
+
+
+/* Crée un point d'attache pour un lien entrant simple. */
+incoming_link_t *create_incoming_link(GGraphCluster *, InstructionLinkType, leaving_link_t *);
+
+/* Crée un point d'attache pour un lien entrant de boucle. */
+incoming_link_t *create_incoming_loop_link(GGraphCluster *, const GdkPoint *, leaving_link_t *);
+
+/* Détruit un point d'attache pour un lien entrant. */
+void delete_incoming_link(incoming_link_t *);
+
+/* Compare deux liens entrants. */
+int cmp_incoming_links(const incoming_link_t **, const incoming_link_t **);
+
+
+
+#endif  /* _GTKEXT_GRAPH_INCOMING_H */
diff --git a/src/gtkext/graph/leaving.c b/src/gtkext/graph/leaving.c
new file mode 100644
index 0000000..ad07f04
--- /dev/null
+++ b/src/gtkext/graph/leaving.c
@@ -0,0 +1,107 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * leaving.c - liens sortants d'un bloc de code dans une représentation graphique
+ *
+ * Copyright (C) 2019 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide 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.
+ *
+ *  Chrysalide 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 Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "leaving.h"
+
+
+#include <malloc.h>
+
+
+#include "cluster-int.h"
+#include "incoming.h"
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : owner = propriétaire du bloc de rattachement.                *
+*                index = indice dans les liens de sortie.                     *
+*                                                                             *
+*  Description : Crée un point d'attache pour un lien sortant.                *
+*                                                                             *
+*  Retour      : Structure mise en place.                                     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+leaving_link_t *create_leaving_link(GGraphCluster *owner, size_t index)
+{
+    leaving_link_t *result;                 /* Structure à retourner       */
+
+    result = malloc(sizeof(leaving_link_t));
+
+    result->owner = owner;
+
+    result->index = index;
+
+    result->straight = false;
+    result->forced_straight = false;
+    result->straight_level = SIZE_MAX;
+    result->cluster_exit = false;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : link = structure à libérer de la mémoire.                    *
+*                                                                             *
+*  Description : Détruit un point d'attache pour un lien sortant.             *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void delete_leaving_link(leaving_link_t *link)
+{
+    free(link);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : link = information sur un lien à consulter.                  *
+*                                                                             *
+*  Description : Calcule l'abscisse d'un lien à son départ d'un bloc.         *
+*                                                                             *
+*  Retour      : Abscisse à attribuer à un départ de lien.                    *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+gint compute_leaving_link_position(const leaving_link_t *link)
+{
+    gint result;                            /* Position à retourner        */
+
+    result = g_graph_cluster_compute_leaving_link_position(link->owner, link->index);
+
+    return result;
+
+}
diff --git a/src/gtkext/graph/leaving.h b/src/gtkext/graph/leaving.h
new file mode 100644
index 0000000..c91f232
--- /dev/null
+++ b/src/gtkext/graph/leaving.h
@@ -0,0 +1,66 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * leaving.h - prototypes pour les liens sortants d'un bloc de code dans une représentation graphique
+ *
+ * Copyright (C) 2019 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide 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.
+ *
+ *  Chrysalide 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 Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GTKEXT_GRAPH_LEAVING_H
+#define _GTKEXT_GRAPH_LEAVING_H
+
+
+#include "cluster.h"
+
+
+/* Depuis incoming.h : définition du tracé d'un lien */
+typedef struct _incoming_link_t incoming_link_t;
+
+/* Détails sur le départ d'un lien */
+typedef struct _leaving_link_t
+{
+    GGraphCluster *owner;                   /* Propriétaire du lien        */
+
+    GdkPoint start[2];                      /* Point de départ d'un lien   */
+    size_t index;                           /* Indice sur ligne de départ  */
+
+    bool straight;                          /* Présence d'une ligne droite */
+    bool forced_straight;                   /* Forçage de verticalité      */
+    size_t straight_level;                  /* Rang atteint en ligne droite*/
+    bool cluster_exit;                      /* Sortie du cluster d'origine */
+
+    incoming_link_t *other;                 /* Autre extrémité du lien     */
+
+} leaving_link_t;
+
+
+#define SHOULD_BE_VERTICAL(l) ((l)->straight || (l)->forced_straight || (l)->cluster_exit)
+
+
+/* Crée un point d'attache pour un lien sortant. */
+leaving_link_t *create_leaving_link(GGraphCluster *, size_t);
+
+/* Détruit un point d'attache pour un lien sortant. */
+void delete_leaving_link(leaving_link_t *);
+
+/* Calcule l'abscisse d'un lien à son départ d'un bloc. */
+gint compute_leaving_link_position(const leaving_link_t *);
+
+
+
+#endif  /* _GTKEXT_GRAPH_LEAVING_H */
diff --git a/src/gtkext/graph/rank.c b/src/gtkext/graph/rank.c
new file mode 100644
index 0000000..0fadb27
--- /dev/null
+++ b/src/gtkext/graph/rank.c
@@ -0,0 +1,914 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * rank.c - classement par rang des descendants directs
+ *
+ * Copyright (C) 2019 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide 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.
+ *
+ *  Chrysalide 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 Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "rank.h"
+
+
+#include <assert.h>
+#include <malloc.h>
+
+
+#include "cluster-int.h"
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : grank   = structure à initialiser. [OUT]                     *
+*                cluster = chef de file d'un ensemble de blocs.               *
+*                                                                             *
+*  Description : Initialise la gestion d'un ensemble de blocs de même rang.   *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void init_graph_rank(graph_rank_t *grank, GGraphCluster *cluster)
+{
+    grank->right2left = NULL;
+    grank->r2l_count = 0;
+
+    grank->left2right = NULL;
+    grank->l2r_count = 0;
+
+    grank->clusters = malloc(sizeof(GGraphCluster *));
+    grank->count = 1;
+
+    grank->clusters[0] = cluster;
+
+    init_vspace_manager(&grank->vspaces);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : grank = structure à vider.                                   *
+*                                                                             *
+*  Description : Termine la gestion d'un ensemble de blocs de même rang.      *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void exit_graph_rank(graph_rank_t *grank)
+{
+    size_t i;                               /* Boucle de parcours          */
+
+    for (i = 0; i < grank->r2l_count; i++)
+        free(grank->right2left[i]);
+
+    if (grank->right2left != NULL)
+        free(grank->right2left);
+
+    for (i = 0; i < grank->l2r_count; i++)
+        free(grank->left2right[i]);
+
+    if (grank->left2right != NULL)
+        free(grank->left2right);
+
+    assert(grank->clusters != NULL);
+
+    free(grank->clusters);
+
+    exit_vspace_manager(&grank->vspaces);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : grank = ensemble de même rang à consulter.                   *
+*                                                                             *
+*  Description : Assigne à un ensemble de blocs un emplacement initial.       *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void reset_graph_rank_allocation(const graph_rank_t *grank)
+{
+    size_t i;                               /* Boucle de parcours          */
+
+    for (i = 0; i < grank->count; i++)
+        g_graph_cluster_reset_allocation(grank->clusters[i]);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : grank = ensemble de même rang à consulter.                   *
+*                                                                             *
+*  Description : Fournit le rang d'un ensemble de blocs.                      *
+*                                                                             *
+*  Retour      : Rang d'un ensemble de blocs de même rang.                    *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+size_t get_graph_rank(const graph_rank_t *grank)
+{
+    size_t result;                          /* Rang à retourner            */
+    GCodeBlock *block;                      /* Bloc de code de référence   */
+
+    block = g_graph_cluster_get_block(grank->clusters[0]);
+
+    result = g_code_block_get_rank(block);
+
+    g_object_unref(G_OBJECT(block));
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : a = premier ensemble de même rang à comparer.                *
+*                b = second ensemble de même rang à comparer.                 *
+*                                                                             *
+*  Description : Compare deux rangées de blocs de code.                       *
+*                                                                             *
+*  Retour      : Bilan de comparaison.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+int cmp_graph_rank(const graph_rank_t *a, const graph_rank_t *b)
+{
+    int result;                             /* Bilan à retourner           */
+    size_t level_a;                         /* Niveau de l'ensemble A      */
+    size_t level_b;                         /* Niveau de l'ensemble B      */
+
+    level_a = get_graph_rank(a);
+    level_b = get_graph_rank(b);
+
+    if (level_a < level_b)
+        result = -1;
+
+    else if (level_a > level_b)
+        result = 1;
+
+    else
+        result = 0;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : grank   = structure à compléter.                             *
+*                cluster = chef de file d'un ensemble de blocs.               *
+*                                                                             *
+*  Description : Etend un ensemble de blocs de même rang.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void extend_graph_rank(graph_rank_t *grank, GGraphCluster *cluster)
+{
+    grank->count++;
+    grank->clusters = realloc(grank->clusters, sizeof(GGraphCluster *) * grank->count);
+
+    grank->clusters[grank->count - 1] = cluster;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : grank   = structure à compléter.                             *
+*                cluster = chef de file d'un ensemble de blocs.               *
+*                                                                             *
+*  Description : Détermine si un groupe de blocs contient un bloc particulier.*
+*                                                                             *
+*  Retour      : true si le chef est bien contenu, false sinon.               *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool has_graph_rank_cluster(const graph_rank_t *grank, GGraphCluster *cluster)
+{
+    bool result;                            /* Bilan à renvoyer            */
+    size_t i;                               /* Boucle de parcours          */
+
+    result = false;
+
+    for (i = 0; i < grank->count && !result; i++)
+        result = (grank->clusters[i] == cluster);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : grank    = ensemble de descendants d'un même rang.           *
+*                from     = point de départ du lien concerné.                 *
+*                to       = point d'arrivée du lien concerné.                 *
+*                pts      = points intermédiaires du tracé complet final.     *
+*                external = précise une sortie du cadre du cluster premier.   *
+*                                                                             *
+*  Description : Inscrit à l'endroit idéal une réservation d'espace latéral.  *
+*                                                                             *
+*  Retour      : true si la demande a bien été traitée.                       *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool extend_graph_rank_vspace_manager(graph_rank_t *grank, leaving_link_t *from, incoming_link_t *to, GdkPoint *pts, bool external)
+{
+    bool result;                            /* Bilan à renvoyer            */
+
+    result = has_graph_rank_cluster(grank, from->owner);
+
+    if (result)
+        extend_vspace_manager(&grank->vspaces, from, to, pts, external);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : grank = ensemble de descendants d'un même rang.              *
+*                all   = table regroupant tous les groupes créés.             *
+*                                                                             *
+*  Description : Met en place les embryons de liens nécessaires.              *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void define_graph_rank_links(const graph_rank_t *grank, GHashTable *all)
+{
+    size_t i;                               /* Boucle de parcours          */
+
+    for (i = 0; i < grank->count; i++)
+        g_graph_cluster_define_links(grank->clusters[i], all);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : grank = ensemble de descendants d'un même rang.              *
+*                                                                             *
+*  Description : Repère les liens marquants à destination d'autres blocs.     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void setup_graph_rank_links(const graph_rank_t *grank)
+{
+    size_t i;                               /* Boucle de parcours          */
+
+    for (i = 0; i < grank->count; i++)
+        g_graph_cluster_setup_links(grank->clusters[i]);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : grank = ensemble de descendants d'un même rang.              *
+*                last  = indique s'il s'agit du dernier étage de l'ensemble.  *
+*                alloc = emplacement idéal pour l'affichage. [OUT]            *
+*                                                                             *
+*  Description : Détermine l'emplacement requis d'un ensemble de blocs.       *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void compute_graph_rank_needed_alloc(const graph_rank_t *grank, bool last, GtkAllocation *alloc)
+{
+    GtkAllocation needed;                   /* Taille requise              */
+
+    switch (grank->count)
+    {
+        case 1:
+
+            g_graph_cluster_compute_needed_alloc(grank->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 (last)
+            {
+                if ((needed.y + needed.height) > (alloc->y + alloc->height))
+                    alloc->height += needed.y + needed.height - alloc->y - alloc->height;
+            }
+
+            break;
+
+        default:
+
+            assert(grank->count >= 2);
+
+            g_graph_cluster_compute_needed_alloc(grank->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 (last)
+            {
+                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(grank->clusters[grank->count - 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 (last)
+            {
+                if ((needed.y + needed.height) > (alloc->y + alloc->height))
+                    alloc->height += needed.y + needed.height - alloc->y - alloc->height;
+            }
+
+            break;
+
+    }
+
+    compute_vspace_manager_needed_alloc(&grank->vspaces, false, alloc);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : iter = début de la boucle de parcours.                       *
+*                loop = nombre d'itérations à mener.                          *
+*                base = position de base sur l'axe des abscisses.             *
+*                dir  = direction du parcours.                                *
+*                                                                             *
+*  Description : Affine l'abscisse d'un ensemble de blocs de même rang.       *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void _place_graph_rank_clusters(GGraphCluster **iter, size_t loop, gint base, int dir)
+{
+    size_t i;                               /* Boucle de parcours          */
+    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);
+
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : grank = ensemble de blocs de même rang à manipuler.          *
+*                                                                             *
+*  Description : Organise la disposition d'un ensemble de blocs basiques.     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void dispatch_x_graph_rank(const graph_rank_t *grank)
+{
+    size_t mid;                             /* Position centrale de départ */
+    GtkAllocation alloc;                    /* Emplacement de cluster      */
+    gint start;                             /* Position initiale de départ */
+
+    if (grank->count % 2 == 1)
+    {
+        if (grank->count > 1)
+        {
+            mid = grank->count / 2;
+
+            g_graph_cluster_get_allocation(grank->clusters[mid], &alloc);
+
+            start = alloc.x - HORIZONTAL_MARGIN;
+
+            _place_graph_rank_clusters(grank->clusters + mid - 1, mid, start, -1);
+
+            start *= -1;
+
+            _place_graph_rank_clusters(grank->clusters + mid + 1, mid, start, 1);
+
+        }
+
+        else
+            g_graph_cluster_dispatch_x(grank->clusters[0]);
+
+    }
+
+    else
+    {
+        mid = grank->count / 2 - 1;
+
+        start = - HORIZONTAL_MARGIN / 2;
+
+        _place_graph_rank_clusters(grank->clusters + mid, mid + 1, start, -1);
+
+        start *= -1;
+
+        _place_graph_rank_clusters(grank->clusters + mid + 1, mid + 1, start, 1);
+
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : grank  = ensemble de blocs de même rang à actualiser.        *
+*                                                                             *
+*  Description : Réorganise au besoin les liens entrants un ensemble de blocs.*
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void sort_graph_rank_incoming_links(graph_rank_t *grank)
+{
+    size_t i;                               /* Boucle de parcours          */
+
+    for (i = 0; i < grank->count; i++)
+        g_graph_cluster_sort_incoming_links(grank->clusters[i]);
+
+    sort_incoming_links_for_vspace_manager(&grank->vspaces);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : grank = ensemble de blocs de même rang à actualiser.         *
+*                                                                             *
+*  Description : Réordonne les blocs sortant d'un ensemble.                   *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void reorder_graph_rank_exit_blocks(graph_rank_t *grank)
+{
+    GGraphCluster **exit_2_left;            /* Liste avec sortie à gauche  */
+    GGraphCluster **exit_2_right;           /* Liste avec sortie à droite  */
+    GGraphCluster **no_exit;                /* Liste sans sortie           */
+    size_t count_2_left;                    /* Quantité de présents        */
+    size_t count_2_right;                   /* Quantité de présents        */
+    size_t count_no;                        /* Quantité de présents        */
+    size_t i;                               /* Boucle de parcours          */
+    bool l2r;                               /* Détermination de catégorie  */
+
+    if (grank->count > 1)
+    {
+        exit_2_left = malloc(grank->count * sizeof(GGraphCluster *));
+        exit_2_right = malloc(grank->count * sizeof(GGraphCluster *));
+        no_exit = malloc(grank->count * sizeof(GGraphCluster *));
+
+        count_2_left = 0;
+        count_2_right = 0;
+        count_no = 0;
+
+        for (i = 0; i < grank->count; i++)
+        {
+            if (g_graph_cluster_has_exit_link(grank->clusters[i], &l2r))
+            {
+                if (l2r)
+                    exit_2_right[count_2_right++] = grank->clusters[i];
+                else
+                    exit_2_left[count_2_left++] = grank->clusters[i];
+            }
+            else
+                no_exit[count_no++] = grank->clusters[i];
+
+        }
+
+        assert((count_2_left + count_2_right + count_no) == grank->count);
+
+        qsort_r(exit_2_left, count_2_left, sizeof(GGraphCluster *),
+                (__compar_d_fn_t)g_graph_cluster_compare_by_exit, (bool []){ false });
+
+        qsort_r(exit_2_right, count_2_right, sizeof(GGraphCluster *),
+                (__compar_d_fn_t)g_graph_cluster_compare_by_exit, (bool []){ true });
+
+        grank->count = 0;
+
+        for (i = 0; i < count_2_left; i++)
+            grank->clusters[grank->count++] = exit_2_left[i];
+
+        for (i = 0; i < count_no; i++)
+            grank->clusters[grank->count++] = no_exit[i];
+
+        for (i = 0; i < count_2_right; i++)
+            grank->clusters[grank->count++] = exit_2_right[i];
+
+    }
+
+    for (i = 0; i < grank->count; i++)
+        g_graph_cluster_reorder_exit_blocks(grank->clusters[i]);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : grank = ensemble de blocs de même rang à actualiser.         *
+*                                                                             *
+*  Description : Réordonne les blocs de départ de boucle d'un ensemble.       *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void reorder_graph_rank_loop_blocks(graph_rank_t *grank)
+{
+    size_t i;                               /* Boucle de parcours #1       */
+    size_t k;                               /* Boucle de parcours #2       */
+    GGraphCluster *tmp;                     /* Stockage temporaire         */
+
+    for (i = 0; i < grank->count; i++)
+        g_graph_cluster_reorder_loop_blocks(grank->clusters[i]);
+
+    if (grank->count > 1)
+    {
+        /* Placement des départs de boucle à gauche ! */
+
+        for (i = 0; i < grank->vspaces.left_count; i++)
+        {
+            tmp = grank->vspaces.left[i]->from->owner;
+
+            for (k = 0; k < grank->count; k++)
+                if (grank->clusters[k] == tmp)
+                    break;
+
+            assert(k < grank->count);
+
+            memmove(&grank->clusters[1], &grank->clusters[0],
+                    k * sizeof(GGraphCluster *));
+
+            grank->clusters[0] = tmp;
+
+            g_graph_cluster_reorder_link_origins(tmp, true);
+
+        }
+
+        /* Placement des départs de boucle à droite ! */
+
+        for (i = 0; i < grank->vspaces.right_count; i++)
+        {
+            tmp = grank->vspaces.right[i]->from->owner;
+
+            for (k = 0; k < grank->count; k++)
+                if (grank->clusters[k] == tmp)
+                    break;
+
+            assert(k < grank->count);
+
+            memmove(&grank->clusters[k], &grank->clusters[k + 1],
+                    (grank->count - k - 1) * sizeof(GGraphCluster *));
+
+            grank->clusters[grank->count - 1] = tmp;
+
+            g_graph_cluster_reorder_link_origins(tmp, false);
+
+        }
+
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : grank  = ensemble de blocs de même rang à actualiser.        *
+*                offset = décalage à appliquer.                               *
+*                                                                             *
+*  Description : Décale vers la droite un ensemble de blocs basiques.         *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void offset_x_graph_rank(graph_rank_t *grank, gint offset)
+{
+    size_t i;                               /* Boucle de parcours          */
+
+    for (i = 0; i < grank->count; i++)
+        g_graph_cluster_offset_x(grank->clusters[i], offset);
+
+    offset_x_vspace_manager(&grank->vspaces, offset);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : grank  = ensemble de blocs de même rang à actualiser.        *
+*                needed = espace nécessaire et alloué pour les blocs.         *
+*                                                                             *
+*  Description : Détermine les abscisses des liens de boucle en place.        *
+*                                                                             *
+*  Retour      : Eventuelle marge à gauche devenue nécessaire.                *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+gint compute_loop_link_x_positions_with_graph_rank(const graph_rank_t *grank, const GtkAllocation *needed)
+{
+    gint result;                            /* Eventuelle marge à renvoyer */
+    size_t i;                               /* Boucle de parcours          */
+
+    for (i = 0; i < grank->count; i++)
+        g_graph_cluster_compute_loop_link_x_positions(grank->clusters[i]);
+
+    result = compute_loop_link_x_with_vspace_manager(&grank->vspaces, needed, false);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : grank = ensemble de blocs de même rang à actualiser.         *
+*                base  = position ordonnée à appliquer.                       *
+*                                                                             *
+*  Description : Décale vers le bas un ensemble de blocs basiques.            *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void set_y_for_graph_rank(const graph_rank_t *grank, gint *base)
+{
+    gint max;                               /* Hauteur maximale rencontrée */
+    size_t i;                               /* Boucle de parcours          */
+    GGraphCluster *sub;                     /* Sous-ensemble traité        */
+    GtkAllocation alloc;                    /* Allocation courante         */
+
+    /* On ajoute l'espace vertical pour les lignes horizontales */
+
+    if (grank->r2l_count > grank->l2r_count)
+        max = grank->r2l_count;
+    else
+        max = grank->l2r_count;
+
+    *base += VERTICAL_MARGIN;
+
+    /**
+     * Comme les liens purement verticaux n'entrainent pas de réservation,
+     * il n'y a potentiellement pas toujours d'espace à ajouter.
+     */
+
+    if (max > 0)
+    {
+        *base += ((max - 1) * LINK_MARGIN);
+        *base += VERTICAL_MARGIN;
+    }
+
+    /* On ajoute l'espace requis pour l'affichage des blocs */
+
+    max = 0;
+
+    for (i = 0; i < grank->count; i++)
+    {
+        sub = grank->clusters[i];
+
+        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  : grank = ensemble de blocs de même rang à actualiser.         *
+*                needed  = espace nécessaire et alloué pour les blocs.        *
+*                                                                             *
+*  Description : Détermine les ordonnées de tous les liens en place.          *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void compute_loop_link_with_graph_rank(const graph_rank_t *grank, const GtkAllocation *needed)
+{
+    size_t i;                               /* Boucle de parcours          */
+
+    for (i = 0; i < grank->count; i++)
+        g_graph_cluster_compute_link_y_positions(grank->clusters[i]);
+
+    compute_loop_link_y_with_vspace_manager(&grank->vspaces, needed);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : grank = ensemble de blocs de même rang à analyser.           *
+*                block = bloc de code à retrouver.                            *
+*                                                                             *
+*  Description : Recherche le groupe de blocs avec un bloc donné comme chef.  *
+*                                                                             *
+*  Retour      : Groupe trouvé ou NULL en cas d'échec.                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GGraphCluster *find_cluster_by_block_in_graph_rank(const graph_rank_t *grank, GCodeBlock *block)
+{
+    GGraphCluster *result;                  /* Trouvaille à retourner      */
+    size_t i;                               /* Boucle de parcours          */
+
+    result = NULL;
+
+    for (i = 0; i < grank->count && result == NULL; i++)
+        result = g_graph_cluster_find_by_block(grank->clusters[i], block);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : grank  = ensemble de blocs de même rang à analyser.          *
+*                widget = composant graphique à retrouver.                    *
+*                                                                             *
+*  Description : Recherche le groupe de blocs avec un composant comme chef.   *
+*                                                                             *
+*  Retour      : Groupe trouvé ou NULL en cas d'échec.                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GGraphCluster *find_cluster_by_widget_in_graph_rank(const graph_rank_t *grank, GtkWidget *widget)
+{
+    GGraphCluster *result;                  /* Trouvaille à retourner      */
+    size_t i;                               /* Boucle de parcours          */
+
+    result = NULL;
+
+    for (i = 0; i < grank->count && result == NULL; i++)
+        result = g_graph_cluster_find_by_widget(grank->clusters[i], widget);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : grank = ensemble de blocs de même rang à analyser.           *
+*                list  = liste en cours de constitution. [OUT]                *
+*                count = taille de cette liste. [OUT]                         *
+*                                                                             *
+*  Description : Collecte tous les chefs de file de blocs de code.            *
+*                                                                             *
+*  Retour      : Liste de graphiques de blocs rassemblés.                     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GGraphCluster **collect_graph_ranks_clusters(const graph_rank_t *grank, GGraphCluster **list, size_t *count)
+{
+    GGraphCluster **result;                 /* Liste complétée à renvoyer  */
+    size_t i;                               /* Boucle de parcours          */
+
+    result = list;
+
+    for (i = 0; i < grank->count; i++)
+        result = g_graph_cluster_collect(grank->clusters[i], result, count);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : grank = ensemble de blocs de même rang à analyser.           *
+*                list  = liste en cours de constitution. [OUT]                *
+*                count = taille de cette liste. [OUT]                         *
+*                                                                             *
+*  Description : Collecte tous les liens de chefs de file de blocs de code.   *
+*                                                                             *
+*  Retour      : Liste de liens graphiques de blocs rassemblés.               *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GGraphEdge **collect_graph_ranks_cluster_edges(const graph_rank_t *grank, GGraphEdge **list, size_t *count)
+{
+    GGraphEdge **result;                    /* Liste complétée à renvoyer  */
+    size_t i;                               /* Boucle de parcours          */
+
+    result = list;
+
+    for (i = 0; i < grank->count; i++)
+        result = g_graph_cluster_collect_edges(grank->clusters[i], result, count);
+
+    return result;
+
+}
diff --git a/src/gtkext/graph/rank.h b/src/gtkext/graph/rank.h
new file mode 100644
index 0000000..1a149fc
--- /dev/null
+++ b/src/gtkext/graph/rank.h
@@ -0,0 +1,126 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * rank.h - prototypes pour le classement par rang des descendants directs
+ *
+ * Copyright (C) 2019 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide 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.
+ *
+ *  Chrysalide 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 Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GTKEXT_GRAPH_RANK_H
+#define _GTKEXT_GRAPH_RANK_H
+
+
+#include "cluster.h"
+#include "edge.h"
+#include "hspace.h"
+#include "vspace.h"
+
+
+
+/* Découpage vertical */
+typedef struct _graph_rank_t
+{
+    hspace_booking **right2left;            /* Réservations de D -> G      */
+    size_t r2l_count;                       /* Quantité de ces réservations*/
+
+    hspace_booking **left2right;            /* Réservations de G -> D      */
+    size_t l2r_count;                       /* Quantité de ces réservations*/
+
+    GGraphCluster **clusters;               /* Ensembles de blocs          */
+    size_t count;                           /* Nombre de ces ensembles     */
+
+    vspace_manager_t vspaces;               /* Gestion des liens latéraux  */
+
+} graph_rank_t;
+
+
+/* Initialise la gestion d'un ensemble de blocs de même rang. */
+void init_graph_rank(graph_rank_t *, GGraphCluster *);
+
+/* Termine la gestion d'un ensemble de blocs de même rang. */
+void exit_graph_rank(graph_rank_t *);
+
+/* Assigne à un ensemble de blocs un emplacement initial. */
+void reset_graph_rank_allocation(const graph_rank_t *);
+
+/* Fournit le rang d'un ensemble de blocs. */
+size_t get_graph_rank(const graph_rank_t *);
+
+/* Compare deux rangées de blocs de code. */
+int cmp_graph_rank(const graph_rank_t *, const graph_rank_t *);
+
+/* Etend un ensemble de blocs de même rang. */
+void extend_graph_rank(graph_rank_t *, GGraphCluster *);
+
+/* Détermine si un groupe de blocs contient un bloc particulier. */
+bool has_graph_rank_cluster(const graph_rank_t *, GGraphCluster *);
+
+/* Inscrit à l'endroit idéal une réservation d'espace latéral. */
+bool extend_graph_rank_vspace_manager(graph_rank_t *, leaving_link_t *, incoming_link_t *, GdkPoint *, bool);
+
+/* Met en place les embryons de liens nécessaires. */
+void define_graph_rank_links(const graph_rank_t *, GHashTable *);
+
+/* Repère les liens marquants à destination d'autres blocs. */
+void setup_graph_rank_links(const graph_rank_t *);
+
+/* Détermine l'emplacement requis d'un ensemble de blocs. */
+void compute_graph_rank_needed_alloc(const graph_rank_t *, bool, GtkAllocation *);
+
+/* Affine l'abscisse d'un ensemble de blocs de même rang. */
+void _place_graph_rank_clusters(GGraphCluster **, size_t, gint, int);
+
+/* Organise la disposition d'un ensemble de blocs basiques. */
+void dispatch_x_graph_rank(const graph_rank_t *);
+
+/* Réorganise au besoin les liens entrants un ensemble de blocs. */
+void sort_graph_rank_incoming_links(graph_rank_t *);
+
+/* Réordonne les blocs sortant d'un ensemble. */
+void reorder_graph_rank_exit_blocks(graph_rank_t *);
+
+/* Réordonne les blocs de départ de boucle d'un ensemble. */
+void reorder_graph_rank_loop_blocks(graph_rank_t *);
+
+/* Décale vers la droite un ensemble de blocs basiques. */
+void offset_x_graph_rank(graph_rank_t *, gint);
+
+/* Détermine les abscisses des liens de boucle en place. */
+gint compute_loop_link_x_positions_with_graph_rank(const graph_rank_t *, const GtkAllocation *);
+
+/* Décale vers le bas un ensemble de blocs basiques. */
+void set_y_for_graph_rank(const graph_rank_t *, gint *);
+
+/* Détermine les ordonnées de tous les liens en place. */
+void compute_loop_link_with_graph_rank(const graph_rank_t *, const GtkAllocation *);
+
+/* Recherche le groupe de blocs avec un bloc donné comme chef. */
+GGraphCluster *find_cluster_by_block_in_graph_rank(const graph_rank_t *, GCodeBlock *);
+
+/* Recherche le groupe de blocs avec un composant comme chef. */
+GGraphCluster *find_cluster_by_widget_in_graph_rank(const graph_rank_t *, GtkWidget *);
+
+/* Collecte tous les chefs de file de blocs de code. */
+GGraphCluster **collect_graph_ranks_clusters(const graph_rank_t *, GGraphCluster **, size_t *);
+
+/* Collecte tous les liens de chefs de file de blocs de code. */
+GGraphEdge **collect_graph_ranks_cluster_edges(const graph_rank_t *, GGraphEdge **, size_t *);
+
+
+
+#endif  /* _GTKEXT_GRAPH_RANK_H */
diff --git a/src/gtkext/graph/vspace.c b/src/gtkext/graph/vspace.c
new file mode 100644
index 0000000..8327759
--- /dev/null
+++ b/src/gtkext/graph/vspace.c
@@ -0,0 +1,374 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * vspace.c - encadrement des espaces verticaux réservés
+ *
+ * Copyright (C) 2019 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide 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.
+ *
+ *  Chrysalide 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 Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "vspace.h"
+
+
+#include <malloc.h>
+
+
+#include "cluster-int.h"
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : manager = structure à initialiser.                           *
+*                                                                             *
+*  Description : Initialise les réservations liens verticaux.                 *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void init_vspace_manager(vspace_manager_t *manager)
+{
+    manager->pending = NULL;
+    manager->pending_count = 0;
+
+    manager->left = NULL;
+    manager->left_count = 0;
+
+    manager->right = NULL;
+    manager->right_count = 0;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : manager = structure à vider.                                 *
+*                                                                             *
+*  Description : Termine les réservations liens verticaux.                    *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void exit_vspace_manager(vspace_manager_t *manager)
+{
+    size_t i;                               /* Boucle de parcours          */
+
+    for (i = 0; i < manager->pending_count; i++)
+        free(manager->pending[i].pts);
+
+    if (manager->pending != NULL)
+        free(manager->pending);
+
+    if (manager->left != NULL)
+        free(manager->left);
+
+    if (manager->right != NULL)
+        free(manager->right);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : manager  = structure à compléter.                            *
+*                from     = point de départ du lien concerné.                 *
+*                to       = point d'arrivée du lien concerné.                 *
+*                pts      = points intermédiaires du tracé complet final.     *
+*                external = précise une sortie du cadre du cluster premier.   *
+*                                                                             *
+*  Description : Inscrit une nouvelle réservation d'espace latéral.           *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void extend_vspace_manager(vspace_manager_t *manager, leaving_link_t *from, incoming_link_t *to, GdkPoint *pts, bool external)
+{
+    vspace_booking_t *new;                  /* Réservation à constituer    */
+
+    manager->pending = realloc(manager->pending, ++manager->pending_count * sizeof(vspace_booking_t));
+
+    new = &manager->pending[manager->pending_count - 1];
+
+    new->from = from;
+    new->to = to;
+
+    new->pts = pts;
+
+    new->external = external;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : manager  = gestion des espaces latéraux à consulter.         *
+*                external = précise une sortie du cadre du cluster premier.   *
+*                alloc    = emplacement idéal pour l'affichage. [OUT]         *
+*                                                                             *
+*  Description : Détermine l'emplacement requis pour les espaces latéraux.    *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void compute_vspace_manager_needed_alloc(const vspace_manager_t *manager, bool external, GtkAllocation *alloc)
+{
+    gint width;                             /* Largeur supplémentaire      */
+    size_t count;                           /* Nombre de liens retenus     */
+    size_t i;                               /* Boucle de parcours          */
+
+    width = 0;
+
+    /* Extension de la largeur, à gauche */
+
+    count = 0;
+
+    for (i = 0; i < manager->left_count; i++)
+        if (manager->left[i]->external == external)
+            count++;
+
+    width += count * LINK_MARGIN;
+
+    alloc->x -= width;
+
+    /* Extension de la largeur, à droite */
+
+    count = 0;
+
+    for (i = 0; i < manager->right_count; i++)
+        if (manager->right[i]->external == external)
+            count++;
+
+    width += count * LINK_MARGIN;
+
+    alloc->width += width;
+
+    /* Extension de la hauteur */
+
+    if (!external)
+        alloc->height += manager->pending_count * VERTICAL_MARGIN;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : manager = gestion d'espaces latéraux à manipuler.            *
+*                                                                             *
+*  Description : Réorganise au besoin les liens de boucle entre blocs.        *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void sort_incoming_links_for_vspace_manager(vspace_manager_t *manager)
+{
+    size_t i;                               /* Boucle de parcours          */
+    vspace_booking_t *pending;              /* Elément traité              */
+    gint x1;                                /* Abscisse de départ de lien  */
+    size_t idx;                             /* Indice du lien entrant      */
+    gint x2;                                /* Abscisse d'arrivée de lien  */
+    bool for_left;                          /* Répartition par la gauche ? */
+
+    for (i = 0; i < manager->pending_count; i++)
+    {
+        pending = &manager->pending[i];
+
+        x1 = g_graph_cluster_compute_leaving_link_position(pending->from->owner, pending->from->index);
+
+        idx = g_graph_cluster_find_incoming_link(pending->to->owner, pending->from);
+
+        x2 = g_graph_cluster_compute_incoming_link_position(pending->to->owner, idx);
+
+        /**
+         * Prise en compte d'une boucle while (1);
+         */
+        if (pending->from->owner == pending->to->owner)
+            for_left = (x2 < x1);
+        else
+            for_left = (x1 < x2);
+
+        if (for_left)
+        {
+            manager->left = realloc(manager->left, ++manager->left_count * sizeof(vspace_booking_t *));
+            manager->left[manager->left_count - 1] = pending;
+        }
+        else
+        {
+            manager->right = realloc(manager->right, ++manager->right_count * sizeof(vspace_booking_t *));
+            manager->right[manager->right_count - 1] = pending;
+        }
+
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : manager = structure à actualiser.                            *
+*                offset = décalage à appliquer.                               *
+*                                                                             *
+*  Description : Décale vers la droite un ensemble de points.                 *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void offset_x_vspace_manager(vspace_manager_t *manager, gint offset)
+{
+    size_t i;                               /* Boucle de parcours          */
+    vspace_booking_t *booking;              /* Réservation à traiter       */
+
+    for (i = 0; i < manager->left_count; i++)
+    {
+        booking = manager->left[i];
+
+        booking->pts[0].x += offset;
+        booking->pts[1].x += offset;
+
+    }
+
+    for (i = 0; i < manager->right_count; i++)
+    {
+        booking = manager->right[i];
+
+        booking->pts[0].x += offset;
+        booking->pts[1].x += offset;
+
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : manager  = structure à consulter.                            *
+*                needed   = espace nécessaire et alloué pour les blocs.       *
+*                external = précise une sortie du cadre du cluster premier.   *
+*                                                                             *
+*  Description : Détermine les abscisses de tous les liens en place.          *
+*                                                                             *
+*  Retour      : Eventuelle marge à gauche devenue nécessaire.                *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+gint compute_loop_link_x_with_vspace_manager(const vspace_manager_t *manager, const GtkAllocation *needed, bool external)
+{
+    gint result;                            /* Eventuelle marge à renvoyer */
+    size_t count;                           /* Quantité de liens traités   */
+    size_t i;                               /* Boucle de parcours          */
+    vspace_booking_t *booking;              /* Réservation à traiter       */
+    gint x;                                 /* Position à appliquer        */
+
+    count = 0;
+
+    for (i = 0; i < manager->left_count; i++)
+    {
+        booking = manager->left[i];
+
+        if (booking->external != external)
+            continue;
+
+        x = ++count * LINK_MARGIN;
+
+        booking->pts[0].x = needed->x - x;
+        booking->pts[1].x = needed->x - x;
+
+    }
+
+    result = count * LINK_MARGIN;
+
+    count = 0;
+
+    for (i = 0; i < manager->right_count; i++)
+    {
+        booking = manager->right[i];
+
+        if (booking->external != external)
+            continue;
+
+        x = ++count * LINK_MARGIN;
+
+        booking->pts[0].x = needed->x + needed->width + x;
+        booking->pts[1].x = needed->x + needed->width + x;
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : manager = structure à consulter.                             *
+*                needed  = espace nécessaire et alloué pour les blocs.        *
+*                                                                             *
+*  Description : Détermine les ordonnées de tous les liens en place.          *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void compute_loop_link_y_with_vspace_manager(const vspace_manager_t *manager, const GtkAllocation *needed)
+{
+    gint real_bottom;                       /* Point de départ réel        */
+    size_t i;                               /* Boucle de parcours          */
+    vspace_booking_t *booking;              /* Réservation à traiter       */
+
+    real_bottom = needed->y + needed->height - manager->pending_count * VERTICAL_MARGIN;
+
+    for (i = 0; i < manager->pending_count; i++)
+    {
+        booking = &manager->pending[i];
+
+        /**
+         * On corrige le raccourci pris sans distinction de type de lien dans
+         * la fonction g_graph_cluster_compute_link_y_positions().
+         */
+
+        booking->from->start[1].y = real_bottom +  (i + 1) * VERTICAL_MARGIN;
+
+        /* Définition de l'ordonnée des points du lien */
+
+        booking->pts[0].y = booking->from->start[1].y;
+
+        booking->pts[1].y = booking->to->end[0].y;
+
+    }
+
+}
diff --git a/src/gtkext/graph/vspace.h b/src/gtkext/graph/vspace.h
new file mode 100644
index 0000000..de83141
--- /dev/null
+++ b/src/gtkext/graph/vspace.h
@@ -0,0 +1,86 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * vspace.h - prototypes pour l'encadrement des espaces verticaux réservés
+ *
+ * Copyright (C) 2019 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide 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.
+ *
+ *  Chrysalide 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 Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GTKEXT_GRAPH_VSPACE_H
+#define _GTKEXT_GRAPH_VSPACE_H
+
+
+#include "incoming.h"
+#include "leaving.h"
+
+
+
+/* Réservations d'espaces latéraux */
+typedef struct _vspace_booking_t
+{
+    leaving_link_t *from;                   /* Bloc de départ du lien      */
+    incoming_link_t *to;                    /* Bloc d'arrivée du lien      */
+
+    GdkPoint *pts;                          /* Coordonnées des points      */
+
+    bool external;                          /* Lien vers un cluster parent */
+
+} vspace_booking_t;
+
+/* Réservations d'espaces latéraux */
+typedef struct _vspace_manager_t
+{
+    vspace_booking_t *pending;              /* Besoins exprimés            */
+    size_t pending_count;                   /* Nombre de ces besoins       */
+
+    vspace_booking_t **left;                /* Lignes disposées à gauche   */
+    size_t left_count;                      /* Quantité de ces lignes      */
+
+    vspace_booking_t **right;               /* Lignes disposées à droite  */
+    size_t right_count;                     /* Quantité de ces lignes      */
+
+} vspace_manager_t;
+
+
+/* Initialise les réservations liens verticaux. */
+void init_vspace_manager(vspace_manager_t *);
+
+/* Termine les réservations liens verticaux. */
+void exit_vspace_manager(vspace_manager_t *);
+
+/* Inscrit une nouvelle réservation d'espace latéral. */
+void extend_vspace_manager(vspace_manager_t *, leaving_link_t *, incoming_link_t *, GdkPoint *, bool);
+
+/* Détermine l'emplacement requis pour les espaces latéraux. */
+void compute_vspace_manager_needed_alloc(const vspace_manager_t *, bool, GtkAllocation *);
+
+/* Réorganise au besoin les liens de boucle entre blocs. */
+void sort_incoming_links_for_vspace_manager(vspace_manager_t *);
+
+/* Décale vers la droite un ensemble de points. */
+void offset_x_vspace_manager(vspace_manager_t *, gint);
+
+/* Détermine les abscisses de tous les liens en place. */
+gint compute_loop_link_x_with_vspace_manager(const vspace_manager_t *, const GtkAllocation *, bool);
+
+/* Détermine les ordonnées de tous les liens en place. */
+void compute_loop_link_y_with_vspace_manager(const vspace_manager_t *, const GtkAllocation *);
+
+
+
+#endif  /* _GTKEXT_GRAPH_VSPACE_H */
-- 
cgit v0.11.2-87-g4458