From b5934203c1cb287eb46b07e866b54d1de240b87b Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Sun, 6 Jun 2010 14:08:21 +0000
Subject: Used a treeview with icons to show all known symbols.

git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@165 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
---
 ChangeLog                          |  54 +++++
 pixmaps/Makefile.am                |  16 +-
 pixmaps/symbol_class_classic.png   | Bin 0 -> 609 bytes
 pixmaps/symbol_package.png         | Bin 0 -> 878 bytes
 pixmaps/symbol_routine_classic.png | Bin 0 -> 568 bytes
 pixmaps/tbutton_collapse.png       | Bin 0 -> 284 bytes
 pixmaps/tbutton_expand.png         | Bin 0 -> 284 bytes
 pixmaps/tbutton_list_view.png      | Bin 0 -> 197 bytes
 pixmaps/tbutton_namespace.png      | Bin 0 -> 358 bytes
 pixmaps/tbutton_tree_view.png      | Bin 0 -> 302 bytes
 src/analysis/routine.c             |  29 ++-
 src/analysis/routine.h             |  18 +-
 src/analysis/type.c                |   7 +-
 src/analysis/type.h                |   4 +-
 src/analysis/variable.c            |  16 +-
 src/analysis/variable.h            |   8 +-
 src/format/dex/dex-int.c           |  67 ++++++
 src/format/dex/dex-int.h           |   6 +
 src/format/dex/dex_def.h           |  15 ++
 src/format/dex/pool.c              |  50 +++-
 src/format/mangling/java_gram.y    |   4 +-
 src/format/mangling/java_tok.l     |   8 +-
 src/gtkext/easygtk.c               | 125 ++++++++++
 src/gtkext/easygtk.h               |  11 +
 src/gtkext/support.c               |  65 +++++
 src/gtkext/support.h               |   6 +
 src/panels/symbols.c               | 482 +++++++++++++++++++++++++++++++++++--
 src/panels/symbols.h               |   1 -
 28 files changed, 929 insertions(+), 63 deletions(-)
 create mode 100644 pixmaps/symbol_class_classic.png
 create mode 100644 pixmaps/symbol_package.png
 create mode 100644 pixmaps/symbol_routine_classic.png
 create mode 100644 pixmaps/tbutton_collapse.png
 create mode 100644 pixmaps/tbutton_expand.png
 create mode 100644 pixmaps/tbutton_list_view.png
 create mode 100644 pixmaps/tbutton_namespace.png
 create mode 100644 pixmaps/tbutton_tree_view.png

diff --git a/ChangeLog b/ChangeLog
index 0d9ce37..e85ea21 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,57 @@
+10-06-06  Cyrille Bagard <nocbos@gmail.com>
+
+	* pixmaps/Makefile.am:
+	Add more pictures to EXTRA_DIST and oidapix_DATA.
+
+	* pixmaps/symbol_class_classic.png:
+	* pixmaps/symbol_package.png:
+	* pixmaps/symbol_routine_classic.png:
+	* pixmaps/tbutton_collapse.png:
+	* pixmaps/tbutton_expand.png:
+	* pixmaps/tbutton_list_view.png:
+	* pixmaps/tbutton_namespace.png:
+	* pixmaps/tbutton_tree_view.png:
+	New entries: add icons to the symbols panel.
+
+	* src/analysis/routine.c:
+	* src/analysis/routine.h:
+	Be able to unset the return type. Add a function to get the namespace.
+	Provide more options when converting an item to string.
+
+	* src/analysis/type.c:
+	* src/analysis/type.h:
+	* src/analysis/variable.c:
+	* src/analysis/variable.h:
+	Provide more options when converting an item to string.
+
+	* src/format/dex/dex_def.h:
+	* src/format/dex/dex-int.c:
+	* src/format/dex/dex-int.h:
+	Define and load 'type_item' and 'type_list' DEX items.
+
+	* src/format/dex/pool.c:
+	Properly load the return type and the argument types for a routine.
+
+	* src/format/mangling/java_gram.y:
+	Fix two bugs: 'V' -> token V and the java_error() prototype.
+
+	* src/format/mangling/java_tok.l:
+	Remove some debug code.
+
+	* src/gtkext/easygtk.c:
+	* src/gtkext/easygtk.h:
+	Provide functions to quickly create toolbar items.
+
+	* src/gtkext/support.c:
+	* src/gtkext/support.h:
+	Provide functions to load images or picture buffers from files.
+
+	* src/panels/symbols.c:
+	Use a treeview with icons to show all known symbols.
+
+	* src/panels/symbols.h:
+	Typo.
+
 10-06-02  Cyrille Bagard <nocbos@gmail.com>
 
 	* src/analysis/binary.c:
diff --git a/pixmaps/Makefile.am b/pixmaps/Makefile.am
index 0de7e75..8cf2b8a 100644
--- a/pixmaps/Makefile.am
+++ b/pixmaps/Makefile.am
@@ -12,12 +12,26 @@ REVISION_PIX =							\
 	revision_9.png						\
 	revision.png
 
+TOOLBAR_BUTTONS =						\
+	tbutton_collapse.png				\
+	tbutton_expand.png					\
+	tbutton_list_view.png				\
+	tbutton_namespace.png				\
+	tbutton_tree_view.png
+
+LIST_ICONS =							\
+	symbol_class_classic.png			\
+	symbol_package.png					\
+	symbol_routine_classic.png
+
 EXTRA_DIST =							\
 	openida.xcf							\
 	openida_text.xcf					\
 	$(REVISION_PIX)						\
+	$(TOOLBAR_BUTTONS)					\
+	$(LIST_ICONS)						\
 	dropwin_back.png
 
 oidapixdir = $(datadir)/openida
 
-oidapix_DATA = dropwin_back.png $(REVISION_PIX)
+oidapix_DATA = dropwin_back.png $(REVISION_PIX) $(TOOLBAR_BUTTONS) $(LIST_ICONS)
diff --git a/pixmaps/symbol_class_classic.png b/pixmaps/symbol_class_classic.png
new file mode 100644
index 0000000..e9c1d24
Binary files /dev/null and b/pixmaps/symbol_class_classic.png differ
diff --git a/pixmaps/symbol_package.png b/pixmaps/symbol_package.png
new file mode 100644
index 0000000..c667b59
Binary files /dev/null and b/pixmaps/symbol_package.png differ
diff --git a/pixmaps/symbol_routine_classic.png b/pixmaps/symbol_routine_classic.png
new file mode 100644
index 0000000..2ddc67a
Binary files /dev/null and b/pixmaps/symbol_routine_classic.png differ
diff --git a/pixmaps/tbutton_collapse.png b/pixmaps/tbutton_collapse.png
new file mode 100644
index 0000000..4ed7c60
Binary files /dev/null and b/pixmaps/tbutton_collapse.png differ
diff --git a/pixmaps/tbutton_expand.png b/pixmaps/tbutton_expand.png
new file mode 100644
index 0000000..09d5757
Binary files /dev/null and b/pixmaps/tbutton_expand.png differ
diff --git a/pixmaps/tbutton_list_view.png b/pixmaps/tbutton_list_view.png
new file mode 100644
index 0000000..2f13bda
Binary files /dev/null and b/pixmaps/tbutton_list_view.png differ
diff --git a/pixmaps/tbutton_namespace.png b/pixmaps/tbutton_namespace.png
new file mode 100644
index 0000000..10bfe98
Binary files /dev/null and b/pixmaps/tbutton_namespace.png differ
diff --git a/pixmaps/tbutton_tree_view.png b/pixmaps/tbutton_tree_view.png
new file mode 100644
index 0000000..c6c10c2
Binary files /dev/null and b/pixmaps/tbutton_tree_view.png differ
diff --git a/src/analysis/routine.c b/src/analysis/routine.c
index c5bf056..8db366d 100644
--- a/src/analysis/routine.c
+++ b/src/analysis/routine.c
@@ -340,6 +340,25 @@ void g_binary_routine_set_namespace(GBinRoutine *routine, GOpenidaType *namespac
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : routine   = routine à mettre à jour.                         *
+*                                                                             *
+*  Description : Fournit le groupe d'appartenance d'une routine donnée.       *
+*                                                                             *
+*  Retour      : éventuelle instance d'appartenance ou NULL.                  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GOpenidaType *g_binary_routine_get_namespace(const GBinRoutine *routine)
+{
+    return routine->namespace;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : routine = routine à mettre à jour.                           *
 *                name    = désignation humainement lisible.                   *
 *                                                                             *
@@ -444,7 +463,9 @@ void g_binary_routine_set_return_type(GBinRoutine *routine, GOpenidaType *type)
         g_object_unref(G_OBJECT(routine->ret_type));
 
     routine->ret_type = type;
-    g_object_ref(G_OBJECT(type));
+
+    if (type != NULL)
+        g_object_ref(G_OBJECT(type));
 
 }
 
@@ -593,7 +614,7 @@ size_t g_binary_routine_get_var_index_from_offset(const GBinRoutine *routine, si
 *                                                                             *
 ******************************************************************************/
 
-char *g_binary_routine_to_string(const GBinRoutine *routine)
+char *_g_binary_routine_to_string(const GBinRoutine *routine, Routine2StringOptions options)
 {
     char *result;                           /* Chaîne à renvoyer           */
     char *namespace;                        /* Groupe d'appartenance       */
@@ -629,7 +650,7 @@ char *g_binary_routine_to_string(const GBinRoutine *routine)
 
     /* Nom de la routine */
 
-    if (routine->namespace != NULL)
+    if (options & RSO_NAMESPACE && routine->namespace != NULL)
     {
         namespace = g_openida_type_to_string(routine->namespace);
 
@@ -650,7 +671,7 @@ char *g_binary_routine_to_string(const GBinRoutine *routine)
     {
         if (i > 0) result = stradd(result, ", ");
 
-        typestr = g_binary_variable_to_string(routine->args[i]);
+        typestr = g_binary_variable_to_string(routine->args[i], !(options & RSO_LONG_TYPE));
         result = stradd(result, typestr);
         free(typestr);
 
diff --git a/src/analysis/routine.h b/src/analysis/routine.h
index 0b673f7..cd17bf3 100644
--- a/src/analysis/routine.h
+++ b/src/analysis/routine.h
@@ -58,6 +58,17 @@ typedef struct _GBinRoutine GBinRoutine;
 typedef struct _GBinRoutineClass GBinRoutineClass;
 
 
+/* Modalités de représentation en chaîne */
+typedef enum _Routine2StringOptions
+{
+    RSO_LONG_TYPE   = (1 << 0),             /* Type avec espace de noms    */
+    RSO_NAMESPACE   = (1 << 1)              /* Affichage de l'appartenance */
+
+} Routine2StringOptions;
+
+#define RSO_ALL (RSO_LONG_TYPE | RSO_NAMESPACE)
+
+
 /* Indique le type définit pour une représentation de routine. */
 GType g_bin_routine_get_type(void);
 
@@ -88,6 +99,9 @@ void g_binary_routine_set_type(GBinRoutine *, RoutineType);
 /* Définit le groupe d'appartenance d'une routine donnée. */
 void g_binary_routine_set_namespace(GBinRoutine *, GOpenidaType *);
 
+/* Fournit le groupe d'appartenance d'une routine donnée. */
+GOpenidaType *g_binary_routine_get_namespace(const GBinRoutine *);
+
 /* Définit le nom humain d'une routine. */
 void g_binary_routine_set_name(GBinRoutine *, char *);
 
@@ -113,7 +127,9 @@ void g_binary_routine_register_if_needed(GBinRoutine *, size_t, bool);
 size_t g_binary_routine_get_var_index_from_offset(const GBinRoutine *, size_t, bool);
 
 /* Décrit le prototype de la routine sous forme de caractères. */
-char *g_binary_routine_to_string(const GBinRoutine *);
+char *_g_binary_routine_to_string(const GBinRoutine *, Routine2StringOptions);
+
+#define g_binary_routine_to_string(r) _g_binary_routine_to_string((r), RSO_ALL)
 
 
 
diff --git a/src/analysis/type.c b/src/analysis/type.c
index 3282e2b..d16917f 100644
--- a/src/analysis/type.c
+++ b/src/analysis/type.c
@@ -366,7 +366,8 @@ void g_openida_type_set_namespace(GOpenidaType *type, GOpenidaType *namespace)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : type = type à convertir.                                     *
+*  Paramètres  : type   = type à convertir.                                   *
+*                simple = indique si l'espace de noms doit être exclus ou non.*
 *                                                                             *
 *  Description : Décrit le type fourni sous forme de caractères.              *
 *                                                                             *
@@ -376,14 +377,14 @@ void g_openida_type_set_namespace(GOpenidaType *type, GOpenidaType *namespace)
 *                                                                             *
 ******************************************************************************/
 
-char *g_openida_type_to_string(const GOpenidaType *type)
+char *_g_openida_type_to_string(const GOpenidaType *type, bool simple)
 {
     char *result;                           /* Chaîne à retourner          */
     char *namespace;                        /* Groupe d'appartenance       */
 
     result = type->to_string(type);
 
-    if (type->namespace != NULL)
+    if (!simple && type->namespace != NULL)
     {
         namespace = g_openida_type_to_string(type->namespace);
 
diff --git a/src/analysis/type.h b/src/analysis/type.h
index 2662235..ac17235 100644
--- a/src/analysis/type.h
+++ b/src/analysis/type.h
@@ -72,7 +72,9 @@ GOpenidaType *g_openida_type_dup(const GOpenidaType *);
 void g_openida_type_set_namespace(GOpenidaType *, GOpenidaType *);
 
 /* Décrit le type fourni sous forme de caractères. */
-char *g_openida_type_to_string(const GOpenidaType *);
+char *_g_openida_type_to_string(const GOpenidaType *, bool);
+
+#define g_openida_type_to_string(t) _g_openida_type_to_string((t), false)
 
 /* Ajoute un qualificatif à une instance de type. */
 void g_openida_type_add_qualifier(GOpenidaType *, TypeQualifier);
diff --git a/src/analysis/variable.c b/src/analysis/variable.c
index 87df60e..86fc4cc 100644
--- a/src/analysis/variable.c
+++ b/src/analysis/variable.c
@@ -234,18 +234,10 @@ void g_binary_variable_set_owner(GBinVariable *var, GOpenidaType *owner)
 }
 
 
-
-
-
-
-
-
-
-
-
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : var = variable à convertir.                                  *
+*  Paramètres  : var    = variable à convertir.                               *
+*                simple = indique si l'espace de noms doit être exclus ou non.*
 *                                                                             *
 *  Description : Décrit la variable donnée sous forme de caractères.          *
 *                                                                             *
@@ -255,11 +247,11 @@ void g_binary_variable_set_owner(GBinVariable *var, GOpenidaType *owner)
 *                                                                             *
 ******************************************************************************/
 
-char *g_binary_variable_to_string(const GBinVariable *var)
+char *g_binary_variable_to_string(const GBinVariable *var, bool simple)
 {
     char *result;                           /* Valeur à retourner          */
 
-    result = g_openida_type_to_string(var->type);
+    result = _g_openida_type_to_string(var->type, simple);
 
     if (var->name != NULL)
     {
diff --git a/src/analysis/variable.h b/src/analysis/variable.h
index 88e2b91..df8ee81 100644
--- a/src/analysis/variable.h
+++ b/src/analysis/variable.h
@@ -72,14 +72,8 @@ GOpenidaType *g_binary_variable_get_owner(const GBinVariable *);
 /* Définit la zone d'appartenance d'une variable donnée. */
 void g_binary_variable_set_owner(GBinVariable *, GOpenidaType *);
 
-
-
-
-
-/* TODO : remme */
-
 /* Décrit la variable donnée sous forme de caractères. */
-char *g_binary_variable_to_string(const GBinVariable *);
+char *g_binary_variable_to_string(const GBinVariable *, bool);
 
 
 
diff --git a/src/format/dex/dex-int.c b/src/format/dex/dex-int.c
index 025429f..8f5b408 100644
--- a/src/format/dex/dex-int.c
+++ b/src/format/dex/dex-int.c
@@ -354,6 +354,73 @@ bool read_dex_encoded_method(const GDexFormat *format, off_t *pos, encoded_metho
 *                pos    = position de début de lecture. [OUT]                 *
 *                item   = structure lue à retourner. [OUT]                    *
 *                                                                             *
+*  Description : Procède à la lecture d'un type DEX.                          *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool read_dex_type_item(const GDexFormat *format, off_t *pos, type_item *item)
+{
+    bool result;                            /* Bilan à retourner           */
+    const bin_t *content;                   /* Contenu binaire à lire      */
+    off_t length;                           /* Taille totale du contenu    */
+
+    result = true;
+
+    content = G_BIN_FORMAT(format)->content;
+    length = G_BIN_FORMAT(format)->length;
+
+    result &= read_u16(&item->type_idx, content, pos, length, SRE_LITTLE);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = informations chargées à consulter.                  *
+*                pos    = position de début de lecture. [OUT]                 *
+*                list   = structure lue à retourner. [OUT]                    *
+*                                                                             *
+*  Description : Procède à la lecture d'une liste de types DEX.               *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool read_dex_type_list(const GDexFormat *format, off_t *pos, type_list *list)
+{
+    bool result;                            /* Bilan à retourner           */
+    const bin_t *content;                   /* Contenu binaire à lire      */
+    off_t length;                           /* Taille totale du contenu    */
+
+    result = true;
+
+    content = G_BIN_FORMAT(format)->content;
+    length = G_BIN_FORMAT(format)->length;
+
+    result &= read_u32(&list->size, content, pos, length, SRE_LITTLE);
+
+    list->list = (type_item *)&content[*pos];
+    result &= ((*pos + list->size * sizeof(type_item)) <= length);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = informations chargées à consulter.                  *
+*                pos    = position de début de lecture. [OUT]                 *
+*                item   = structure lue à retourner. [OUT]                    *
+*                                                                             *
 *  Description : Procède à la lecture d'un contenu de classe DEX.             *
 *                                                                             *
 *  Retour      : Bilan de l'opération.                                        *
diff --git a/src/format/dex/dex-int.h b/src/format/dex/dex-int.h
index 2e3cc00..4b15c83 100755
--- a/src/format/dex/dex-int.h
+++ b/src/format/dex/dex-int.h
@@ -94,6 +94,12 @@ bool read_dex_encoded_field(const GDexFormat *, off_t *, encoded_field *);
 /* Procède à la lecture d'une méthode quelconque DEX. */
 bool read_dex_encoded_method(const GDexFormat *, off_t *, encoded_method *);
 
+/* Procède à la lecture d'un type DEX. */
+bool read_dex_type_item(const GDexFormat *, off_t *, type_item *);
+
+/* Procède à la lecture d'une liste de types DEX. */
+bool read_dex_type_list(const GDexFormat *, off_t *, type_list *);
+
 /* Procède à la lecture d'un contenu de classe DEX. */
 bool read_dex_class_data_item(const GDexFormat *, off_t *, class_data_item *);
 
diff --git a/src/format/dex/dex_def.h b/src/format/dex/dex_def.h
index 9faf050..3f6950d 100755
--- a/src/format/dex/dex_def.h
+++ b/src/format/dex/dex_def.h
@@ -117,6 +117,21 @@ typedef struct _encoded_method
 
 } encoded_method;
 
+/* Type quelconque */
+typedef struct _type_item
+{
+    uint16_t type_idx;                      /* Indice dans la table adaptée*/
+
+} type_item;
+
+/* Liste de types */
+typedef struct _type_list
+{
+    uint32_t size;                          /* Nombre d'éléments présents  */
+    type_item *list;                        /* Liste des éléments inscrits */
+
+} type_list;
+
 /* Données de fonctionnement pour classe */
 typedef struct _class_data_item
 {
diff --git a/src/format/dex/pool.c b/src/format/dex/pool.c
index b2ca105..d82144f 100644
--- a/src/format/dex/pool.c
+++ b/src/format/dex/pool.c
@@ -92,7 +92,7 @@ GOpenidaType *get_type_from_dex_pool(const GDexFormat *format, uint16_t index)
     string_data_item str_data;              /* Description de chaîne       */
 
 
-    //printf("Index :: 0x%04hx\n", index);
+    //printf("Tp Index :: %hd / %d\n", index, format->header.type_ids_size);
 
 
     if (index >= format->header.type_ids_size)
@@ -255,6 +255,12 @@ GBinRoutine *get_routine_from_dex_pool(const GDexFormat *format, uint32_t index)
     string_id_item str_id;                  /* Identifiant de chaîne       */
     string_data_item str_data;              /* Description de chaîne       */
 
+
+    proto_id_item proto_id;                 /* Information de prototypage  */
+    type_list args;                         /* Liste des arguments         */
+    uint32_t i;                             /* Boucle de parcours          */
+    GBinVariable *arg;                      /* Argument reconstitué        */
+
     if (index >= format->header.method_ids_size)
         return NULL;
 
@@ -302,8 +308,50 @@ GBinRoutine *get_routine_from_dex_pool(const GDexFormat *format, uint32_t index)
         g_binary_routine_set_namespace(result, type);
 
 
+
+    /*
+    printf("  ####\n");
+    printf("  ####  ROUTINE '%s'\n", g_binary_routine_to_string(result));
+    printf("  ####\n");
+    printf("  ####\n");
+    */
+
     //printf("==>>> routine :: '%s'\n", g_binary_routine_to_string(result));
 
+
+
+
+
+
+
+    /* Retour de la routine */
+
+    pos = format->header.proto_ids_off + meth_id.proto_idx * sizeof(proto_id_item);
+
+    if (!read_dex_proto_id_item(format, &pos, &proto_id))
+        goto no_more_info;
+
+    type = get_type_from_dex_pool(format, proto_id.return_type_idx);
+
+    g_binary_routine_set_return_type(result, type);
+
+    /* Arguments de la routine */
+
+    pos = proto_id.parameters_off;
+
+    if (read_dex_type_list(format, &pos, &args))
+        for (i = 0; i < args.size; i++)
+        {
+            type = get_type_from_dex_pool(format, args.list[i].type_idx);
+            if (type == NULL) continue;
+
+            arg = g_binary_variable_new(type);
+            g_binary_routine_add_arg(result, arg);
+
+        }
+
+ no_more_info:
+
     return result;
 
 }
diff --git a/src/format/mangling/java_gram.y b/src/format/mangling/java_gram.y
index 3522b01..859dce4 100644
--- a/src/format/mangling/java_gram.y
+++ b/src/format/mangling/java_gram.y
@@ -98,7 +98,7 @@ input:
 	;
 
 type_descriptor:
-    'V'                                 { $$ = g_basic_type_new(BTP_VOID); }
+    V                                   { $$ = g_basic_type_new(BTP_VOID); }
     | field_type_descriptor             { $$ = $1; }
     ;
 
@@ -227,7 +227,7 @@ GDemanglingContext *g_java_dcontext_new(void)
  * @param msg indications humaines sur l'événement.
  * @return 0.
  */
-int java_error(/*const YYLTYPE *yyloc, bool hunt, char **ucode, unsigned char *index, */char *msg)
+int java_error(/*const YYLTYPE *yyloc, bool hunt, char **ucode, unsigned char *index, */GJavaDContext *context, char *msg)
 {
 
 
diff --git a/src/format/mangling/java_tok.l b/src/format/mangling/java_tok.l
index 06777f9..c19cd04 100644
--- a/src/format/mangling/java_tok.l
+++ b/src/format/mangling/java_tok.l
@@ -23,11 +23,11 @@ I                       { return I; }
 J                       { return J; }
 F                       { return F; }
 D                       { return D; }
-L                       { printf("Got 'L'\n"); BEGIN(string); return L; }
-<string>[/]             { printf("Got '/'\n"); return SLASH; }
-<string>[$]             { printf("Got '$'\n"); return DOLLAR; }
+L                       { BEGIN(string); return L; }
+<string>[/]             { return SLASH; }
+<string>[$]             { return DOLLAR; }
 <string>[;]             { BEGIN(INITIAL); return SEMICOLON; }
 
-<string>[A-Za-z0-9]*    { java_lval.text = yytext; printf("Got text:'%s'\n", yytext); return TEXT; }
+<string>[A-Za-z0-9]*    { java_lval.text = yytext; return TEXT; }
 
 %%
diff --git a/src/gtkext/easygtk.c b/src/gtkext/easygtk.c
index 5d44723..c14042c 100644
--- a/src/gtkext/easygtk.c
+++ b/src/gtkext/easygtk.c
@@ -24,6 +24,9 @@
 #include "easygtk.h"
 
 
+#include "support.h"
+
+
 
 
 /******************************************************************************
@@ -608,3 +611,125 @@ GtkWidget *qck_create_menu_separator(void)
     return result;
 
 }
+
+
+
+
+
+
+
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : object   = espace dédié à l'inscription de références.       *
+*                name     = nom à donner au nouveau composant.                *
+*                filename = nom du fichier d'image à charger.                 *
+*                handler  = éventuelle fonction de sélection associée.        *
+*                data     = données à transmettre avec l'événement si besoin. *
+*                                                                             *
+*  Description : Crée et enregistre un composant 'GtkToolButton'.             *
+*                                                                             *
+*  Retour      : Simple élément de barre d'outils mis en place.               *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GtkWidget *qck_create_tool_button(GObject *object, const char *name, const char *filename, GCallback handler, gpointer data)
+{
+    GtkWidget *result;                      /* Résultat à renvoyer         */
+    GtkWidget *image;                       /* Image de représentation     */
+
+    image = get_image_from_file(filename);
+    result = GTK_WIDGET(gtk_tool_button_new(image, NULL));
+
+    if (G_IS_OBJECT(object) && name != NULL)
+    {
+        gtk_widget_ref(result);
+        g_object_set_data_full(object, name, result, (GtkDestroyNotify)g_object_unref);
+    }
+
+    gtk_widget_show(result);
+
+    if (handler != NULL)
+        g_signal_connect(result, "clicked", handler, data);
+
+	return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : object   = espace dédié à l'inscription de références.       *
+*                name     = nom à donner au nouveau composant.                *
+*                filename = nom du fichier d'image à charger.                 *
+*                handler  = éventuelle fonction de sélection associée.        *
+*                data     = données à transmettre avec l'événement si besoin. *
+*                                                                             *
+*  Description : Crée et enregistre un composant 'GtkToggleToolButton'.       *
+*                                                                             *
+*  Retour      : Simple élément de barre d'outils mis en place.               *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GtkWidget *qck_create_toggle_tool_button(GObject *object, const char *name, const char *filename, GCallback handler, gpointer data)
+{
+    GtkWidget *result;                      /* Résultat à renvoyer         */
+    GtkWidget *image;                       /* Image de représentation     */
+
+    result = GTK_WIDGET(gtk_toggle_tool_button_new());
+
+    image = get_image_from_file(filename);
+    gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(result), image);
+
+    if (G_IS_OBJECT(object) && name != NULL)
+    {
+        gtk_widget_ref(result);
+        g_object_set_data_full(object, name, result, (GtkDestroyNotify)g_object_unref);
+    }
+
+    gtk_widget_show(result);
+
+    if (handler != NULL)
+        g_signal_connect(result, "toggled", handler, data);
+
+	return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : object = espace dédié à l'inscription de références.         *
+*                name   = nom à donner au nouveau composant.                  *
+*                                                                             *
+*  Description : Crée et enregistre un composant 'GtkSeparatorToolItem'.      *
+*                                                                             *
+*  Retour      : Simple élément de barre d'outils mis en place.               *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GtkWidget *qck_create_tool_separator(GObject *object, const char *name)
+{
+    GtkWidget *result;                      /* Résultat à renvoyer         */
+
+    result = GTK_WIDGET(gtk_separator_tool_item_new());
+
+    if (G_IS_OBJECT(object) && name != NULL)
+    {
+        gtk_widget_ref(result);
+        g_object_set_data_full(object, name, result, (GtkDestroyNotify)g_object_unref);
+    }
+
+    gtk_widget_show(result);
+
+	return result;
+
+}
diff --git a/src/gtkext/easygtk.h b/src/gtkext/easygtk.h
index d7ed830..1dae530 100644
--- a/src/gtkext/easygtk.h
+++ b/src/gtkext/easygtk.h
@@ -83,4 +83,15 @@ GtkWidget *qck_create_menu_separator(void);
 
 
 
+/* Crée et enregistre un composant 'GtkToolButton'. */
+GtkWidget *qck_create_tool_button(GObject *, const char *, const char *, GCallback, gpointer);
+
+/* Crée et enregistre un composant 'GtkToggleToolButton'. */
+GtkWidget *qck_create_toggle_tool_button(GObject *, const char *, const char *, GCallback, gpointer);
+
+/* Crée et enregistre un composant 'GtkSeparatorToolItem'. */
+GtkWidget *qck_create_tool_separator(GObject *, const char *);
+
+
+
 #endif  /* _EASYGTK_H */
diff --git a/src/gtkext/support.c b/src/gtkext/support.c
index 67e7605..4eab7fe 100644
--- a/src/gtkext/support.c
+++ b/src/gtkext/support.c
@@ -90,3 +90,68 @@ gchar *find_pixmap_file(const char *filename)
     return result;
 
 }
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : filename = nom de fichier seul comme indice.                 *
+*                                                                             *
+*  Description : Construit une image à partir d'un nom de fichier.            *
+*                                                                             *
+*  Retour      : Elément mis en place ou NULL en cas d'erreur.                *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GtkWidget *get_image_from_file(const char *filename)
+{
+    GtkWidget *result;                      /* Instance à retourner        */
+    gchar *fullname;                        /* Chemin d'accès complet      */
+
+    fullname = find_pixmap_file(filename);
+
+    if (fullname != NULL)
+    {
+        result = gtk_image_new_from_file(fullname);
+        g_free(fullname);
+
+        gtk_widget_show(result);
+
+    }
+    else result = NULL;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : filename = nom de fichier seul comme indice.                 *
+*                                                                             *
+*  Description : Construit un tampon d'image à partir d'un nom de fichier.    *
+*                                                                             *
+*  Retour      : Elément mis en place ou NULL en cas d'erreur.                *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GdkPixbuf *get_pixbuf_from_file(const char *filename)
+{
+    GdkPixbuf *result;                      /* Instance à retourner        */
+    gchar *fullname;                        /* Chemin d'accès complet      */
+
+    fullname = find_pixmap_file(filename);
+
+    if (fullname != NULL)
+    {
+        result = gdk_pixbuf_new_from_file(fullname, NULL);
+        g_free(fullname);
+    }
+    else result = NULL;
+
+    return result;
+
+}
diff --git a/src/gtkext/support.h b/src/gtkext/support.h
index 8664750..1dcb3e7 100644
--- a/src/gtkext/support.h
+++ b/src/gtkext/support.h
@@ -36,6 +36,12 @@ void add_pixmap_directory(const char *);
 /* Trouve le chemin d'accès complet à un fichier donné. */
 gchar *find_pixmap_file(const char *);
 
+/* Construit une image à partir d'un nom de fichier. */
+GtkWidget *get_image_from_file(const char *);
+
+/* Construit un tampon d'image à partir d'un nom de fichier. */
+GdkPixbuf *get_pixbuf_from_file(const char *);
+
 
 
 #endif  /* _GTKEXT_SUPPORT_H */
diff --git a/src/panels/symbols.c b/src/panels/symbols.c
index c7c8369..534afee 100644
--- a/src/panels/symbols.c
+++ b/src/panels/symbols.c
@@ -25,11 +25,14 @@
 #include "symbols.h"
 
 
+#include <string.h>
 #include <gtk/gtk.h>
 
 
 #include "panel-int.h"
 #include "../format/format.h"
+#include "../gtkext/easygtk.h"
+#include "../gtkext/support.h"
 
 
 
@@ -37,12 +40,15 @@
 
 
 
+/* -------------------------- PARTIE PRINCIPALE DU PANNEAU -------------------------- */
+
 
 /* Panneau d'aperçu de graphiques (instance) */
 struct _GSymbolsPanel
 {
     GEditorPanel parent;                    /* A laisser en premier        */
 
+    GtkTreeView *treeview;                  /* Composant d'affichage       */
     GtkTreeStore *store;                    /* Modèle de gestion           */
 
     GtkBinView *binview;                    /* Affichage à faire défiler   */
@@ -50,7 +56,6 @@ struct _GSymbolsPanel
 };
 
 
-
 /* Panneau d'aperçu de graphiques (classe) */
 struct _GSymbolsPanelClass
 {
@@ -63,14 +68,17 @@ struct _GSymbolsPanelClass
 typedef enum _SymbolsColumn
 {
     SBC_ADDRESS,                            /* Adresse mémoire du symbole  */
+
+    SBC_ICON,                               /* Image de représentation     */
     SBC_NAME,                               /* Désignation humaine         */
 
+    SBC_EXPAND,                             /* Affichage des classes       */
+
     SBC_COUNT                               /* Nombre de colonnes          */
 
 } SymbolsColumn;
 
 
-
 /* Initialise la classe des panneaux d'aperçu de graphiques. */
 static void g_symbols_panel_class_init(GSymbolsPanelClass *);
 
@@ -85,6 +93,42 @@ static void reload_symbols_for_new_view(GSymbolsPanel *, GtkBinView *, bool);
 
 
 
+/* ------------------------- AFFICHAGE A L'AIDE D'UNE LISTE ------------------------- */
+
+
+/* Réagit à un changement d'affichage principal de contenu. */
+static void reload_symbols_for_new_list_view(GSymbolsPanel *);
+
+
+
+/* -------------------------- AFFICHAGE SOUS FORME D'ARBRE -------------------------- */
+
+
+/* S'assure qu'un noeud donné existe bien. */
+static GtkTreeIter ensure_symbol_node_exist(GtkTreeStore *, GtkTreeIter *, const char *);
+
+/* Détermine le point d'insertion parent d'une routine. */
+static bool find_parent_for_routine(GtkTreeStore *, const GBinRoutine *, GtkTreeIter *);
+
+/* Réagit à un changement d'affichage principal de contenu. */
+static void reload_symbols_for_new_tree_view(GSymbolsPanel *);
+
+/* Réagit à une nouvelle demande de réorganisation. */
+static void reorganize_symbols_tree_view(GtkToolButton *, GObject *);
+
+/* Fait en sorte que toutes les classes soient affichées. */
+static gboolean show_all_classes_in_tree_view(GtkTreeModel *, GtkTreePath *, GtkTreeIter *, GtkTreeView *);
+
+/* Réagit à une demande de nouvelle forme d'affichage. */
+static void modify_types_in_symbols_tree_view(GtkToggleToolButton *, GObject *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                            PARTIE PRINCIPALE DU PANNEAU                            */
+/* ---------------------------------------------------------------------------------- */
+
+
 /* Indique le type définit pour un panneau d'aperçu de graphiques. */
 G_DEFINE_TYPE(GSymbolsPanel, g_symbols_panel, G_TYPE_EDITOR_PANEL);
 
@@ -122,6 +166,12 @@ static void g_symbols_panel_class_init(GSymbolsPanelClass *klass)
 static void g_symbols_panel_init(GSymbolsPanel *panel)
 {
     GEditorPanel *base;                     /* Version basique d'instance  */
+    GObject *ref;                           /* Espace de référencement     */
+    GtkTooltips *tooltips;                  /* Affichage des bulles d'aide */
+    GtkWidget *toolbar;                     /* Barre d'outils              */
+    GtkWidget *button;                      /* Bouton de cette même barre  */
+    GtkWidget *separator;                   /* Barre de séparation vert.   */
+    GtkWidget *scrollwnd;                   /* Support défilant            */
     GtkWidget *treeview;                    /* Affichage de la liste       */
     GtkCellRenderer *renderer;              /* Moteur de rendu de colonne  */
     GtkTreeViewColumn *column;              /* Colonne de la liste         */
@@ -132,33 +182,105 @@ static void g_symbols_panel_init(GSymbolsPanel *panel)
     base->name = _("Symbols");
     base->reload_view = (reload_for_new_view_fc)reload_symbols_for_new_view;
 
-    base->widget = gtk_scrolled_window_new(NULL, NULL);
+    base->widget = gtk_vbox_new(FALSE, 0);
     gtk_widget_show(base->widget);
 
-    gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(base->widget), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
-    gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(base->widget), GTK_SHADOW_IN);
+    ref = G_OBJECT(base->widget);
+    g_object_set_data(ref, "panel", panel);
+
+    /* Barre d'outils supérieure */
+
+    tooltips = gtk_tooltips_new();
+
+    toolbar = gtk_toolbar_new();
+    gtk_widget_show(toolbar);
+    gtk_box_pack_start(GTK_BOX(base->widget), toolbar, FALSE, FALSE, 0);
+
+    //group = gtk_tool_item_group_new(_("View"));
+    //gtk_widget_show(group);
+    //gtk_container_add(GTK_CONTAINER(toolbar), group);
+
+    button = qck_create_toggle_tool_button(ref, "list", "tbutton_list_view.png", G_CALLBACK(NULL), NULL);
+    gtk_container_add(GTK_CONTAINER(toolbar), button);
+    //gtk_tool_item_group_insert(GTK_TOOL_ITEM_GROUP(group), GTK_TOOL_ITEM(button), -1);
+
+    button = qck_create_toggle_tool_button(ref, "tree", "tbutton_tree_view.png", G_CALLBACK(NULL), NULL);
+    gtk_container_add(GTK_CONTAINER(toolbar), button);
+    gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(button), TRUE);
+
 
-    panel->store = gtk_tree_store_new(SBC_COUNT, G_TYPE_STRING, G_TYPE_STRING);
+    //gtk_tool_item_group_insert(GTK_TOOL_ITEM_GROUP(group), GTK_TOOL_ITEM(button), -1);
+
+
+
+    separator = qck_create_tool_separator(NULL, NULL);
+    gtk_container_add(GTK_CONTAINER(toolbar), separator);
+
+    button = qck_create_tool_button(ref, "collapse", "tbutton_collapse.png", G_CALLBACK(reorganize_symbols_tree_view), ref);
+    gtk_container_add(GTK_CONTAINER(toolbar), button);
+
+    button = qck_create_tool_button(ref, "expand", "tbutton_expand.png", G_CALLBACK(reorganize_symbols_tree_view), ref);
+    gtk_container_add(GTK_CONTAINER(toolbar), button);
+
+    button = qck_create_tool_button(ref, "classes", "symbol_class_classic.png", G_CALLBACK(reorganize_symbols_tree_view), ref);
+    gtk_container_add(GTK_CONTAINER(toolbar), button);
+
+    separator = qck_create_tool_separator(NULL, NULL);
+    gtk_container_add(GTK_CONTAINER(toolbar), separator);
+
+    button = qck_create_toggle_tool_button(ref, "namespace", "tbutton_namespace.png", G_CALLBACK(modify_types_in_symbols_tree_view), ref);
+    gtk_container_add(GTK_CONTAINER(toolbar), button);
+
+    /* Liste arborescente ou linéaire */
+
+    scrollwnd = gtk_scrolled_window_new(NULL, NULL);
+    gtk_widget_show(scrollwnd);
+    gtk_box_pack_start(GTK_BOX(base->widget), scrollwnd, TRUE, TRUE, 0);
+
+    gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwnd), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+    gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrollwnd), GTK_SHADOW_IN);
+
+    panel->store = gtk_tree_store_new(SBC_COUNT, G_TYPE_STRING, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_BOOLEAN);
 
     treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(panel->store));
     gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(treeview), FALSE);
+    gtk_tree_view_set_enable_tree_lines(GTK_TREE_VIEW(treeview), TRUE);
+    gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(treeview), TRUE);
+
+    panel->treeview = GTK_TREE_VIEW(treeview);
+
     gtk_widget_show(treeview);
-    gtk_container_add(GTK_CONTAINER(base->widget), treeview);
+    gtk_container_add(GTK_CONTAINER(scrollwnd), treeview);
 
     g_object_unref(G_OBJECT(panel->store));
 
+    /*
     column = gtk_tree_view_column_new();
     gtk_tree_view_column_set_visible(column, FALSE);
     gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
     gtk_tree_view_set_expander_column(GTK_TREE_VIEW(treeview), column);
+    */
 
     renderer = gtk_cell_renderer_text_new();
     column = gtk_tree_view_column_new_with_attributes("Address", renderer, "text", SBC_ADDRESS, NULL);
+    //gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
+    //gtk_tree_view_set_expander_column(GTK_TREE_VIEW(treeview), column);
+
+    column = gtk_tree_view_column_new();
     gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
+    gtk_tree_view_set_expander_column(GTK_TREE_VIEW(treeview), column);
+
+    renderer = gtk_cell_renderer_pixbuf_new();
+    //column = gtk_tree_view_column_new_with_attributes("Icon", renderer, "pixbuf", SBC_ICON, NULL);
+    gtk_tree_view_column_pack_start(column, renderer, FALSE);
+    gtk_tree_view_column_add_attribute(column, renderer, "pixbuf", SBC_ICON);
 
     renderer = gtk_cell_renderer_text_new();
-    column = gtk_tree_view_column_new_with_attributes("Name", renderer, "text", SBC_NAME, NULL);
-    gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
+    //column = gtk_tree_view_column_new_with_attributes("Name", renderer, "text", SBC_NAME, NULL);
+    gtk_tree_view_column_pack_end(column, renderer, TRUE);
+    gtk_tree_view_column_add_attribute(column, renderer, "text", SBC_NAME);
+    //gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
+    //gtk_tree_view_set_expander_column(GTK_TREE_VIEW(treeview), column);
 
     select = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview));
     gtk_tree_selection_set_mode(select, GTK_SELECTION_SINGLE);
@@ -209,7 +331,7 @@ static void on_symbols_selection_change(GtkTreeSelection *selection, GSymbolsPan
     GtkTreeModel *model;                    /* Modèle de gestion           */
     gchar *string;                          /* Chaîne sélectionnée         */
     vmpa_t address;                         /* Adresse à rejoindre         */
-
+    return;
     if (gtk_tree_selection_get_selected(selection, &model, &iter))
     {
         gtk_tree_model_get(model, &iter, SBC_ADDRESS, &string, -1);
@@ -239,46 +361,354 @@ static void on_symbols_selection_change(GtkTreeSelection *selection, GSymbolsPan
 
 static void reload_symbols_for_new_view(GSymbolsPanel *panel, GtkBinView *view, bool same)
 {
+    GtkToggleToolButton *button;            /* Mode de représentation      */
+
+    panel->binview = view;
+
+    if (same) return;
+
+    gtk_tree_store_clear(panel->store);
+
+    button = g_object_get_data(G_OBJECT(G_EDITOR_PANEL(panel)->widget), "list");
+
+    if (gtk_toggle_tool_button_get_active(button))
+        reload_symbols_for_new_list_view(panel);
+    else
+        reload_symbols_for_new_tree_view(panel);
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                           AFFICHAGE A L'AIDE D'UNE LISTE                           */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : panel = panneau à mettre à jour.                             *
+*                                                                             *
+*  Description : Réagit à un changement d'affichage principal de contenu.     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void reload_symbols_for_new_list_view(GSymbolsPanel *panel)
+{
     GOpenidaBinary *binary;                 /* Binaire en cours d'édition  */
     GExeFormat *format;                     /* Format associé au binaire   */
-    GBinSymbol **symbols;                   /* Symboles trouvés            */
-    size_t count;                           /* Nombre de ces symboles      */
+    GBinRoutine **routines;                 /* Liste des routines trouvées */
+    size_t routines_count;                  /* Nombre de ces routines      */
     GArchProcessor *proc;                   /* Architecture utilisée       */
     size_t i;                               /* Boucle de parcours          */
     vmpa_t address;                         /* Adresse associée au symbole */
     char tmp[VMPA_MAX_SIZE];                /* Version humainement lisible */
     GtkTreeIter iter;                       /* Point d'insertion           */
 
-    panel->binview = view;
+    binary = gtk_bin_view_get_binary(panel->binview);
+    format = g_openida_binary_get_format(binary);
 
-    if (same) return;
+    routines = g_binary_format_get_routines(G_BIN_FORMAT(format), &routines_count);
+    qsort(routines, routines_count, sizeof(GBinRoutine *), g_binary_routine_rcompare);
 
-    gtk_tree_store_clear(panel->store);
+    if (routines != NULL)
+    {
+        proc = get_arch_processor_from_format(format);
+
+        for (i = 0; i < routines_count; i++)
+        {
+            address = g_binary_routine_get_address(routines[i]);
+            vmpa_to_string(address, g_arch_processor_get_memory_size(proc), tmp);
+
+            gtk_tree_store_append(panel->store, &iter, NULL);
+            gtk_tree_store_set(panel->store, &iter,
+                               SBC_ADDRESS, tmp,
+                               SBC_NAME, g_binary_routine_to_string(routines[i]),
+                               -1);
+
+        }
+
+    }
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                            AFFICHAGE SOUS FORME D'ARBRE                            */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : store  = gestion des différents éléments insérés.            *
+*                parent = point d'insertion parent à retrouver. [OUT]         *
+*                name   = nom du noeud ciblé.                                 *
+*                                                                             *
+*  Description : S'assure qu'un noeud donné existe bien.                      *
+*                                                                             *
+*  Retour      : Point d'insertion prochain.                                  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static GtkTreeIter ensure_symbol_node_exist(GtkTreeStore *store, GtkTreeIter *parent, const char *name)
+{
+    bool found;                             /* Bilan des recherches        */
+    GtkTreeIter iter;                       /* Boucle de parcours          */
+    gchar *string;                          /* Chaîne sélectionnée         */
+    GdkPixbuf *pixbuf;                      /* Icone pour l'élément inséré */
+
+    found = false;
+
+    if (gtk_tree_model_iter_children(GTK_TREE_MODEL(store), &iter, parent))
+        do
+        {
+            gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, SBC_NAME, &string, -1);
+            found = (strcmp(string, name) == 0);
+            g_free(string);
+
+            if (found) break;
+
+        }
+        while (gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter));
+
+    if (!found) 
+    {
+        pixbuf = get_pixbuf_from_file("symbol_package.png");
 
-    binary = gtk_bin_view_get_binary(view);
+        gtk_tree_store_append(store, &iter, parent);
+        gtk_tree_store_set(store, &iter,
+                           SBC_ICON, pixbuf,
+                           SBC_NAME, name,
+                           -1);
+
+    }
+
+    return iter;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : store   = gestion des différents éléments insérés.           *
+*                routine = routine à intégrer.                                *
+*                parent  = point d'insertion parent à constituer.             *
+*                                                                             *
+*  Description : Détermine le point d'insertion parent d'une routine.         *
+*                                                                             *
+*  Retour      : true si le point n'est pas la racine, false sinon.           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool find_parent_for_routine(GtkTreeStore *store, const GBinRoutine *routine, GtkTreeIter *parent)
+{
+    GOpenidaType *namespace;                /* Espace d'appartenance       */
+    char *string;                           /* Conversion en chaîne        */
+    char *iter;                             /* Boucle de parcours          */
+    char *token;                            /* Partie de texte isolée      */ 
+    char *saveptr;                          /* Ctx. interne de découpage   */
+
+    namespace = g_binary_routine_get_namespace(routine);
+    if (routine == NULL) return false;
+
+    string = g_openida_type_to_string(namespace);
+
+    for (iter = string; ; iter = NULL)
+    {
+        token = strtok_r(iter, "::", &saveptr);
+        if (token == NULL) break;
+
+        *parent = ensure_symbol_node_exist(store, (iter == string ? NULL : parent), token);
+
+    }
+
+    return true;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : panel = panneau à mettre à jour.                             *
+*                                                                             *
+*  Description : Réagit à un changement d'affichage principal de contenu.     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void reload_symbols_for_new_tree_view(GSymbolsPanel *panel)
+{
+    GOpenidaBinary *binary;                 /* Binaire en cours d'édition  */
+    GExeFormat *format;                     /* Format associé au binaire   */
+    GBinRoutine **routines;                 /* Liste des routines trouvées */
+    size_t routines_count;                  /* Nombre de ces routines      */
+    GArchProcessor *proc;                   /* Architecture utilisée       */
+    Routine2StringOptions options;          /* Options de rendu            */
+    GtkToggleToolButton *button;            /* Mode de représentation      */
+    size_t i;                               /* Boucle de parcours          */
+    vmpa_t address;                         /* Adresse associée au symbole */
+    char tmp[VMPA_MAX_SIZE];                /* Version humainement lisible */
+    GtkTreeIter parent;                     /* Point d'insertion parent    */
+    GtkTreeIter iter;                       /* Point d'insertion           */
+    GdkPixbuf *pixbuf;                      /* Icone pour l'élément inséré */
+
+    binary = gtk_bin_view_get_binary(panel->binview);
     format = g_openida_binary_get_format(binary);
-    symbols = g_binary_format_get_symbols(G_BIN_FORMAT(format), &count);
 
-    if (symbols != NULL)
+    routines = g_binary_format_get_routines(G_BIN_FORMAT(format), &routines_count);
+    qsort(routines, routines_count, sizeof(GBinRoutine *), g_binary_routine_rcompare);
+
+    if (routines != NULL)
     {
         proc = get_arch_processor_from_format(format);
 
-        for (i = 0; i < count; i++)
-        {
-            if (g_binary_symbol_get_target_type(symbols[i]) == STP_STRING)
-                continue;
+        options = 0;
+
+        button = g_object_get_data(G_OBJECT(G_EDITOR_PANEL(panel)->widget), "namespace");
+
+        if (gtk_toggle_tool_button_get_active(button))
+            options |= RSO_LONG_TYPE;
 
-            address = g_binary_symbol_get_address(symbols[i]);
+        for (i = 0; i < routines_count; i++)
+        {
+            address = g_binary_routine_get_address(routines[i]);
             vmpa_to_string(address, g_arch_processor_get_memory_size(proc), tmp);
 
-            gtk_tree_store_append(panel->store, &iter, NULL);
+            if (find_parent_for_routine(panel->store, routines[i], &parent))
+            {
+                pixbuf = get_pixbuf_from_file("symbol_class_classic.png");
+
+                gtk_tree_store_set(panel->store, &parent,
+                                   SBC_ICON, pixbuf,
+                                   SBC_EXPAND, TRUE,
+                                   -1);
+
+                gtk_tree_store_append(panel->store, &iter, &parent);
+
+            }
+            else
+                gtk_tree_store_append(panel->store, &iter, NULL);
+
+            pixbuf = get_pixbuf_from_file("symbol_routine_classic.png");
+
             gtk_tree_store_set(panel->store, &iter,
-                               SBC_ADDRESS, tmp,
-                               SBC_NAME, g_binary_symbol_to_string(symbols[i]),
+                               SBC_ICON, pixbuf,
+                               SBC_NAME, _g_binary_routine_to_string(routines[i], options),
                                -1);
 
+            if (pixbuf != NULL)
+                g_object_unref(G_OBJECT(pixbuf));
+
+
         }
 
     }
 
 }
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : button = bouton concerné par l'action.                       *
+*                ref    = espace de référencement des composants.             *
+*                                                                             *
+*  Description : Réagit à une nouvelle demande de réorganisation.             *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void reorganize_symbols_tree_view(GtkToolButton *button, GObject *ref)
+{
+    GSymbolsPanel *panel;                   /* Données du panneau          */
+
+    panel = (GSymbolsPanel *)g_object_get_data(ref, "panel");
+
+    if (g_object_get_data(ref, "collapse") == button)
+        gtk_tree_view_collapse_all(panel->treeview);
+
+    else if (g_object_get_data(ref, "expand") == button)
+        gtk_tree_view_expand_all(panel->treeview);
+
+    else
+        gtk_tree_model_foreach(GTK_TREE_MODEL(panel->store),
+                               (GtkTreeModelForeachFunc)show_all_classes_in_tree_view,
+                               panel->treeview);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : model    = modèle de gestion des éléments.                   *
+*                path     = chemin d'accès à l'élément courant.               *
+*                iter     = itérateur courant.                                *
+*                treeview = arborescence à manipuler ici.                     *
+*                                                                             *
+*  Description : Fait en sorte que toutes les classes soient affichées.       *
+*                                                                             *
+*  Retour      : FALSE pour continuer le parcours.                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static gboolean show_all_classes_in_tree_view(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, GtkTreeView *treeview)
+{
+    gboolean expand;                        /* Besoin en intervention      */
+    GtkTreePath *tmp;                       /* Copie pour modification     */
+
+    gtk_tree_model_get(model, iter, SBC_EXPAND, &expand, -1);
+
+    if (expand)
+    {
+        tmp = gtk_tree_path_copy(path);
+
+        if (gtk_tree_path_up(tmp))
+            gtk_tree_view_expand_to_path(treeview, tmp);
+
+        gtk_tree_path_free(tmp);
+
+    }
+
+    return FALSE;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : button = bouton concerné par l'action.                       *
+*                ref    = espace de référencement des composants.             *
+*                                                                             *
+*  Description : Réagit à une demande de nouvelle forme d'affichage.          *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void modify_types_in_symbols_tree_view(GtkToggleToolButton *button, GObject *ref)
+{
+    GSymbolsPanel *panel;                   /* Données du panneau          */
+
+    panel = (GSymbolsPanel *)g_object_get_data(ref, "panel");
+
+    reload_symbols_for_new_view(panel, panel->binview, false);
+
+}
diff --git a/src/panels/symbols.h b/src/panels/symbols.h
index 7978b30..cebf542 100644
--- a/src/panels/symbols.h
+++ b/src/panels/symbols.h
@@ -48,7 +48,6 @@ typedef struct _GSymbolsPanel GSymbolsPanel;
 typedef struct _GSymbolsPanelClass GSymbolsPanelClass;
 
 
-
 /* Indique le type définit pour un panneau d'affichage des symboles. */
 GType g_symbols_panel_get_type(void);
 
-- 
cgit v0.11.2-87-g4458