From ac447bc36e65b91f97434cf2613ccb1e768267e0 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Sun, 30 Aug 2009 10:55:45 +0000
Subject: Rendered using the GTK buffer (crappy version).

git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@107 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
---
 ChangeLog                     |  59 ++++++
 configure.ac                  |   4 +-
 plugins/stackvars/stackvars.c |   6 +-
 src/analysis/Makefile.am      |   4 +-
 src/analysis/exporter-int.h   |  67 +++++++
 src/analysis/exporter.c       | 253 ++++++++++++++++++++++++++
 src/analysis/exporter.h       |  92 ++++++++++
 src/analysis/line-int.h       |  12 +-
 src/analysis/line.c           |  26 +--
 src/analysis/line_code.c      | 136 +++++---------
 src/analysis/line_comment.c   | 130 ++++---------
 src/analysis/line_prologue.c  |  39 ++--
 src/analysis/roptions.h       |  12 ++
 src/arch/Makefile.am          |   2 +-
 src/arch/archbase.c           |  79 ++++++++
 src/arch/archbase.h           |   8 +
 src/arch/immediate.c          | 173 +++++++++++-------
 src/arch/instruction-int.h    |   5 +-
 src/arch/instruction.c        |  66 ++++++-
 src/arch/operand-int.h        |   5 +-
 src/arch/operand.c            |   2 +-
 src/arch/x86/operand.c        | 220 +++++++++++-----------
 src/arch/x86/operand.h        |   4 +-
 src/arch/x86/registers.c      | 413 ++++++++++++++++++++++++------------------
 src/arch/x86/registers.h      |  35 ++--
 src/gtkext/gtkblockview.c     | 177 +++++++++++++++++-
 src/gtkext/gtkextstatusbar.c  |  12 ++
 src/main.c                    |   5 +
 28 files changed, 1424 insertions(+), 622 deletions(-)
 create mode 100644 src/analysis/exporter-int.h
 create mode 100644 src/analysis/exporter.c
 create mode 100644 src/analysis/exporter.h
 create mode 100644 src/arch/archbase.c

diff --git a/ChangeLog b/ChangeLog
index 6d9709f..fadf8f6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,62 @@
+09-08-30  Cyrille Bagard <nocbos@gmail.com>
+
+	* configure.ac:
+	Enable AM_SILENT_RULES and disable GTK_DISABLE_DEPRECATED.
+
+	* plugins/stackvars/stackvars.c:
+	Update call (is_x86_register_...() -> g_x86_register_is_...()).
+
+	* src/analysis/exporter.c:
+	* src/analysis/exporter.h:
+	* src/analysis/exporter-int.h:
+	New entries: define a new interface for rendering/exporting disassembly.
+
+	* src/analysis/line.c:
+	* src/analysis/line_code.c:
+	* src/analysis/line_comment.c:
+	* src/analysis/line-int.h:
+	* src/analysis/line_prologue.c:
+	Follow the new way of rendering.
+
+	* src/analysis/Makefile.am:
+	Add exporter*.[ch] to libanalysis_la_SOURCES.
+
+	* src/analysis/roptions.h:
+	Define the ShowingArea enumeration (may be removed).
+
+	* src/arch/archbase.c:
+	New entry: provide one function to translate addresses into strings.
+
+	* src/arch/archbase.h:
+	Define VMPA_MAX_SIZE for translating into strings.
+
+	* src/arch/immediate.c:
+	* src/arch/instruction.c:
+	* src/arch/instruction-int.h:
+	Follow the new way of rendering and remove some unused code.
+
+	* src/arch/Makefile.am:
+	Add archbase.c to libarch_la_SOURCES.
+
+	* src/arch/operand.c:
+	* src/arch/operand-int.h:
+	* src/arch/x86/operand.c:
+	* src/arch/x86/operand.h:
+	Follow the new way of rendering and remove some unused code.
+
+	* src/arch/x86/registers.c:
+	* src/arch/x86/registers.h:
+	Make GLib objects from registers and follow the new way of rendering.
+
+	* src/gtkext/gtkblockview.c:
+	Render using the GTK buffer (crappy version).
+
+	* src/gtkext/gtkextstatusbar.c:
+	Fix one bug relative to threads.
+
+	* src/main.c:
+	Load the tag table for the GTK rendering.
+
 09-08-12  Cyrille Bagard <nocbos@gmail.com>
 
 	* src/analysis/binary.c:
diff --git a/configure.ac b/configure.ac
index 2570718..c483d47 100644
--- a/configure.ac
+++ b/configure.ac
@@ -9,6 +9,7 @@ AC_INIT([openida], [0.0.1], [nocbos@gmail.com])
 
 AC_CONFIG_HEADERS([config.h])
 AM_INIT_AUTOMAKE
+AM_SILENT_RULES
 
 AM_GNU_GETTEXT_VERSION([0.17])
 AM_GNU_GETTEXT([external])
@@ -150,7 +151,8 @@ AC_SUBST(WARNING_FLAGS)
 # _XOPEN_SOURCE: strdup, snprintf
 # _ISOC99_SOURCE: INFINITY; NAN
 # GTK_DISABLE_DEPRECATED: on reste conforme au C99
-COMPLIANCE_FLAGS="-D_GNU_SOURCE -DGTK_DISABLE_DEPRECATED"
+COMPLIANCE_FLAGS="-D_GNU_SOURCE "
+#-DGTK_DISABLE_DEPRECATED"
 
 AC_SUBST(COMPLIANCE_FLAGS)
 
diff --git a/plugins/stackvars/stackvars.c b/plugins/stackvars/stackvars.c
index 5d0da59..32535e9 100644
--- a/plugins/stackvars/stackvars.c
+++ b/plugins/stackvars/stackvars.c
@@ -232,8 +232,8 @@ static GArchOperand *replace_stack_vars_in_operand(const GArchOperand *operand)
 {
     GArchOperand *result;                   /* Encapsulation à retourner   */
     uint8_t scale;                          /* Puissance de deux           */
-    x86_register *index;                    /* Registre servant d'indice   */
-    x86_register *base;                     /* Registre de base            */
+    GX86Register *index;                    /* Registre servant d'indice   */
+    GX86Register *base;                     /* Registre de base            */
     GImmOperand *displacement;              /* Décallage supplémentaire    */
 
     result = NULL;
@@ -244,7 +244,7 @@ static GArchOperand *replace_stack_vars_in_operand(const GArchOperand *operand)
         base = g_x86_mod_rm_operand_get_base(G_X86_MOD_RM_OPERAND(operand));
         displacement = g_x86_mod_rm_operand_get_displacement(G_X86_MOD_RM_OPERAND(operand));
 
-        if (scale == 0 && is_x86_register_base_pointer(index) && base == NULL)
+        if (scale == 0 && g_x86_register_is_base_pointer(index) && base == NULL)
         {
 
             printf(" [+] found one ebp !!\n");
diff --git a/src/analysis/Makefile.am b/src/analysis/Makefile.am
index 2a456ff..d7c694b 100755
--- a/src/analysis/Makefile.am
+++ b/src/analysis/Makefile.am
@@ -4,8 +4,10 @@ noinst_LTLIBRARIES  = libanalysis.la
 libanalysis_la_SOURCES =				\
 	binary.h binary.c					\
 	delayed.h delayed.c					\
-	line.h line.c						\
+	exporter-int.h						\
+	exporter.h exporter.c				\
 	line-int.h							\
+	line.h line.c						\
 	line_code.h line_code.c				\
 	line_comment.h line_comment.c		\
 	line_prologue.h line_prologue.c		\
diff --git a/src/analysis/exporter-int.h b/src/analysis/exporter-int.h
new file mode 100644
index 0000000..0c93980
--- /dev/null
+++ b/src/analysis/exporter-int.h
@@ -0,0 +1,67 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * line-int.h - prototypes pour la traduction humaine des lignes de rendus
+ *
+ * Copyright (C) 2009 Cyrille Bagard
+ *
+ *  This file is part of OpenIDA.
+ *
+ *  OpenIDA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  OpenIDA is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ANALYSIS_EXPORTER_INT_H
+#define _ANALYSIS_EXPORTER_INT_H
+
+
+#include "exporter.h"
+
+
+
+/* Ajoute à un texte GTK le contenu de la ligne de rendu. */
+typedef void (* add_to_gtk_buffer_fc) (GContentExporter *, MainRendering, GtkTextBuffer *, GtkTextIter *, gint [SAR_COUNT]);
+
+/* Traduit une instruction en version humainement lisible. */
+typedef void (* add_arch_to_gtk_buffer_fc) (const GContentExporter *, const GExeFormat *, AsmSyntax, GtkTextBuffer *, GtkTextIter *);
+
+
+
+/* Exportation de contenu (instance) */
+struct _GContentExporter
+{
+    GObject parent;                         /* A laisser en premier        */
+
+    add_to_gtk_buffer_fc add_to_gtk_buffer; /* Constitution du texte GTK   */
+
+    add_arch_to_gtk_buffer_fc add_arch_to_gtk_buffer;   /* Constitution... */
+
+};
+
+
+/* Exportation de contenu (classe) */
+struct _GContentExporterClass
+{
+    GObjectClass parent;                    /* A laisser en premier        */
+
+    GtkTextTag *tags[RTT_COUNT];            /* Décorateurs pour les textes */
+
+};
+
+
+/* Ajoute du texte à un texte GTK via l'instance spécifiée. */
+void g_content_exporter_insert_with_gtk_tag(GContentExporter *, GtkTextBuffer *, GtkTextIter *, const char *, size_t, RenderingTagType);
+
+
+
+#endif  /* _ANALYSIS_EXPORTER_INT_H */
diff --git a/src/analysis/exporter.c b/src/analysis/exporter.c
new file mode 100644
index 0000000..dd0f6c0
--- /dev/null
+++ b/src/analysis/exporter.c
@@ -0,0 +1,253 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * exporter.c - traduction humaine des lignes de rendus
+ *
+ * Copyright (C) 2009 Cyrille Bagard
+ *
+ *  This file is part of OpenIDA.
+ *
+ *  OpenIDA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  OpenIDA is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "exporter.h"
+
+
+#include "exporter-int.h"
+
+
+
+/* Indique le type défini pour une exportation de contenu. */
+G_DEFINE_TYPE(GContentExporter, g_content_exporter, G_TYPE_OBJECT);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des lignes de représentation.           *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_content_exporter_class_init(GContentExporterClass *klass)
+{
+    GtkTextTagTable *table;                 /* Seule table globale valable */
+    GtkTextTag *tag;
+
+    /* Décorateurs GTK */
+
+    table = get_gtk_tag_table();
+
+    tag = gtk_text_tag_new(NULL);
+
+    g_object_set(G_OBJECT(tag), "foreground", "green", NULL);
+
+    klass->tags[RTT_COMMENT] = tag;
+    gtk_text_tag_table_add(table, tag);
+
+    tag = gtk_text_tag_new(NULL);
+
+    g_object_set(G_OBJECT(tag), "foreground", "gray", NULL);
+
+    klass->tags[RTT_RAW_CODE] = tag;
+    gtk_text_tag_table_add(table, tag);
+
+    tag = gtk_text_tag_new(NULL);
+
+    g_object_set(G_OBJECT(tag), "foreground", "red", NULL);
+
+    klass->tags[RTT_INSTRUCTION] = tag;
+    gtk_text_tag_table_add(table, tag);
+
+    tag = gtk_text_tag_new(NULL);
+
+    g_object_set(G_OBJECT(tag), "foreground", "purple", NULL);
+
+    klass->tags[RTT_IMMEDIATE] = tag;
+    gtk_text_tag_table_add(table, tag);
+
+    tag = gtk_text_tag_new(NULL);
+
+    g_object_set(G_OBJECT(tag), "foreground", "blue", NULL);
+
+    klass->tags[RTT_REGISTER] = tag;
+    gtk_text_tag_table_add(table, tag);
+
+    tag = gtk_text_tag_new(NULL);
+
+    g_object_set(G_OBJECT(tag), "foreground", "blue", "background", "black", NULL);
+
+    klass->tags[RTT_HOOK] = tag;
+    gtk_text_tag_table_add(table, tag);
+
+    tag = gtk_text_tag_new(NULL);
+
+    g_object_set(G_OBJECT(tag), "foreground", "white", "background", "black", NULL);
+
+    klass->tags[RTT_SIGNS] = tag;
+    gtk_text_tag_table_add(table, tag);
+
+    tag = gtk_text_tag_new(NULL);
+
+    g_object_set(G_OBJECT(tag), "foreground", "red", "background", "black", NULL);
+
+    klass->tags[RTT_LTGT] = tag;
+    gtk_text_tag_table_add(table, tag);
+
+    tag = gtk_text_tag_new(NULL);
+
+    g_object_set(G_OBJECT(tag), "foreground", "black", NULL);
+
+    klass->tags[RTT_SEGMENT] = tag;
+    gtk_text_tag_table_add(table, tag);
+
+    tag = gtk_text_tag_new(NULL);
+
+    g_object_set(G_OBJECT(tag), "foreground", "orange", NULL);
+
+    klass->tags[RTT_STRING] = tag;
+    gtk_text_tag_table_add(table, tag);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : exporter = instance à initialiser.                           *
+*                                                                             *
+*  Description : Initialise une instance de ligne de représentation.          *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_content_exporter_init(GContentExporter *exporter)
+{
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : table = éventuelle instance à enregistrer.                   *
+*                                                                             *
+*  Description : Définit et/ou renvoie le singleton pour les marques de texte.*
+*                                                                             *
+*  Retour      : Table courante à utiliser.                                   *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GtkTextTagTable *_get_gtk_tag_table(GtkTextTagTable *table)
+{
+    static GtkTextTagTable *result = NULL;  /* Table valable à renvoyer    */
+
+    if (table != NULL)
+    {
+        if (result != NULL) /* TODO : free() */;
+        result = table;
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : exporter = instance sachant exporter son contenu.            *
+*                buffer   = zone de texte à venir compléter.                  *
+*                iter     = point d'insertion du nouveau texte. [OUT]         *
+*                text     = texte à insérer dans l'existant.                  *
+*                length   = taille du texte à traiter.                        *
+*                tag      = type de décorateur à utiliser.                    *
+*                                                                             *
+*  Description : Ajoute du texte à un texte GTK via l'instance spécifiée.     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_content_exporter_insert_with_gtk_tag(GContentExporter *exporter, GtkTextBuffer *buffer, GtkTextIter *iter, const char *text, size_t length, RenderingTagType tag)
+{
+    size_t init;                            /* Point d'insertion initial   */
+
+    init = gtk_text_iter_get_offset(iter);
+
+    if (tag != RTT_NONE)
+        gtk_text_buffer_insert_with_tags(buffer, iter, text, length,
+                                         G_CONTENT_EXPORTER_GET_CLASS(exporter)->tags[tag],
+                                         NULL);
+
+    else gtk_text_buffer_insert_with_tags(buffer, iter, text, length, NULL);
+
+    gtk_text_iter_set_offset(iter, init + length);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : exporter  = instance sachant exporter son contenu.           *
+*                rendering = support effectif final des lignes de code.       *
+*                buffer    = zone de texte à venir compléter.                 *
+*                iter      = point d'insertion du nouveau texte.              *
+*                                                                             *
+*  Description : Ajoute à un texte GTK le contenu de l'instance spécifiée.    *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_content_exporter_add_to_gtk_buffer(GContentExporter *exporter, MainRendering rendering, GtkTextBuffer *buffer, GtkTextIter *iter)
+{
+    if (exporter->add_to_gtk_buffer != NULL)
+        exporter->add_to_gtk_buffer(exporter, rendering, buffer, iter, NULL);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : exporter  = instance sachant exporter son contenu.           *
+*                format    = format du binaire manipulé.                      *
+*                syntax    = type de représentation demandée.                 *
+*                buffer    = zone de texte à venir compléter.                 *
+*                iter      = point d'insertion du nouveau texte.              *
+*                                                                             *
+*  Description : Ajoute à un texte GTK le contenu d'une architecture.         *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_content_exporter_add_arch_to_gtk_buffer(const GContentExporter *exporter, const GExeFormat *format, AsmSyntax syntax, GtkTextBuffer *buffer, GtkTextIter *iter)
+{
+    if (exporter->add_arch_to_gtk_buffer != NULL)
+        exporter->add_arch_to_gtk_buffer(exporter, format, syntax, buffer, iter);
+
+}
diff --git a/src/analysis/exporter.h b/src/analysis/exporter.h
new file mode 100644
index 0000000..6d99463
--- /dev/null
+++ b/src/analysis/exporter.h
@@ -0,0 +1,92 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * exporter.h - prototypes pour la traduction humaine des lignes de rendus
+ *
+ * Copyright (C) 2009 Cyrille Bagard
+ *
+ *  This file is part of OpenIDA.
+ *
+ *  OpenIDA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  OpenIDA is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ANALYSIS_EXPORTER_H
+#define _ANALYSIS_EXPORTER_H
+
+
+#include <glib-object.h>
+#include <gtk/gtktextbuffer.h>
+
+
+#include "roptions.h"
+
+
+/* Types de partie de rendu */
+typedef enum _RenderingTagType
+{
+    RTT_COMMENT,                            /* Commentaire                 */
+    RTT_RAW_CODE,                           /* Code binaire brut           */
+
+    RTT_INSTRUCTION,                        /* Code binaire brut           */
+
+    RTT_IMMEDIATE,                          /* Valeur immédiate            */
+
+    RTT_REGISTER,                           /* Registre                    */
+
+    RTT_HOOK,                               /* Crochets '[' et ']'         */
+    RTT_SIGNS,                              /* Signes '+', '-' et '*'      */
+    RTT_LTGT,                               /* Caractères '<' et '>'       */
+
+    RTT_SEGMENT,                            /* Indication de segment       */
+    RTT_STRING,                             /* Chaîne de caractères avec " */
+
+    RTT_COUNT
+
+} RenderingTagType;
+
+
+#define RTT_NONE RTT_COUNT
+
+
+#define G_TYPE_CONTENT_EXPORTER               g_content_exporter_get_type()
+#define G_CONTENT_EXPORTER(obj)               (G_TYPE_CHECK_INSTANCE_CAST((obj), g_content_exporter_get_type(), GContentExporter))
+#define G_IS_CONTENT_EXPORTER(obj)            (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_content_exporter_get_type()))
+#define G_CONTENT_EXPORTER_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_CONTENT_EXPORTER, GContentExporterClass))
+#define G_IS_CONTENT_EXPORTER_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_CONTENT_EXPORTER))
+#define G_CONTENT_EXPORTER_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_CONTENT_EXPORTER, GContentExporterClass))
+
+
+/* Exportation de contenu (instance) */
+typedef struct _GContentExporter GContentExporter;
+
+/* Exportation de contenu (classe) */
+typedef struct _GContentExporterClass GContentExporterClass;
+
+
+/* Indique le type défini pour une exportation de contenu. */
+GType g_content_exporter_get_type(void);
+
+/* Définit et/ou renvoie le singleton pour les marques de texte. */
+GtkTextTagTable *_get_gtk_tag_table(GtkTextTagTable *);
+
+#define get_gtk_tag_table() _get_gtk_tag_table(NULL)
+
+/* Ajoute à un texte GTK le contenu de l'instance spécifiée. */
+void g_content_exporter_add_to_gtk_buffer(GContentExporter *, MainRendering, GtkTextBuffer *, GtkTextIter *);
+
+/* Ajoute à un texte GTK le contenu d'une architecture. */
+void g_content_exporter_add_arch_to_gtk_buffer(const GContentExporter *, const GExeFormat *, AsmSyntax, GtkTextBuffer *, GtkTextIter *);
+
+
+#endif  /* _ANALYSIS_EXPORTER_H */
diff --git a/src/analysis/line-int.h b/src/analysis/line-int.h
index 4d181f9..c603837 100644
--- a/src/analysis/line-int.h
+++ b/src/analysis/line-int.h
@@ -28,6 +28,7 @@
 #include "line.h"
 
 
+#include "exporter-int.h"
 #include "../common/dllist.h"
 
 
@@ -35,18 +36,15 @@
 /* Méthode de mise à jour du nombre d'octets maximal par instruction. */
 typedef void (* get_bin_len_fc) (GRenderingLine *, off_t *);
 
-/* Méthode de mise à jour d'une ligne de représentation. */
-typedef void (* refresh_markup_fc) (GRenderingLine *, MainRendering);
-
 
 /* Ligne de représentation générique (instance) */
 struct _GRenderingLine
 {
-    GObject parent;                         /* A laisser en premier        */
+    GContentExporter parent;                /* A laisser en premier        */
 
     DL_LIST_ITEM(link);                     /* Maillon de liste chaînée    */
 
-    uint64_t offset;                        /* Position en mémoire/physique*/
+    vmpa_t offset;                          /* Position en mémoire/physique*/
     off_t length;                           /* Nombre d'adresses associées */
 
     RenderingLineType type;                 /* Type de représentation      */
@@ -63,8 +61,6 @@ struct _GRenderingLine
     get_bin_len_fc get_bin_len;             /* Nbre d'octets représentés   */
     off_t max_bin_len[MRD_COUNT];           /* Nombre global maximal       */
 
-    refresh_markup_fc refresh_markup;       /* Reconstruit la représentat° */
-
 };
 
 
@@ -77,7 +73,7 @@ struct _GRenderingLine
 /* Ligne de représentation générique (classe) */
 struct _GRenderingLineClass
 {
-    GObjectClass parent;                    /* A laisser en premier        */
+    GContentExporterClass parent;           /* A laisser en premier        */
 
     GtkStyle *style;                        /* Style GTK commun aux lignes */
 
diff --git a/src/analysis/line.c b/src/analysis/line.c
index 988de1f..739db2c 100644
--- a/src/analysis/line.c
+++ b/src/analysis/line.c
@@ -62,7 +62,7 @@ static GdkPixbuf *g_rendering_line_render_icon(const GRenderingLine *, const cha
 
 
 /* Indique le type définit pour une ligne de représentation. */
-G_DEFINE_TYPE(GRenderingLine, g_rendering_line, G_TYPE_OBJECT);
+G_DEFINE_TYPE(GRenderingLine, g_rendering_line, G_TYPE_CONTENT_EXPORTER);
 
 
 /******************************************************************************
@@ -106,29 +106,8 @@ static void g_rendering_line_class_init(GRenderingLineClass *klass)
 
 static void g_rendering_line_init(GRenderingLine *line)
 {
-    GdkScreen *screen;                      /* Ecran d'application         */
-    PangoFontDescription *desc;             /* Description de la police    */
-    MainRendering i;                        /* Boucle de parcours          */
-
-    static PangoContext *context = NULL;    /* Contexte graphique Pango    */
-
     DL_LIST_ITEM_INIT(&line->link);
 
-    if (context == NULL)
-    {
-        screen = gdk_screen_get_default();
-        desc = pango_font_description_from_string("mono 10");
-
-        context = gdk_pango_context_get_for_screen(screen);
-        pango_context_set_font_description(context, desc);
-
-    }
-
-    for (i = 0; i < MRD_COUNT; i++)
-        line->layout[i] = pango_layout_new(context);
-
-    line->get_bin_len = NULL;
-    line->refresh_markup = NULL;
 
 }
 
@@ -429,7 +408,7 @@ static GdkPixbuf *g_rendering_line_render_icon(const GRenderingLine *line, const
 void g_rendering_line_draw(GRenderingLine *line, GdkDrawable *drawable, GdkGC *gc, gint x0, gint x1, gint y, gint h, MainRendering rendering)
 {
     GdkPixbuf *pixbuf;                      /* Données utiles au dessin    */
-
+    return ;
     gdk_draw_layout(drawable, gc, x1, y, line->layout[rendering]);
 
     if (line->to != NULL)
@@ -604,7 +583,6 @@ void g_rendering_line_update_bin_len(GRenderingLine *lines, GRenderingLine *last
     lines_list_for_each(iter, lines)
     {
         iter->max_bin_len[rendering] = (bin_len > 0 ? bin_len * 2 + (bin_len - 1) : 0);
-        iter->refresh_markup(iter, rendering);
 
         if (iter == last) break;
 
diff --git a/src/analysis/line_code.c b/src/analysis/line_code.c
index 697dd7d..4ceabec 100644
--- a/src/analysis/line_code.c
+++ b/src/analysis/line_code.c
@@ -61,8 +61,8 @@ static void g_code_line_init(GCodeLine *);
 /* Met à jour le nombre d'octets maximal par instruction. */
 void g_code_line_get_binary_len(GCodeLine *, off_t *);
 
-/* Met à jour la ligne de représentation de code. */
-void g_code_line_refresh_markup(GCodeLine *, MainRendering);
+/* Ajoute à un texte GTK le contenu de la ligne de code. */
+static void g_code_line_add_to_gtk_buffer(GCodeLine *, MainRendering, GtkTextBuffer *, GtkTextIter *, gint [SAR_COUNT]);
 
 
 
@@ -103,14 +103,18 @@ static void g_code_line_class_init(GCodeLineClass *klass)
 
 static void g_code_line_init(GCodeLine *line)
 {
-    GRenderingLine *parent;                 /* Instance parente            */
+    GContentExporter *exporter_parent;      /* Instance parente #1         */
+    GRenderingLine *line_parent;            /* Instance parente #2         */
 
-    parent = G_RENDERING_LINE(line);
+    exporter_parent = G_CONTENT_EXPORTER(line);
 
-    parent->type = RLT_CODE;
+    exporter_parent->add_to_gtk_buffer = (add_to_gtk_buffer_fc)g_code_line_add_to_gtk_buffer;
 
-    parent->get_bin_len = (get_bin_len_fc)g_code_line_get_binary_len;
-    parent->refresh_markup = (refresh_markup_fc)g_code_line_refresh_markup;
+    line_parent = G_RENDERING_LINE(line);
+
+    line_parent->type = RLT_CODE;
+
+    line_parent->get_bin_len = (get_bin_len_fc)g_code_line_get_binary_len;
 
 }
 
@@ -143,8 +147,11 @@ void g_code_line_get_binary_len(GCodeLine *line, off_t *blen)
 *                                                                             *
 *  Paramètres  : line      = ligne de représentation à actualiser.            *
 *                rendering = support effectif final des lignes de code.       *
+*                buffer    = zone de texte à venir compléter.                 *
+*                iter      = point d'insertion du nouveau texte.              *
+*                lengths   = taille des différentes composantes de la ligne.  *
 *                                                                             *
-*  Description : Met à jour la ligne de représentation de code.               *
+*  Description : Ajoute à un texte GTK le contenu de la ligne de code.        *
 *                                                                             *
 *  Retour      : -                                                            *
 *                                                                             *
@@ -152,68 +159,35 @@ void g_code_line_get_binary_len(GCodeLine *line, off_t *blen)
 *                                                                             *
 ******************************************************************************/
 
-void g_code_line_refresh_markup(GCodeLine *line, MainRendering rendering)
+static void g_code_line_add_to_gtk_buffer(GCodeLine *line, MainRendering rendering, GtkTextBuffer *buffer, GtkTextIter *iter, gint lengths[SAR_COUNT])
 {
     bool show_address;                      /* Affichage de l'adresse ?    */
     bool show_code;                         /* Affichage du code brut ?    */
-    size_t len;                             /* Taille du contenu           */
-    char *content;                          /* Contenu réellement imprimé  */
+    MemoryDataSize msize;                   /* Taille du bus d'adresses    */
+    char address[VMPA_MAX_SIZE];            /* Adresse au format texte     */
+    size_t len;                             /* Taille de l'élément inséré  */
+    const bin_t *content;                   /* Contenu binaire global      */
     off_t bin_offset;                       /* Début de l'instruction      */
     off_t bin_len;                          /* Taille d'instruction        */
-    char buffer[CODE_BUFFER_LEN];           /* Zone tampon à utiliser #1   */
-    char *buffer2;                          /* Zone tampon à utiliser #2   */
-    const uint8_t *exe_content;             /* Contenu binaire global      */
-    const off_t *max_bin_len;               /* Taille de ligne max/globale */
     char *bin_code;                         /* Tampon du code binaire      */
-    off_t k;                                /* Boucle de parcours #2       */
-    off_t j;                                /* Boucle de parcours #1       */
+    off_t i;                                /* Boucle de parcours          */
 
     show_address = g_rendering_options_has_to_show_address(line->options, rendering);
     show_code = g_rendering_options_has_to_show_code(line->options, rendering);
 
-    len = strlen("<tt>") + 1;
-    content = (char *)calloc(len, sizeof(char));
-    strcpy(content, "<tt>");
-
-    if (show_code)
-        g_arch_instruction_get_location(line->instr, &bin_offset, &bin_len, NULL);
-
-    /* Eventuelle adresse virtuelle */
+    /* Eventuelle adresse virtuelle ou physique */
 
     if (show_address)
     {
-        switch (g_arch_processor_get_memory_size(g_rendering_options_get_processor(line->options)))
-        {
-            case MDS_8_BITS:
-                snprintf(buffer, CODE_BUFFER_LEN,
-                         "<span foreground='#333333'>0x%02llx</span>",
-                         G_RENDERING_LINE(line)->offset);
-                break;
-
-            case MDS_16_BITS:
-                snprintf(buffer, CODE_BUFFER_LEN,
-                         "<span foreground='#333333'>0x%04llx</span>",
-                         G_RENDERING_LINE(line)->offset);
-                break;
-
-            case MDS_32_BITS:
-                snprintf(buffer, CODE_BUFFER_LEN,
-                         "<span foreground='#333333'>0x%08llx</span>",
-                         G_RENDERING_LINE(line)->offset);
-                break;
-
-            default:
-            case MDS_64_BITS:
-                snprintf(buffer, CODE_BUFFER_LEN,
-                         "<span foreground='#333333'>0x%16llx</span>",
-                         G_RENDERING_LINE(line)->offset);
-                break;
+        msize = g_arch_processor_get_memory_size(g_rendering_options_get_processor(line->options));
 
-        }
+        len = vmpa_to_string(G_RENDERING_LINE(line)->offset, msize, address);
 
-        len += strlen(buffer);
-        content = (char *)realloc(content, len * sizeof(char));
-        strcat(content, buffer);
+        g_content_exporter_insert_with_gtk_tag(G_CONTENT_EXPORTER(line), buffer, iter,
+                                           address, len, RTT_NONE);
+
+        g_content_exporter_insert_with_gtk_tag(G_CONTENT_EXPORTER(line), buffer, iter,
+                                               "\t", 1, RTT_NONE);
 
     }
 
@@ -221,56 +195,34 @@ void g_code_line_refresh_markup(GCodeLine *line, MainRendering rendering)
 
     if (show_code)
     {
-        exe_content = g_binary_format_get_content(G_BIN_FORMAT(g_rendering_options_get_format(line->options)), NULL);
-        max_bin_len = &G_RENDERING_LINE(line)->max_bin_len[rendering];
-
-        bin_code = (char *)calloc(*max_bin_len + 1, sizeof(char));
+        content = g_binary_format_get_content(G_BIN_FORMAT(g_rendering_options_get_format(line->options)), NULL);
+        g_arch_instruction_get_location(line->instr, &bin_offset, &bin_len, NULL);
 
-        k = 0;
+        bin_code = (char *)calloc(bin_len * 3, sizeof(char));
 
-        for (j = 0; j < bin_len; j++)
+        for (i = 0; i < bin_len; i++)
         {
-            if ((j + 1) < bin_len)
-                k += snprintf(&bin_code[j * (2 + 1)], 4, "%02hhx ", exe_content[bin_offset + j]);
+            if ((i + 1) < bin_len)
+                snprintf(&bin_code[i * (2 + 1)], 4, "%02hhx ", content[bin_offset + i]);
             else
-                k += snprintf(&bin_code[j * (2 + 1)], 3, "%02hhx", exe_content[bin_offset + j]);
+                snprintf(&bin_code[i * (2 + 1)], 3, "%02hhx", content[bin_offset + i]);
         }
  
-        for (; k < *max_bin_len; k++)
-            snprintf(&bin_code[k], 2, " ");
-
-        if (show_address) len += strlen("\t");
-        len += strlen(bin_code);
-        content = (char *)realloc(content, len * sizeof(char));
-        if (show_address) strcat(content, "\t");
-        strcat(content, bin_code);
+        g_content_exporter_insert_with_gtk_tag(G_CONTENT_EXPORTER(line), buffer, iter,
+                                               bin_code, bin_len * 3 - 1, RTT_RAW_CODE);
 
         free(bin_code);
 
+        g_content_exporter_insert_with_gtk_tag(G_CONTENT_EXPORTER(line), buffer, iter,
+                                               "\t", 1, RTT_NONE);
+
     }
 
     /* Instruction proprement dite */
 
-    buffer2 = g_arch_instruction_get_text(line->instr, g_rendering_options_get_format(line->options), ASX_INTEL/*FIXME*/);
-
-    if (show_address || show_code) len += strlen("\t");
-    len += strlen(buffer2);
-
-    content = (char *)realloc(content, len * sizeof(char));
-    if (show_address || show_code) strcat(content, "\t");
-    strcat(content, buffer2);
-
-    free(buffer2);
-
-    /* Finalisation */
-
-    len += strlen("</tt>");
-    content = (char *)realloc(content, len * sizeof(char));
-    strcat(content, "</tt>");
-
-    pango_layout_set_markup(G_RENDERING_LINE(line)->layout[rendering], content, len - 1);
-
-    free(content);
+    g_content_exporter_add_arch_to_gtk_buffer(G_CONTENT_EXPORTER(line->instr),
+                                              g_rendering_options_get_format(line->options),
+                                              ASX_INTEL/*FIXME*/, buffer, iter);
 
 }
 
diff --git a/src/analysis/line_comment.c b/src/analysis/line_comment.c
index a39cb11..2a3030c 100644
--- a/src/analysis/line_comment.c
+++ b/src/analysis/line_comment.c
@@ -57,8 +57,8 @@ static void g_comment_line_class_init(GCommentLineClass *);
 /* Initialise la classe des lignes de commentaires entière. */
 static void g_comment_line_init(GCommentLine *);
 
-/* Met à jour la ligne de représentation de commentaires. */
-void g_comment_line_refresh_markup(GCommentLine *, MainRendering);
+/* Ajoute à un texte GTK le contenu de la ligne de commentaires. */
+static void g_comment_line_add_to_gtk_buffer(GCommentLine *, MainRendering, GtkTextBuffer *, GtkTextIter *, gint [SAR_COUNT]);
 
 
 
@@ -99,13 +99,16 @@ static void g_comment_line_class_init(GCommentLineClass *klass)
 
 static void g_comment_line_init(GCommentLine *line)
 {
-    GRenderingLine *parent;                 /* Instance parente            */
+    GContentExporter *exporter_parent;      /* Instance parente #1         */
+    GRenderingLine *line_parent;            /* Instance parente #2         */
 
-    parent = G_RENDERING_LINE(line);
+    exporter_parent = G_CONTENT_EXPORTER(line);
 
-    parent->type = RLT_PROTOTYPE/* TODO */;
+    exporter_parent->add_to_gtk_buffer = (add_to_gtk_buffer_fc)g_comment_line_add_to_gtk_buffer;
 
-    parent->refresh_markup = (refresh_markup_fc)g_comment_line_refresh_markup;
+    line_parent = G_RENDERING_LINE(line);
+
+    line_parent->type = RLT_PROTOTYPE/* TODO */;
 
 }
 
@@ -114,8 +117,11 @@ static void g_comment_line_init(GCommentLine *line)
 *                                                                             *
 *  Paramètres  : line      = ligne de représentation à actualiser.            *
 *                rendering = support effectif final des lignes de code.       *
+*                buffer    = zone de texte à venir compléter.                 *
+*                iter      = point d'insertion du nouveau texte.              *
+*                lengths   = taille des différentes composantes de la ligne.  *
 *                                                                             *
-*  Description : Met à jour la ligne de représentation de commentaires.       *
+*  Description : Ajoute à un texte GTK le contenu de la ligne de commentaires.*
 *                                                                             *
 *  Retour      : -                                                            *
 *                                                                             *
@@ -123,116 +129,48 @@ static void g_comment_line_init(GCommentLine *line)
 *                                                                             *
 ******************************************************************************/
 
-void g_comment_line_refresh_markup(GCommentLine *line, MainRendering rendering)
+static void g_comment_line_add_to_gtk_buffer(GCommentLine *line, MainRendering rendering, GtkTextBuffer *buffer, GtkTextIter *iter, gint lengths[SAR_COUNT])
 {
     bool show_address;                      /* Affichage de l'adresse ?    */
     bool show_code;                         /* Affichage du code brut ?    */
-    size_t len;                             /* Taille du contenu           */
-    char *content;                          /* Contenu réellement imprimé  */
-    char buffer[CODE_BUFFER_LEN];           /* Zone tampon à utiliser      */
-    const off_t *max_bin_len;               /* Taille de ligne max/globale */
-    size_t clen;                            /* Taille du commentaire       */
+    MemoryDataSize msize;                   /* Taille du bus d'adresses    */
+    char address[VMPA_MAX_SIZE];            /* Adresse au format texte     */
+    size_t len;                             /* Taille de l'élément inséré  */
 
     show_address = g_rendering_options_has_to_show_address(line->options, rendering);
     show_code = g_rendering_options_has_to_show_code(line->options, rendering);
 
-    len = strlen("<tt>") + 1;
-    content = (char *)calloc(len, sizeof(char));
-    strcpy(content, "<tt>");
-
-    /* Eventuelle adresse virtuelle */
+    /* Eventuelle adresse virtuelle ou physique */
 
     if (show_address)
     {
-        switch (g_arch_processor_get_memory_size(g_rendering_options_get_processor(line->options)))
-        {
-            case MDS_8_BITS:
-                snprintf(buffer, CODE_BUFFER_LEN,
-                         "<span foreground='#333333'>0x%02llx</span>",
-                         G_RENDERING_LINE(line)->offset);
-                break;
-
-            case MDS_16_BITS:
-                snprintf(buffer, CODE_BUFFER_LEN,
-                         "<span foreground='#333333'>0x%04llx</span>",
-                         G_RENDERING_LINE(line)->offset);
-                break;
-
-            case MDS_32_BITS:
-                snprintf(buffer, CODE_BUFFER_LEN,
-                         "<span foreground='#333333'>0x%08llx</span>",
-                         G_RENDERING_LINE(line)->offset);
-                break;
-
-            default:
-            case MDS_64_BITS:
-                snprintf(buffer, CODE_BUFFER_LEN,
-                         "<span foreground='#333333'>0x%16llx</span>",
-                         G_RENDERING_LINE(line)->offset);
-                break;
-
-        }
-
-        len += strlen(buffer);
-        content = (char *)realloc(content, len * sizeof(char));
-        strcat(content, buffer);
-
-    }
-
-    /* Eventuel code brut (sauté) */
-
-    if (show_code)
-    {
-        max_bin_len = &G_RENDERING_LINE(line)->max_bin_len[rendering];
-
-        clen = (show_address ? strlen("\t") : 0);
-        clen += *max_bin_len;
-
-        content = (char *)realloc(content, (len + clen) * sizeof(char));
+        msize = g_arch_processor_get_memory_size(g_rendering_options_get_processor(line->options));
 
-        if (show_address)
-        {
-            strcat(content, "\t");
-            len += strlen("\t");
-        }
+        len = vmpa_to_string(G_RENDERING_LINE(line)->offset, msize, address);
 
-        memset(&content[len - 1],
-               G_RENDERING_LINE(line)->type == RLT_PROTOTYPE ? '-' : ' ', *max_bin_len);
-        len += *max_bin_len;
+        g_content_exporter_insert_with_gtk_tag(G_CONTENT_EXPORTER(line), buffer, iter,
+                                           address, len, RTT_NONE);
 
-        content[len - 1] = '\0';
+        g_content_exporter_insert_with_gtk_tag(G_CONTENT_EXPORTER(line), buffer, iter,
+                                               "\t", 1, RTT_NONE);
 
     }
 
-    /* Commentaire proprement dit */
-
-    clen = (show_address || show_code ? strlen("\t") : 0);
-    clen += strlen("<b><span foreground='#003300'>");
-    clen += strlen("; ") + strlen(line->comment);
-    clen += strlen("</span></b>");
-
-    content = (char *)realloc(content, (len + clen) * sizeof(char));
-
-    if (show_address || show_code)
-    {
-        strcat(content, "\t");
-        len += strlen("\t");
-        clen -= strlen("\t");
-    }
-
-    snprintf(&content[len - 1], clen + 1, "<b><span foreground='#003300'>; %s</span></b>", line->comment);
+    /* Eventuel code brut (sauté) */
 
-    len += clen;
+    if (show_code)
+        g_content_exporter_insert_with_gtk_tag(G_CONTENT_EXPORTER(line), buffer, iter,
+                                               "\t", 1, RTT_NONE);
 
-    /* Finalisation */
+    /* Commentaire proprement dit */
 
-    len += strlen("</tt>");
-    content = (char *)realloc(content, len * sizeof(char));
-    strcat(content, "</tt>");
+    g_content_exporter_insert_with_gtk_tag(G_CONTENT_EXPORTER(line), buffer, iter,
+                                           "; ", 2, RTT_COMMENT);
 
-    pango_layout_set_markup(G_RENDERING_LINE(line)->layout[rendering], content, len - 1);
+    len = strlen(line->comment);
 
-    free(content);
+    g_content_exporter_insert_with_gtk_tag(G_CONTENT_EXPORTER(line), buffer, iter,
+                                           line->comment, len, RTT_COMMENT);
 
 }
 
diff --git a/src/analysis/line_prologue.c b/src/analysis/line_prologue.c
index 4b83b68..13f0c1e 100644
--- a/src/analysis/line_prologue.c
+++ b/src/analysis/line_prologue.c
@@ -56,8 +56,8 @@ static void g_prologue_line_class_init(GPrologueLineClass *);
 /* Initialise la classe des lignes de descriptions initiales. */
 static void g_prologue_line_init(GPrologueLine *);
 
-/* Met à jour la ligne de représentation de prologue. */
-void g_prologue_line_refresh_markup(GPrologueLine *, MainRendering);
+/* Ajoute à un texte GTK le contenu de la ligne d'ouverture. */
+static void g_prologue_line_add_to_gtk_buffer(GPrologueLine *, MainRendering, GtkTextBuffer *, GtkTextIter *, gint [SAR_COUNT]);
 
 
 
@@ -98,15 +98,16 @@ static void g_prologue_line_class_init(GPrologueLineClass *klass)
 
 static void g_prologue_line_init(GPrologueLine *line)
 {
-    GRenderingLine *parent;                 /* Instance parente            */
+    GContentExporter *exporter_parent;      /* Instance parente #1         */
+    GRenderingLine *line_parent;            /* Instance parente #2         */
 
-    parent = G_RENDERING_LINE(line);
+    exporter_parent = G_CONTENT_EXPORTER(line);
 
-    parent->offset = 0;
+    exporter_parent->add_to_gtk_buffer = (add_to_gtk_buffer_fc)g_prologue_line_add_to_gtk_buffer;
 
-    parent->type = RLT_PROLOGUE;
+    line_parent = G_RENDERING_LINE(line);
 
-    parent->refresh_markup = (refresh_markup_fc)g_prologue_line_refresh_markup;
+    line_parent->type = RLT_PROLOGUE;
 
 }
 
@@ -115,8 +116,11 @@ static void g_prologue_line_init(GPrologueLine *line)
 *                                                                             *
 *  Paramètres  : line      = ligne de représentation à actualiser.            *
 *                rendering = support effectif final des lignes de code.       *
+*                buffer    = zone de texte à venir compléter.                 *
+*                iter      = point d'insertion du nouveau texte.              *
+*                lengths   = taille des différentes composantes de la ligne.  *
 *                                                                             *
-*  Description : Met à jour la ligne de représentation de prologue.           *
+*  Description : Ajoute à un texte GTK le contenu de la ligne d'ouverture.    *
 *                                                                             *
 *  Retour      : -                                                            *
 *                                                                             *
@@ -124,22 +128,17 @@ static void g_prologue_line_init(GPrologueLine *line)
 *                                                                             *
 ******************************************************************************/
 
-void g_prologue_line_refresh_markup(GPrologueLine *line, MainRendering rendering)
+static void g_prologue_line_add_to_gtk_buffer(GPrologueLine *line, MainRendering rendering, GtkTextBuffer *buffer, GtkTextIter *iter, gint lengths[SAR_COUNT])
 {
-    size_t len;                             /* Taille du contenu           */
-    char *content;                          /* Contenu réellement imprimé  */
+    size_t len;                             /* Taille de l'élément inséré  */
 
-    len = strlen("<b><span foreground='#003300'>");
-    len += strlen("; ") + strlen(line->comment);
-    len += strlen("</span></b>");
+    len = strlen(line->comment);
 
-    content = (char *)calloc(len + 1, sizeof(char));
+    g_content_exporter_insert_with_gtk_tag(G_CONTENT_EXPORTER(line), buffer, iter,
+                                           "; ", 2, RTT_COMMENT);
 
-    snprintf(content, len + 1, "<b><span foreground='#003300'>; %s</span></b>", line->comment);
-
-    pango_layout_set_markup(G_RENDERING_LINE(line)->layout[rendering], content, len);
-
-    free(content);
+    g_content_exporter_insert_with_gtk_tag(G_CONTENT_EXPORTER(line), buffer, iter,
+                                           line->comment, len, RTT_COMMENT);
 
 }
 
diff --git a/src/analysis/roptions.h b/src/analysis/roptions.h
index 85dc5fb..b2e4973 100644
--- a/src/analysis/roptions.h
+++ b/src/analysis/roptions.h
@@ -45,6 +45,18 @@ typedef enum _MainRendering
 } MainRendering;
 
 
+/* Zone de rendu */
+typedef enum _ShowingArea
+{
+    SAR_ADDRESS,                            /* Adresse d'une ligne         */
+    SAR_CODE,                               /* Code brut d'une ligne       */
+    SAR_INSTRUCTION,                        /* Instruction d'une ligne     */
+
+    SAR_COUNT
+
+} ShowingArea;
+
+
 #define G_TYPE_RENDERING_OPTIONS               g_rendering_options_get_type()
 #define G_RENDERING_OPTIONS(obj)               (G_TYPE_CHECK_INSTANCE_CAST((obj), g_rendering_options_get_type(), GRenderingOptions))
 #define G_IS_RENDERING_OPTIONS(obj)            (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_rendering_options_get_type()))
diff --git a/src/arch/Makefile.am b/src/arch/Makefile.am
index 6a1d45b..2aa57b7 100644
--- a/src/arch/Makefile.am
+++ b/src/arch/Makefile.am
@@ -2,7 +2,7 @@
 noinst_LTLIBRARIES = libarch.la
 
 libarch_la_SOURCES =					\
-	archbase.h							\
+	archbase.h archbase.c				\
 	artificial.h artificial.c			\
 	immediate.h immediate.c				\
 	instruction-int.h					\
diff --git a/src/arch/archbase.c b/src/arch/archbase.c
new file mode 100644
index 0000000..61e2396
--- /dev/null
+++ b/src/arch/archbase.c
@@ -0,0 +1,79 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * archbase.c - définitions de base pour les architectures
+ *
+ * Copyright (C) 2009 Cyrille Bagard
+ *
+ *  This file is part of OpenIDA.
+ *
+ *  OpenIDA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  OpenIDA is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "archbase.h"
+
+
+#include <stdio.h>
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : addr   = adresse virtuelle ou physique à traiter.            *
+*                msize  = taille de cette adresse.                            *
+*                buffer = chaîne de caractères à constituer. [OUT]            *
+*                                                                             *
+*  Description : Transforme une adresse en chaîne de caractères.              *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+size_t vmpa_to_string(vmpa_t addr, MemoryDataSize msize, char buffer[VMPA_MAX_SIZE])
+{
+    size_t result;                          /* Taille en place à renvoyer  */
+
+    switch (msize)
+    {
+        case MDS_8_BITS:
+            snprintf(buffer, VMPA_MAX_SIZE,"0x%02llx", addr);
+            result = 4;
+            break;
+
+        case MDS_16_BITS:
+            snprintf(buffer, VMPA_MAX_SIZE, "0x%04llx", addr);
+            result = 6;
+            break;
+
+        case MDS_32_BITS:
+            snprintf(buffer, VMPA_MAX_SIZE, "0x%08llx", addr);
+            result = 10;
+            break;
+
+        case MDS_64_BITS:
+            snprintf(buffer, VMPA_MAX_SIZE, "0x%016llx", addr);
+            result = 18;
+            break;
+
+        default:
+            result = 0;
+            break;
+
+    }
+
+    return result;
+
+}
diff --git a/src/arch/archbase.h b/src/arch/archbase.h
index 2a0c80e..330e194 100644
--- a/src/arch/archbase.h
+++ b/src/arch/archbase.h
@@ -26,6 +26,7 @@
 
 
 #include <stdint.h>
+#include <sys/types.h>
 
 
 
@@ -36,6 +37,9 @@ typedef uint8_t bin_t;
 typedef uint64_t vmpa_t;
 
 
+#define VMPA_MAX_SIZE 19
+
+
 /* Taille des données intégrées */
 typedef enum _MemoryDataSize
 {
@@ -72,4 +76,8 @@ typedef enum _AsmSyntax
 
 
 
+/* Transforme une adresse en chaîne de caractères. */
+size_t vmpa_to_string(vmpa_t, MemoryDataSize, char [VMPA_MAX_SIZE]);
+
+
 #endif  /* _ARCH_ARCHBASE_H */
diff --git a/src/arch/immediate.c b/src/arch/immediate.c
index f8bba35..54d8135 100644
--- a/src/arch/immediate.c
+++ b/src/arch/immediate.c
@@ -27,6 +27,7 @@
 #include <malloc.h>
 #include <stdarg.h>
 #include <stdio.h>
+#include <string.h>
 
 
 #include "operand-int.h"
@@ -83,8 +84,8 @@ static void g_imm_operand_class_init(GImmOperandClass *);
 /* Initialise la classe des lignes de descriptions initiales. */
 static void g_imm_operand_init(GImmOperand *);
 
-/* Traduit un opérande en version humainement lisible. */
-static char *g_imm_operand_get_text(const GImmOperand *, const GExeFormat *, AsmSyntax);
+/* Ajoute à un texte GTK le contenu d'un opérande. */
+static void g_imm_operand_add_to_gtk_buffer(const GImmOperand *, const GExeFormat *, AsmSyntax, GtkTextBuffer *, GtkTextIter *);
 
 
 /* Indique le type défini pour un opérande de valeur numérique. */
@@ -124,11 +125,11 @@ static void g_imm_operand_class_init(GImmOperandClass *klass)
 
 static void g_imm_operand_init(GImmOperand *operand)
 {
-    GArchOperand *parent;                   /* Instance parente            */
+    GContentExporter *parent;               /* Instance parente            */
 
-    parent = G_ARCH_OPERAND(operand);
+    parent = G_CONTENT_EXPORTER(operand);
 
-    parent->get_text = (get_operand_text_fc)g_imm_operand_get_text;
+    parent->add_arch_to_gtk_buffer = (add_arch_to_gtk_buffer_fc)g_imm_operand_add_to_gtk_buffer;
 
 }
 
@@ -174,21 +175,35 @@ GArchOperand *g_imm_operand_new_from_data(MemoryDataSize size, const bin_t *data
                 goto gionfd_error;
             break;
 
+        case AOS_64_BITS_UNSIGNED:
+            if (!read_u64(&result->unsigned_imm.val64, data, pos, len, endian))
+                goto gionfd_error;
+            break;
+
         case AOS_8_BITS_SIGNED:
-            if (!read_u8(&result->signed_imm.val8, data, pos, len, endian))
+            if (!read_s8(&result->signed_imm.val8, data, pos, len, endian))
                 goto gionfd_error;
             break;
 
         case AOS_16_BITS_SIGNED:
-            if (!read_u16(&result->signed_imm.val16, data, pos, len, endian))
+            if (!read_s16(&result->signed_imm.val16, data, pos, len, endian))
                 goto gionfd_error;
             break;
 
         case AOS_32_BITS_SIGNED:
-            if (!read_u32(&result->signed_imm.val32, data, pos, len, endian))
+            if (!read_s32(&result->signed_imm.val32, data, pos, len, endian))
                 goto gionfd_error;
             break;
 
+        case AOS_64_BITS_SIGNED:
+            if (!read_s64(&result->signed_imm.val64, data, pos, len, endian))
+                goto gionfd_error;
+            break;
+
+        case MDS_UNDEFINED:
+            goto gionfd_error;
+            break;
+
     }
 
     return G_ARCH_OPERAND(result);
@@ -326,74 +341,73 @@ bool g_imm_operand_is_negative(const GImmOperand *operand)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : operand = opérande à traiter.                                *
-*                format  = format du binaire manipulé.                        *
-*                syntax  = type de représentation demandée.                   *
+*  Paramètres  : operand = opérande à transcrire.                             *
+*                format = format du binaire manipulé.                         *
+*                syntax = type de représentation demandée.                    *
+*                buffer = zone de texte à venir compléter.                    *
+*                iter   = point d'insertion du nouveau texte.                 *
 *                                                                             *
-*  Description : Traduit un opérande en version humainement lisible.          *
+*  Description : Ajoute à un texte GTK le contenu d'un opérande.              *
 *                                                                             *
-*  Retour      : Chaîne de caractères à libérer de la mémoire.                *
+*  Retour      : -                                                            *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static char *g_imm_operand_get_text(const GImmOperand *operand, const GExeFormat *format, AsmSyntax syntax)
+static void g_imm_operand_add_to_gtk_buffer(const GImmOperand *operand, const GExeFormat *format, AsmSyntax syntax, GtkTextBuffer *buffer, GtkTextIter *iter)
 {
-    char *result;                           /* Chaîne à retourner          */
+    char value[VMPA_MAX_SIZE];              /* Chaîne à imprimer           */
     vmpa_t address;                         /* Décallage final constaté    */
     const char *label;                      /* Etiquette de symbole        */
     SymbolType symtype;                     /* Type de symbole             */
     char *printable;                        /* Version texte présentable   */
-    char buffer[256];                       /* Complément d'information    */
 
     /* Valeur brute */
 
-    result = (char *)calloc(19, sizeof(char));
-
     switch (syntax)
     {
         case ASX_INTEL:
             switch (operand->size)
             {
                 case MDS_UNDEFINED:
-                    snprintf(result, 19, "$0x???");
+                    snprintf(value, VMPA_MAX_SIZE, "0x???");
                     break;
                 case AOS_8_BITS_UNSIGNED:
-                    snprintf(result, 19, "0x%hhx", operand->unsigned_imm.val8);
+                    snprintf(value, VMPA_MAX_SIZE, "0x%hhx", operand->unsigned_imm.val8);
                     break;
                 case AOS_16_BITS_UNSIGNED:
-                    snprintf(result, 19, "0x%hx", operand->unsigned_imm.val16);
+                    snprintf(value, VMPA_MAX_SIZE, "0x%hx", operand->unsigned_imm.val16);
                     break;
                 case AOS_32_BITS_UNSIGNED:
-                    snprintf(result, 19, "0x%x", operand->unsigned_imm.val32);
+                    snprintf(value, VMPA_MAX_SIZE, "0x%x", operand->unsigned_imm.val32);
                     break;
                 case AOS_64_BITS_UNSIGNED:
-                    snprintf(result, 19, "0x%llx", operand->unsigned_imm.val64);
+                    snprintf(value, VMPA_MAX_SIZE, "0x%llx", operand->unsigned_imm.val64);
                     break;
                 case AOS_8_BITS_SIGNED:
                     if (g_imm_operand_is_negative(operand))
-                        snprintf(result, 19, "0x%hhx", ~operand->signed_imm.val8 + 1);
+                        snprintf(value, VMPA_MAX_SIZE, "0x%hhx", ~operand->signed_imm.val8 + 1);
                     else
-                        snprintf(result, 19, "0x%hhx", operand->signed_imm.val8);
+                        snprintf(value, VMPA_MAX_SIZE, "0x%hhx", operand->signed_imm.val8);
                     break;
                 case AOS_16_BITS_SIGNED:
                     if (g_imm_operand_is_negative(operand))
-                        snprintf(result, 19, "0x%hx", ~operand->signed_imm.val16 + 1);
+                        snprintf(value, VMPA_MAX_SIZE, "0x%hx", ~operand->signed_imm.val16 + 1);
                     else
-                        snprintf(result, 19, "0x%hx", operand->signed_imm.val16);
+                        snprintf(value, VMPA_MAX_SIZE, "0x%hx", operand->signed_imm.val16);
                     break;
                 case AOS_32_BITS_SIGNED:
                     if (g_imm_operand_is_negative(operand))
-                        snprintf(result, 19, "0x%x", ~operand->signed_imm.val32 + 1);
+                        snprintf(value, VMPA_MAX_SIZE, "0x%x", ~operand->signed_imm.val32 + 1);
                     else
-                        snprintf(result, 19, "0x%x", operand->signed_imm.val32);
+                        snprintf(value, VMPA_MAX_SIZE, "0x%x", operand->signed_imm.val32);
                     break;
                 case AOS_64_BITS_SIGNED:
                     if (g_imm_operand_is_negative(operand))
-                        snprintf(result, 19, "0x%llx", ~operand->signed_imm.val64 + 1);
+                        snprintf(value, VMPA_MAX_SIZE, "0x%llx", ~operand->signed_imm.val64 + 1);
                     else
-                        snprintf(result, 19, "0x%llx", operand->signed_imm.val64);
+                        snprintf(value, VMPA_MAX_SIZE, "0x%llx", operand->signed_imm.val64);
                     break;
             }
             break;
@@ -402,63 +416,100 @@ static char *g_imm_operand_get_text(const GImmOperand *operand, const GExeFormat
             switch (operand->size)
             {
                 case MDS_UNDEFINED:
-                    snprintf(result, 19, "$0x???");
+                    snprintf(value, VMPA_MAX_SIZE, "$0x???");
                     break;
                 case AOS_8_BITS_UNSIGNED:
-                    snprintf(result, 19, "$0x%hhx", operand->unsigned_imm.val8);
+                    snprintf(value, VMPA_MAX_SIZE, "$0x%hhx", operand->unsigned_imm.val8);
                     break;
                 case AOS_16_BITS_UNSIGNED:
-                    snprintf(result, 19, "$0x%hx", operand->unsigned_imm.val16);
+                    snprintf(value, VMPA_MAX_SIZE, "$0x%hx", operand->unsigned_imm.val16);
                     break;
                 case AOS_32_BITS_UNSIGNED:
-                    snprintf(result, 19, "$0x%x", operand->unsigned_imm.val32);
+                    snprintf(value, VMPA_MAX_SIZE, "$0x%x", operand->unsigned_imm.val32);
                     break;
                 case AOS_64_BITS_UNSIGNED:
-                    snprintf(result, 19, "$0x%llx", operand->unsigned_imm.val64);
+                    snprintf(value, VMPA_MAX_SIZE, "$0x%llx", operand->unsigned_imm.val64);
                     break;
                 case AOS_8_BITS_SIGNED:
-                    snprintf(result, 19, "$0x%hhx", ~operand->signed_imm.val8 + 1);
+                    snprintf(value, VMPA_MAX_SIZE, "$0x%hhx", ~operand->signed_imm.val8 + 1);
                     break;
                 case AOS_16_BITS_SIGNED:
-                    snprintf(result, 19, "$0x%hx", ~operand->signed_imm.val16 + 1);
+                    snprintf(value, VMPA_MAX_SIZE, "$0x%hx", ~operand->signed_imm.val16 + 1);
                     break;
                 case AOS_32_BITS_SIGNED:
-                    snprintf(result, 19, "$0x%x", ~operand->signed_imm.val32 + 1);
+                    snprintf(value, VMPA_MAX_SIZE, "$0x%x", ~operand->signed_imm.val32 + 1);
                     break;
                 case AOS_64_BITS_SIGNED:
-                    snprintf(result, 19, "$0x%llx", ~operand->signed_imm.val64 + 1);
+                    snprintf(value, VMPA_MAX_SIZE, "$0x%llx", ~operand->signed_imm.val64 + 1);
                     break;
             }
             break;
 
+        default:
+            break;
+
     }
 
+    g_content_exporter_insert_with_gtk_tag(G_CONTENT_EXPORTER(operand), buffer, iter,
+                                           value, strlen(value), RTT_IMMEDIATE);
+
     /* Complément d'information */
 
-    if (operand->size == AOS_32_BITS_SIGNED || operand->size == AOS_32_BITS_UNSIGNED)   /* FIXME */
+    if (operand->size == g_arch_processor_get_memory_size(get_arch_processor_from_format(format)))
     {
-        address = operand->unsigned_imm.val32; /* FIXME !!! */
-
-        if (g_binary_format_resolve_symbol(G_BIN_FORMAT(format), &label, &symtype, &address))
+        if (g_imm_operand_to_vmpa_t(operand, &address))
         {
-            switch (symtype)
+            if (g_binary_format_resolve_symbol(G_BIN_FORMAT(format), &label, &symtype, &address))
             {
-                case STP_OBJECT:
-                case STP_FUNCTION:
-                    if (address == 0) snprintf(buffer, 256, " &lt;%s&gt;", label);
-                    else snprintf(buffer, 256, " &lt;%s+0x%llx&gt;", label, address);
-                    result = stradd(result, buffer);
-                    break;
+                switch (symtype)
+                {
+                    case STP_OBJECT:
+                    case STP_FUNCTION:
+                        g_content_exporter_insert_with_gtk_tag(G_CONTENT_EXPORTER(operand), buffer, iter,
+                                                               " ", 1, RTT_NONE);
+                        g_content_exporter_insert_with_gtk_tag(G_CONTENT_EXPORTER(operand), buffer, iter,
+                                                               "<", 1, RTT_LTGT);
 
-                case STP_STRING:
-                    printable = strdup(label);
-                    printable = escape_crlf(printable);
-                    printable = strrpl(printable, "<", "&lt;");
-                    printable = strrpl(printable, ">", "&gt;");
-                    snprintf(buffer, 256, " \"%s\"", printable);
-                    result = stradd(result, buffer);
-                    free(printable);
-                    break;
+                        g_content_exporter_insert_with_gtk_tag(G_CONTENT_EXPORTER(operand), buffer, iter,
+                                                               label, strlen(label), RTT_LTGT);
+
+                        if (address > 0)
+                        {
+                            g_content_exporter_insert_with_gtk_tag(G_CONTENT_EXPORTER(operand), buffer, iter,
+                                                                   "+", 1, RTT_LTGT);
+
+                            snprintf(value, VMPA_MAX_SIZE, "0x%llx", address);
+
+                            g_content_exporter_insert_with_gtk_tag(G_CONTENT_EXPORTER(operand), buffer, iter,
+                                                                   value, strlen(value), RTT_LTGT);
+
+                        }
+
+                        g_content_exporter_insert_with_gtk_tag(G_CONTENT_EXPORTER(operand), buffer, iter,
+                                                               ">", 1, RTT_LTGT);
+
+                        break;
+
+                    case STP_STRING:
+                        printable = strdup(label);
+                        printable = escape_crlf(printable);
+                        /*printable = strrpl(printable, "<", "&lt;");
+                        printable = strrpl(printable, ">", "&gt;");*/
+
+                        g_content_exporter_insert_with_gtk_tag(G_CONTENT_EXPORTER(operand), buffer, iter,
+                                                               " ", 1, RTT_NONE);
+                        g_content_exporter_insert_with_gtk_tag(G_CONTENT_EXPORTER(operand), buffer, iter,
+                                                               "\"", 1, RTT_STRING);
+                        g_content_exporter_insert_with_gtk_tag(G_CONTENT_EXPORTER(operand), buffer, iter,
+                                                               printable, strlen(printable), RTT_STRING);
+                        g_content_exporter_insert_with_gtk_tag(G_CONTENT_EXPORTER(operand), buffer, iter,
+                                                               "\"", 1, RTT_STRING);
+
+                        free(printable);
+
+                        break;
+
+                }
 
             }
 
@@ -466,8 +517,6 @@ static char *g_imm_operand_get_text(const GImmOperand *operand, const GExeFormat
 
     }
 
-    return result;
-
 }
 
 
diff --git a/src/arch/instruction-int.h b/src/arch/instruction-int.h
index ab37d62..4ecb173 100644
--- a/src/arch/instruction-int.h
+++ b/src/arch/instruction-int.h
@@ -27,6 +27,7 @@
 
 #include "archbase.h"
 #include "instruction.h"
+#include "../analysis/exporter-int.h"
 
 
 
@@ -43,7 +44,7 @@ typedef bool (* is_instruction_return_fc) (const GArchInstruction *);
 /* Définition générique d'une instruction d'architecture (instance) */
 struct _GArchInstruction
 {
-    GObject parent;                         /* A laisser en premier        */
+    GContentExporter parent;                /* A laisser en premier        */
 
     off_t offset;                           /* Position physique de départ */
     off_t length;                           /* Taille de l'instruction     */
@@ -63,7 +64,7 @@ struct _GArchInstruction
 /* Définition générique d'une instruction d'architecture (classe) */
 struct _GArchInstructionClass
 {
-    GObjectClass parent;                    /* A laisser en premier        */
+    GContentExporterClass parent;           /* A laisser en premier        */
 
 };
 
diff --git a/src/arch/instruction.c b/src/arch/instruction.c
index 338f496..8bc317b 100644
--- a/src/arch/instruction.c
+++ b/src/arch/instruction.c
@@ -38,10 +38,13 @@ static void g_arch_instruction_class_init(GArchInstructionClass *);
 /* Initialise une instance d'opérande d'architecture. */
 static void g_arch_instruction_init(GArchInstruction *);
 
+/* Ajoute à un texte GTK le contenu d'une instruction. */
+static void g_arch_instruction_add_to_gtk_buffer(const GArchInstruction *, const GExeFormat *, AsmSyntax, GtkTextBuffer *, GtkTextIter *);
+
 
 
 /* Indique le type défini pour une instruction d'architecture. */
-G_DEFINE_TYPE(GArchInstruction, g_arch_instruction, G_TYPE_OBJECT);
+G_DEFINE_TYPE(GArchInstruction, g_arch_instruction, G_TYPE_CONTENT_EXPORTER);
 
 
 /******************************************************************************
@@ -76,6 +79,65 @@ static void g_arch_instruction_class_init(GArchInstructionClass *klass)
 
 static void g_arch_instruction_init(GArchInstruction *instr)
 {
+    GContentExporter *parent;               /* Instance parente            */
+
+    parent = G_CONTENT_EXPORTER(instr);
+
+    parent->add_arch_to_gtk_buffer = (add_arch_to_gtk_buffer_fc)g_arch_instruction_add_to_gtk_buffer;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : instr   = instruction à transcrire.                          *
+*                format = format du binaire manipulé.                         *
+*                syntax = type de représentation demandée.                    *
+*                buffer = zone de texte à venir compléter.                    *
+*                iter   = point d'insertion du nouveau texte.                 *
+*                                                                             *
+*  Description : Ajoute à un texte GTK le contenu d'une instruction.          *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_arch_instruction_add_to_gtk_buffer(const GArchInstruction *instr, const GExeFormat *format, AsmSyntax syntax, GtkTextBuffer *buffer, GtkTextIter *iter)
+{
+    const char *key;                        /* Mot clef principal          */
+    size_t klen;                            /* Taille de ce mot clef       */
+    size_t i;                               /* Boucle de parcours          */
+
+    key = instr->get_text(instr, format, syntax);
+    klen = strlen(key);
+
+    g_content_exporter_insert_with_gtk_tag(G_CONTENT_EXPORTER(instr), buffer, iter,
+                                           key, klen, RTT_INSTRUCTION);
+
+    if (instr->operands_count > 0)
+    {
+        g_content_exporter_insert_with_gtk_tag(G_CONTENT_EXPORTER(instr), buffer, iter,
+                                               "\t", 1, RTT_NONE);
+
+        g_content_exporter_add_arch_to_gtk_buffer(G_CONTENT_EXPORTER(G_ARCH_INSTRUCTION(instr)->operands[0]),
+                                                  format, syntax, buffer, iter);
+
+        for (i = 1; i < instr->operands_count; i++)
+        {
+            g_content_exporter_insert_with_gtk_tag(G_CONTENT_EXPORTER(instr), buffer, iter,
+                                                   ",", 1, RTT_NONE/* FIXME */);
+
+            g_content_exporter_insert_with_gtk_tag(G_CONTENT_EXPORTER(instr), buffer, iter,
+                                                   " ", 1, RTT_NONE);
+
+            g_content_exporter_add_arch_to_gtk_buffer(G_CONTENT_EXPORTER(G_ARCH_INSTRUCTION(instr)->operands[i]),
+                                                      format, syntax, buffer, iter);
+
+        }
+
+    }
 
 }
 
@@ -322,7 +384,7 @@ char *g_arch_instruction_get_text(const GArchInstruction *instr, const GExeForma
     char *result;                           /* Chaîne à retourner          */
     size_t i;                               /* Boucle de parcours          */
     char *opstr;                            /* Chaîne d'opérande           */
-
+    return strdup("");
     if (instr->operands_count == 0)
         result = strdup(instr->get_text(instr, format, syntax));
 
diff --git a/src/arch/operand-int.h b/src/arch/operand-int.h
index 90e3e06..258a60e 100644
--- a/src/arch/operand-int.h
+++ b/src/arch/operand-int.h
@@ -26,6 +26,7 @@
 
 
 #include "operand.h"
+#include "../analysis/exporter-int.h"
 
 
 
@@ -36,7 +37,7 @@ typedef char * (* get_operand_text_fc) (const GArchOperand *, const GExeFormat *
 /* Définition générique d'un opérande d'architecture (instance) */
 struct _GArchOperand
 {
-    GObject parent;                         /* A laisser en premier        */
+    GContentExporter parent;                /* A laisser en premier        */
 
     get_operand_text_fc get_text;           /* Texte humain équivalent     */
 
@@ -46,7 +47,7 @@ struct _GArchOperand
 /* Définition générique d'un opérande d'architecture (classe) */
 struct _GArchOperandClass
 {
-    GObjectClass parent;                    /* A laisser en premier        */
+    GContentExporterClass parent;           /* A laisser en premier        */
 
 };
 
diff --git a/src/arch/operand.c b/src/arch/operand.c
index 724f3c0..d4f6b56 100644
--- a/src/arch/operand.c
+++ b/src/arch/operand.c
@@ -37,7 +37,7 @@ static void g_arch_operand_init(GArchOperand *);
 
 
 /* Indique le type défini pour un opérande d'architecture. */
-G_DEFINE_TYPE(GArchOperand, g_arch_operand, G_TYPE_OBJECT);
+G_DEFINE_TYPE(GArchOperand, g_arch_operand, G_TYPE_CONTENT_EXPORTER);
 
 
 
diff --git a/src/arch/x86/operand.c b/src/arch/x86/operand.c
index 69c08dc..31c993f 100644
--- a/src/arch/x86/operand.c
+++ b/src/arch/x86/operand.c
@@ -70,7 +70,7 @@ struct _GX86RegisterOperand
 {
     GX86Operand parent;                     /* Instance parente            */
 
-    x86_register *reg;                      /* Registre représenté         */
+    GX86Register *reg;                      /* Registre représenté         */
 
 };
 
@@ -89,8 +89,8 @@ static void g_x86_register_operand_class_init(GX86RegisterOperandClass *);
 /* Initialise une instance d'opérande de registre x86. */
 static void g_x86_register_operand_init(GX86RegisterOperand *);
 
-/* Traduit un opérande en version humainement lisible. */
-static char *g_x86_register_operand_get_text(const GX86RegisterOperand *, const GExeFormat *, AsmSyntax);
+/* Ajoute à un texte GTK le contenu d'un opérande. */
+static void g_x86_register_operand_add_to_gtk_buffer(const GX86RegisterOperand *, const GExeFormat *, AsmSyntax, GtkTextBuffer *, GtkTextIter *);
 
 
 
@@ -103,8 +103,8 @@ struct _GX86ModRMOperand
     GX86Operand parent;                     /* Instance parente            */
 
     uint8_t scale;                          /* Puissance de deux           */
-    x86_register *index;                    /* Registre servant d'indice   */
-    x86_register *base;                     /* Registre de base            */
+    GX86Register *index;                    /* Registre servant d'indice   */
+    GX86Register *base;                     /* Registre de base            */
     GImmOperand *displacement;              /* Décallage supplémentaire    */
 
 };
@@ -124,8 +124,8 @@ static void g_x86_mod_rm_operand_class_init(GX86ModRMOperandClass *);
 /* Initialise une instance d'opérande x86 de type ModRM. */
 static void g_x86_mod_rm_operand_init(GX86ModRMOperand *);
 
-/* Traduit un opérande en version humainement lisible. */
-static char *g_x86_mod_rm_operand_get_text(const GX86ModRMOperand *, const GExeFormat *, AsmSyntax);
+/* Ajoute à un texte GTK le contenu d'un opérande. */
+static void g_x86_mod_rm_operand_add_to_gtk_buffer(const GX86ModRMOperand *, const GExeFormat *, AsmSyntax, GtkTextBuffer *, GtkTextIter *);
 
 
 
@@ -155,8 +155,8 @@ static void g_x86_relative_operand_class_init(GX86RelativeOperandClass *);
 /* Initialise une instance d'opérande x86 d'adresse relative. */
 static void g_x86_relative_operand_init(GX86RelativeOperand *);
 
-/* Traduit un opérande en version humainement lisible. */
-static char *g_x86_relative_operand_get_text(const GX86RelativeOperand *, const GExeFormat *, AsmSyntax);
+/* Ajoute à un texte GTK le contenu d'un opérande. */
+static void g_x86_relative_operand_add_to_gtk_buffer(const GX86RelativeOperand *, const GExeFormat *, AsmSyntax, GtkTextBuffer *, GtkTextIter *);
 
 
 
@@ -186,8 +186,8 @@ static void g_x86_moffs_operand_class_init(GX86MOffsOperandClass *);
 /* Initialise une instance d'opérande d'emplacement mémoire x86. */
 static void g_x86_moffs_operand_init(GX86MOffsOperand *);
 
-/* Traduit un opérande en version humainement lisible. */
-static char *g_x86_moffs_operand_get_text(const GX86MOffsOperand *, const GExeFormat *, AsmSyntax);
+/* Ajoute à un texte GTK le contenu d'un opérande. */
+static void g_x86_moffs_operand_add_to_gtk_buffer(const GX86MOffsOperand *, const GExeFormat *, AsmSyntax, GtkTextBuffer *, GtkTextIter *);
 
 
 
@@ -278,11 +278,11 @@ static void g_x86_register_operand_class_init(GX86RegisterOperandClass *klass)
 
 static void g_x86_register_operand_init(GX86RegisterOperand *operand)
 {
-    GArchOperand *parent;                   /* Instance parente            */
+    GContentExporter *parent;               /* Instance parente            */
 
-    parent = G_ARCH_OPERAND(operand);
+    parent = G_CONTENT_EXPORTER(operand);
 
-    parent->get_text = (get_operand_text_fc)g_x86_register_operand_get_text;
+    parent->add_arch_to_gtk_buffer = (add_arch_to_gtk_buffer_fc)g_x86_register_operand_add_to_gtk_buffer;
 
 }
 
@@ -306,9 +306,9 @@ static void g_x86_register_operand_init(GX86RegisterOperand *operand)
 GArchOperand *g_x86_register_operand_new_from_opcode(const bin_t *data, off_t *pos, off_t len, AsmOperandSize size, bin_t base)
 {
     GX86RegisterOperand *result;            /* Structure à retourner       */
-    x86_register *reg;                      /* Registre lu                 */
+    GX86Register *reg;                      /* Registre lu                 */
 
-    reg = get_x86_register(size, data[*pos] - base);
+    reg = g_x86_register_new(size, data[*pos] - base);
 
     if (reg != NULL)
     {
@@ -346,12 +346,12 @@ GArchOperand *g_x86_register_operand_new_from_mod_rm(const bin_t *data, off_t *p
 {
     GX86RegisterOperand *result;            /* Structure à retourner       */
     bin_t index;                            /* Registre lu                 */
-    x86_register *reg;                      /* Registre créé               */
+    GX86Register *reg;                      /* Registre créé               */
 
     if (first) index = data[*pos] & 0x07;
     else index = (data[*pos] & 0x38) >> 3;
 
-    reg = get_x86_register(size, index);
+    reg = g_x86_register_new(size, index);
 
     if (reg != NULL)
     {
@@ -385,9 +385,9 @@ GArchOperand *g_x86_register_operand_new_from_mod_rm(const bin_t *data, off_t *p
 GArchOperand *g_x86_register_operand_new_from_index(bin_t index, AsmOperandSize size)
 {
     GX86RegisterOperand *result;            /* Structure à retourner       */
-    x86_register *reg;                      /* Registre lu                 */
+    GX86Register *reg;                      /* Registre lu                 */
 
-    reg = get_x86_register(size, index);
+    reg = g_x86_register_new(size, index);
 
     if (reg != NULL)
     {
@@ -405,25 +405,23 @@ GArchOperand *g_x86_register_operand_new_from_index(bin_t index, AsmOperandSize
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : operand = opérande à traiter.                                *
-*                format  = format du binaire manipulé.                        *
-*                syntax  = type de représentation demandée.                   *
+*  Paramètres  : operand = opérande à transcrire.                             *
+*                format = format du binaire manipulé.                         *
+*                syntax = type de représentation demandée.                    *
+*                buffer = zone de texte à venir compléter.                    *
+*                iter   = point d'insertion du nouveau texte.                 *
 *                                                                             *
-*  Description : Traduit un opérande en version humainement lisible.          *
+*  Description : Ajoute à un texte GTK le contenu d'un opérande.              *
 *                                                                             *
-*  Retour      : Chaîne de caractères à libérer de la mémoire.                *
+*  Retour      : -                                                            *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static char *g_x86_register_operand_get_text(const GX86RegisterOperand *operand, const GExeFormat *format, AsmSyntax syntax)
+static void g_x86_register_operand_add_to_gtk_buffer(const GX86RegisterOperand *operand, const GExeFormat *format, AsmSyntax syntax, GtkTextBuffer *buffer, GtkTextIter *iter)
 {
-    char *result;                           /* Chaîne à retourner          */
-
-    result = x86_register_as_text(operand->reg, syntax);
-
-    return result;
+    g_content_exporter_add_arch_to_gtk_buffer(G_CONTENT_EXPORTER(operand->reg), format, syntax, buffer, iter);
 
 }
 
@@ -470,11 +468,11 @@ static void g_x86_mod_rm_operand_class_init(GX86ModRMOperandClass *klass)
 
 static void g_x86_mod_rm_operand_init(GX86ModRMOperand *operand)
 {
-    GArchOperand *parent;                   /* Instance parente            */
+    GContentExporter *parent;               /* Instance parente            */
 
-    parent = G_ARCH_OPERAND(operand);
+    parent = G_CONTENT_EXPORTER(operand);
 
-    parent->get_text = (get_operand_text_fc)g_x86_mod_rm_operand_get_text;
+    parent->add_arch_to_gtk_buffer = (add_arch_to_gtk_buffer_fc)g_x86_mod_rm_operand_add_to_gtk_buffer;
 
 }
 
@@ -498,43 +496,43 @@ GArchOperand *g_x86_mod_rm_operand_new(const bin_t *data, off_t *pos, off_t len,
 {
     GX86ModRMOperand *result;               /* Structure à retourner       */
     uint8_t mod;                            /* Modificateur présent        */
-    x86_register *reg;                      /* Registre lu                 */
+    GX86Register *reg;                      /* Registre lu                 */
 
     mod = (data[*pos] & 0xc0);
 
     if (mod == 0xc0)
         return g_x86_register_operand_new_from_mod_rm(data, pos, len, size, true);
 
-    reg = get_x86_register(size, data[*pos] & 0x07);
+    reg = g_x86_register_new(size, data[*pos] & 0x07);
     if (reg == NULL) return NULL;
 
     (*pos)++;
 
     /* Vieille astuce de l'emplacement mémoire fixe ? */
-    if (is_x86_register_base_pointer(reg) && mod == 0x00)
+    if (g_x86_register_is_base_pointer(reg) && mod == 0x00)
     {
-        free_x86_register(reg);
+        /* FIXME *///free_x86_register(reg);
         return g_imm_operand_new_from_data(MDS_32_BITS/* FIXME */, data, pos, len, SRE_LITTLE);
     }
 
     result = g_object_new(G_TYPE_X86_MOD_RM_OPERAND, NULL);
 
     /* A la recherche d'un SIB */
-    if (is_x86_register_stack_pointer(reg))
+    if (g_x86_register_is_stack_pointer(reg))
     {
-        free_x86_register(reg);
+        /* FIXME *///free_x86_register(reg);
 
-        result->base = get_x86_register(size, data[*pos] & 0x07);
+        result->base = g_x86_register_new(size, data[*pos] & 0x07);
         if (result->base == NULL) goto gxmron_error;
 
-        result->index = get_x86_register(size, (data[*pos] & 0x38) >> 3);
+        result->index = g_x86_register_new(size, (data[*pos] & 0x38) >> 3);
         if (result->index == NULL) goto gxmron_error;
 
         result->scale = ((data[*pos] & 0xc0) >> 6);
 
-        if (is_x86_register_stack_pointer(result->index))
+        if (g_x86_register_is_stack_pointer(result->index))
         {
-            free_x86_register(result->index);
+            /* FIXME *///free_x86_register(result->index);
             result->index = result->base;
             result->base = NULL;
         }
@@ -549,9 +547,9 @@ GArchOperand *g_x86_mod_rm_operand_new(const bin_t *data, off_t *pos, off_t len,
     switch (mod)
     {
         case 0x00:
-            if (result->base != NULL && is_x86_register_base_pointer(result->base))
+            if (result->base != NULL && g_x86_register_is_base_pointer(result->base))
             {
-                free_x86_register(result->base);
+                /* FIXME *///free_x86_register(result->base);
                 result->base = NULL;
 
                 result->displacement = g_imm_operand_new_from_data(size/* FIXME : !convert mds/aos */, data, pos, len, SRE_LITTLE);
@@ -584,72 +582,79 @@ GArchOperand *g_x86_mod_rm_operand_new(const bin_t *data, off_t *pos, off_t len,
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : operand = opérande à traiter.                                *
-*                format  = format du binaire manipulé.                        *
-*                syntax  = type de représentation demandée.                   *
+*  Paramètres  : operand = opérande à transcrire.                             *
+*                format = format du binaire manipulé.                         *
+*                syntax = type de représentation demandée.                    *
+*                buffer = zone de texte à venir compléter.                    *
+*                iter   = point d'insertion du nouveau texte.                 *
 *                                                                             *
-*  Description : Traduit un opérande en version humainement lisible.          *
+*  Description : Ajoute à un texte GTK le contenu d'un opérande.              *
 *                                                                             *
-*  Retour      : Chaîne de caractères à libérer de la mémoire.                *
+*  Retour      : -                                                            *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static char *g_x86_mod_rm_operand_get_text(const GX86ModRMOperand *operand, const GExeFormat *format, AsmSyntax syntax)
+static void g_x86_mod_rm_operand_add_to_gtk_buffer(const GX86ModRMOperand *operand, const GExeFormat *format, AsmSyntax syntax, GtkTextBuffer *buffer, GtkTextIter *iter)
 {
-    char *result;                           /* Chaîne à retourner          */
-    char *tmp;                              /* Chaîne de registre          */
+    char tmp[2];                            /* Echelle en puissance de 2   */
 
     switch (syntax)
     {
         case ASX_INTEL:
 
-            result = (char *)calloc(1 + 10 + 2, sizeof(char));
-
-            strcpy(result, "[");
+            g_content_exporter_insert_with_gtk_tag(G_CONTENT_EXPORTER(operand), buffer, iter,
+                                                   "[", 1, RTT_HOOK);
 
             if (operand->scale > 0)
-                snprintf(&result[1], 12, "%d*", (int)pow(2, operand->scale)); 
-
-            tmp = x86_register_as_text(operand->index, syntax);
-            result = stradd(result, tmp);
-            free(tmp);
-
-            if (operand->base != NULL)
             {
-                result = stradd(result, "+");
+                snprintf(tmp, 2, "%d", (int)pow(2, operand->scale)); 
+
+                g_content_exporter_insert_with_gtk_tag(G_CONTENT_EXPORTER(operand), buffer, iter,
+                                                       tmp, 1, RTT_IMMEDIATE);
 
-                tmp = x86_register_as_text(operand->base, syntax);
-                result = stradd(result, tmp);
-                free(tmp);
+                g_content_exporter_insert_with_gtk_tag(G_CONTENT_EXPORTER(operand), buffer, iter,
+                                                       "*", 1, RTT_SIGNS);
 
             }
 
+            g_content_exporter_add_arch_to_gtk_buffer(G_CONTENT_EXPORTER(operand->index),
+                                                      format, syntax, buffer, iter);
+
+            if (operand->base != NULL)
+                g_content_exporter_add_arch_to_gtk_buffer(G_CONTENT_EXPORTER(operand->base),
+                                                          format, syntax, buffer, iter);
+
             if (operand->displacement != NULL)
             {
-                if (g_imm_operand_is_negative(operand->displacement)) result = stradd(result, "-");
-                else result = stradd(result, "+");
+                if (g_imm_operand_is_negative(operand->displacement))
+                    g_content_exporter_insert_with_gtk_tag(G_CONTENT_EXPORTER(operand), buffer, iter,
+                                                           "-", 1, RTT_SIGNS);
+                else
+                    g_content_exporter_insert_with_gtk_tag(G_CONTENT_EXPORTER(operand), buffer, iter,
+                                                           "+", 1, RTT_SIGNS);
 
-                tmp = g_arch_operand_get_text(G_ARCH_OPERAND(operand->displacement), format, syntax);
-                result = stradd(result, tmp);
-                free(tmp);
+                g_content_exporter_add_arch_to_gtk_buffer(G_CONTENT_EXPORTER(operand->displacement),
+                                                          format, syntax, buffer, iter);
 
             }
 
-            result = stradd(result, "]");
+            g_content_exporter_insert_with_gtk_tag(G_CONTENT_EXPORTER(operand), buffer, iter,
+                                                   "]", 1, RTT_HOOK);
 
             break;
 
         case ASX_ATT:
 
-            result = strdup("[modRM]");
+            /* TODO */
+            g_content_exporter_insert_with_gtk_tag(G_CONTENT_EXPORTER(operand), buffer, iter,
+                                                   "[ModRM]", 7, RTT_HOOK);
+
             break;
 
     }
 
-    return result;
-
 }
 
 
@@ -667,7 +672,7 @@ static char *g_x86_mod_rm_operand_get_text(const GX86ModRMOperand *operand, cons
 *                                                                             *
 ******************************************************************************/
 
-void g_x86_mod_rm_operand_get_scale_and_index(const GX86ModRMOperand *operand, uint8_t *scale, const x86_register **index)
+void g_x86_mod_rm_operand_get_scale_and_index(const GX86ModRMOperand *operand, uint8_t *scale, const GX86Register **index)
 {
     *scale = operand->scale;
     *index = operand->index;
@@ -687,7 +692,7 @@ void g_x86_mod_rm_operand_get_scale_and_index(const GX86ModRMOperand *operand, u
 *                                                                             *
 ******************************************************************************/
 
-const x86_register *g_x86_mod_rm_operand_get_base(const GX86ModRMOperand *operand)
+const GX86Register *g_x86_mod_rm_operand_get_base(const GX86ModRMOperand *operand)
 {
     return operand->base;
 
@@ -755,11 +760,11 @@ static void g_x86_relative_operand_class_init(GX86RelativeOperandClass *klass)
 
 static void g_x86_relative_operand_init(GX86RelativeOperand *operand)
 {
-    GArchOperand *parent;                   /* Instance parente            */
+    GContentExporter *parent;               /* Instance parente            */
 
-    parent = G_ARCH_OPERAND(operand);
+    parent = G_CONTENT_EXPORTER(operand);
 
-    parent->get_text = (get_operand_text_fc)g_x86_relative_operand_get_text;
+    parent->add_arch_to_gtk_buffer = (add_arch_to_gtk_buffer_fc)g_x86_relative_operand_add_to_gtk_buffer;
 
 }
 
@@ -822,25 +827,24 @@ GArchOperand *g_x86_relative_operand_new(const bin_t *data, off_t *pos, off_t le
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : operand = opérande à traiter.                                *
-*                format  = format du binaire manipulé.                        *
-*                syntax  = type de représentation demandée.                   *
+*  Paramètres  : operand = opérande à transcrire.                             *
+*                format = format du binaire manipulé.                         *
+*                syntax = type de représentation demandée.                    *
+*                buffer = zone de texte à venir compléter.                    *
+*                iter   = point d'insertion du nouveau texte.                 *
 *                                                                             *
-*  Description : Traduit un opérande en version humainement lisible.          *
+*  Description : Ajoute à un texte GTK le contenu d'un opérande.              *
 *                                                                             *
-*  Retour      : Chaîne de caractères à libérer de la mémoire.                *
+*  Retour      : -                                                            *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static char *g_x86_relative_operand_get_text(const GX86RelativeOperand *operand, const GExeFormat *format, AsmSyntax syntax)
+static void g_x86_relative_operand_add_to_gtk_buffer(const GX86RelativeOperand *operand, const GExeFormat *format, AsmSyntax syntax, GtkTextBuffer *buffer, GtkTextIter *iter)
 {
-    char *result;                           /* Chaîne à retourner          */
-
-    result = g_arch_operand_get_text(operand->immediate, format, syntax);
-
-    return result;
+    g_content_exporter_add_arch_to_gtk_buffer(G_CONTENT_EXPORTER(operand->immediate),
+                                              format, syntax, buffer, iter);
 
 }
 
@@ -906,11 +910,11 @@ static void g_x86_moffs_operand_class_init(GX86MOffsOperandClass *klass)
 
 static void g_x86_moffs_operand_init(GX86MOffsOperand *operand)
 {
-    GArchOperand *parent;                   /* Instance parente            */
+    GContentExporter *parent;               /* Instance parente            */
 
-    parent = G_ARCH_OPERAND(operand);
+    parent = G_CONTENT_EXPORTER(operand);
 
-    parent->get_text = (get_operand_text_fc)g_x86_moffs_operand_get_text;
+    parent->add_arch_to_gtk_buffer = (add_arch_to_gtk_buffer_fc)g_x86_moffs_operand_add_to_gtk_buffer;
 
 }
 
@@ -952,27 +956,27 @@ GArchOperand *g_x86_moffs_operand_new(const bin_t *data, off_t *pos, off_t len,
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : operand = opérande à traiter.                                *
-*                format  = format du binaire manipulé.                        *
-*                syntax  = type de représentation demandée.                   *
+*  Paramètres  : operand = opérande à transcrire.                             *
+*                format = format du binaire manipulé.                         *
+*                syntax = type de représentation demandée.                    *
+*                buffer = zone de texte à venir compléter.                    *
+*                iter   = point d'insertion du nouveau texte.                 *
 *                                                                             *
-*  Description : Traduit un opérande en version humainement lisible.          *
+*  Description : Ajoute à un texte GTK le contenu d'un opérande.              *
 *                                                                             *
-*  Retour      : Chaîne de caractères à libérer de la mémoire.                *
+*  Retour      : -                                                            *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static char *g_x86_moffs_operand_get_text(const GX86MOffsOperand *operand, const GExeFormat *format, AsmSyntax syntax)
+static void g_x86_moffs_operand_add_to_gtk_buffer(const GX86MOffsOperand *operand, const GExeFormat *format, AsmSyntax syntax, GtkTextBuffer *buffer, GtkTextIter *iter)
 {
-    char *result;                           /* Chaîne à retourner          */
-
-    result = g_arch_operand_get_text(operand->offset, format, syntax);
-
-    result = strprep(result, "ds:");
+    g_content_exporter_insert_with_gtk_tag(G_CONTENT_EXPORTER(operand), buffer, iter,
+                                           "ds:", 3, RTT_SEGMENT);
 
-    return result;
+    g_content_exporter_add_arch_to_gtk_buffer(G_CONTENT_EXPORTER(operand->offset),
+                                              format, syntax, buffer, iter);
 
 }
 
diff --git a/src/arch/x86/operand.h b/src/arch/x86/operand.h
index cbf2ed2..cb04ca8 100644
--- a/src/arch/x86/operand.h
+++ b/src/arch/x86/operand.h
@@ -108,10 +108,10 @@ GType g_x86_mod_rm_operand_get_type(void);
 GArchOperand *g_x86_mod_rm_operand_new(const bin_t *, off_t *, off_t, AsmOperandSize);
 
 /* Fournit l'indice et l'échelle d'un opérande x86 ModRM. */
-void g_x86_mod_rm_operand_get_scale_and_index(const GX86ModRMOperand *operand, uint8_t *, const x86_register **);
+void g_x86_mod_rm_operand_get_scale_and_index(const GX86ModRMOperand *operand, uint8_t *, const GX86Register **);
 
 /* Fournit le registre de base d'un opérande x86 ModRM. */
-const x86_register *g_x86_mod_rm_operand_get_base(const GX86ModRMOperand *);
+const GX86Register *g_x86_mod_rm_operand_get_base(const GX86ModRMOperand *);
 
 /* Fournit le décallage supplémentaire d'un opérande x86 ModRM. */
 const GImmOperand *g_x86_mod_rm_operand_get_displacement(const GX86ModRMOperand *);
diff --git a/src/arch/x86/registers.c b/src/arch/x86/registers.c
index 802e2f6..4e186ed 100644
--- a/src/arch/x86/registers.c
+++ b/src/arch/x86/registers.c
@@ -24,10 +24,12 @@
 #include "registers.h"
 
 
-#include <malloc.h>
 #include <stdio.h>
 
 
+#include "../operand-int.h"
+
+
 
 /* Liste des registres 8 bits */
 typedef enum _X868bRegister
@@ -78,9 +80,13 @@ typedef enum _X8632bRegister
 } X8632bRegister;
 
 
-/* Registre x86 */
-struct _x86_register
+/* Représentation d'un registre x86 (instance) */
+struct _GX86Register
 {
+    GArchOperand parent;                    /* Instance parente            */
+
+    MemoryDataSize size;                    /* Taille de ce registre       */
+
     union
     {
         X868bRegister reg8;                 /* Registre 8 bits             */
@@ -89,30 +95,85 @@ struct _x86_register
 
     } reg;
 
-    AsmOperandSize size;                    /* Taille de ce registre       */
+};
+
+
+/* Représentation d'un registre x86 (classe) */
+struct _GX86RegisterClass
+{
+    GArchOperandClass parent;               /* Classe parente              */
 
 };
 
 
+/* Ajoute à un texte GTK le contenu d'un opérande. */
+static void g_x86_register_add_to_gtk_buffer(const GX86Register *, const GExeFormat *, AsmSyntax, GtkTextBuffer *, GtkTextIter *);
+
+
+
+/* Indique le type défini pour une représentation d'un registre x86. */
+G_DEFINE_TYPE(GX86Register, g_x86_register, G_TYPE_CONTENT_EXPORTER);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des lignes de représentation.           *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_x86_register_class_init(GX86RegisterClass *klass)
+{
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : reg = instance à initialiser.                                *
+*                                                                             *
+*  Description : Initialise une instance de ligne de représentation.          *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_x86_register_init(GX86Register *reg)
+{
+    GContentExporter *parent;               /* Instance parente            */
+
+    parent = G_CONTENT_EXPORTER(reg);
+
+    parent->add_arch_to_gtk_buffer = (add_arch_to_gtk_buffer_fc)g_x86_register_add_to_gtk_buffer;
+
+}
+
 
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : size  = indique la taille du registre.                       *
 *                value = valeur correspondant au registre.                    *
 *                                                                             *
-*  Description : Récupère l'indentifiant interne d'un registre.               *
+*  Description : Crée une réprésentation de registre x86.                     *
 *                                                                             *
-*  Retour      : Registre définit ou NULL.                                    *
+*  Retour      : Adresse de la structure mise en place.                       *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-x86_register *get_x86_register(AsmOperandSize size, bin_t value)
+GX86Register *g_x86_register_new(MemoryDataSize size, bin_t value)
 {
-    x86_register *result;                   /* Représentation à renvoyer   */
+    GX86Register *result;                   /* Structure à retourner       */
 
-    result = (x86_register *)calloc(1, sizeof(x86_register));
+    result = g_object_new(G_TYPE_X86_REGISTER, NULL);
 
     result->size = size;
 
@@ -125,7 +186,7 @@ x86_register *get_x86_register(AsmOperandSize size, bin_t value)
                     result->reg.reg8 = (X868bRegister)value;
                     break;
                 default:
-                    goto gxr_error;
+                    goto gxrn_error;
                     break;
             }
             break;
@@ -137,7 +198,7 @@ x86_register *get_x86_register(AsmOperandSize size, bin_t value)
                     result->reg.reg16 = (X8616bRegister)value;
                     break;
                 default:
-                    goto gxr_error;
+                    goto gxrn_error;
                     break;
             }
             break;
@@ -149,22 +210,22 @@ x86_register *get_x86_register(AsmOperandSize size, bin_t value)
                     result->reg.reg32 = (X8632bRegister)value;
                     break;
                 default:
-                    goto gxr_error;
+                    goto gxrn_error;
                     break;
             }
             break;
 
         default:
-            goto gxr_error;
+            goto gxrn_error;
             break;
 
     }
 
     return result;
 
- gxr_error:
+ gxrn_error:
 
-    free(result);
+    /* FIXME free(result); */
 
     return NULL;
 
@@ -173,133 +234,26 @@ x86_register *get_x86_register(AsmOperandSize size, bin_t value)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : reg = registre à supprimer.                                  *
-*                                                                             *
-*  Description : Efface de la mémoire l'indentifiant interne d'un registre.   *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-void free_x86_register(x86_register *reg)
-{
-    free(reg);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : reg = registre à consulter.                                  *
-*                                                                             *
-*  Description : Indique si le registre correspond à ebp ou similaire.        *
-*                                                                             *
-*  Retour      : true si la correspondance est avérée, false sinon.           *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-bool is_x86_register_base_pointer(const x86_register *reg)
-{
-    bool result;                            /* Bilan à remonter            */
-
-    switch (reg->size)
-    {
-        case AOS_8_BITS_UNSIGNED:
-        case AOS_8_BITS_SIGNED:
-            result = (reg->reg.reg8 == X86_REG8_CH);
-            break;
-        case AOS_16_BITS_UNSIGNED:
-        case AOS_16_BITS_SIGNED:
-            result = (reg->reg.reg16 == X86_REG16_BP);
-            break;
-        case AOS_32_BITS_UNSIGNED:
-        case AOS_32_BITS_SIGNED:
-            result = (reg->reg.reg32 == X86_REG32_EBP);
-            break;
-            /*
-        case AOS_64_BITS_UNSIGNED:
-        case AOS_64_BITS_SIGNED:
-            result = (reg->reg.reg8 == X86_REG8_CH);
-            break;
-            */
-        default:
-            result = false;
-
-    }
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : reg = registre à consulter.                                  *
-*                                                                             *
-*  Description : Indique si le registre correspond à esp ou similaire.        *
-*                                                                             *
-*  Retour      : true si la correspondance est avérée, false sinon.           *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-bool is_x86_register_stack_pointer(const x86_register *reg)
-{
-    bool result;                            /* Bilan à remonter            */
-
-    switch (reg->size)
-    {
-        case AOS_8_BITS_UNSIGNED:
-        case AOS_8_BITS_SIGNED:
-            result = (reg->reg.reg8 == X86_REG8_AH);
-            break;
-        case AOS_16_BITS_UNSIGNED:
-        case AOS_16_BITS_SIGNED:
-            result = (reg->reg.reg16 == X86_REG16_SP);
-            break;
-        case AOS_32_BITS_UNSIGNED:
-        case AOS_32_BITS_SIGNED:
-            result = (reg->reg.reg32 == X86_REG32_ESP);
-            break;
-            /*
-        case AOS_64_BITS_UNSIGNED:
-        case AOS_64_BITS_SIGNED:
-            result = (reg->reg.reg8 == X86_REG8_CH);
-            break;
-            */
-        default:
-            result = false;
-
-    }
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : reg    = registre à imprimer.                                *
+*  Paramètres  : operand = opérande à transcrire.                             *
+*                format = format du binaire manipulé.                         *
 *                syntax = type de représentation demandée.                    *
+*                buffer = zone de texte à venir compléter.                    *
+*                iter   = point d'insertion du nouveau texte.                 *
 *                                                                             *
-*  Description : Traduit un registre x86 en texte.                            *
+*  Description : Ajoute à un texte GTK le contenu d'un opérande.              *
 *                                                                             *
-*  Retour      : Traduction en chaîne à libérer de la mémoire.                *
+*  Retour      : -                                                            *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-char *x86_register_as_text(const x86_register *reg, AsmSyntax syntax)
+static void g_x86_register_add_to_gtk_buffer(const GX86Register *reg, const GExeFormat *format, AsmSyntax syntax, GtkTextBuffer *buffer, GtkTextIter *iter)
 {
-    char *result;                           /* Chaîne à renvoyer           */
+    char key[5];                            /* Mot clef principal          */
+    size_t klen;                            /* Taille de ce mot clef       */
 
-    result = (char *)calloc(5, sizeof(char));
+    klen = 0;
 
     switch (syntax)
     {
@@ -307,31 +261,32 @@ char *x86_register_as_text(const x86_register *reg, AsmSyntax syntax)
             switch (reg->size)
             {
                 case AOS_8_BITS:
+                    klen = 2;
                     switch (reg->reg.reg8)
                     {
                         case X86_REG8_AL:
-                            snprintf(result, 5, "al");
+                            snprintf(key, 5, "al");
                             break;
                         case X86_REG8_CL:
-                            snprintf(result, 5, "cl");
+                            snprintf(key, 5, "cl");
                             break;
                         case X86_REG8_DL:
-                            snprintf(result, 5, "dl");
+                            snprintf(key, 5, "dl");
                             break;
                         case X86_REG8_BL:
-                            snprintf(result, 5, "bl");
+                            snprintf(key, 5, "bl");
                             break;
                         case X86_REG8_AH:
-                            snprintf(result, 5, "ah");
+                            snprintf(key, 5, "ah");
                             break;
                         case X86_REG8_CH:
-                            snprintf(result, 5, "ch");
+                            snprintf(key, 5, "ch");
                             break;
                         case X86_REG8_DH:
-                            snprintf(result, 5, "dh");
+                            snprintf(key, 5, "dh");
                             break;
                         case X86_REG8_BH:
-                            snprintf(result, 5, "bh");
+                            snprintf(key, 5, "bh");
                             break;
                         case X86_REG8_NONE:
                             /* Ne devrait jamais arriver */
@@ -340,31 +295,32 @@ char *x86_register_as_text(const x86_register *reg, AsmSyntax syntax)
                     break;
 
                 case AOS_16_BITS:
+                    klen = 2;
                     switch (reg->reg.reg16)
                     {
                         case X86_REG16_AX:
-                            snprintf(result, 5, "ax");
+                            snprintf(key, 5, "ax");
                             break;
                         case X86_REG16_CX:
-                            snprintf(result, 5, "cx");
+                            snprintf(key, 5, "cx");
                             break;
                         case X86_REG16_DX:
-                            snprintf(result, 5, "dx");
+                            snprintf(key, 5, "dx");
                             break;
                         case X86_REG16_BX:
-                            snprintf(result, 5, "bx");
+                            snprintf(key, 5, "bx");
                             break;
                         case X86_REG16_SP:
-                            snprintf(result, 5, "sp");
+                            snprintf(key, 5, "sp");
                             break;
                         case X86_REG16_BP:
-                            snprintf(result, 5, "bp");
+                            snprintf(key, 5, "bp");
                             break;
                         case X86_REG16_SI:
-                            snprintf(result, 5, "si");
+                            snprintf(key, 5, "si");
                             break;
                         case X86_REG16_DI:
-                            snprintf(result, 5, "di");
+                            snprintf(key, 5, "di");
                             break;
                         case X86_REG16_NONE:
                             /* Ne devrait jamais arriver */
@@ -373,31 +329,32 @@ char *x86_register_as_text(const x86_register *reg, AsmSyntax syntax)
                     break;
 
                 case AOS_32_BITS:
+                    klen = 3;
                     switch (reg->reg.reg32)
                     {
                         case X86_REG32_EAX:
-                            snprintf(result, 5, "eax");
+                            snprintf(key, 5, "eax");
                             break;
                         case X86_REG32_ECX:
-                            snprintf(result, 5, "ecx");
+                            snprintf(key, 5, "ecx");
                             break;
                         case X86_REG32_EDX:
-                            snprintf(result, 5, "edx");
+                            snprintf(key, 5, "edx");
                             break;
                         case X86_REG32_EBX:
-                            snprintf(result, 5, "ebx");
+                            snprintf(key, 5, "ebx");
                             break;
                         case X86_REG32_ESP:
-                            snprintf(result, 5, "esp");
+                            snprintf(key, 5, "esp");
                             break;
                         case X86_REG32_EBP:
-                            snprintf(result, 5, "ebp");
+                            snprintf(key, 5, "ebp");
                             break;
                         case X86_REG32_ESI:
-                            snprintf(result, 5, "esi");
+                            snprintf(key, 5, "esi");
                             break;
                         case X86_REG32_EDI:
-                            snprintf(result, 5, "edi");
+                            snprintf(key, 5, "edi");
                             break;
                         case X86_REG32_NONE:
                             printf("null reg\n");
@@ -416,31 +373,32 @@ char *x86_register_as_text(const x86_register *reg, AsmSyntax syntax)
             switch (reg->size)
             {
                 case AOS_8_BITS:
+                    klen = 3;
                     switch (reg->reg.reg8)
                     {
                         case X86_REG8_AL:
-                            snprintf(result, 5, "%%al");
+                            snprintf(key, 5, "%%al");
                             break;
                         case X86_REG8_CL:
-                            snprintf(result, 5, "%%cl");
+                            snprintf(key, 5, "%%cl");
                             break;
                         case X86_REG8_DL:
-                            snprintf(result, 5, "%%dl");
+                            snprintf(key, 5, "%%dl");
                             break;
                         case X86_REG8_BL:
-                            snprintf(result, 5, "%%bl");
+                            snprintf(key, 5, "%%bl");
                             break;
                         case X86_REG8_AH:
-                            snprintf(result, 5, "%%ah");
+                            snprintf(key, 5, "%%ah");
                             break;
                         case X86_REG8_CH:
-                            snprintf(result, 5, "%%ch");
+                            snprintf(key, 5, "%%ch");
                             break;
                         case X86_REG8_DH:
-                            snprintf(result, 5, "%%dh");
+                            snprintf(key, 5, "%%dh");
                             break;
                         case X86_REG8_BH:
-                            snprintf(result, 5, "%%bh");
+                            snprintf(key, 5, "%%bh");
                             break;
                         case X86_REG8_NONE:
                             /* Ne devrait jamais arriver */
@@ -449,31 +407,32 @@ char *x86_register_as_text(const x86_register *reg, AsmSyntax syntax)
                     break;
 
                 case AOS_16_BITS:
+                    klen = 3;
                     switch (reg->reg.reg16)
                     {
                         case X86_REG16_AX:
-                            snprintf(result, 5, "%%ax");
+                            snprintf(key, 5, "%%ax");
                             break;
                         case X86_REG16_CX:
-                            snprintf(result, 5, "%%cx");
+                            snprintf(key, 5, "%%cx");
                             break;
                         case X86_REG16_DX:
-                            snprintf(result, 5, "%%dx");
+                            snprintf(key, 5, "%%dx");
                             break;
                         case X86_REG16_BX:
-                            snprintf(result, 5, "%%bx");
+                            snprintf(key, 5, "%%bx");
                             break;
                         case X86_REG16_SP:
-                            snprintf(result, 5, "%%sp");
+                            snprintf(key, 5, "%%sp");
                             break;
                         case X86_REG16_BP:
-                            snprintf(result, 5, "%%bp");
+                            snprintf(key, 5, "%%bp");
                             break;
                         case X86_REG16_SI:
-                            snprintf(result, 5, "%%si");
+                            snprintf(key, 5, "%%si");
                             break;
                         case X86_REG16_DI:
-                            snprintf(result, 5, "%%di");
+                            snprintf(key, 5, "%%di");
                             break;
                         case X86_REG16_NONE:
                             /* Ne devrait jamais arriver */
@@ -482,31 +441,32 @@ char *x86_register_as_text(const x86_register *reg, AsmSyntax syntax)
                     break;
 
                 case AOS_32_BITS:
+                    klen = 4;
                     switch (reg->reg.reg32)
                     {
                         case X86_REG32_EAX:
-                            snprintf(result, 5, "%%eax");
+                            snprintf(key, 5, "%%eax");
                             break;
                         case X86_REG32_ECX:
-                            snprintf(result, 5, "%%ecx");
+                            snprintf(key, 5, "%%ecx");
                             break;
                         case X86_REG32_EDX:
-                            snprintf(result, 5, "%%edx");
+                            snprintf(key, 5, "%%edx");
                             break;
                         case X86_REG32_EBX:
-                            snprintf(result, 5, "%%ebx");
+                            snprintf(key, 5, "%%ebx");
                             break;
                         case X86_REG32_ESP:
-                            snprintf(result, 5, "%%esp");
+                            snprintf(key, 5, "%%esp");
                             break;
                         case X86_REG32_EBP:
-                            snprintf(result, 5, "%%ebp");
+                            snprintf(key, 5, "%%ebp");
                             break;
                         case X86_REG32_ESI:
-                            snprintf(result, 5, "%%esi");
+                            snprintf(key, 5, "%%esi");
                             break;
                         case X86_REG32_EDI:
-                            snprintf(result, 5, "%%edi");
+                            snprintf(key, 5, "%%edi");
                             break;
                         case X86_REG32_NONE:
                             /* Ne devrait jamais arriver */
@@ -525,6 +485,99 @@ char *x86_register_as_text(const x86_register *reg, AsmSyntax syntax)
 
     }
 
+    g_content_exporter_insert_with_gtk_tag(G_CONTENT_EXPORTER(reg), buffer, iter,
+                                           key, klen, RTT_REGISTER);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : reg = registre à consulter.                                  *
+*                                                                             *
+*  Description : Indique si le registre correspond à ebp ou similaire.        *
+*                                                                             *
+*  Retour      : true si la correspondance est avérée, false sinon.           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_x86_register_is_base_pointer(const GX86Register *reg)
+{
+    bool result;                            /* Bilan à remonter            */
+
+    switch (reg->size)
+    {
+        case AOS_8_BITS_UNSIGNED:
+        case AOS_8_BITS_SIGNED:
+            result = (reg->reg.reg8 == X86_REG8_CH);
+            break;
+        case AOS_16_BITS_UNSIGNED:
+        case AOS_16_BITS_SIGNED:
+            result = (reg->reg.reg16 == X86_REG16_BP);
+            break;
+        case AOS_32_BITS_UNSIGNED:
+        case AOS_32_BITS_SIGNED:
+            result = (reg->reg.reg32 == X86_REG32_EBP);
+            break;
+            /*
+        case AOS_64_BITS_UNSIGNED:
+        case AOS_64_BITS_SIGNED:
+            result = (reg->reg.reg8 == X86_REG8_CH);
+            break;
+            */
+        default:
+            result = false;
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : reg = registre à consulter.                                  *
+*                                                                             *
+*  Description : Indique si le registre correspond à esp ou similaire.        *
+*                                                                             *
+*  Retour      : true si la correspondance est avérée, false sinon.           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_x86_register_is_stack_pointer(const GX86Register *reg)
+{
+    bool result;                            /* Bilan à remonter            */
+
+    switch (reg->size)
+    {
+        case AOS_8_BITS_UNSIGNED:
+        case AOS_8_BITS_SIGNED:
+            result = (reg->reg.reg8 == X86_REG8_AH);
+            break;
+        case AOS_16_BITS_UNSIGNED:
+        case AOS_16_BITS_SIGNED:
+            result = (reg->reg.reg16 == X86_REG16_SP);
+            break;
+        case AOS_32_BITS_UNSIGNED:
+        case AOS_32_BITS_SIGNED:
+            result = (reg->reg.reg32 == X86_REG32_ESP);
+            break;
+            /*
+        case AOS_64_BITS_UNSIGNED:
+        case AOS_64_BITS_SIGNED:
+            result = (reg->reg.reg8 == X86_REG8_CH);
+            break;
+            */
+        default:
+            result = false;
+
+    }
+
     return result;
 
 }
diff --git a/src/arch/x86/registers.h b/src/arch/x86/registers.h
index 491d5bc..18bced7 100644
--- a/src/arch/x86/registers.h
+++ b/src/arch/x86/registers.h
@@ -25,29 +25,40 @@
 #define _ARCH_X86_REGISTERS_H
 
 
+#include <glib-object.h>
+#include <stdbool.h>
+
+
 #include "../archbase.h"
-#include "../operand.h"
 
 
 
-/* Registre x86 */
-typedef struct _x86_register x86_register;
+#define G_TYPE_X86_REGISTER               g_x86_register_get_type()
+#define G_X86_REGISTER(obj)               (G_TYPE_CHECK_INSTANCE_CAST((obj), g_x86_register_get_type(), GX86Register))
+#define G_IS_X86_REGISTER(obj)            (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_x86_register_get_type()))
+#define G_X86_REGISTER_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_X86_REGISTER, GX86RegisterClass))
+#define G_IS_X86_REGISTER_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_X86_REGISTER))
+#define G_X86_REGISTER_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_X86_REGISTER, GX86RegisterClass))
+
 
+/* Représentation d'un registre x86 (instance) */
+typedef struct _GX86Register GX86Register;
 
-/* Récupère l'indentifiant interne d'un registre. */
-x86_register *get_x86_register(AsmOperandSize, bin_t);
+/* Représentation d'un registre x86 (classe) */
+typedef struct _GX86RegisterClass GX86RegisterClass;
 
-/* Efface de la mémoire l'indentifiant interne d'un registre. */
-void free_x86_register(x86_register *);
+
+/* Indique le type défini pour une représentation d'un registre x86. */
+GType g_x86_register_get_type(void);
+
+/* Crée une réprésentation de registre x86. */
+GX86Register *g_x86_register_new(MemoryDataSize, bin_t);
 
 /* Indique si le registre correspond à ebp ou similaire. */
-bool is_x86_register_base_pointer(const x86_register *);
+bool g_x86_register_is_base_pointer(const GX86Register *);
 
 /* Indique si le registre correspond à esp ou similaire. */
-bool is_x86_register_stack_pointer(const x86_register *);
-
-/* Traduit un registre x86 en texte. */
-char *x86_register_as_text(const x86_register *, AsmSyntax);
+bool g_x86_register_is_stack_pointer(const GX86Register *);
 
 
 
diff --git a/src/gtkext/gtkblockview.c b/src/gtkext/gtkblockview.c
index 2659b0d..99825f0 100644
--- a/src/gtkext/gtkblockview.c
+++ b/src/gtkext/gtkblockview.c
@@ -27,8 +27,12 @@
 #include <malloc.h>
 #include <string.h>
 
+#define GTK_TEXT_USE_INTERNAL_UNSUPPORTED_API
+#include <gtk/gtktextdisplay.h>
+
 
 #include "gtkbinview-int.h"
+#include "../analysis/exporter.h"
 #include "../common/dllist.h"
 
 
@@ -46,6 +50,9 @@ struct _GtkBlockView
     bool show_vaddress;                     /* Affichage des adresses ?    */
     bool show_code;                         /* Affichage du code brut ?    */
 
+    GtkTextBuffer *buffer;                  /* Code sous forme de texte    */
+    GtkTextLayout *_layout;                  /* Disposition du texte        */
+
     PangoLayout *layout;                    /* Moteur de rendu du code ASM */
     int line_height;                        /* Hauteur maximale des lignes */
 
@@ -61,6 +68,26 @@ struct _GtkBlockViewClass
 
 
 
+
+static void
+gtk_text_view2_set_attributes_from_style (GtkTextAttributes  *values,
+                                         GtkStyle           *style)
+{
+    PangoFontDescription *font_desc;
+
+  values->appearance.bg_color = style->base[GTK_STATE_NORMAL];
+  values->appearance.fg_color = style->text[GTK_STATE_NORMAL];
+
+  if (values->font)
+    pango_font_description_free (values->font);
+
+        font_desc = pango_font_description_from_string ("mono 10");
+
+  values->font = pango_font_description_copy (/*style->*/font_desc);
+        pango_font_description_free (font_desc);
+}
+
+
 /* Procède à l'initialisation de l'afficheur d'un bloc binaire. */
 static void gtk_block_view_init(GtkBlockView *);
 
@@ -110,7 +137,7 @@ static void gtk_block_view_size_allocate(GtkWidget *widget,
 static gboolean gtk_block_view_button_press(GtkWidget *, GdkEventButton *event);
 
 /* Met à jour l'affichage de la vue sous forme de bloc. */
-static gboolean gtk_block_view_expose(GtkWidget *widget, GdkEventExpose *event);
+static gboolean gtk_block_view_expose(GtkWidget *, GdkEventExpose *);
 
 static void gtk_block_view_destroy(GtkObject *object);
 
@@ -182,11 +209,100 @@ static void gtk_block_view_init(GtkBlockView *view)
 {
     GtkBinView *binview;                    /* Instance parente            */
 
+
+    PangoTabArray *tabs;
+    gint current_y;
+    PangoFontDescription *font_desc;
+    GList *child_exposes;
+    PangoContext *ltr_context, *rtl_context;
+    GtkTextAttributes *style;
+    static bool done = false;
+
+
     binview = GTK_BIN_VIEW(view);
 
     binview->set_lines = (set_rendering_lines_fc)gtk_block_view_set_rendering_lines;
     binview->get_coordinates = (get_addr_coordinates_fc)gtk_block_view_get_address_coordinates;
 
+
+
+    view->buffer = gtk_text_buffer_new(get_gtk_tag_table());
+
+
+
+    view->_layout = gtk_text_layout_new();
+    gtk_text_layout_set_buffer(view->_layout, view->buffer);
+
+
+
+    if (!done || 1)
+    {
+        done = true;
+
+        gtk_text_layout_set_cursor_visible(GTK_BLOCK_VIEW(view)->_layout, FALSE);
+
+        gtk_text_layout_set_overwrite_mode(GTK_BLOCK_VIEW(view)->_layout, FALSE);
+
+
+        ltr_context = gtk_widget_create_pango_context(view);
+        pango_context_set_base_dir(ltr_context, PANGO_DIRECTION_LTR);
+        rtl_context = gtk_widget_create_pango_context(view);
+        pango_context_set_base_dir(rtl_context, PANGO_DIRECTION_RTL);
+
+        gtk_text_layout_set_contexts(GTK_BLOCK_VIEW(view)->_layout, ltr_context, rtl_context);
+
+
+
+        tabs = pango_tab_array_new_with_positions(5, TRUE,
+                                                  PANGO_TAB_LEFT, 120,
+                                                  PANGO_TAB_LEFT, 290,
+                                                  PANGO_TAB_LEFT, 50,
+                                                  PANGO_TAB_LEFT, 50,
+                                                  PANGO_TAB_LEFT, 50);
+
+
+        style = gtk_text_attributes_new ();
+
+        gtk_widget_ensure_style(view);
+
+        font_desc = pango_font_description_from_string ("mono 10");
+        gtk_widget_modify_font (view, font_desc);
+        pango_font_description_free (font_desc);
+
+        gtk_text_view2_set_attributes_from_style(style, GTK_WIDGET(view)->style);
+        /*
+        style->pixels_above_lines = 5;
+        style->pixels_below_lines = 5;
+        style->pixels_inside_wrap = 10;
+        style->left_margin = 10;
+        style->right_margin = 10;
+        style->indent = 10;*/
+        style->left_margin = 10;
+        style->right_margin = 10;
+        style->tabs = tabs;
+
+        style->wrap_mode = GTK_WRAP_WORD;
+        style->justification = GTK_JUSTIFY_LEFT;
+
+        style->direction = gtk_widget_get_direction(view);
+
+
+        gtk_text_layout_set_default_style(GTK_BLOCK_VIEW(view)->_layout, style);
+
+        gtk_text_attributes_unref(style);
+
+
+        //gtk_text_layout_get_size (GTK_BLOCK_VIEW(view)->_layout, &width, &height);
+
+        gtk_text_layout_set_screen_width (GTK_BLOCK_VIEW(view)->_layout,
+                                          MAX (1, 1000));
+
+    }
+
+
+    gtk_text_buffer_set_text(view->buffer, "\t|\t|\t|\t|\t|\n", -1);
+
+
 }
 
 
@@ -240,6 +356,7 @@ gtk_block_view_size_allocate(GtkWidget *widget,
 static void gtk_block_view_realize(GtkWidget *widget)
 {
     GtkBinViewClass *parent_class;          /* Version pure du parent      */
+    PangoFontDescription *font_desc;
 
     parent_class = GTK_BIN_VIEW_CLASS(g_type_class_peek_parent(GTK_BLOCK_VIEW_GET_CLASS(widget)));
 
@@ -247,6 +364,10 @@ static void gtk_block_view_realize(GtkWidget *widget)
 
     GTK_BLOCK_VIEW(widget)->layout = gtk_widget_create_pango_layout(widget, NULL);
 
+    font_desc = pango_font_description_from_string("mono 10");
+    gtk_widget_modify_font(widget, font_desc);
+    pango_font_description_free(font_desc);
+
 }
 
 
@@ -334,8 +455,12 @@ static gboolean gtk_block_view_expose(GtkWidget *widget, GdkEventExpose *event)
     int y;                                  /* Ordonnée du haut d'une ligne*/
     GRenderingLine *iter;                   /* Boucle de parcours          */
 
-    view = GTK_BIN_VIEW(widget);
 
+    PangoFontDescription *font_desc;
+    GList *child_exposes;
+
+    view = GTK_BIN_VIEW(widget);
+#if 0
     gdk_window_begin_paint_region(GDK_DRAWABLE(widget->window), event->region);
 
     gdk_gc_set_clip_region(view->gc, event->region);
@@ -351,7 +476,7 @@ static gboolean gtk_block_view_expose(GtkWidget *widget, GdkEventExpose *event)
                        TRUE, 0, 0, width, height);
 
     gdk_gc_set_foreground(view->gc, &values.foreground);
-
+    /*
     y = event->area.y;
     iter = g_rendering_line_find_by_y(view->lines, view->last, &y);
 
@@ -367,8 +492,21 @@ static gboolean gtk_block_view_expose(GtkWidget *widget, GdkEventExpose *event)
         y += GTK_BLOCK_VIEW(view)->line_height;
 
     }
-
+    */
     gdk_window_end_paint(GDK_DRAWABLE(widget->window));
+#endif
+
+    gtk_text_layout_set_screen_width (GTK_BLOCK_VIEW(view)->_layout,
+                                      MAX (1, 1000));
+
+    //gtk_text_buffer_set_text(GTK_BLOCK_VIEW(view)->buffer, "Hello, this some text\n", -1);
+
+        font_desc = pango_font_description_from_string ("mono 10");
+        gtk_widget_modify_font (view, font_desc);
+        pango_font_description_free (font_desc);
+
+    gtk_text_layout_draw(GTK_BLOCK_VIEW(view)->_layout, widget, GDK_DRAWABLE(widget->window),
+                         NULL, 0, 0, 0, 0, 5000, 50000, &child_exposes);
 
     return TRUE;
 
@@ -482,6 +620,7 @@ void gtk_block_view_set_format(GtkBlockView *view, const exe_format *format)
 static void gtk_block_view_set_rendering_lines(GtkBlockView *view, GRenderingLine *lines, GRenderingLine *last)
 {
     GRenderingLine *iter;                   /* Boucle de parcours          */
+    GtkTextIter pos;                        /* Point d'insertion           */
 
     for (iter = GTK_BIN_VIEW(view)->lines;
          iter != NULL;
@@ -494,6 +633,24 @@ static void gtk_block_view_set_rendering_lines(GtkBlockView *view, GRenderingLin
     g_rendering_line_update_bin_len(GTK_BIN_VIEW(view)->lines,
                                     GTK_BIN_VIEW(view)->last, view->rendering);
 
+    for (iter = GTK_BIN_VIEW(view)->lines;
+         iter != NULL;
+         iter = g_rendering_line_get_next_iter(GTK_BIN_VIEW(view)->lines, iter, GTK_BIN_VIEW(view)->last))
+    {
+        if (iter != GTK_BIN_VIEW(view)->lines)
+        {
+            gtk_text_buffer_get_end_iter(view->buffer, &pos);
+            gtk_text_buffer_insert_with_tags(view->buffer, &pos, "\n", 1, NULL);
+        }
+
+        gtk_text_buffer_get_end_iter(view->buffer, &pos);
+        g_content_exporter_add_to_gtk_buffer(G_CONTENT_EXPORTER(iter), view->rendering,
+                                             view->buffer, &pos);
+
+    }
+
+    gtk_text_layout_validate(GTK_BLOCK_VIEW(view)->_layout, 100000);
+
     gtk_block_view_recompute_size_request(view);
 
 }
@@ -519,6 +676,16 @@ void gtk_block_view_recompute_size_request(GtkBlockView *view)
     int width;                              /* Largeur de l'objet actuelle */
     int height;                             /* Hauteur de l'objet actuelle */
 
+    gtk_text_layout_get_size(view->_layout, &width, &height);
+
+    gtk_widget_set_size_request(GTK_WIDGET(view),
+                                width + 2 * MARGIN_SPACE + 20/*view->line_height*/,
+                                height);
+
+
+    printf("req size :: (%d ; %d)\n", width, height);
+
+    /*
     g_rendering_line_get_size(GTK_BIN_VIEW(view)->lines,
                               GTK_BIN_VIEW(view)->last,
                               view->rendering,
@@ -527,7 +694,7 @@ void gtk_block_view_recompute_size_request(GtkBlockView *view)
     gtk_widget_set_size_request(GTK_WIDGET(view),
                                 width + 2 * MARGIN_SPACE + view->line_height,
                                 height);
-
+    */
 }
 
 
diff --git a/src/gtkext/gtkextstatusbar.c b/src/gtkext/gtkextstatusbar.c
index cb6851d..79beda2 100644
--- a/src/gtkext/gtkextstatusbar.c
+++ b/src/gtkext/gtkextstatusbar.c
@@ -124,6 +124,8 @@ guint gtk_extended_status_bar_push(GtkExtStatusBar *bar, const gchar *message, g
 {
     guint result;                           /* Identifiant à retourner     */
 
+    gdk_threads_enter();
+
     result = gtk_statusbar_push(GTK_STATUSBAR(bar), bar->context, message);
 
     bar->msg_count++;
@@ -143,6 +145,10 @@ guint gtk_extended_status_bar_push(GtkExtStatusBar *bar, const gchar *message, g
     }
     else gtk_widget_hide(GTK_WIDGET(bar->progress));
 
+    gdk_flush ();
+
+    gdk_threads_leave();
+
     return result;
 
 }
@@ -203,6 +209,8 @@ void gtk_extended_status_bar_remove(GtkExtStatusBar *bar, guint id)
 {
     size_t i;                               /* Boucle de parcours          */
 
+    gdk_threads_enter();
+
     gtk_statusbar_remove(GTK_STATUSBAR(bar), bar->context, id);
 
     for (i = 0; i < bar->msg_count; i++)
@@ -225,4 +233,8 @@ void gtk_extended_status_bar_remove(GtkExtStatusBar *bar, guint id)
     else
         gtk_widget_hide(GTK_WIDGET(bar->progress));
 
+    gdk_flush ();
+
+    gdk_threads_leave();
+
 }
diff --git a/src/main.c b/src/main.c
index dd21785..e1572d5 100644
--- a/src/main.c
+++ b/src/main.c
@@ -32,6 +32,7 @@
 #include "params.h"
 #include "project.h"
 #include "analysis/delayed.h"
+#include "analysis/exporter.h"
 #include "arch/processor.h"
 #include "format/format.h"
 #include "format/mangling/demangler.h"
@@ -92,6 +93,8 @@ int main(int argc, char **argv)
     init_all_demanglers();
     init_all_formats();
 
+    _get_gtk_tag_table(gtk_text_tag_table_new());
+
     /* Création de l'interface */
     editor = create_editor();
     gtk_widget_show(editor);
@@ -115,6 +118,8 @@ int main(int argc, char **argv)
     gtk_main();
     gdk_threads_leave();
 
+    _get_gtk_tag_table(0xdeadc0de);
+
     unload_configuration(config);
 
     return EXIT_SUCCESS;
-- 
cgit v0.11.2-87-g4458