From 6cfa350c21c1e54cf9c597d92a9ea3d1aab01d78 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Fri, 3 Apr 2015 13:10:42 +0000
Subject: Tried to show basic blocks in the graphic view again.

git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@499 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
---
 ChangeLog                     |  28 +++++++
 src/analysis/disass/output.c  |   5 +-
 src/glibext/gcodebuffer.c     | 133 ++++++++++++++++++++++++++----
 src/glibext/gcodebuffer.h     |   4 +-
 src/gtkext/graph/layout.c     |  15 +++-
 src/gtkext/graph/node.c       |  16 ++--
 src/gtkext/graph/node.h       |   4 +-
 src/gtkext/graph/nodes/flow.c | 144 ++++++++++++++++++++++++++++----
 src/gtkext/gtkbufferview.c    |  35 ++++++--
 src/gtkext/gtkgraphview.c     | 188 +++++++++++++++++++++++++++---------------
 src/gtkext/gtkviewpanel-int.h |   5 +-
 src/gtkext/gtkviewpanel.c     |  14 ++--
 src/gui/menus/view.c          |   6 +-
 13 files changed, 463 insertions(+), 134 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index cbc0d57..f5359b5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,31 @@
+15-04-03  Cyrille Bagard <nocbos@gmail.com>
+
+	* src/analysis/disass/output.c:
+	Set an empty size for lines showing a routine label.
+
+	* src/glibext/gcodebuffer.c:
+	* src/glibext/gcodebuffer.h:
+	Rewrite restrictions for buffer views using the new vmpa_t type.
+
+	* src/gtkext/graph/layout.c:
+	* src/gtkext/graph/node.c:
+	* src/gtkext/graph/node.h:
+	Update code.
+
+	* src/gtkext/graph/nodes/flow.c:
+	Select only meaningful link when building flow entries/exits.
+
+	* src/gtkext/gtkbufferview.c:
+	Assign a temporary fake size to the widget.
+
+	* src/gtkext/gtkgraphview.c:
+	* src/gtkext/gtkviewpanel.c:
+	* src/gtkext/gtkviewpanel-int.h:
+	Try to show basic blocks in the graphic view again.
+
+	* src/gui/menus/view.c:
+	Update old code.
+
 15-04-01  Cyrille Bagard <nocbos@gmail.com>
 
 	* src/analysis/disass/macro.c:
diff --git a/src/analysis/disass/output.c b/src/analysis/disass/output.c
index f1e8a3b..edd6843 100644
--- a/src/analysis/disass/output.c
+++ b/src/analysis/disass/output.c
@@ -87,6 +87,7 @@ void print_disassembled_instructions(GCodeBuffer *buffer, const GExeFormat *form
     int compared;                           /* Bilan d'une comparaison     */
 
     const char *label;                      /* Etiquette ciblant un symbole*/
+    mrange_t range;                         /* Couverture sans surface     */
 
     GDbComment *comment;                    /* Commentaire à ajouter       */
 
@@ -216,7 +217,9 @@ void print_disassembled_instructions(GCodeBuffer *buffer, const GExeFormat *form
 
                 if (label != NULL)
                 {
-                    line = g_code_buffer_append_new_line(buffer, g_binary_symbol_get_range(symbols[sym_index]));
+                    init_mrange(&range, get_mrange_addr(g_binary_symbol_get_range(symbols[sym_index])), 0);
+
+                    line = g_code_buffer_append_new_line(buffer, &range);
                     g_buffer_line_fill_mrange(line, msize, msize);
 
                     g_buffer_line_start_merge_at(line, BLC_ASSEMBLY_HEAD);
diff --git a/src/glibext/gcodebuffer.c b/src/glibext/gcodebuffer.c
index ac6e807..b504473 100644
--- a/src/glibext/gcodebuffer.c
+++ b/src/glibext/gcodebuffer.c
@@ -24,8 +24,8 @@
 #include "gcodebuffer.h"
 
 
-#include <limits.h>
 #include <malloc.h>
+#include <stdlib.h>
 #include <string.h>
 
 
@@ -143,8 +143,8 @@ struct _GBufferView
     GObject parent;                         /* A laisser en premier        */
 
     GCodeBuffer *buffer;                    /* Tampon de code visualisé    */
-    vmpa_t start;                           /* Première ligne intégrée     */
-    vmpa_t end;                             /* Dernière ligne intégrée     */
+    vmpa2t *start;                          /* Première ligne intégrée     */
+    vmpa2t *end;                            /* Dernière ligne intégrée     */
     size_t first_index;                     /* Indice de la première ligne */
 
     gint line_height;                       /* Hauteur maximale des lignes */
@@ -512,7 +512,7 @@ static size_t _g_code_buffer_get_index_from_address_new(const GCodeBuffer *buffe
 *                                                                             *
 *  Description : Convertit une adresse en indice de ligne.                    *
 *                                                                             *
-*  Retour      : Indice de l'adresse trouvée, ou 0 en cas d'échec.            *
+*  Retour      : Indice de l'adresse trouvée, ou le nombre de lignes sinon.   *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
@@ -521,6 +521,108 @@ static size_t _g_code_buffer_get_index_from_address_new(const GCodeBuffer *buffe
 static size_t g_code_buffer_get_index_from_address(GCodeBuffer *buffer, const vmpa2t *addr, bool first)
 {
     size_t result;                          /* Indice à retourner          */
+    GBufferLine **found;                    /* Renvoi vers une trouvaille  */
+    const mrange_t *range;                  /* Couverture d'une ligne      */
+
+    /**
+     * Si aucune adresse (ie. aucune limite ?) n'est précisée, on se base sur
+     * la direction pour trouver le bon indice.
+     */
+
+    if (addr == NULL)
+        result = (first ? 0 : buffer->used - 1);
+
+    /**
+     * Sinon on parcourt méthodiquement toutes les lignes !
+     */
+
+    else
+    {
+
+#if 0
+        int cmp_addr_and_line(const vmpa2t *addr, const GBufferLine **line)
+        {
+            int status;                     /* Bilan d'une comparaison     */
+            const mrange_t *lrange;         /* Couverture d'une ligne      */
+
+            lrange = g_buffer_line_get_range(*line);
+
+            if (mrange_contains_addr(lrange, addr))
+                status = 0;
+
+            else
+            {
+                if (cmp_vmpa(addr, get_mrange_addr(lrange)) < 0)
+                    status = -1;
+                else
+                    status = 1;
+            }
+
+            return status;
+
+        }
+
+        found = bsearch(addr, buffer->lines, buffer->used, sizeof(GBufferLine *),
+                        (__compar_fn_t)cmp_addr_and_line);
+#endif
+
+
+
+
+        found = NULL;
+
+
+
+        for (result = 0; result < buffer->used; result++)
+        {
+            range = g_buffer_line_get_range(buffer->lines[result]);
+
+            if (mrange_contains_addr(range, addr))
+            {
+                found = &buffer->lines[result];
+                break;
+            }
+
+        }
+
+
+        if (found == NULL)
+            result = buffer->used;
+
+        else
+        {
+            result = found - buffer->lines;
+
+            //printf("  [index] [B] 0x%08x -> %zu\n", (unsigned int)addr->virtual, result);
+
+            if (first)
+                for (; result > 0; result--)
+                {
+                    range = g_buffer_line_get_range(buffer->lines[result - 1]);
+                    if (!mrange_contains_addr(range, addr)) break;
+                }
+
+            else
+                for (; (result + 1) < buffer->used; result++)
+                {
+                    range = g_buffer_line_get_range(buffer->lines[result + 1]);
+                    if (!mrange_contains_addr(range, addr)) break;
+                }
+
+            //printf("          [A] 0x%08x -> %zu\n", (unsigned int)addr->virtual, result);
+
+        }
+
+    }
+
+    return result;
+
+
+
+
+
+#if 0
+    size_t result;                          /* Indice à retourner          */
 
     result = _g_code_buffer_get_index_from_address(buffer, addr, first);
 
@@ -533,7 +635,7 @@ static size_t g_code_buffer_get_index_from_address(GCodeBuffer *buffer, const vm
         result = 0;
 
     return result;
-
+#endif
 }
 
 
@@ -671,6 +773,7 @@ GBufferLine *g_code_buffer_find_line_by_addr(const GCodeBuffer *buffer, const vm
 
     if (index == buffer->used)
         result = NULL;
+
     else
     {
         result = buffer->lines[index];
@@ -844,8 +947,8 @@ GBufferView *g_buffer_view_new(GCodeBuffer *buffer)
     g_object_ref(G_OBJECT(buffer));
 
     result->buffer = buffer;
-    result->start = 0;
-    result->end = VMPA_MAX;
+    result->start = NULL;
+    result->end = NULL;
 
     return result;
 
@@ -866,10 +969,10 @@ GBufferView *g_buffer_view_new(GCodeBuffer *buffer)
 *                                                                             *
 ******************************************************************************/
 
-void g_buffer_view_restrict(GBufferView *view, vmpa_t start, vmpa_t end)
+void g_buffer_view_restrict(GBufferView *view, const vmpa2t *start, const vmpa2t *end)
 {
-    view->start = start;
-    view->end = end;
+    view->start = dup_vmpa(start);
+    view->end = dup_vmpa(end);
 
 }
 
@@ -888,10 +991,10 @@ void g_buffer_view_restrict(GBufferView *view, vmpa_t start, vmpa_t end)
 *                                                                             *
 ******************************************************************************/
 
-void g_buffer_view_get_restrictions(GBufferView *view, vmpa_t *start, vmpa_t *end)
+void g_buffer_view_get_restrictions(GBufferView *view, vmpa2t *start, vmpa2t *end)
 {
-    if (start != NULL) *start = view->start;
-    if (end != NULL) *end = view->end;
+    if (start != NULL) copy_vmpa(start, view->start);
+    if (end != NULL) copy_vmpa(end, view->end);
 
 }
 
@@ -1081,7 +1184,7 @@ gint g_buffer_view_get_width(GBufferView *view, const bool *display)
     gint full_width;                        /* Calcul selon les fusions    */
     BufferLineColumn i;                     /* Boucle de parcours          */
 
-    if (!WIDTHS_CACHED(view))
+    //if (!WIDTHS_CACHED(view))
         g_buffer_view_compute_required_widths(view, display);
 
     result = view->left_text;
@@ -1685,7 +1788,7 @@ void g_buffer_view_highlight_segments(GBufferView *view, gint x, gint y)
     first = g_code_buffer_get_index_from_address(view->buffer, view->start, true);
     last = g_code_buffer_get_index_from_address(view->buffer, view->end, false);
 
-    for (i = first; i < last; i++)
+    for (i = first; i <= last; i++)
         view->highlighted = g_buffer_line_highlight_all_same_segments(view->buffer->lines[i],
                                                                       view->highlighted, segment);
 
diff --git a/src/glibext/gcodebuffer.h b/src/glibext/gcodebuffer.h
index e607b9c..cb17821 100644
--- a/src/glibext/gcodebuffer.h
+++ b/src/glibext/gcodebuffer.h
@@ -111,10 +111,10 @@ GType g_buffer_view_get_type(void);
 GBufferView *g_buffer_view_new(GCodeBuffer *);
 
 /* Restreint le champ d'application de l'affichage. */
-void g_buffer_view_restrict(GBufferView *, vmpa_t, vmpa_t);
+void g_buffer_view_restrict(GBufferView *, const vmpa2t *, const vmpa2t *);
 
 /* Indique le champ d'application de l'affichage. */
-void g_buffer_view_get_restrictions(GBufferView *, vmpa_t *, vmpa_t *);
+void g_buffer_view_get_restrictions(GBufferView *, vmpa2t *, vmpa2t *);
 
 /* Fournit le tampon de code lié à un visualisateur donné. */
 GCodeBuffer *g_buffer_view_get_buffer(const GBufferView *);
diff --git a/src/gtkext/graph/layout.c b/src/gtkext/graph/layout.c
index 94f59e6..ee91aff 100644
--- a/src/gtkext/graph/layout.c
+++ b/src/gtkext/graph/layout.c
@@ -160,14 +160,14 @@ bool build_graph_view(GtkGraphView *view, GInstrBlock *blocks, GtkViewPanel **vi
 
 static bool rank_graph_nodes(GInstrBlock *block, BlockVisitOrder order, visitor_dot_params *params)
 {
-    vmpa_t start;                           /* Adresse de départ d'un bloc */
+    vmpa2t start;                           /* Adresse de départ d'un bloc */
     GGraphNode *node;                       /* Noeud rattaché              */
     unsigned int rank;                      /* Classement du bloc lié      */
 
     if (G_IS_FLOW_BLOCK(block))
     {
         g_flow_block_get_boundary_addresses(G_FLOW_BLOCK(block), &start, NULL);
-        node = find_graph_node_by_start_address(params->nodes, params->count, start);
+        node = find_graph_node_by_start_address(params->nodes, params->count, &start);
 
         rank = g_flow_block_get_rank(G_FLOW_BLOCK(block));
         /* BUG_ON(count >= params->count) */
@@ -251,7 +251,7 @@ static void build_graph_ranking(visitor_dot_params *params)
 static bool register_graph_nodes(GInstrBlock *block, BlockVisitOrder order, visitor_dot_params *params)
 {
     char *cmds;                             /* Raccourci d'usage pratique  */
-    vmpa_t start;                           /* Adresse de départ d'un bloc */
+    vmpa2t start;                           /* Adresse de départ d'un bloc */
     GGraphNode *node;                       /* Noeud rattaché              */
     unsigned int i;                         /* Boucle de parcours          */
     char buffer[CLUSTER_DESC_LEN];          /* Tampon pour les commandes   */
@@ -261,7 +261,7 @@ static bool register_graph_nodes(GInstrBlock *block, BlockVisitOrder order, visi
     if (G_IS_FLOW_BLOCK(block))
     {
         g_flow_block_get_boundary_addresses(G_FLOW_BLOCK(block), &start, NULL);
-        node = find_graph_node_by_start_address(params->nodes, params->count, start);
+        node = find_graph_node_by_start_address(params->nodes, params->count, &start);
 
         cmds = g_graph_node_register_for_dot(node, cmds, params->level);
 
@@ -784,6 +784,13 @@ void g_graph_layout_size_request(const GGraphLayout *layout, GtkRequisition *req
 
     requisition->height = g_graph_ranks_get_height(layout->ranks);
 
+
+    requisition->width = 3000;
+    requisition->height = 3000;
+
+
+    printf("SIZE REQ\n");
+
 }
 
 
diff --git a/src/gtkext/graph/node.c b/src/gtkext/graph/node.c
index f286457..3801d1a 100644
--- a/src/gtkext/graph/node.c
+++ b/src/gtkext/graph/node.c
@@ -742,12 +742,12 @@ void g_graph_node_connect(const GGraphNode *node, gint x, gint y, GdkPoint **poi
 *                                                                             *
 ******************************************************************************/
 
-GtkBufferView *find_graph_view_by_start_address(GtkBufferView **views, size_t count, vmpa_t addr)
+GtkBufferView *find_graph_view_by_start_address(GtkBufferView **views, size_t count, const vmpa2t *addr)
 {
     GtkBufferView *result;                  /* Trouvaille à remonter       */
     size_t i;                               /* Boucle de parcours          */
     GBufferView *buffer;                    /* Tampon d'une partie de code */
-    vmpa_t start;                           /* Adresse de départ du tampon */
+    vmpa2t start;                           /* Adresse de départ du tampon */
 
     result = NULL;
 
@@ -756,7 +756,7 @@ GtkBufferView *find_graph_view_by_start_address(GtkBufferView **views, size_t co
         buffer = gtk_buffer_view_get_buffer(GTK_BUFFER_VIEW(views[i]));
         g_buffer_view_get_restrictions(buffer, &start, NULL);
 
-        if (start == addr)
+        if (cmp_vmpa(&start, addr) == 0)
             result = views[i];
 
     }
@@ -783,7 +783,7 @@ GtkBufferView *find_graph_view_by_start_address(GtkBufferView **views, size_t co
 GGraphNode *convert_blocks_into_nodes(GInstrBlock *block, GtkBufferView **views, size_t count)
 {
     GGraphNode *result;                     /* Instance nouvelle à renvoyer*/
-    vmpa_t start;                           /* Adresse de départ           */
+    vmpa2t start;                           /* Adresse de départ           */
     GtkBufferView *view;                    /* Vue existante à retrouver   */
     size_t max;                             /* Nombre de blocs à gérer     */
     size_t i;                               /* Boucle de parcours          */
@@ -795,7 +795,7 @@ GGraphNode *convert_blocks_into_nodes(GInstrBlock *block, GtkBufferView **views,
     if (G_IS_FLOW_BLOCK(block))
     {
         g_flow_block_get_boundary_addresses(G_FLOW_BLOCK(block), &start, NULL);
-        view = find_graph_view_by_start_address(views, count, start);
+        view = find_graph_view_by_start_address(views, count, &start);
 
         result = g_flow_node_new(G_FLOW_BLOCK(block), view);
 
@@ -890,12 +890,12 @@ GGraphNode *find_node_for_instruction(GGraphNode *nodes, GArchInstruction *instr
 *                                                                             *
 ******************************************************************************/
 
-GGraphNode *find_graph_node_by_start_address(GGraphNode **nodes, size_t count, vmpa_t addr)
+GGraphNode *find_graph_node_by_start_address(GGraphNode **nodes, size_t count, const vmpa2t *addr)
 {
     GGraphNode *result;                     /* Trouvaille à remonter       */
     size_t i;                               /* Boucle de parcours          */
     GBufferView *buffer;                    /* Tampon d'une partie de code */
-    vmpa_t start;                           /* Adresse de départ du tampon */
+    vmpa2t start;                           /* Adresse de départ du tampon */
 
     result = NULL;
 
@@ -904,7 +904,7 @@ GGraphNode *find_graph_node_by_start_address(GGraphNode **nodes, size_t count, v
         buffer = gtk_buffer_view_get_buffer(GTK_BUFFER_VIEW(nodes[i]->view));
         g_buffer_view_get_restrictions(buffer, &start, NULL);
 
-        if (start == addr)
+        if (cmp_vmpa(&start, addr) == 0)
             result = nodes[i];
 
     }
diff --git a/src/gtkext/graph/node.h b/src/gtkext/graph/node.h
index 712d9a3..4dcb02a 100644
--- a/src/gtkext/graph/node.h
+++ b/src/gtkext/graph/node.h
@@ -166,7 +166,7 @@ void g_graph_node_connect(const GGraphNode *, gint, gint, GdkPoint **, size_t *)
 
 
 /* Recherche une vue donnée dans une série de vues. */
-GtkBufferView *find_graph_view_by_start_address(GtkBufferView **, size_t, vmpa_t);
+GtkBufferView *find_graph_view_by_start_address(GtkBufferView **, size_t, const vmpa2t *);
 
 /* Réalise une conversion de blocs en noeuds. */
 GGraphNode *convert_blocks_into_nodes(GInstrBlock *, GtkBufferView **, size_t);
@@ -178,7 +178,7 @@ GGraphNode *find_node_for_instruction(GGraphNode *, GArchInstruction *);
 
 
 /* Recherche un noeud donné dans une série de noeuds. */
-GGraphNode *find_graph_node_by_start_address(GGraphNode **, size_t, vmpa_t);
+GGraphNode *find_graph_node_by_start_address(GGraphNode **, size_t, const vmpa2t *);
 
 /* Recherche un noeud donné dans une série de noeuds. */
 GGraphNode *find_graph_node_by_name(GGraphNode **, size_t, const char *);
diff --git a/src/gtkext/graph/nodes/flow.c b/src/gtkext/graph/nodes/flow.c
index 7ebaf78..5173810 100644
--- a/src/gtkext/graph/nodes/flow.c
+++ b/src/gtkext/graph/nodes/flow.c
@@ -24,6 +24,9 @@
 #include "flow.h"
 
 
+#include <assert.h>
+
+
 #include "../layout.h"
 #include "../node-int.h"
 
@@ -242,8 +245,13 @@ GGraphNode *g_flow_node_new(GFlowBlock *block, GtkBufferView *view)
     result->block = block;
     result->view = view;
 
+    gtk_widget_show(GTK_WIDGET(result->view));
+    gtk_widget_size_allocate(GTK_WIDGET(result->view), (GtkAllocation []) { { 0, 0, 100, 100 } });
+
     gtk_widget_get_preferred_size(GTK_WIDGET(result->view), NULL, &requisition);
 
+    printf("PREFERED :: (%d ; %d)\n", requisition.width, requisition.height);
+
     G_GRAPH_NODE(result)->alloc.width = requisition.width;
     G_GRAPH_NODE(result)->alloc.height = requisition.height;
 
@@ -614,26 +622,76 @@ static void g_flow_node_setup_entry_slots(GFlowNode *node)
     GArchInstruction **instrs;              /* Instr. visée par une autre  */
     InstructionLinkType *types;             /* Type de lien entre lignes   */
     size_t icount;                          /* Nombre de liens de dest.    */
+    size_t usable;                          /* Nombre de liens utiles ici  */
     size_t i;                               /* Boucle de parcours          */
+    size_t used;                            /* Nombre de liens utilisés    */
 
     g_flow_block_get_boundary(node->block, &first, NULL);
     icount = g_arch_instruction_get_sources(first, &instrs, &types);
 
-    node->entries = (node_slot_t *)calloc(icount, sizeof(node_slot_t));
-    node->entries_count = icount;
+    usable = 0;
 
     for (i = 0; i < icount; i++)
-    {
-        g_object_ref(instrs[i]);
-        node->entries[i].instr = instrs[i];
+        switch (types[i])
+        {
+            case ILT_EXEC_FLOW:
+            case ILT_JUMP:
+            case ILT_CASE_JUMP:
+            case ILT_JUMP_IF_TRUE:
+            case ILT_JUMP_IF_FALSE:
+            case ILT_LOOP:
+            case ILT_CATCH_EXCEPTION:
+                usable++;
+                break;
 
-        node->entries[i].type = types[i];
-        node->entries[i].group_index = g_arch_instruction_compute_group_index(&instrs[i],
-                                                                              instrs, icount);
-        node->entries[i].slot_index = i;
+            default:
+                break;
 
+        }
+
+    if (usable == 0)
+    {
+        node->entries = NULL;
+        node->entries_count = 0;
+    }
+    else
+    {
+        node->entries = (node_slot_t *)calloc(usable, sizeof(node_slot_t));
+        node->entries_count = usable;
     }
 
+    used = 0;
+
+    for (i = 0; i < icount; i++)
+        switch (types[i])
+        {
+            case ILT_EXEC_FLOW:
+            case ILT_JUMP:
+            case ILT_CASE_JUMP:
+            case ILT_JUMP_IF_TRUE:
+            case ILT_JUMP_IF_FALSE:
+            case ILT_LOOP:
+            case ILT_CATCH_EXCEPTION:
+
+                g_object_ref(instrs[i]);
+                node->entries[used].instr = instrs[i];
+
+                node->entries[used].type = types[i];
+                node->entries[used].group_index = g_arch_instruction_compute_group_index(&instrs[i],
+                                                                                      instrs, icount);
+                node->entries[used].slot_index = i;
+
+                used++;
+
+                break;
+
+            default:
+                break;
+
+        }
+
+    assert(used == usable);
+
 }
 
 
@@ -655,25 +713,75 @@ static void g_flow_node_setup_exit_slots(GFlowNode *node)
     GArchInstruction **instrs;              /* Instr. visée par une autre  */
     InstructionLinkType *types;             /* Type de lien entre lignes   */
     size_t icount;                          /* Nombre de liens de dest.    */
+    size_t usable;                          /* Nombre de liens utiles ici  */
     size_t i;                               /* Boucle de parcours          */
+    size_t used;                            /* Nombre de liens utilisés    */
 
     g_flow_block_get_boundary(node->block, NULL, &last);
     icount = g_arch_instruction_get_destinations(last, &instrs, &types, NULL);
 
-    node->exits = (node_slot_t *)calloc(icount, sizeof(node_slot_t));
-    node->exits_count = icount;
+    usable = 0;
 
     for (i = 0; i < icount; i++)
-    {
-        g_object_ref(instrs[i]);
-        node->exits[i].instr = instrs[i];
+        switch (types[i])
+        {
+            case ILT_EXEC_FLOW:
+            case ILT_JUMP:
+            case ILT_CASE_JUMP:
+            case ILT_JUMP_IF_TRUE:
+            case ILT_JUMP_IF_FALSE:
+            case ILT_LOOP:
+            case ILT_CATCH_EXCEPTION:
+                usable++;
+                break;
 
-        node->exits[i].type = types[i];
-        node->exits[i].group_index = g_arch_instruction_compute_group_index(&instrs[i],
-                                                                            instrs, icount);
-        node->exits[i].slot_index = i;
+            default:
+                break;
 
+        }
+
+    if (usable == 0)
+    {
+        node->exits = NULL;
+        node->exits_count = 0;
     }
+    else
+    {
+        node->exits = (node_slot_t *)calloc(usable, sizeof(node_slot_t));
+        node->exits_count = usable;
+    }
+
+    used = 0;
+
+    for (i = 0; i < icount; i++)
+        switch (types[i])
+        {
+            case ILT_EXEC_FLOW:
+            case ILT_JUMP:
+            case ILT_CASE_JUMP:
+            case ILT_JUMP_IF_TRUE:
+            case ILT_JUMP_IF_FALSE:
+            case ILT_LOOP:
+            case ILT_CATCH_EXCEPTION:
+
+                g_object_ref(instrs[i]);
+                node->exits[used].instr = instrs[i];
+
+                node->exits[used].type = types[i];
+                node->exits[used].group_index = g_arch_instruction_compute_group_index(&instrs[i],
+                                                                                    instrs, icount);
+                node->exits[used].slot_index = i;
+
+                used++;
+
+                break;
+
+            default:
+                break;
+
+        }
+
+    assert(used == usable);
 
 }
 
diff --git a/src/gtkext/gtkbufferview.c b/src/gtkext/gtkbufferview.c
index c7c0267..be75d2f 100644
--- a/src/gtkext/gtkbufferview.c
+++ b/src/gtkext/gtkbufferview.c
@@ -92,6 +92,28 @@ static gboolean gtk_buffer_view_refresh_caret(GtkBufferView *);
 G_DEFINE_TYPE(GtkBufferView, gtk_buffer_view, GTK_TYPE_VIEW_PANEL)
 
 
+/*
+  void               (* get_preferred_height)           (GtkWidget       *widget,
+                                                         gint            *minimum_height,
+                                                         gint            *natural_height);
+
+  void               (* get_preferred_width_for_height) (GtkWidget       *widget,
+                                                         gint             height,
+                                                         gint            *minimum_width,
+                                                         gint            *natural_width);
+  void               (* get_preferred_width)            (GtkWidget       *widget,
+                                                         gint            *minimum_width,
+                                                         gint            *natural_width);
+*/
+
+
+void get_preferred(GtkWidget *widget, gint *minimum, gint *natural)
+{
+    if (minimum != NULL) *minimum = 500;
+    if (natural != NULL) *natural = 500;
+}
+
+
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : class = classe GTK à initialiser.                            *
@@ -117,6 +139,11 @@ static void gtk_buffer_view_class_init(GtkBufferViewClass *class)
     widget_class->draw = gtk_buffer_view_draw;
     widget_class->key_press_event = gtk_buffer_view_key_press;
 
+
+    widget_class->get_preferred_height = get_preferred;
+    widget_class->get_preferred_width = get_preferred;
+
+
     panel_class->compute_size = (compute_requested_size)gtk_buffer_view_compute_requested_size;
     panel_class->compute_inc = (compute_scroll_inc)gtk_buffer_view_compute_scroll_inc;
     panel_class->get_coordinates = (get_addr_coordinates_fc)gtk_buffer_view_get_address_coordinates;
@@ -361,7 +388,7 @@ static gboolean gtk_buffer_view_draw(GtkWidget *widget, cairo_t *cr)
 
     gtk_style_context_add_class(context, GTK_STYLE_CLASS_TROUGH);
 
-    gtk_render_background (context, cr, 0, area.y, view->left_margin, area.height);
+    gtk_render_background(context, cr, 0, area.y, view->left_margin, area.height);
     gtk_render_frame(context, cr, 0, area.y - 10, view->left_margin, area.height + 20);
 
     gtk_style_context_restore(context);
@@ -549,12 +576,6 @@ static void gtk_buffer_view_compute_scroll_inc(GtkBufferView *view, gint size, G
 }
 
 
-
-
-
-
-
-
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : view  = composant GTK à consulter.                           *
diff --git a/src/gtkext/gtkgraphview.c b/src/gtkext/gtkgraphview.c
index 0265518..1f8d51c 100644
--- a/src/gtkext/gtkgraphview.c
+++ b/src/gtkext/gtkgraphview.c
@@ -79,15 +79,15 @@ static gboolean gtk_graph_view_draw(GtkWidget *, cairo_t *, GtkGraphView *);
 /* Indique les dimensions de travail du composant d'affichage. */
 static void gtk_graph_view_compute_requested_size(GtkGraphView *, gint *, gint *);
 
-
-/* Réagit à la sélection externe d'une adresse. */
-static void gtk_graph_view_define_main_address(GtkGraphView *, vmpa_t);
-
 /* Actualise les besoins internes avant un redimensionnement. */
 static void gtk_graph_view_prepare_resize(GtkGraphView *);
 
+
+/* Réagit à la sélection externe d'une adresse. */
+static void gtk_graph_view_define_main_address(GtkGraphView *, const vmpa2t *);
+
 /* Indique la position d'affichage d'une adresse donnée. */
-static bool gtk_graph_view_get_address_coordinates(const GtkGraphView *, vmpa_t, gint *, gint *);
+static bool gtk_graph_view_get_address_coordinates(const GtkGraphView *, const vmpa2t *addr, gint *x, gint *y, ScrollPositionTweak tweak);
 
 /* Place en cache un rendu destiné à l'aperçu graphique rapide. */
 static void gtk_graph_view_cache_glance(GtkGraphView *, cairo_t *, const GtkAllocation *, double);
@@ -129,6 +129,8 @@ static void gtk_graph_view_class_init(GtkGraphViewClass *class)
     widget_class->size_allocate = gtk_graph_view_size_allocate;
 
     panel_class->compute_size = (compute_requested_size)gtk_graph_view_compute_requested_size;
+    panel_class->define = (define_address_fc)gtk_graph_view_define_main_address;
+    panel_class->get_coordinates = (get_addr_coordinates_fc)gtk_graph_view_get_address_coordinates;
 
 }
 
@@ -144,7 +146,7 @@ static void gtk_graph_view_class_init(GtkGraphViewClass *class)
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
-
+#include "easygtk.h"////////////
 static void gtk_graph_view_init(GtkGraphView *view)
 {
     GtkViewPanel *viewpanel;                /* Instance parente #1         */
@@ -153,7 +155,6 @@ static void gtk_graph_view_init(GtkGraphView *view)
 
     viewpanel = GTK_VIEW_PANEL(view);
 
-    viewpanel->define = (define_address_fc)gtk_graph_view_define_main_address;
     viewpanel->resize = (prepare_resize_fc)gtk_graph_view_prepare_resize;
     ////////viewpanel->get_coordinates = (get_addr_coordinates_fc)gtk_graph_view_get_address_coordinates;
     viewpanel->cache_glance = (cache_glance_fc)gtk_graph_view_cache_glance;
@@ -166,6 +167,7 @@ static void gtk_graph_view_init(GtkGraphView *view)
 
     view->support = GTK_FIXED(gtk_fixed_new());
     gtk_widget_set_has_window(GTK_WIDGET(view->support), TRUE);
+    gtk_widget_set_can_focus(GTK_WIDGET(view->support), TRUE);
 
     g_signal_connect(G_OBJECT(view->support), "draw",
                      G_CALLBACK(gtk_graph_view_draw), view);
@@ -179,6 +181,26 @@ static void gtk_graph_view_init(GtkGraphView *view)
 
     gtk_fixed_put(GTK_FIXED(view), GTK_WIDGET(view->support), 0, 0);
 
+    //gtk_widget_size_allocate(view->support, (GtkAllocation []){ { 200, 200, 500, 500 } });
+
+#if 0
+    do
+    {
+        GtkWidget *btn;
+
+        btn = qck_create_button(NULL, NULL, "caption 0", NULL, NULL);
+        gtk_fixed_put(GTK_FIXED(view), btn, 10, 10);
+
+
+        btn = qck_create_button(NULL, NULL, "caption 1", NULL, NULL);
+        gtk_fixed_put(GTK_FIXED(view->support), btn, 100, 100);
+
+
+
+    }
+    while (0);
+#endif
+
     //view->mutex = g_mutex_new();
     //view->cond = g_cond_new();
 
@@ -215,19 +237,32 @@ static void gtk_graph_view_size_allocate(GtkWidget *widget, GtkAllocation *alloc
     GdkWindow *window;                      /* Fenêtre associée au support */
     gboolean changed;                       /* Changement de valeur ?      */
 
-    return;
+
+    printf("GRAPH SIZE ALLOC :: (%d ; %d) - (%d ; %d)\n",
+           allocation->x, allocation->y,
+           allocation->width, allocation->height);
+
+
+    GTK_WIDGET_CLASS(gtk_graph_view_parent_class)->size_allocate(widget, allocation);
+
 
     /* Mise à jour GTK */
 
+    /*
     fixed_class = g_type_class_peek_parent(GTK_GRAPH_VIEW_GET_CLASS(widget));
     fixed_class = g_type_class_peek_parent(fixed_class);
 
     GTK_WIDGET_CLASS(fixed_class)->size_allocate(widget, allocation);
+    */
+
+
 
     panel = GTK_VIEW_PANEL(widget);
 
+    /*
     if (panel->hadjustment == NULL || panel->vadjustment == NULL)
         return;
+    */
 
     // !!!! moved !!! gtk_view_panel_compute_allocation(panel, &valloc);
 
@@ -238,8 +273,24 @@ static void gtk_graph_view_size_allocate(GtkWidget *widget, GtkAllocation *alloc
     view = GTK_GRAPH_VIEW(widget);
     window = gtk_widget_get_window(GTK_WIDGET(view->support));
 
+
+
+    gtk_widget_size_allocate(view->support, (GtkAllocation []){ { 0, 0, 1500, 1500 } });
+
+    //gdk_window_resize(window, 500, 500);
+
+    /*
+    printf(" --> cmp :: (%d ; %d) vs (%d ; %d)\n",
+           gdk_window_get_width(window), gdk_window_get_height(window),
+           req.width, req.height);
+    */
+    /*
     if (gdk_window_get_width(window) != req.width || gdk_window_get_height(window) != req.height)
         gdk_window_resize(window, req.width, req.height);
+    */
+
+    return;
+
 
     /* Défilement horizontal */
 
@@ -299,7 +350,7 @@ static void gtk_graph_view_compute_requested_size(GtkGraphView *view, gint *widt
     if (width != NULL && view->layout != NULL)
     {
         g_graph_layout_size_request(view->layout, &requisition);
-        *width = requisition.height;
+        *width = requisition.width;
     }
 
     if (height != NULL && view->layout != NULL)
@@ -340,6 +391,42 @@ static gboolean gtk_graph_view_draw(GtkWidget *widget, cairo_t *cr, GtkGraphView
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : view = composant GTK à mettre à jour.                        *
+*                                                                             *
+*  Description : Actualise les besoins internes avant un redimensionnement.   *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void gtk_graph_view_prepare_resize(GtkGraphView *view)
+{
+    size_t i;                               /* Boucle de parcours          */
+
+    if (view->children_count > 0)
+    {
+        for (i = 0; i < view->children_count; i++)
+            gtk_widget_queue_resize(GTK_WIDGET(view->children[i]));
+
+        /*
+        build_graph_view(view, g_binary_routine_get_basic_blocks(view->routine),
+                         view->children, view->children_count);
+        */
+
+        g_graph_layout_refresh(view->layout);
+        g_graph_layout_place(view->layout, view);
+
+        change_editor_items_current_view_content(GTK_VIEW_PANEL(view));
+
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : view = composant GTK à mettre à jour.                        *
 *                addr = adresse sélectionnée de manière externe.              *
 *                                                                             *
 *  Description : Réagit à la sélection externe d'une adresse.                 *
@@ -350,16 +437,24 @@ static gboolean gtk_graph_view_draw(GtkWidget *widget, cairo_t *cr, GtkGraphView
 *                                                                             *
 ******************************************************************************/
 
-static void gtk_graph_view_define_main_address(GtkGraphView *view, vmpa_t addr)
+static void gtk_graph_view_define_main_address(GtkGraphView *view, const vmpa2t *addr)
 {
+    bool need_update;                       /* Mise à jour du contenu ?    */
+    const mrange_t *range;                  /* Couverture courante         */
     GExeFormat *format;                     /* Type de fichier chargé      */
     GBinRoutine **routines;                 /* Liste des routines trouvées */
     size_t routines_count;                  /* Nombre de ces routines      */
     size_t i;                               /* Boucle de parcours          */
-    vmpa_t start;                           /* Début d'une routine         */
-    vmpa_t end;                             /* Fin d'une routine           */
 
-    if (!(view->start <= addr && addr < view->end))
+    if (view->routine == NULL)
+        need_update = true;
+    else
+    {
+        range = g_binary_routine_get_range(view->routine);
+        need_update = !mrange_contains_addr(range, addr);
+    }
+
+    if (need_update)
     {
         gtk_graph_view_reset(view);
 
@@ -368,17 +463,13 @@ static void gtk_graph_view_define_main_address(GtkGraphView *view, vmpa_t addr)
 
         for (i = 0; i < routines_count; i++)
         {
-            start = g_binary_routine_get_address(routines[i]);
-            end = start + g_binary_routine_get_size(routines[i]);
+            range = g_binary_routine_get_range(routines[i]);
 
-            if (start <= addr && addr < end)
+            if (mrange_contains_addr(range, addr))
             {
                 view->routine = routines[i];
                 g_object_ref(G_OBJECT(view->routine));
 
-                view->start = start;
-                view->end = end;
-
                 view->children = gtk_graph_view_load_nodes(view, GTK_VIEW_PANEL(view)->binary,
                                                            routines[i]);
 
@@ -411,46 +502,11 @@ static void gtk_graph_view_define_main_address(GtkGraphView *view, vmpa_t addr)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : view = composant GTK à mettre à jour.                        *
-*                                                                             *
-*  Description : Actualise les besoins internes avant un redimensionnement.   *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void gtk_graph_view_prepare_resize(GtkGraphView *view)
-{
-    size_t i;                               /* Boucle de parcours          */
-
-    if (view->children_count > 0)
-    {
-        for (i = 0; i < view->children_count; i++)
-            gtk_widget_queue_resize(GTK_WIDGET(view->children[i]));
-
-        /*
-        build_graph_view(view, g_binary_routine_get_basic_blocks(view->routine),
-                         view->children, view->children_count);
-        */
-
-        g_graph_layout_refresh(view->layout);
-        g_graph_layout_place(view->layout, view);
-
-        change_editor_items_current_view_content(GTK_VIEW_PANEL(view));
-
-    }
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : view = composant GTK à consulter.                            *
-*                addr = adresse à présenter à l'écran.                        *
-*                x    = position horizontale au sein du composant. [OUT]      *
-*                y    = position verticale au sein du composant. [OUT]        *
+*  Paramètres  : view  = composant GTK à consulter.                           *
+*                addr  = adresse à présenter à l'écran.                       *
+*                x     = position horizontale au sein du composant. [OUT]     *
+*                y     = position verticale au sein du composant. [OUT]       *
+*                tweak = adaptation finale à effectuer.                       *
 *                                                                             *
 *  Description : Indique la position d'affichage d'une adresse donnée.        *
 *                                                                             *
@@ -460,10 +516,9 @@ static void gtk_graph_view_prepare_resize(GtkGraphView *view)
 *                                                                             *
 ******************************************************************************/
 
-static bool gtk_graph_view_get_address_coordinates(const GtkGraphView *view, vmpa_t addr, gint *x, gint *y)
+static bool gtk_graph_view_get_address_coordinates(const GtkGraphView *view, const vmpa2t *addr, gint *x, gint *y, ScrollPositionTweak tweak)
 {
-
-
+    /* TODO */
 
     return false;
 
@@ -564,7 +619,8 @@ void gtk_graph_view_put(GtkGraphView *view, GtkWidget *widget, const GtkAllocati
         gtk_container_remove(GTK_CONTAINER(parent), widget);
     }
 
-    gtk_fixed_put(view->support, widget, alloc->x, alloc->y);
+    //gtk_fixed_put(view->support, widget, alloc->x, alloc->y);
+    gtk_fixed_put(view->support, widget, i * 200, i * 150);
 
     if (parent != NULL)
         g_object_unref(G_OBJECT(widget));
@@ -665,8 +721,8 @@ static GtkViewPanel **gtk_graph_view_load_nodes(GtkGraphView *view, GLoadedBinar
     GInstrBlock *main_block;                /* Premier bloc rattaché       */
     GInstrBlock **blocks;                   /* Liste des blocs basiques    */
     size_t i;                               /* Boucle de parcours          */
-    vmpa_t first;                           /* Début d'un groupe de lignes */
-    vmpa_t last;                            /* Fin d'un groupe de lignes   */
+    vmpa2t first;                           /* Début d'un groupe de lignes */
+    vmpa2t last;                            /* Fin d'un groupe de lignes   */
     GBufferView *subview;                   /* Partie affichée du tampon   */
 
     buffer = g_loaded_binary_get_disassembled_buffer(binary);
@@ -692,7 +748,7 @@ static GtkViewPanel **gtk_graph_view_load_nodes(GtkGraphView *view, GLoadedBinar
         g_flow_block_get_boundary_addresses(G_FLOW_BLOCK(blocks[i]), &first, &last);
 
         subview = g_buffer_view_new(buffer);
-        g_buffer_view_restrict(subview, first, last);
+        g_buffer_view_restrict(subview, &first, &last);
         gtk_buffer_view_attach_buffer(GTK_BUFFER_VIEW(result[i]), subview);
 
     }
diff --git a/src/gtkext/gtkviewpanel-int.h b/src/gtkext/gtkviewpanel-int.h
index 220b253..d51c637 100644
--- a/src/gtkext/gtkviewpanel-int.h
+++ b/src/gtkext/gtkviewpanel-int.h
@@ -43,7 +43,7 @@ typedef void (* compute_scroll_inc) (GtkViewPanel *, gint, GtkOrientation, gdoub
 typedef void (* attach_binary_fc) (GtkViewPanel *, GLoadedBinary *);
 
 /* Réagit à la sélection externe d'une adresse. */
-typedef void (* define_address_fc) (GtkViewPanel *, vmpa_t);
+typedef void (* define_address_fc) (GtkViewPanel *, const vmpa2t *);
 
 /* Actualise les besoins internes avant un redimensionnement. */
 typedef void (* prepare_resize_fc) (GtkViewPanel *);
@@ -76,7 +76,7 @@ struct _GtkViewPanel
     GLoadedBinary *binary;                  /* Binaire à visualiser        */
 
     attach_binary_fc attach;                /* Association avec un binaire */
-    define_address_fc define;               /* Centrage sur une partie     */
+    //define_address_fc define;               /* Centrage sur une partie     */
     prepare_resize_fc resize;               /* Prépare une nouvelle taille */
     cache_glance_fc cache_glance;           /* Cache de la mignature       */
 
@@ -89,6 +89,7 @@ struct _GtkViewPanelClass
 
     compute_requested_size compute_size;    /* Calcul de la taille requise */
     compute_scroll_inc compute_inc;         /* Calcul des bonds            */
+    define_address_fc define;               /* Centrage sur une partie     */
     get_addr_coordinates_fc get_coordinates;/* Conversion adresse <-> pos. */
     get_view_position_fc get_position;      /* Indications sur la position */
 
diff --git a/src/gtkext/gtkviewpanel.c b/src/gtkext/gtkviewpanel.c
index d434f1e..3c8febd 100644
--- a/src/gtkext/gtkviewpanel.c
+++ b/src/gtkext/gtkviewpanel.c
@@ -320,6 +320,11 @@ static void gtk_view_panel_size_allocate(GtkWidget *widget, GtkAllocation *alloc
 
     GTK_WIDGET_CLASS(gtk_view_panel_parent_class)->size_allocate(widget, allocation);
 
+
+    printf("[%s / %p] __SIZE :: (%d ; %d)\n", G_OBJECT_TYPE_NAME(widget), widget,
+           allocation->width, allocation->height);
+
+
     panel = GTK_VIEW_PANEL(widget);
 
     gtk_view_panel_update_adjustment(panel, GTK_ORIENTATION_HORIZONTAL);
@@ -347,6 +352,8 @@ static gboolean gtk_view_panel_draw(GtkWidget *widget, cairo_t *cr)
     GtkRequisition req;                     /* Taille allouée à l'élément  */
     GtkStyleContext *context;               /* Contexte du thème actuel    */
 
+    GTK_WIDGET_CLASS(gtk_view_panel_parent_class)->draw(widget, cr);
+
     panel = GTK_VIEW_PANEL(widget);
 
     if (panel->show_border)
@@ -776,11 +783,8 @@ void gtk_view_panel_scroll_to_address(GtkViewPanel *panel, const vmpa2t *addr, S
     gdouble page_size;                      /* Taille de l'affichage       */
     double value;                           /* Valeur courante             */
 
-    /*
-    if (panel->define != NULL)
-        panel->define(panel, addr);
-    */
-
+    if (GTK_VIEW_PANEL_GET_CLASS(panel)->define != NULL)
+        GTK_VIEW_PANEL_GET_CLASS(panel)->define(panel, addr);
 
     if (GTK_VIEW_PANEL_GET_CLASS(panel)->get_coordinates(panel, addr, &x, &y, tweak))
     {
diff --git a/src/gui/menus/view.c b/src/gui/menus/view.c
index 9abcbd3..c907bc8 100644
--- a/src/gui/menus/view.c
+++ b/src/gui/menus/view.c
@@ -219,8 +219,7 @@ static void mcb_view_change_support(GtkRadioMenuItem *menuitem, GMenuBar *bar)
         /**
          * La hiérarchie des composants empilés est la suivante :
          *
-         *  - GtkBlockView / GtkGraphView / GtkSourceView
-         *  - GtkViewport
+         *  - GtkBlockView / GtkGraphView / GtkSourceView (avec GtkViewport intégré)
          *  - GtkScrolledWindow
          *  - GtkNotebook
          *  - GtkDockStation
@@ -228,8 +227,7 @@ static void mcb_view_change_support(GtkRadioMenuItem *menuitem, GMenuBar *bar)
          */
 
         vpanel = g_editor_item_get_current_view(G_EDITOR_ITEM(bar));
-        station = gtk_widget_get_parent(GTK_WIDGET(vpanel));    /* GtkViewport */
-        station = gtk_widget_get_parent(GTK_WIDGET(station));   /* ScrollWindow */
+        station = gtk_widget_get_parent(GTK_WIDGET(vpanel));   /* ScrollWindow */
         station = gtk_widget_get_parent(station);   /* NoteBook */
         station = gtk_widget_get_parent(station);   /* DockStation */
 
-- 
cgit v0.11.2-87-g4458