From 53edb30496d1065019406de16f9f9d96ba61cd3c Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Tue, 18 Jun 2024 08:31:42 +0200
Subject: Rebuild hex views for large contents.

---
 src/Makefile.am                    |   5 +-
 src/common/Makefile.am             |   2 +-
 src/core/core.c                    |   4 +-
 src/framework.c                    |  63 +++
 src/glibext/Makefile.am            |  33 +-
 src/glibext/buffercache-int.h      |  38 +-
 src/glibext/buffercache.c          | 937 ++++++++++++++++++++-----------------
 src/glibext/buffercache.h          |  72 ++-
 src/glibext/bufferline-int.h       |  94 ++++
 src/glibext/bufferline.c           | 248 ++++++++--
 src/glibext/bufferline.h           |  50 +-
 src/glibext/bufferview-int.h       |  83 ++++
 src/glibext/bufferview.c           | 380 +++++++++++----
 src/glibext/bufferview.h           |  53 ++-
 src/glibext/generator-int.h        |  51 +-
 src/glibext/generator.c            | 135 +++---
 src/glibext/generator.h            |  53 +--
 src/glibext/generators/Makefile.am |  11 +-
 src/glibext/generators/hex.c       | 469 ++++++++++++++++---
 src/glibext/generators/hex.h       |  30 +-
 src/glibext/helpers.h              |  34 +-
 src/glibext/linecolumn.c           | 140 ++++--
 src/glibext/linecolumn.h           |  58 ++-
 src/glibext/linetoken.c            | 627 +++++++++++++++----------
 src/glibext/linetoken.h            |  74 ++-
 src/glibext/options/hex.c          |   2 +-
 src/glibext/options/hex.h          |  10 +
 src/glibext/tokenstyle.c           | 142 ++++--
 src/glibext/tokenstyle.css         |  17 +-
 src/glibext/tokenstyle.h           |  19 +-
 src/glibext/widthtracker-int.h     |  80 ++++
 src/glibext/widthtracker.c         | 556 +++++++++++++---------
 src/glibext/widthtracker.h         |  39 +-
 src/gtkext/Makefile.am             |   5 +-
 src/gtkext/bufferview-int.h        |  49 +-
 src/gtkext/bufferview.c            | 449 ++++++++++++++++--
 src/gtkext/bufferview.h            |  38 +-
 src/gtkext/contentview-int.h       |  52 +-
 src/gtkext/contentview.c           | 532 +++++++++++----------
 src/gtkext/hexview-int.h           |  71 +++
 src/gtkext/hexview.c               | 437 ++++++++++-------
 src/gtkext/hexview.h               |   8 +-
 src/gtkext/hexview.ui              |   7 +-
 src/gui/core/Makefile.am           |   4 +-
 src/gui/core/core.c                |  76 +++
 src/gui/core/core.h                |  29 +-
 46 files changed, 4456 insertions(+), 1910 deletions(-)
 create mode 100644 src/glibext/bufferline-int.h
 create mode 100644 src/glibext/bufferview-int.h
 create mode 100644 src/glibext/widthtracker-int.h
 create mode 100644 src/gtkext/hexview-int.h

diff --git a/src/Makefile.am b/src/Makefile.am
index a01ed63..1250b59 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -81,6 +81,7 @@ libchrysacore4_la_LIBADD =					\
 	arch/libarch4.la						\
 	common/libcommon4.la					\
 	core/libcore4.la						\
+	glibext/libglibext4.la					\
 	plugins/libplugins.la
 
 libchrysacore4_la_LDFLAGS =					\
@@ -98,8 +99,10 @@ libchrysacoreui_la_LIBADD =					\
 	gtkext/libgtkext4.la					\
 	gui/libgui4.la
 
+# -lm: log()
 libchrysacoreui_la_LDFLAGS =				\
-	$(LIBGTK4_CFLAGS) -L.libs -lchrysacore4
+	$(LIBGTK4_CFLAGS) -L.libs -lchrysacore4	\
+	-lm
 
 
 
diff --git a/src/common/Makefile.am b/src/common/Makefile.am
index a57868d..8161f8e 100644
--- a/src/common/Makefile.am
+++ b/src/common/Makefile.am
@@ -17,7 +17,6 @@ libcommon_la_SOURCES =					\
 	ibuf.h ibuf.c						\
 	io.h io.c							\
 	itoa.h itoa.c						\
-	fnv1a.h fnv1a.c						\
 	leb128.h leb128.c					\
 	macros.h							\
 	net.h net.c							\
@@ -58,6 +57,7 @@ libcommon4_la_SOURCES =						\
 	datatypes.h								\
 	environment.h environment.c				\
 	extstr.h extstr.c						\
+	fnv1a.h fnv1a.c							\
 	io.h io.c								\
 	leb128.h leb128.c						\
 	packed.h packed.c						\
diff --git a/src/core/core.c b/src/core/core.c
index addd58c..f67e23d 100644
--- a/src/core/core.c
+++ b/src/core/core.c
@@ -183,7 +183,7 @@ void unload_all_core_components(bool cs)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : selected = liste d'éléments à décharger.                     *
+*  Paramètres  : flags = liste d'éléments à charger.                          *
 *                                                                             *
 *  Description : Charge une sélection d'éléments de base du programme.        *
 *                                                                             *
@@ -231,7 +231,7 @@ bool load_core_components(AvailableCoreComponent flags)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : selected = liste d'éléments à décharger.                     *
+*  Paramètres  : flags = liste d'éléments à décharger.                        *
 *                                                                             *
 *  Description : Décharge une sélection d'éléments de base du programme.      *
 *                                                                             *
diff --git a/src/framework.c b/src/framework.c
index b7a1332..96c97c3 100644
--- a/src/framework.c
+++ b/src/framework.c
@@ -28,6 +28,9 @@
 
 #include "framework.h"
 #include "glibext/helpers.h"
+#include "gui/core/core.h"
+#include "analysis/contents/file.h" // REMME
+#include "gtkext/hexview.h" // REMME
 
 
 
@@ -249,8 +252,63 @@ static void gtk_chrysalide_framework_activate(GApplication *app)
     gtk_window_set_title(window, "Chrysalide");
     gtk_window_present(window);
 
+
+    do
+    {
+        GBinContent *cnt;
+
+        GtkWidget *parent;
+        GtkHexView *wgt;
+
+
+#if 0
+
+        cnt = g_file_content_new("tmp.bin");
+
+        parent = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);
+        gtk_box_set_homogeneous(GTK_BOX(parent), FALSE);
+        gtk_window_set_child(window, parent);
+
+        wgt = gtk_hex_view_new(cnt);
+        gtk_box_append(GTK_BOX(parent), GTK_WIDGET(wgt));
+
+        wgt = gtk_hex_view_new(cnt);
+        gtk_box_append(GTK_BOX(parent), GTK_WIDGET(wgt));
+
+#else
+
+        cnt = g_file_content_new("/bin/id");
+        //cnt = g_file_content_new("tmp.bin");
+
+
+        parent = gtk_scrolled_window_new();
+        gtk_window_set_child(window, parent);
+
+        wgt = gtk_hex_view_new(cnt);
+        gtk_scrolled_window_set_child(GTK_SCROLLED_WINDOW(parent), GTK_WIDGET(wgt));
+
+#endif
+
+
+
+
+    }
+    while (0);
+
+
     /* Chargement des extensions de thème */
 
+    /*
+    css = gtk_css_provider_new();
+
+    gtk_css_provider_load_from_resource(css, "/re/chrysalide/framework/glibext/linestyle.css");
+
+    gtk_style_context_add_provider_for_display(gtk_widget_get_display(GTK_WIDGET(window)),
+                                               GTK_STYLE_PROVIDER(css), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+
+    unref_object(css);
+    */
+
     css = gtk_css_provider_new();
 
     gtk_css_provider_load_from_resource(css, "/re/chrysalide/framework/gtkext/hexview.css");
@@ -287,12 +345,17 @@ int main(int argc, char **argv)
     int result;                             /* Bilan de l'exécution        */
     GtkChrysalideFramework *app;            /* Gestion d'application GTK   */
 
+    if (!load_gui_components(AGC_BUFFER_FEATURES))
+        return EXIT_FAILURE;
+
     app = gtk_chrysalide_framework_new();
 
     result = g_application_run(G_APPLICATION(app), argc, argv);
 
     g_object_unref(G_OBJECT(app));
 
+    unload_gui_components(AGC_BUFFER_FEATURES);
+
     return result;
 
 }
diff --git a/src/glibext/Makefile.am b/src/glibext/Makefile.am
index ba4e3fa..e2c9d69 100644
--- a/src/glibext/Makefile.am
+++ b/src/glibext/Makefile.am
@@ -4,10 +4,6 @@ BUILT_SOURCES = chrysamarshal.h chrysamarshal.c resources.h resources.c
 noinst_LTLIBRARIES  = libglibext4.la libglibextui.la # libglibext.la
 
 libglibext_la_SOURCES =						\
-	buffercache-int.h						\
-	buffercache.h buffercache.c				\
-	bufferline.h bufferline.c				\
-	chrysamarshal.h chrysamarshal.c			\
 	comparison-int.h						\
 	comparison.h comparison.c				\
 	configuration-int.h						\
@@ -17,11 +13,9 @@ libglibext_la_SOURCES =						\
 	gbinarycursor.h gbinarycursor.c			\
 	gbinportion-int.h						\
 	gbinportion.h gbinportion.c				\
-	displayoptions.h displayoptions.c		\
 	glinecursor-int.h						\
 	glinecursor.h glinecursor.c				\
 	gnhash.h gnhash.c						\
-	linecolumn.h linecolumn.c				\
 	notifier.h								\
 	objhole.h								\
 	proto.h									\
@@ -35,12 +29,10 @@ libglibext_la_SOURCES =						\
 if BUILD_GTK_SUPPORT
 
 libglibext_la_SOURCES +=					\
-	bufferview.h bufferview.c				\
 	gloadedpanel-int.h						\
 	gloadedpanel.h gloadedpanel.c			\
 	named-int.h								\
-	named.h named.c							\
-	widthtracker.h widthtracker.c
+	named.h named.c
 
 endif
 
@@ -51,6 +43,7 @@ libglibext_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS)
 
 
 libglibext4_la_SOURCES =					\
+	chrysamarshal.h chrysamarshal.c			\
 	helpers.h
 
 libglibext4_la_CFLAGS = $(TOOLKIT_CFLAGS)
@@ -60,19 +53,37 @@ RES_FILES =									\
 	tokenstyle.css
 
 libglibextui_la_SOURCES =					\
+	buffercache-int.h						\
+	buffercache.h buffercache.c				\
+	bufferline-int.h						\
+	bufferline.h bufferline.c				\
+	bufferview-int.h						\
+	bufferview.h bufferview.c				\
+	generator-int.h							\
+	generator.h generator.c					\
+	linecolumn.h linecolumn.c				\
+	linetoken.h linetoken.c					\
+	options-int.h							\
+	options.h options.c						\
 	tokenstyle-int.h						\
 	tokenstyle.h tokenstyle.c				\
-	resources.h resources.c
+	resources.h resources.c					\
+	widthtracker-int.h						\
+	widthtracker.h widthtracker.c
 
 libglibextui_la_CFLAGS = $(LIBGTK4_CFLAGS)
 
+libglibextui_la_LIBADD = 					\
+	generators/libglibextgenerators.la		\
+	options/libglibextoptions.la
+
 
 devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%)
 
 dev_HEADERS = $(libglibext_la_SOURCES:%c=)
 
 
-#SUBDIRS = generators
+SUBDIRS = generators options
 
 
 chrysamarshal.h: chrysamarshal.list
diff --git a/src/glibext/buffercache-int.h b/src/glibext/buffercache-int.h
index 0e831a2..59d273b 100644
--- a/src/glibext/buffercache-int.h
+++ b/src/glibext/buffercache-int.h
@@ -33,20 +33,20 @@
 
 
 /* Informations rattachées à la génération d'une ligne */
-typedef struct _generator_link
+typedef struct _generator_link_t
 {
-    GLineGenerator *instance;               /* Fournisseur de contenu      */
+    GTokenGenerator *instance;              /* Fournisseur de contenu      */
     size_t repeat;                          /* Compteur de successions     */
 
-} generator_link;
+} generator_link_t;
 
 /* Suivi interne de l'état d'une ligne */
-typedef struct _cache_info
+typedef struct _cache_info_t
 {
     union
     {
-        generator_link generator;           /* Générateur unique           */
-        generator_link *generators;         /* Liste de générateurs        */
+        generator_link_t generator;         /* Générateur unique           */
+        generator_link_t *generators;       /* Liste de générateurs        */
     };
     size_t count;                           /* Taille de cette liste       */
 
@@ -54,7 +54,7 @@ typedef struct _cache_info
 
     BufferLineFlags extra_flags;            /* Propriétés supplémentaires  */
 
-} cache_info;
+} cache_info_t;
 
 
 
@@ -66,13 +66,25 @@ struct _GBufferCache
 {
     GObject parent;                         /* A laisser en premier        */
 
+    size_t opt_count;                       /* Qté de colonnes en option   */
+    size_t reg_count;                       /* Nombre de colonnes normales */
+#ifndef NDEBUG
+    size_t col_count;                       /* Nombre maximum de colonnes  */
+#endif
+
+
+
+#if 0
     GBinContent *content;                   /* Contenu binaire global      */
 
 #ifdef INCLUDE_GTK_SUPPORT
     GWidthTracker *tracker;                 /* Suivi des largeurs          */
 #endif
+#endif
+
 
-    cache_info *lines;                      /* Liste des lignes intégrées  */
+
+    cache_info_t *lines;                    /* Liste des lignes intégrées  */
     size_t count;                           /* Quantité en cache           */
     size_t used;                            /* Quantité utilisée           */
     GRWLock access;                         /* Verrou de protection        */
@@ -84,18 +96,20 @@ struct _GBufferCacheClass
 {
     GObjectClass parent;                    /* A laisser en premier        */
 
-    gint line_height;                       /* Hauteur maximale des lignes */
-    gint left_margin;                       /* Marge gauche + espace       */
-    gint text_pos;                          /* Début d'impression du code  */
-
     /* Signaux */
 
     void (* size_changed) (GBufferCache *, bool, size_t, size_t);
 
+#if 0
     void (* line_updated) (GBufferCache *, size_t);
+#endif
 
 };
 
 
+/* Met en place un nouveau tampon pour lignes quelconques. */
+bool g_buffer_cache_create(GBufferCache *, size_t, size_t);
+
+
 
 #endif  /* _GLIBEXT_BUFFERCACHE_INT_H */
diff --git a/src/glibext/buffercache.c b/src/glibext/buffercache.c
index 78c7479..7856ff2 100644
--- a/src/glibext/buffercache.c
+++ b/src/glibext/buffercache.c
@@ -37,40 +37,45 @@
 /* --------------------- FONCTIONS AUXILIAIRES DE MANIPULATIONS --------------------- */
 
 
-/* Gros verrou global pour alléger les structures... */
-G_LOCK_DEFINE_STATIC(_line_update);
-
-
 /* Met en place un nouvel ensemble d'information sur une ligne. */
-static void init_cache_info(cache_info *, GLineGenerator *, size_t, BufferLineFlags);
+static void init_cache_info(cache_info_t *, GTokenGenerator *, size_t, BufferLineFlags);
 
 /* Libère la mémoire occupée par des informations sur une ligne. */
-static void release_cache_info(cache_info *);
+static void release_cache_info(cache_info_t *);
+
+/* Force la réinitialisation d'une éventuelle ligne cachée. */
+static void reset_cache_info_line(cache_info_t *);
+
+/* Suivit les variations du compteur de références d'une ligne. */
+static void on_line_ref_toggle(cache_info_t *, GBufferLine *, gboolean);
+
+/* Fournit la ligne de tampon correspondant aux générateurs. */
+static GBufferLine *get_cache_info_line(cache_info_t *, size_t, size_t, void *);
+
+/* Calcule l'indice d'apparition d'un générateur. */
+static size_t compute_cache_info_repetition(const cache_info_t *, GTokenGenerator *);
+
+
+
+#if 0
+/* Gros verrou global pour alléger les structures... */
+G_LOCK_DEFINE_STATIC(_line_update);
+
 
 /* Ajoute un générateur aux informations sur une ligne. */
-static void extend_cache_info(cache_info *, GLineGenerator *, BufferLineFlags);
+static void extend_cache_info(cache_info_t *, GLineGenerator *, BufferLineFlags);
 
 /* Retire un générateur aux informations d'une ligne. */
-static void remove_from_cache_info(cache_info *, GLineGenerator *);
+static void remove_from_cache_info(cache_info_t *, GLineGenerator *);
 
 /* Retrouve l'emplacement correspondant à une position de ligne. */
-static void get_cache_info_cursor(const cache_info *, size_t, gint, GLineCursor **);
-
-/* Suivit les variations du compteur de références d'une ligne. */
-static void on_line_ref_toggle(cache_info *, GBufferLine *, gboolean);
+static void get_cache_info_cursor(const cache_info_t *, size_t, gint, GLineCursor **);
 
 #ifdef INCLUDE_GTK_SUPPORT
 
-/* Fournit la ligne de tampon correspondant aux générateurs. */
-static GBufferLine *get_cache_info_line(cache_info *, const GWidthTracker *, size_t, const GBinContent *);
-
 #endif
 
-/* Force la réinitialisation d'une éventuelle ligne cachée. */
-static void _reset_cache_info_line_unlocked(cache_info *);
-
-/* Force la réinitialisation d'une éventuelle ligne cachée. */
-static void reset_cache_info_line(cache_info *);
+#endif
 
 
 
@@ -78,7 +83,7 @@ static void reset_cache_info_line(cache_info *);
 
 
 /* Taille des allocations de masse */
-#define LINE_ALLOC_BULK 1000
+//#define LINE_ALLOC_BULK 1000
 
 
 /* Procède à l'initialisation d'une classe de tampon de lignes. */
@@ -93,9 +98,6 @@ static void g_buffer_cache_dispose(GBufferCache *);
 /* Procède à la libération totale de la mémoire. */
 static void g_buffer_cache_finalize(GBufferCache *);
 
-/* Calcule l'indice d'apparition d'un générateur dans le tampon. */
-static size_t g_buffer_cache_compute_repetition(GBufferCache *, size_t, GLineGenerator *);
-
 
 
 /* ---------------------------------------------------------------------------------- */
@@ -118,12 +120,12 @@ static size_t g_buffer_cache_compute_repetition(GBufferCache *, size_t, GLineGen
 *                                                                             *
 ******************************************************************************/
 
-static void init_cache_info(cache_info *info, GLineGenerator *generator, size_t repeat, BufferLineFlags flags)
+static void init_cache_info(cache_info_t *info, GTokenGenerator *generator, size_t repeat, BufferLineFlags flags)
 {
     info->generator.instance = generator;
     info->generator.repeat = repeat;
 
-    g_object_ref(G_OBJECT(generator));
+    ref_object(generator);
 
     info->count = 1;
 
@@ -146,16 +148,16 @@ static void init_cache_info(cache_info *info, GLineGenerator *generator, size_t
 *                                                                             *
 ******************************************************************************/
 
-static void release_cache_info(cache_info *info)
+static void release_cache_info(cache_info_t *info)
 {
     size_t i;                               /* Boucle de parcours          */
 
     if (info->count == 1)
-        g_object_unref(G_OBJECT(info->generator.instance));
+        unref_object(info->generator.instance);
 
     else
         for (i = 0; i < info->count; i++)
-            g_object_unref(G_OBJECT(info->generators[i].instance));
+            unref_object(info->generators[i].instance);
 
     reset_cache_info_line(info);
 
@@ -164,6 +166,155 @@ static void release_cache_info(cache_info *info)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : info = informations sur une ligne à venir manipuler.         *
+*                                                                             *
+*  Description : Force la réinitialisation d'une éventuelle ligne cachée.     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void reset_cache_info_line(cache_info_t *info)
+{
+    if (info->line != NULL)
+    {
+        g_object_remove_toggle_ref(G_OBJECT(info->line), (GToggleNotify)on_line_ref_toggle, info);
+
+        info->line = NULL;
+
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : info = informations sur une ligne à venir manipuler.         *
+*                line = tampon de lignes à venir supprimer au besoin.         *
+*                last = indication sur la valeur du compteur de références.   *
+*                                                                             *
+*  Description : Suivit les variations du compteur de références d'une ligne. *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void on_line_ref_toggle(cache_info_t *info, GBufferLine *line, gboolean last)
+{
+    if (last)
+    {
+        assert(info->line != NULL);
+
+        reset_cache_info_line(info);
+
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : info      = informations sur une ligne à venir manipuler.    *
+*                index     = indice de la ligne à constituer.                 *
+*                col_count = quantité de colonnes à considérer.               *
+*                data      = éventuelle donnée complémentaire fournie.        *
+*                                                                             *
+*  Description : Fournit la ligne de tampon correspondant aux générateurs.    *
+*                                                                             *
+*  Retour      : Ligne déjà en place ou créée pour le besoin.                 *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static GBufferLine *get_cache_info_line(cache_info_t *info, size_t index, size_t col_count, void *data)
+{
+    GBufferLine *result;                    /* Construction à retourner    */
+    size_t i;                               /* Boucle de parcours          */
+
+    result = info->line;
+
+    if (result != NULL)
+        ref_object(result);
+
+    else
+    {
+        result = g_buffer_line_new(col_count);
+
+        //g_buffer_line_add_flag(result, info->extra_flags);
+
+        g_object_add_toggle_ref(G_OBJECT(result), (GToggleNotify)on_line_ref_toggle, info);
+
+        if (info->count == 1)
+            g_token_generator_populate_line(info->generator.instance,
+                                            index, info->generator.repeat,
+                                            result, data);
+
+        else
+            for (i = 0; i < info->count; i++)
+                g_token_generator_populate_line(info->generators[i].instance,
+                                                index, info->generators[i].repeat,
+                                                result, data);
+
+        info->line = result;
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : info      = informations sur une ligne à consulter.          *
+*                generator = générateur associé à au moins une ligne.         *
+*                                                                             *
+*  Description : Calcule l'indice d'apparition d'un générateur.               *
+*                                                                             *
+*  Retour      : Indice de répétition, 0 si aucune.                           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static size_t compute_cache_info_repetition(const cache_info_t *info, GTokenGenerator *generator)
+{
+    size_t result;                          /* Compteur à retourner        */
+    size_t i;                               /* Boucle de parcours          */
+
+    result = 0;
+
+    if (info->count == 1)
+    {
+        if (info->generator.instance == generator)
+            result = info->generator.repeat + 1;
+
+    }
+
+    else
+        for (i = 0; i < info->count; i++)
+            if (info->generators[i].instance == generator)
+            {
+                result = info->generators[i].repeat + 1;
+                break;
+            }
+
+    return result;
+
+}
+
+
+
+
+
+#if 0
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : info      = informations concernant une ligne à actualiser.  *
 *                generator = générateur à associer à toutes les lignes.       *
 *                flags     = propriétés supplémentaires à associer à la ligne.*
@@ -176,7 +327,7 @@ static void release_cache_info(cache_info *info)
 *                                                                             *
 ******************************************************************************/
 
-static void extend_cache_info(cache_info *info, GLineGenerator *generator, BufferLineFlags flags)
+static void extend_cache_info(cache_info_t *info, GLineGenerator *generator, BufferLineFlags flags)
 {
     generator_link first;                   /* Générateur déjà en place    */
     generator_link *new;                    /* Nouveau générateur placé    */
@@ -235,7 +386,7 @@ static void extend_cache_info(cache_info *info, GLineGenerator *generator, Buffe
 *                                                                             *
 ******************************************************************************/
 
-static void remove_from_cache_info(cache_info *info, GLineGenerator *generator)
+static void remove_from_cache_info(cache_info_t *info, GLineGenerator *generator)
 {
     generator_link *link;                   /* Accès simplifié             */
     size_t i;                               /* Boucle de parcours          */
@@ -326,7 +477,7 @@ static void remove_from_cache_info(cache_info *info, GLineGenerator *generator)
 *                                                                             *
 ******************************************************************************/
 
-static void get_cache_info_cursor(const cache_info *info, size_t index, gint x, GLineCursor **cursor)
+static void get_cache_info_cursor(const cache_info_t *info, size_t index, gint x, GLineCursor **cursor)
 {
     const generator_link *generator;        /* Générateur retenu           */
 
@@ -340,13 +491,34 @@ static void get_cache_info_cursor(const cache_info *info, size_t index, gint x,
 }
 
 
+
+#ifdef INCLUDE_GTK_SUPPORT
+
+
+
+
+#endif
+
+
+
+
+#endif
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                            TAMPON POUR CODE DESASSEMBLE                            */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Détermine le type du composant de tampon pour gestion de lignes optimisée. */
+G_DEFINE_TYPE(GBufferCache, g_buffer_cache, G_TYPE_OBJECT);
+
+
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : info = informations sur une ligne à venir manipuler.         *
-*                line = tampon de lignes à venir supprimer au besoin.         *
-*                last = indication sur la valeur du compteur de références.   *
+*  Paramètres  : class = classe de composant GLib à initialiser.              *
 *                                                                             *
-*  Description : Suivit les variations du compteur de références d'une ligne. *
+*  Description : Procède à l'initialisation d'une classe de tampon de lignes. *
 *                                                                             *
 *  Retour      : -                                                            *
 *                                                                             *
@@ -354,89 +526,124 @@ static void get_cache_info_cursor(const cache_info *info, size_t index, gint x,
 *                                                                             *
 ******************************************************************************/
 
-static void on_line_ref_toggle(cache_info *info, GBufferLine *line, gboolean last)
+static void g_buffer_cache_class_init(GBufferCacheClass *class)
 {
-    if (last)
-    {
-        G_LOCK(_line_update);
+    GObjectClass *object;                   /* Autre version de la classe  */
 
-        assert(info->line != NULL);
+    object = G_OBJECT_CLASS(class);
 
-        _reset_cache_info_line_unlocked(info);
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_buffer_cache_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_buffer_cache_finalize;
 
-        G_UNLOCK(_line_update);
+    /* Signaux */
 
-    }
+    g_signal_new("size-changed",
+                 G_TYPE_BUFFER_CACHE,
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET(GBufferCacheClass, size_changed),
+                 NULL, NULL,
+                 g_cclosure_user_marshal_VOID__BOOLEAN_ULONG_ULONG,
+                 G_TYPE_NONE, 3, G_TYPE_BOOLEAN, G_TYPE_ULONG, G_TYPE_ULONG);
 
-}
+#if 0
 
+    g_signal_new("line-updated",
+                 G_TYPE_BUFFER_CACHE,
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET(GBufferCacheClass, line_updated),
+                 NULL, NULL,
+                 g_cclosure_marshal_VOID__ULONG,
+                 G_TYPE_NONE, 1, G_TYPE_ULONG);
 
-#ifdef INCLUDE_GTK_SUPPORT
+#endif
+
+}
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : info    = informations sur une ligne à venir manipuler.      *
-*                tracker = gestionnaire de largeurs à consulter si besoin est.*
-*                index   = indice de la ligne à constituer.                   *
-*                content = éventuel contenu binaire brut à imprimer.          *
+*  Paramètres  : cache = composant GLib à initialiser.                        *
 *                                                                             *
-*  Description : Fournit la ligne de tampon correspondant aux générateurs.    *
+*  Description : Procède à l'initialisation d'un tampon de gestion de lignes. *
 *                                                                             *
-*  Retour      : Ligne déjà en place ou créée pour le besoin.                 *
+*  Retour      : -                                                            *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static GBufferLine *get_cache_info_line(cache_info *info, const GWidthTracker *tracker, size_t index, const GBinContent *content)
+static void g_buffer_cache_init(GBufferCache *cache)
 {
-    GBufferLine *result;                    /* Construction à retourner    */
-    size_t i;                               /* Boucle de parcours          */
+#if 0
 
-    G_LOCK(_line_update);
+    cache->content = NULL;
 
-    result = info->line;
+    cache->lines = NULL;
+    cache->count = 0;
+    cache->used = 0;
+    g_rw_lock_init(&cache->access);
 
-    if (result == NULL)
-    {
-        result = g_buffer_line_new(g_width_tracker_count_columns(tracker));
+#ifdef INCLUDE_GTK_SUPPORT
+    cache->tracker = NULL;
+#endif
+
+#endif
 
-        g_buffer_line_add_flag(result, info->extra_flags);
+}
 
-        g_object_add_toggle_ref(G_OBJECT(result), (GToggleNotify)on_line_ref_toggle, info);
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : cache = instance d'objet GLib à traiter.                     *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_buffer_cache_dispose(GBufferCache *cache)
+{
+#if 0
+    size_t i;                               /* Boucle de parcours #1       */
+    cache_info_t *info;                       /* Accès direct à une ligne    */
+    size_t j;                               /* Boucle de parcours #2       */
+
+    g_clear_object(&cache->content);
+
+    for (i = 0; i < cache->used; i++)
+    {
+        info = &cache->lines[i];
 
         if (info->count == 1)
-            g_line_generator_print(info->generator.instance, result, index,
-                                   info->generator.repeat, content);
+            g_clear_object(&info->generator.instance);
 
         else
-            for (i = 0; i < info->count; i++)
-                g_line_generator_print(info->generators[i].instance, result, index,
-                                       info->generators[i].repeat, content);
+            for (j = 0; j < info->count; j++)
+                g_clear_object(&info->generators[j].instance);
 
-        info->line = result;
+        g_clear_object(&info->line);
 
     }
 
-    else
-        g_object_ref(G_OBJECT(result));
+#ifdef INCLUDE_GTK_SUPPORT
+    g_clear_object(&cache->tracker);
+#endif
 
-    G_UNLOCK(_line_update);
+#endif
 
-    return result;
+    G_OBJECT_CLASS(g_buffer_cache_parent_class)->dispose(G_OBJECT(cache));
 
 }
 
 
-#endif
-
-
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : info = informations sur une ligne à venir manipuler.         *
+*  Paramètres  : cache = instance d'objet GLib à traiter.                     *
 *                                                                             *
-*  Description : Force la réinitialisation d'une éventuelle ligne cachée.     *
+*  Description : Procède à la libération totale de la mémoire.                *
 *                                                                             *
 *  Retour      : -                                                            *
 *                                                                             *
@@ -444,57 +651,100 @@ static GBufferLine *get_cache_info_line(cache_info *info, const GWidthTracker *t
 *                                                                             *
 ******************************************************************************/
 
-static void _reset_cache_info_line_unlocked(cache_info *info)
+static void g_buffer_cache_finalize(GBufferCache *cache)
 {
-    if (info->line != NULL)
+
+#if 0
+    size_t i;                               /* Boucle de parcours          */
+    cache_info_t *info;                       /* Accès direct à une ligne    */
+
+    for (i = 0; i < cache->used; i++)
     {
-        g_object_remove_toggle_ref(G_OBJECT(info->line), (GToggleNotify)on_line_ref_toggle, info);
+        info = &cache->lines[i];
 
-        info->line = NULL;
+        if (info->count > 1)
+            free(info->generators);
 
     }
 
+    if (cache->lines != NULL)
+        free(cache->lines);
+
+    g_rw_lock_clear(&cache->access);
+
+#endif
+
+    G_OBJECT_CLASS(g_buffer_cache_parent_class)->finalize(G_OBJECT(cache));
+
 }
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : info = informations sur une ligne à venir manipuler.         *
+*  Paramètres  : opt_count = quantité de colonnes optionnelles.               *
+*                reg_count = quantité de colonnes normales à considérer.      *
 *                                                                             *
-*  Description : Force la réinitialisation d'une éventuelle ligne cachée.     *
+*  Description : Crée un nouveau tampon pour lignes quelconques.              *
 *                                                                             *
-*  Retour      : -                                                            *
+*  Retour      : Composant GLib créé.                                         *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static void reset_cache_info_line(cache_info *info)
+GBufferCache *g_buffer_cache_new(size_t opt_count, size_t reg_count)
 {
-    G_LOCK(_line_update);
+    GBufferCache *result;                   /* Composant à retourner       */
 
-    _reset_cache_info_line_unlocked(info);
+    result = g_object_new(G_TYPE_BUFFER_CACHE, NULL);
 
-    G_UNLOCK(_line_update);
+    if (!g_buffer_cache_create(result, opt_count, reg_count))
+        g_clear_object(&result);
+
+    return result;
 
 }
 
 
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : cache     = cache de lignes à initialiser.                   *
+*                opt_count = quantité de colonnes optionnelles.               *
+*                reg_count = quantité de colonnes normales à considérer.      *
+*                                                                             *
+*  Description : Met en place un nouveau tampon pour lignes quelconques.      *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_buffer_cache_create(GBufferCache *cache, size_t opt_count, size_t reg_count)
+{
+    bool result;                            /* Bilen à retourner           */
+
+    result = true;
 
-/* ---------------------------------------------------------------------------------- */
-/*                            TAMPON POUR CODE DESASSEMBLE                            */
-/* ---------------------------------------------------------------------------------- */
+    cache->opt_count = opt_count;
+    cache->reg_count = reg_count;
 
+#ifndef NDEBUG
+    cache->col_count = opt_count + reg_count;
+#endif
 
-/* Détermine le type du composant de tampon pour gestion de lignes optimisée. */
-G_DEFINE_TYPE(GBufferCache, g_buffer_cache, G_TYPE_OBJECT);
+    return result;
+
+}
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : class = classe de composant GLib à initialiser.              *
+*  Paramètres  : cache     = tampon de lignes à consulter.                    *
+*                opt_count = quantité de colonnes optionnelles. [OUT]         *
+*                reg_count = quantité de colonnes normales à considérer. [OUT]*
 *                                                                             *
-*  Description : Procède à l'initialisation d'une classe de tampon de lignes. *
+*  Description : Fournit le nombre de colonnes supportées par un tampon.      *
 *                                                                             *
 *  Retour      : -                                                            *
 *                                                                             *
@@ -502,45 +752,76 @@ G_DEFINE_TYPE(GBufferCache, g_buffer_cache, G_TYPE_OBJECT);
 *                                                                             *
 ******************************************************************************/
 
-static void g_buffer_cache_class_init(GBufferCacheClass *class)
+void g_buffer_cache_count_columns(const GBufferCache *cache, size_t *opt_count, size_t *reg_count)
 {
-    GObjectClass *object;                   /* Autre version de la classe  */
+    *opt_count = cache->opt_count;
+    *reg_count = cache->reg_count;
 
-    object = G_OBJECT_CLASS(class);
+}
 
-    object->dispose = (GObjectFinalizeFunc/* ! */)g_buffer_cache_dispose;
-    object->finalize = (GObjectFinalizeFunc)g_buffer_cache_finalize;
 
-    class->line_height = 17;
-    class->left_margin = 2 * class->line_height;
-    class->text_pos = 2.5 * class->line_height;
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : cache = cache de lignes à mettre à jour.                     *
+*                write = précise le type d'accès prévu (lecture/écriture).    *
+*                lock  = indique le sens du verrouillage à mener.             *
+*                                                                             *
+*  Description : Met à disposition un encadrement des accès aux lignes.       *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
 
-    /* Signaux */
+void g_buffer_cache_lock_unlock(GBufferCache *cache, bool write, bool lock)
+{
+    if (write)
+    {
+        if (lock) g_rw_lock_writer_lock(&cache->access);
+        else g_rw_lock_writer_unlock(&cache->access);
+    }
+    else
+    {
+        if (lock) g_rw_lock_reader_lock(&cache->access);
+        else g_rw_lock_reader_unlock(&cache->access);
+    }
 
-    g_signal_new("size-changed",
-                 G_TYPE_BUFFER_CACHE,
-                 G_SIGNAL_RUN_LAST,
-                 G_STRUCT_OFFSET(GBufferCacheClass, size_changed),
-                 NULL, NULL,
-                 g_cclosure_user_marshal_VOID__BOOLEAN_ULONG_ULONG,
-                 G_TYPE_NONE, 3, G_TYPE_BOOLEAN, G_TYPE_ULONG, G_TYPE_ULONG);
+}
 
-    g_signal_new("line-updated",
-                 G_TYPE_BUFFER_CACHE,
-                 G_SIGNAL_RUN_LAST,
-                 G_STRUCT_OFFSET(GBufferCacheClass, line_updated),
-                 NULL, NULL,
-                 g_cclosure_marshal_VOID__ULONG,
-                 G_TYPE_NONE, 1, G_TYPE_ULONG);
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : cache = instance GLib à consulter.                           *
+*                                                                             *
+*  Description : Compte le nombre de lignes rassemblées dans un tampon.       *
+*                                                                             *
+*  Retour      : Nombre de lignes constituant le tampon.                      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+size_t g_buffer_cache_count_lines(GBufferCache *cache)
+{
+    size_t result;                          /* Quantité à retourner        */
+
+    assert(!g_rw_lock_writer_trylock(&cache->access));
+
+    result = cache->used;
+
+    return result;
 
 }
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : cache = composant GLib à initialiser.                        *
+*  Paramètres  : cache     = instance GLib à modifier.                        *
+*                count     = quantité totale de lignes à avoir à disposition. *
+*                generator = générateur à associer à toutes les lignes.       *
 *                                                                             *
-*  Description : Procède à l'initialisation d'un tampon de gestion de lignes. *
+*  Description : Etend un tampon avec un générateur de lignes unique.         *
 *                                                                             *
 *  Retour      : -                                                            *
 *                                                                             *
@@ -548,27 +829,54 @@ static void g_buffer_cache_class_init(GBufferCacheClass *class)
 *                                                                             *
 ******************************************************************************/
 
-static void g_buffer_cache_init(GBufferCache *cache)
+void g_buffer_cache_extend_with(GBufferCache *cache, size_t count, GTokenGenerator *generator)
 {
-    cache->content = NULL;
+    size_t index;                           /* Point d'insertion           */
+    size_t repeat;                          /* Compteur de répétition      */
+    size_t i;                               /* Boucle de parcours          */
+    size_t added;                           /* Nombre d'ajouts effectués   */
 
-    cache->lines = NULL;
-    cache->count = 0;
-    cache->used = 0;
-    g_rw_lock_init(&cache->access);
+    assert(!g_rw_lock_writer_trylock(&cache->access));
 
-#ifdef INCLUDE_GTK_SUPPORT
-    cache->tracker = NULL;
-#endif
+    assert(count >= cache->used);
+
+    if (count > cache->count)
+    {
+        cache->lines = realloc(cache->lines, count * sizeof(cache_info_t));
+        cache->count = count;
+    }
+
+    index = cache->used;
+
+    if (index == 0)
+        repeat = 0;
+    else
+        repeat = compute_cache_info_repetition(&cache->lines[index - 1], generator);
+
+    for (i = index; i < count; i++)
+        init_cache_info(&cache->lines[i], generator, repeat++, BLF_NONE);
+
+    added = count - cache->used;
+
+    cache->used = count;
+
+    if (added > 0)
+    {
+        //g_width_tracker_update_added(cache->tracker, index, added);
+
+        g_signal_emit_by_name(cache, "size-changed", true, index, added);
+
+    }
 
 }
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : cache = instance d'objet GLib à traiter.                     *
+*  Paramètres  : cache = instance GLib à modifier.                            *
+*                max   = nombre maximal de lignes à conserver.                *
 *                                                                             *
-*  Description : Supprime toutes les références externes.                     *
+*  Description : Réduit le tampon à une quantité de lignes précise.           *
 *                                                                             *
 *  Retour      : -                                                            *
 *                                                                             *
@@ -576,43 +884,47 @@ static void g_buffer_cache_init(GBufferCache *cache)
 *                                                                             *
 ******************************************************************************/
 
-static void g_buffer_cache_dispose(GBufferCache *cache)
+void g_buffer_cache_truncate(GBufferCache *cache, size_t max)
 {
-    size_t i;                               /* Boucle de parcours #1       */
-    cache_info *info;                       /* Accès direct à une ligne    */
-    size_t j;                               /* Boucle de parcours #2       */
+    size_t i;                               /* Boucle de parcours          */
+    size_t removed;                         /* Nombre de retraits effectués*/
 
-    g_clear_object(&cache->content);
+    assert(!g_rw_lock_writer_trylock(&cache->access));
 
-    for (i = 0; i < cache->used; i++)
+    for (i = max; i < cache->used; i++)
+        release_cache_info(&cache->lines[i]);
+
+    if (max < cache->used)
     {
-        info = &cache->lines[i];
+        removed = cache->used - max;
 
-        if (info->count == 1)
-            g_clear_object(&info->generator.instance);
+        cache->used = max;
 
-        else
-            for (j = 0; j < info->count; j++)
-                g_clear_object(&info->generators[j].instance);
+        //g_width_tracker_update_deleted(cache->tracker, max, max + removed - 1);
+
+        g_signal_emit_by_name(cache, "size-changed", false, max, removed);
+
+    }
+
+}
 
-        g_clear_object(&info->line);
 
-    }
 
-#ifdef INCLUDE_GTK_SUPPORT
-    g_clear_object(&cache->tracker);
-#endif
 
-    G_OBJECT_CLASS(g_buffer_cache_parent_class)->dispose(G_OBJECT(cache));
 
-}
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : cache = instance d'objet GLib à traiter.                     *
+*  Paramètres  : cache  = visualisation à représenter.                        *
+*                cr     = contexte graphique dédié à la procédure.            *
+*                column = (première) colonne à traiter.                       *
+*                top    = ordonnée attribuée à la première ligne.             *
+*                first  = première ligne à dessiner.                          *
+*                last   = dernière ligne à dessiner.                          *
+*                style  = style de rendu pour les bribes de texte.            *
 *                                                                             *
-*  Description : Procède à la libération totale de la mémoire.                *
+*  Description : Imprime une partie choisie du tampon contenant des lignes.   *
 *                                                                             *
 *  Retour      : -                                                            *
 *                                                                             *
@@ -620,65 +932,47 @@ static void g_buffer_cache_dispose(GBufferCache *cache)
 *                                                                             *
 ******************************************************************************/
 
-static void g_buffer_cache_finalize(GBufferCache *cache)
+void g_buffer_cache_draw(GBufferCache *cache, cairo_t *cr, size_t column, int top, size_t first, size_t last, const GTokenStyle *style)
 {
+    int y;                                  /* Point de départ en ordonnée */
+    int lheight;                            /* Hauteur d'une ligne         */
     size_t i;                               /* Boucle de parcours          */
-    cache_info *info;                       /* Accès direct à une ligne    */
+    GBufferLine *line;                      /* Ligne à venir dessiner      */
 
-    for (i = 0; i < cache->used; i++)
+    if (cache->used > 0)
     {
-        info = &cache->lines[i];
+        y = top;
 
-        if (info->count > 1)
-            free(info->generators);
+        lheight = g_token_style_get_line_height(style);
 
-    }
+        g_buffer_cache_rlock(cache);
 
-    if (cache->lines != NULL)
-        free(cache->lines);
+        for (i = first; i <= last; i++)
+        {
+            line = get_cache_info_line(&cache->lines[i], i, cache->opt_count + cache->reg_count, NULL);
 
-    g_rw_lock_clear(&cache->access);
+            g_buffer_line_draw(line, cr, column, y, style);
 
-    G_OBJECT_CLASS(g_buffer_cache_parent_class)->finalize(G_OBJECT(cache));
+            unref_object(line);
 
-}
+            y += lheight;
 
+        }
 
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : content   = éventuel contenu binaire brut à référencer.      *
-*                col_count = quantité maximale de colonnes à considérer.      *
-*                opt_count = quantité de colonnes optionnelles.               *
-*                                                                             *
-*  Description : Crée un nouveau composant de tampon pour code désassemblé.   *
-*                                                                             *
-*  Retour      : Composant GLib créé.                                         *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
+        g_buffer_cache_runlock(cache);
 
-GBufferCache *g_buffer_cache_new(GBinContent *content, size_t col_count, size_t opt_count)
-{
-    GBufferCache *result;                   /* Composant à retourner       */
+    }
+
+}
 
-    result = g_object_new(G_TYPE_BUFFER_CACHE, NULL);
 
-    if (content != NULL)
-    {
-        result->content = content;
-        g_object_ref(G_OBJECT(content));
-    }
 
-#ifdef INCLUDE_GTK_SUPPORT
-    result->tracker = g_width_tracker_new(result, col_count, opt_count);
-#endif
 
-    return result;
 
-}
 
 
+
+#if 0
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : cache = tampon de lignes à consulter.                        *
@@ -805,107 +1099,10 @@ GWidthTracker *g_buffer_cache_get_width_tracker(const GBufferCache *cache)
 #endif
 
 
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : cache = cache de lignes à mettre à jour.                     *
-*                write = précise le type d'accès prévu (lecture/écriture).    *
-*                lock  = indique le sens du verrouillage à mener.             *
-*                                                                             *
-*  Description : Met à disposition un encadrement des accès aux lignes.       *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-void g_buffer_cache_lock_unlock(GBufferCache *cache, bool write, bool lock)
-{
-    if (write)
-    {
-        if (lock) g_rw_lock_writer_lock(&cache->access);
-        else g_rw_lock_writer_unlock(&cache->access);
-    }
-    else
-    {
-        if (lock) g_rw_lock_reader_lock(&cache->access);
-        else g_rw_lock_reader_unlock(&cache->access);
-    }
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : cache = instance GLib à consulter.                           *
-*                                                                             *
-*  Description : Compte le nombre de lignes rassemblées dans un tampon.       *
-*                                                                             *
-*  Retour      : Nombre de lignes constituant le tampon.                      *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-size_t g_buffer_cache_count_lines(GBufferCache *cache)
-{
-    size_t result;                          /* Quantité à retourner        */
-
-    assert(!g_rw_lock_writer_trylock(&cache->access));
-
-    result = cache->used;
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : cache     = instance GLib à consulter.                       *
-*                index     = indice de la ligne où se trouve le générateur.   *
-*                generator = générateur associé à au moins une ligne.         *
-*                                                                             *
-*  Description : Calcule l'indice d'apparition d'un générateur dans le tampon.*
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static size_t g_buffer_cache_compute_repetition(GBufferCache *cache, size_t index, GLineGenerator *generator)
-{
-    size_t result;                          /* Compteur à retourner        */
-    cache_info *info;                       /* Accès direct à une ligne    */
-    size_t i;                               /* Boucle de parcours          */
-
-    result = 0;
-
-    if (index > 0)
-    {
-        info = &cache->lines[index - 1];
-
-        if (info->count == 1)
-        {
-            if (info->generator.instance == generator)
-                result = info->generator.repeat + 1;
-
-        }
 
-        else
-            for (i = 0; i < info->count; i++)
-                if (info->generators[i].instance == generator)
-                {
-                    result = info->generators[i].repeat + 1;
-                    break;
-                }
 
-    }
 
-    return result;
 
-}
 
 
 /******************************************************************************
@@ -1063,7 +1260,7 @@ void g_buffer_cache_insert_at(GBufferCache *cache, size_t index, GLineGenerator
 
 void g_buffer_cache_delete_at(GBufferCache *cache, size_t index)
 {
-    cache_info *info;                       /* Accès direct à une ligne    */
+    cache_info_t *info;                       /* Accès direct à une ligne    */
 
     assert(!g_rw_lock_writer_trylock(&cache->access));
 
@@ -1107,7 +1304,7 @@ void g_buffer_cache_delete_at(GBufferCache *cache, size_t index)
 GLineGenerator *g_buffer_cache_delete_type_at(GBufferCache *cache, size_t index, GType type, bool before, bool after)
 {
     GLineGenerator *result;                 /* Prédécesseur à retourner    */
-    cache_info *info;                       /* Accès direct à une ligne    */
+    cache_info_t *info;                       /* Accès direct à une ligne    */
     generator_link *link;                   /* Accès simplifié             */
     size_t i;                               /* Boucle de parcours          */
     size_t count;                           /* Emplacements occupés        */
@@ -1236,7 +1433,7 @@ void g_buffer_cache_append(GBufferCache *cache, GLineGenerator *generator, Buffe
     size_t count;                           /* Nombre de lignes générées   */
     size_t index;                           /* Point d'insertion           */
     size_t i;                               /* Boucle de parcours          */
-    cache_info *info;                       /* Accès direct à une ligne    */
+    cache_info_t *info;                       /* Accès direct à une ligne    */
     size_t repeat;                          /* Compteur de répétition      */
 
     assert(!g_rw_lock_writer_trylock(&cache->access));
@@ -1255,146 +1452,37 @@ void g_buffer_cache_append(GBufferCache *cache, GLineGenerator *generator, Buffe
 
     index = cache->used;
 
-    for (i = 0; i < count; i++)
-    {
-        info = &cache->lines[index + i];
-
-        repeat = g_buffer_cache_compute_repetition(cache, index + i, generator);
-
-        init_cache_info(info, generator, repeat, flags);
-
-    }
-
-    cache->used += count;
-
-#ifdef INCLUDE_GTK_SUPPORT
-    g_width_tracker_update_added(cache->tracker, index, count);
-#endif
-
-    g_signal_emit_by_name(cache, "size-changed", true, index, count);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : cache     = instance GLib à modifier.                        *
-*                count     = quantité totale de lignes à avoir à disposition. *
-*                generator = générateur à associer à toutes les lignes.       *
-*                                                                             *
-*  Description : Etend un tampon avec un générateur de lignes unique.         *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-void g_buffer_cache_extend_with(GBufferCache *cache, size_t count, GLineGenerator *generator)
-{
-    size_t index;                           /* Point d'insertion           */
-    size_t i;                               /* Boucle de parcours          */
-    cache_info *info;                       /* Accès direct à une ligne    */
-    size_t repeat;                          /* Compteur de répétition      */
-    size_t added;                           /* Nombre d'ajouts effectués   */
-
-    assert(!g_rw_lock_writer_trylock(&cache->access));
 
-    assert(count >= cache->used);
+    if (index == 0)
+        repeat = 0;
 
-    if (count > cache->count)
+    else
     {
-        cache->lines = realloc(cache->lines, count * sizeof(cache_info));
-        cache->count = count;
+        info = &cache->lines[index - 1];
+        repeat = compute_cache_info_repetition(info, generator);
     }
 
-    index = cache->used;
-
-    for (i = index; i < count; i++)
+    for (i = 0; i < count; i++)
     {
-        info = &cache->lines[i];
-
-        repeat = g_buffer_cache_compute_repetition(cache, i, generator);
-
-        init_cache_info(info, generator, repeat, BLF_NONE);
-
+        info = &cache->lines[index + i];
+        init_cache_info(info, generator, repeat++, flags);
     }
 
-    added = count - cache->used;
+    cache->used += count;
 
-    cache->used = count;
+    /*
 
-    if (added > 0)
-    {
 #ifdef INCLUDE_GTK_SUPPORT
-        g_width_tracker_update_added(cache->tracker, index, added);
+    g_width_tracker_update_added(cache->tracker, index, count);
 #endif
 
-        g_signal_emit_by_name(cache, "size-changed", true, index, added);
+    g_signal_emit_by_name(cache, "size-changed", true, index, count);
 
-    }
+    */
 
 }
 
 
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : cache = instance GLib à modifier.                            *
-*                max   = nombre maximal de lignes à conserver.                *
-*                                                                             *
-*  Description : Réduit le tampon à une quantité de lignes précise.           *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-void g_buffer_cache_truncate(GBufferCache *cache, size_t max)
-{
-    size_t i;                               /* Boucle de parcours #1       */
-    cache_info *info;                       /* Accès direct à une ligne    */
-    size_t j;                               /* Boucle de parcours #2       */
-    size_t removed;                         /* Nombre de retraits effectués*/
-
-    assert(!g_rw_lock_writer_trylock(&cache->access));
-
-    for (i = max; i < cache->used; i++)
-    {
-        info = &cache->lines[i];
-
-        if (info->count == 1)
-            g_object_unref(G_OBJECT(info->generator.instance));
-
-        else
-        {
-            for (j = 0; j < info->count; j++)
-                g_object_unref(G_OBJECT(info->generators[j].instance));
-
-            free(info->generators);
-
-        }
-
-        reset_cache_info_line(info);
-
-    }
-
-    if (max < cache->used)
-    {
-        removed = cache->used - max;
-
-        cache->used = max;
-
-#ifdef INCLUDE_GTK_SUPPORT
-        g_width_tracker_update_deleted(cache->tracker, max, max + removed - 1);
-#endif
-
-        g_signal_emit_by_name(cache, "size-changed", false, max, removed);
-
-    }
-
-}
-
 
 #ifdef INCLUDE_GTK_SUPPORT
 
@@ -1444,7 +1532,7 @@ void g_buffer_cache_get_line_cursor(GBufferCache *cache, size_t index, gint x, G
 
 void g_buffer_cache_add_line_flag(GBufferCache *cache, size_t index, BufferLineFlags flag)
 {
-    cache_info *info;                       /* Accès direct à une ligne    */
+    cache_info_t *info;                       /* Accès direct à une ligne    */
 
     assert(!g_rw_lock_writer_trylock(&cache->access));
 
@@ -1482,7 +1570,7 @@ void g_buffer_cache_add_line_flag(GBufferCache *cache, size_t index, BufferLineF
 BufferLineFlags g_buffer_cache_get_line_flags(GBufferCache *cache, size_t index)
 {
     BufferLineFlags result;                 /* Somme à renvoyer            */
-    cache_info *info;                       /* Accès direct à une ligne    */
+    cache_info_t *info;                       /* Accès direct à une ligne    */
     const generator_link *generator;        /* Générateur retenu           */
     size_t i;                               /* Boucle de parcours          */
 
@@ -1528,7 +1616,7 @@ BufferLineFlags g_buffer_cache_get_line_flags(GBufferCache *cache, size_t index)
 
 void g_buffer_cache_remove_line_flag(GBufferCache *cache, size_t index, BufferLineFlags flag)
 {
-    cache_info *info;                       /* Accès direct à une ligne    */
+    cache_info_t *info;                       /* Accès direct à une ligne    */
 
     assert(!g_rw_lock_writer_trylock(&cache->access));
 
@@ -1621,7 +1709,7 @@ size_t g_buffer_cache_look_for_flag(GBufferCache *cache, size_t start, BufferLin
 
 void g_buffer_cache_refresh_line(GBufferCache *cache, size_t index)
 {
-    cache_info *info;                       /* Accès direct à une ligne    */
+    cache_info_t *info;                       /* Accès direct à une ligne    */
 
     assert(!g_rw_lock_writer_trylock(&cache->access));
 
@@ -1689,6 +1777,8 @@ void g_buffer_cache_collect_widths(GBufferCache *cache, size_t index, size_t col
 {
     GBufferLine *line;                      /* Ligne éphémère à mesurer    */
 
+    // Need lock
+
     line = get_cache_info_line(&cache->lines[index], cache->tracker, index, cache->content);
 
     g_buffer_line_collect_widths(line, col_count, opt_count, widths, merged);
@@ -1723,7 +1813,7 @@ void g_buffer_cache_draw(const GBufferCache *cache, cairo_t *cr, size_t first, s
     gint y;                                 /* Point de départ en ordonnée */
     bool wait_selection;                    /* Sélection déjà passée ?     */
     size_t i;                               /* Boucle de parcours          */
-    cache_info *info;                       /* Accès direct à une ligne    */
+    cache_info_t *info;                       /* Accès direct à une ligne    */
     GBufferLine *line;                      /* Ligne à venir dessiner      */
 
     class = G_BUFFER_CACHE_GET_CLASS(cache);
@@ -1749,6 +1839,8 @@ void g_buffer_cache_draw(const GBufferCache *cache, cairo_t *cr, size_t first, s
 
             info = &cache->lines[i];
 
+            // Need lock
+
             line = get_cache_info_line(info, cache->tracker, i, cache->content);
 
             g_buffer_line_draw(line, i, cr, class->text_pos, y, cache->tracker, options, list);
@@ -1784,11 +1876,11 @@ void g_buffer_cache_draw(const GBufferCache *cache, cairo_t *cr, size_t first, s
 size_t _g_buffer_cache_find_index_by_cursor(GBufferCache *cache, const GLineCursor *cursor, bool first, size_t start, size_t end)
 {
     size_t result;                          /* Indice à retourner          */
-    cache_info *found;                      /* Eventuel élément trouvé     */
+    cache_info_t *found;                      /* Eventuel élément trouvé     */
 
     assert(!g_rw_lock_writer_trylock(&cache->access));
 
-    int find_containing_generator(const GLineCursor *c, const cache_info *i)
+    int find_containing_generator(const GLineCursor *c, const cache_info_t *i)
     {
         const generator_link *generator;    /* Générateur retenu           */
 
@@ -1802,7 +1894,7 @@ size_t _g_buffer_cache_find_index_by_cursor(GBufferCache *cache, const GLineCurs
 
     }
 
-    found = (cache_info *)bsearch(cursor, &cache->lines[start], end - start + 1,
+    found = (cache_info_t *)bsearch(cursor, &cache->lines[start], end - start + 1,
                                   sizeof(cache_info), (__compar_fn_t)find_containing_generator);
 
     if (found == NULL)
@@ -1898,7 +1990,7 @@ bool g_buffer_cache_get_cursor_coordinates(GBufferCache *cache, const GLineCurso
     bool result;                            /* Bilan à retourner           */
     size_t index;                           /* Indice de correspondance    */
     gint lheight;                           /* Hauteur d'une ligne         */
-    const cache_info *info;                 /* Infos sur une ligne donnée  */
+    const cache_info_t *info;                 /* Infos sur une ligne donnée  */
     const generator_link *generator;        /* Générateur retenu           */
 
     assert(!g_rw_lock_writer_trylock(&cache->access));
@@ -1944,3 +2036,4 @@ bool g_buffer_cache_get_cursor_coordinates(GBufferCache *cache, const GLineCurso
 
 
 #endif
+#endif
diff --git a/src/glibext/buffercache.h b/src/glibext/buffercache.h
index 68941c5..87aae4e 100644
--- a/src/glibext/buffercache.h
+++ b/src/glibext/buffercache.h
@@ -25,6 +25,57 @@
 #define _GLIBEXT_BUFFERCACHE_H
 
 
+#include <gtk/gtk.h>
+
+
+#include "helpers.h"
+#include "generator.h"
+
+
+
+#define G_TYPE_BUFFER_CACHE (g_buffer_cache_get_type())
+
+DECLARE_GTYPE(GBufferCache, g_buffer_cache, G, BUFFER_CACHE);
+
+
+/* Crée un nouveau tampon pour lignes quelconques. */
+GBufferCache *g_buffer_cache_new(size_t, size_t);
+
+/* Fournit le nombre de colonnes supportées par un tampon. */
+void g_buffer_cache_count_columns(const GBufferCache *, size_t *, size_t *);
+
+/*  Met à disposition un encadrement des accès aux lignes. */
+void g_buffer_cache_lock_unlock(GBufferCache *, bool, bool);
+
+#define g_buffer_cache_wlock(cache) g_buffer_cache_lock_unlock(cache, true, true);
+#define g_buffer_cache_wunlock(cache) g_buffer_cache_lock_unlock(cache, true, false);
+
+#define g_buffer_cache_rlock(cache) g_buffer_cache_lock_unlock(cache, false, true);
+#define g_buffer_cache_runlock(cache) g_buffer_cache_lock_unlock(cache, false, false);
+
+/* Compte le nombre de lignes rassemblées dans un tampon. */
+size_t g_buffer_cache_count_lines(GBufferCache *);
+
+/* Etend un tampon avec un générateur de lignes unique. */
+void g_buffer_cache_extend_with(GBufferCache *, size_t, GTokenGenerator *);
+
+/* Réduit le tampon à une quantité de lignes précise. */
+void g_buffer_cache_truncate(GBufferCache *, size_t);
+
+
+
+
+/* Imprime une partie choisie du tampon contenant des lignes. */
+void g_buffer_cache_draw(GBufferCache *, cairo_t *, size_t, int, size_t, size_t, const GTokenStyle *);
+
+
+
+
+
+
+
+#if 0
+
 #include <glib-object.h>
 #include <stdbool.h>
 #ifdef INCLUDE_GTK_SUPPORT
@@ -84,18 +135,18 @@ GWidthTracker *g_buffer_cache_get_width_tracker(const GBufferCache *);
 #endif
 
 /*  Met à disposition un encadrement des accès aux lignes. */
-void g_buffer_cache_lock_unlock(GBufferCache *, bool, bool);
+//void g_buffer_cache_lock_unlock(GBufferCache *, bool, bool);
 
 
-#define g_buffer_cache_wlock(cache) g_buffer_cache_lock_unlock(cache, true, true);
-#define g_buffer_cache_wunlock(cache) g_buffer_cache_lock_unlock(cache, true, false);
+//#define g_buffer_cache_wlock(cache) g_buffer_cache_lock_unlock(cache, true, true);
+//#define g_buffer_cache_wunlock(cache) g_buffer_cache_lock_unlock(cache, true, false);
 
-#define g_buffer_cache_rlock(cache) g_buffer_cache_lock_unlock(cache, false, true);
-#define g_buffer_cache_runlock(cache) g_buffer_cache_lock_unlock(cache, false, false);
+//#define g_buffer_cache_rlock(cache) g_buffer_cache_lock_unlock(cache, false, true);
+//#define g_buffer_cache_runlock(cache) g_buffer_cache_lock_unlock(cache, false, false);
 
 
 /* Compte le nombre de lignes rassemblées dans un tampon. */
-size_t g_buffer_cache_count_lines(GBufferCache *);
+//size_t g_buffer_cache_count_lines(GBufferCache *);
 
 /* Insère un générateur dans des lignes à une position donnée. */
 void g_buffer_cache_insert_at(GBufferCache *, size_t, GLineGenerator *, BufferLineFlags, bool, bool);
@@ -110,10 +161,10 @@ GLineGenerator *g_buffer_cache_delete_type_at(GBufferCache *, size_t, GType, boo
 void g_buffer_cache_append(GBufferCache *, GLineGenerator *, BufferLineFlags);
 
 /* Etend un tampon avec un générateur de lignes unique. */
-void g_buffer_cache_extend_with(GBufferCache *, size_t, GLineGenerator *);
+//void g_buffer_cache_extend_with(GBufferCache *, size_t, GLineGenerator *);
 
 /* Réduit le tampon à une quantité de lignes précise. */
-void g_buffer_cache_truncate(GBufferCache *, size_t);
+//void g_buffer_cache_truncate(GBufferCache *, size_t);
 
 #ifdef INCLUDE_GTK_SUPPORT
 
@@ -146,7 +197,7 @@ GBufferLine *g_buffer_cache_find_line_by_index(GBufferCache *, size_t);
 void g_buffer_cache_collect_widths(GBufferCache *, size_t, size_t, size_t, gint *, gint *);
 
 /* Imprime une partie choisie du tampon contenant des lignes. */
-void g_buffer_cache_draw(const GBufferCache *, cairo_t *, size_t, size_t, const cairo_rectangle_int_t *, const GDisplayOptions *, const gint *, const segcnt_list *);
+//void g_buffer_cache_draw(const GBufferCache *, cairo_t *, size_t, size_t, const cairo_rectangle_int_t *, const GDisplayOptions *, const gint *, const segcnt_list *);
 
 #endif
 
@@ -164,5 +215,8 @@ bool g_buffer_cache_get_cursor_coordinates(GBufferCache *, const GLineCursor *,
 #endif
 
 
+#endif
+
+
 
 #endif  /* _GLIBEXT_BUFFERCACHE_H */
diff --git a/src/glibext/bufferline-int.h b/src/glibext/bufferline-int.h
new file mode 100644
index 0000000..8bee3c2
--- /dev/null
+++ b/src/glibext/bufferline-int.h
@@ -0,0 +1,94 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * bufferline-int.h - prototypes pour la définition interne d'une représentation de fragments de texte en ligne
+ *
+ * Copyright (C) 2024 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Chrysalide is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GLIBEXT_BUFFERLINE_INT_H
+#define _GLIBEXT_BUFFERLINE_INT_H
+
+
+#include "bufferline.h"
+#include "linecolumn.h"
+
+
+
+#if 0
+/* Mémorisation des origines de texte */
+typedef struct _content_origin
+{
+    col_coord_t coord;                      /* Localisation d'attachement  */
+
+    GObject *creator;                       /* Origine de la création      */
+
+} content_origin;
+#endif
+
+
+/* Représentation de fragments de texte en ligne (instance) */
+struct _GBufferLine
+{
+    GObject parent;                         /* A laisser en premier        */
+
+    line_column_t *columns;                 /* Répartition du texte        */
+    size_t col_count;                       /* Nombre de colonnes présentes*/
+    size_t merge_start;                     /* Début de la zone globale    */
+
+    BufferLineFlags flags;                  /* Drapeaux particuliers       */
+
+#if 0
+
+    content_origin *origins;                /* Mémorisation des origines   */
+    size_t ocount;                          /* Nombre de ces mémorisations */
+
+#endif
+
+};
+
+/* Représentation de fragments de texte en ligne (classe) */
+struct _GBufferLineClass
+{
+    GObjectClass parent;                    /* A laisser en premier        */
+
+#if 0
+
+#ifdef INCLUDE_GTK_SUPPORT
+    cairo_surface_t *entrypoint_img;        /* Image pour les entrées      */
+    cairo_surface_t *bookmark_img;          /* Image pour les signets      */
+#endif
+
+    /* Signaux */
+
+    void (* content_changed) (GBufferLine *, line_segment *);
+
+    void (* flip_flag) (GBufferLine *, BufferLineFlags, BufferLineFlags);
+
+#endif
+
+};
+
+
+
+/* Met en place une nouvelle représentation de bribes de texte. */
+bool g_buffer_line_create(GBufferLine *, size_t);
+
+
+
+#endif  /* _GLIBEXT_BUFFERLINE_INT_H */
diff --git a/src/glibext/bufferline.c b/src/glibext/bufferline.c
index 2bdfebc..4862e9f 100644
--- a/src/glibext/bufferline.c
+++ b/src/glibext/bufferline.c
@@ -24,63 +24,27 @@
 #include "bufferline.h"
 
 
+#include "bufferline-int.h"
+
+
+
+#if 0
+
 #include <assert.h>
 #include <malloc.h>
 #include <string.h>
 
 
 #include "chrysamarshal.h"
-#include "linecolumn.h"
+//#include "linecolumn.h"
 #include "../common/extstr.h"
 #include "../core/paths.h"
 
-
-
-/* ---------------------------- GESTION DE LINE COMPLETE ---------------------------- */
-
-
-/* Mémorisation des origines de texte */
-typedef struct _content_origin
-{
-    col_coord_t coord;                      /* Localisation d'attachement  */
-
-    GObject *creator;                       /* Origine de la création      */
-
-} content_origin;
-
-/* Représentation de fragments de texte en ligne (instance) */
-struct _GBufferLine
-{
-    GObject parent;                         /* A laisser en premier        */
-
-    line_column *columns;                   /* Répartition du texte        */
-    size_t col_count;                       /* Nombre de colonnes présentes*/
-    size_t merge_start;                     /* Début de la zone globale    */
-
-    BufferLineFlags flags;                  /* Drapeaux particuliers       */
-
-    content_origin *origins;                /* Mémorisation des origines   */
-    size_t ocount;                          /* Nombre de ces mémorisations */
-
-};
-
-/* Représentation de fragments de texte en ligne (classe) */
-struct _GBufferLineClass
-{
-    GObjectClass parent;                    /* A laisser en premier        */
-
-#ifdef INCLUDE_GTK_SUPPORT
-    cairo_surface_t *entrypoint_img;        /* Image pour les entrées      */
-    cairo_surface_t *bookmark_img;          /* Image pour les signets      */
 #endif
 
-    /* Signaux */
 
-    void (* content_changed) (GBufferLine *, line_segment *);
 
-    void (* flip_flag) (GBufferLine *, BufferLineFlags, BufferLineFlags);
-
-};
+/* ---------------------------- GESTION DE LINE COMPLETE ---------------------------- */
 
 
 /* Procède à l'initialisation d'une classe de représentation. */
@@ -106,7 +70,6 @@ static void g_buffer_line_finalize(GBufferLine *);
 G_DEFINE_TYPE(GBufferLine, g_buffer_line, G_TYPE_OBJECT);
 
 
-
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : class = classe de composant GTK à initialiser.               *
@@ -131,6 +94,9 @@ static void g_buffer_line_class_init(GBufferLineClass *class)
     object->dispose = (GObjectFinalizeFunc/* ! */)g_buffer_line_dispose;
     object->finalize = (GObjectFinalizeFunc)g_buffer_line_finalize;
 
+
+#if 0
+
 #ifdef INCLUDE_GTK_SUPPORT
 
     filename = find_pixmap_file("entrypoint.png");
@@ -165,12 +131,14 @@ static void g_buffer_line_class_init(GBufferLineClass *class)
                  g_cclosure_user_marshal_VOID__ENUM_ENUM,
                  G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT);
 
+#endif
+
 }
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : line = composant GTK à initialiser.                          *
+*  Paramètres  : line = composant GLib à initialiser.                         *
 *                                                                             *
 *  Description : Procède à l'initialisation d'une représentation de fragments.*
 *                                                                             *
@@ -203,10 +171,12 @@ static void g_buffer_line_init(GBufferLine *line)
 
 static void g_buffer_line_dispose(GBufferLine *line)
 {
+#if 0
     size_t i;                               /* Boucle de parcours          */
 
     for (i = 0; i < line->ocount; i++)
         g_object_unref(G_OBJECT(line->origins[i].creator));
+#endif
 
     G_OBJECT_CLASS(g_buffer_line_parent_class)->dispose(G_OBJECT(line));
 
@@ -235,8 +205,10 @@ static void g_buffer_line_finalize(GBufferLine *line)
     if (line->columns != NULL)
         free(line->columns);
 
+#if 0
     if (line->origins != NULL)
         free(line->origins);
+#endif
 
     G_OBJECT_CLASS(g_buffer_line_parent_class)->finalize(G_OBJECT(line));
 
@@ -258,22 +230,195 @@ static void g_buffer_line_finalize(GBufferLine *line)
 GBufferLine *g_buffer_line_new(size_t col_count)
 {
     GBufferLine *result;                    /* Composant à retourner       */
-    size_t i;                               /* Boucle de parcours          */
 
     result = g_object_new(G_TYPE_BUFFER_LINE, NULL);
 
-    result->columns = malloc(col_count * sizeof(line_column));
+    if (!g_buffer_line_create(result, col_count))
+        g_clear_object(&result);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : line      = ligne de représentation à initialiser.           *
+*                col_count = quantité de colonnes à considérer.               *
+*                                                                             *
+*  Description : Met en place une nouvelle représentation de bribes de texte. *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_buffer_line_create(GBufferLine *line, size_t col_count)
+{
+    bool result;                            /* Bilen à retourner           */
+    size_t i;                               /* Boucle de parcours          */
+
+    result = true;
+
+    line->columns = malloc(col_count * sizeof(line_column_t));
 
     for (i = 0; i < col_count; i++)
-        init_line_column(&result->columns[i]);
+        init_line_column(&line->columns[i]);
 
-    result->col_count = col_count;
+    line->col_count = col_count;
 
     return result;
 
 }
 
 
+
+
+
+
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : line    = ligne à venir compléter.                           *
+*                column  = colonne de la ligne visée par l'insertion.         *
+*                tag     = type de décorateur à utiliser.                     *
+*                text    = texte à insérer dans l'existant.                   *
+*                length  = taille du texte à traiter.                         *
+*                style   = gestionnaire de paramètres de rendu à consulter.   *
+*                creator = instance GLib quelconque à associer.               *
+*                                                                             *
+*  Description : Ajoute du texte à formater dans une ligne donnée.            *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_buffer_line_append_text(GBufferLine *line, size_t column, TokenRenderingTag tag, const char *text, size_t length, const GTokenStyle *style, GObject *creator)
+{
+    size_t index;                           /* Indice d'insertion          */
+    //content_origin *origin;                 /* Définition d'une origine    */
+
+    assert(column < line->col_count);
+    assert(length > 0);
+
+    index = append_text_to_line_column(&line->columns[column], tag, text, length, style);
+
+    /*
+    if (creator != NULL)
+    {
+        line->origins = realloc(line->origins, ++line->ocount * sizeof(content_origin));
+
+        origin = &line->origins[line->ocount - 1];
+
+        origin->coord.column = column;
+        origin->coord.index = index;
+
+        origin->creator = creator;
+        g_object_ref(G_OBJECT(creator));
+
+    }
+    */
+
+}
+
+
+
+
+
+
+
+
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : line   = ligne de texte à manipuler.                         *
+*                cr     = contexte graphique dédié à la procédure.            *
+*                column = (première) colonne à traiter.                       *
+*                y      = ordonnée du point d'impression.                     *
+*                style  = style de rendu pour les bribes de texte.            *
+*                                                                             *
+*  Description : Imprime la ligne de texte représentée.                       *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_buffer_line_draw(const GBufferLine *line, cairo_t *cr, size_t column, int y, const GTokenStyle *style)
+{
+#if 0
+    GBufferLineClass *class;                /* Stockage de briques de base */
+    bool has_src_surface;                   /* Note une présence définie   */
+#endif
+    size_t max_column;                      /* Borne de fin des colonnes   */
+    int x;                                  /* Point de départ d'impression*/
+    size_t i;                               /* Boucle de parcours          */
+
+    /*
+    if (line->flags != BLF_NONE)
+    {
+        class = G_BUFFER_LINE_GET_CLASS(line);
+
+        if (line->flags & BLF_ENTRYPOINT)
+        {
+            cairo_set_source_surface(cairo, class->entrypoint_img, 5, y);
+            has_src_surface = true;
+        }
+        else if (line->flags & BLF_BOOKMARK)
+        {
+            cairo_set_source_surface(cairo, class->bookmark_img, 5, y);
+            has_src_surface = true;
+        }
+        else
+            has_src_surface = false;
+
+        if (has_src_surface)
+            cairo_paint(cairo);
+
+    }
+    */
+
+
+    /* Détermination de l'éventail des colonnes à traiter */
+
+    if (column == line->merge_start)
+        max_column = line->col_count;
+
+    else if (column > line->merge_start)
+        max_column = 0;
+
+    else
+        max_column = column + 1;
+
+    /* Dessin du contenu de ces colonnes */
+
+    x = 0;
+
+    for (i = column; i < max_column; i++)
+        draw_line_column(&line->columns[i], cr, &x, y, style);
+
+}
+
+
+
+
+
+
+
+
+
+
+#if 0
+
+
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : line = ligne à venir compléter.                              *
@@ -1492,3 +1637,6 @@ void g_buffer_line_draw(GBufferLine *line, size_t index, cairo_t *cairo, gint x_
 
 
 #endif
+
+
+#endif
diff --git a/src/glibext/bufferline.h b/src/glibext/bufferline.h
index f5f25d0..d6a2e2d 100644
--- a/src/glibext/bufferline.h
+++ b/src/glibext/bufferline.h
@@ -25,10 +25,21 @@
 #define _GLIBEXT_BUFFERLINE_H
 
 
-#include <glib-object.h>
 #include <stdbool.h>
 
 
+#include "helpers.h"
+#include "tokenstyle.h"
+
+
+
+
+
+#if 0
+
+#include <glib-object.h>
+
+
 #include "gdisplayoptions.h"
 #include "linesegment.h"
 #ifdef INCLUDE_GTK_SUPPORT
@@ -60,6 +71,14 @@ typedef struct _GBufferLineClass GBufferLineClass;
 /* Espace entre les colonnes */
 #define COL_MARGIN 23
 
+#endif
+
+
+
+#define G_TYPE_BUFFER_LINE (g_buffer_line_get_type())
+
+DECLARE_GTYPE(GBufferLine, g_buffer_line, G, BUFFER_LINE);
+
 
 /* Propriétés particulières supplémentaires */
 typedef enum _BufferLineFlags
@@ -76,12 +95,28 @@ typedef enum _BufferLineFlags
 } BufferLineFlags;
 
 
-/* Détermine le type de la représentation de fragments de texte en ligne. */
-GType g_buffer_line_get_type(void);
-
 /* Crée une nouvelle représentation de fragments de texte. */
 GBufferLine *g_buffer_line_new(size_t);
 
+
+
+/* Ajoute du texte à formater dans une ligne donnée. */
+void g_buffer_line_append_text(GBufferLine *, size_t, TokenRenderingTag, const char *, size_t, const GTokenStyle *, GObject *);
+
+
+
+/* Imprime la ligne de texte représentée. */
+void g_buffer_line_draw(const GBufferLine *, cairo_t *, size_t, int, const GTokenStyle *);
+
+
+
+
+
+#if 0
+
+/* Détermine le type de la représentation de fragments de texte en ligne. */
+GType g_buffer_line_get_type(void);
+
 /* Construit le tronc commun d'une ligne autour de sa position. */
 void g_buffer_line_fill_phys(GBufferLine *, size_t, MemoryDataSize, const vmpa2t *);
 
@@ -95,7 +130,7 @@ void g_buffer_line_fill_content(GBufferLine *, size_t, const GBinContent *, cons
 GObject *g_buffer_line_find_first_segment_creator(const GBufferLine *, size_t);
 
 /* Ajoute du texte à formater dans une ligne donnée. */
-void g_buffer_line_append_text(GBufferLine *, size_t, const char *, size_t, RenderingTagType, GObject *);
+//void g_buffer_line_append_text(GBufferLine *, size_t, const char *, size_t, RenderingTagType, GObject *);
 
 /* Remplace du texte dans une ligne donnée. */
 bool g_buffer_line_replace_text(GBufferLine *, const GObject *, const char *, size_t);
@@ -162,7 +197,10 @@ GObject *g_buffer_line_get_creator_at(const GBufferLine *, size_t, GWidthTracker
 bool g_buffer_line_find_near_coord(const GBufferLine *, size_t, col_coord_t *, GWidthTracker *, const GDisplayOptions *, GdkScrollDirection, gint *);
 
 /* Imprime la ligne de texte représentée. */
-void g_buffer_line_draw(GBufferLine *, size_t, cairo_t *, gint, gint, GWidthTracker *, const GDisplayOptions *, const segcnt_list *);
+//void g_buffer_line_draw(GBufferLine *, size_t, cairo_t *, gint, gint, GWidthTracker *, const GDisplayOptions *, const segcnt_list *);
+
+#endif
+
 
 #endif
 
diff --git a/src/glibext/bufferview-int.h b/src/glibext/bufferview-int.h
new file mode 100644
index 0000000..7751c1e
--- /dev/null
+++ b/src/glibext/bufferview-int.h
@@ -0,0 +1,83 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * bufferview.h - prototypes pour l'affichage d'une vue particulière d'un tampon de lignes
+ *
+ * Copyright (C) 2016-2024 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Chrysalide is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GLIBEXT_BUFFERVIEW_INT_H
+#define _GLIBEXT_BUFFERVIEW_INT_H
+
+
+#include "bufferview.h"
+
+
+/* Vue d'un tampon pour code désassemblé (instance) */
+struct _GBufferView
+{
+    GObject parent;                         /* A laisser en premier        */
+
+    GBufferCache *cache;                    /* Tampon du contenu visualisé */
+    GWidthTracker *tracker;                 /* Collecteur de largeurs      */
+    GTokenStyle *style;                     /* Style dédié aux rendus      */
+
+
+
+    bool unrestricted;                      /* Validité des informations   */
+
+
+    size_t first;                           /* Indice de la première ligne */
+    size_t last;                            /* Indice de la dernière ligne */
+
+
+#if 0
+
+    segcnt_list *highlighted;               /* Segments mis en évidence    */
+
+    //bool unrestricted;                      /* Validité des informations   */
+    GLineCursor *start;                     /* Première ligne intégrée     */
+    GLineCursor *end;                       /* Dernière ligne intégrée     */
+
+    //size_t first;                           /* Indice de la première ligne */
+    //size_t last;                            /* Indice de la dernière ligne */
+
+    GWidthTracker *tracker;                 /* Suivi des largeurs          */
+
+#endif
+
+};
+
+/* Vue d'un tampon pour code désassemblé (classe) */
+struct _GBufferViewClass
+{
+    GObjectClass parent;                    /* A laisser en premier        */
+
+    /* Signaux */
+
+    void (* need_redraw) (GBufferView *);
+
+};
+
+
+/* Met en place une nouvelle vue pour un tampon de texte. */
+bool g_buffer_view_create(GBufferView *, GBufferCache *, GTokenStyle *);
+
+
+
+#endif  /* _GLIBEXT_BUFFERVIEW_INT_H */
diff --git a/src/glibext/bufferview.c b/src/glibext/bufferview.c
index 72740b1..3747e2c 100644
--- a/src/glibext/bufferview.c
+++ b/src/glibext/bufferview.c
@@ -2,7 +2,7 @@
 /* Chrysalide - Outil d'analyse de fichiers binaires
  * bufferview.c - affichage d'une vue particulière d'un tampon de lignes
  *
- * Copyright (C) 2016-2019 Cyrille Bagard
+ * Copyright (C) 2016-2024 Cyrille Bagard
  *
  *  This file is part of Chrysalide.
  *
@@ -24,46 +24,17 @@
 #include "bufferview.h"
 
 
-#include <assert.h>
-
+#include "bufferview-int.h"
 
 
-/* Vue d'un tampon pour code désassemblé (instance) */
-struct _GBufferView
-{
-    GObject parent;                         /* A laisser en premier        */
 
-    GBufferCache *cache;                    /* Tampon du contenu visualisé */
-
-    segcnt_list *highlighted;               /* Segments mis en évidence    */
-
-    bool unrestricted;                      /* Validité des informations   */
-    GLineCursor *start;                     /* Première ligne intégrée     */
-    GLineCursor *end;                       /* Dernière ligne intégrée     */
-
-    size_t first;                           /* Indice de la première ligne */
-    size_t last;                            /* Indice de la dernière ligne */
-
-    GWidthTracker *tracker;                 /* Suivi des largeurs          */
-
-};
-
-/* Vue d'un tampon pour code désassemblé (classe) */
-struct _GBufferViewClass
-{
-    GObjectClass parent;                    /* A laisser en premier        */
-
-    /* Signaux */
-
-    void (* need_redraw) (GBufferView *);
-
-};
+/* -------------------------- DEFINITION D'UN NOUVEL OBJET -------------------------- */
 
 
 /* Procède à l'initialisation d'une classe de vue de tampon. */
 static void g_buffer_view_class_init(GBufferViewClass *);
 
-/* Procède à l'initialisation d'une vue d'un tampon pour code. */
+/* Procède à l'initialisation d'une vue d'un tampon. */
 static void g_buffer_view_init(GBufferView *);
 
 /* Supprime toutes les références externes. */
@@ -75,23 +46,15 @@ static void g_buffer_view_finalize(GBufferView *);
 /* Accompagne une variation de la quantité de lignes du tampon. */
 static void on_buffer_cache_size_changed(const GBufferCache *, bool, size_t, size_t, GBufferView *);
 
-/* Réagit à la modification d'une ligne du tampon. */
-static void on_buffer_cache_line_updated(const GBufferCache *, size_t, GBufferView *);
-
-/* Calcule la position idéale de curseur pour un point donné. */
-static bool _g_buffer_view_compute_caret_full(GBufferView *, gint, GBufferLine *, size_t, const GDisplayOptions *, cairo_rectangle_int_t *, GLineCursor **);
-
-/* Fournit la ligne présente à une ordonnée donnée. */
-static GBufferLine *g_buffer_view_find_line_at(GBufferView *, gint, size_t *);
-
-/* Déplace le curseur au sein d'une vue de tampon. */
-static bool _g_buffer_view_move_caret(GBufferView *, const GBufferLine *, size_t, cairo_rectangle_int_t *, bool, GdkScrollDirection, const GDisplayOptions *);
 
 
 
 
 
 
+/* ---------------------------------------------------------------------------------- */
+/*                            DEFINITION D'UN NOUVEL OBJET                            */
+/* ---------------------------------------------------------------------------------- */
 
 
 /* Détermine le type de la vue d'un tampon pour code désassemblé. */
@@ -100,7 +63,7 @@ G_DEFINE_TYPE(GBufferView, g_buffer_view, G_TYPE_OBJECT);
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : class = classe de composant GTK à initialiser.               *
+*  Paramètres  : class = classe de composant GLib à initialiser.              *
 *                                                                             *
 *  Description : Procède à l'initialisation d'une classe de vue de tampon.    *
 *                                                                             *
@@ -136,7 +99,7 @@ static void g_buffer_view_class_init(GBufferViewClass *class)
 *                                                                             *
 *  Paramètres  : view = composant GLib à initialiser.                         *
 *                                                                             *
-*  Description : Procède à l'initialisation d'une vue d'un tampon pour code.  *
+*  Description : Procède à l'initialisation d'une vue d'un tampon.            *
 *                                                                             *
 *  Retour      : -                                                            *
 *                                                                             *
@@ -147,22 +110,26 @@ static void g_buffer_view_class_init(GBufferViewClass *class)
 static void g_buffer_view_init(GBufferView *view)
 {
     view->cache = NULL;
-
-    view->highlighted = NULL;
+    view->tracker = NULL;
+    view->style = NULL;
 
     /**
      * Inversion du statut pour forcer l'actualisation lors de la création.
      */
     view->unrestricted = false;
 
+#if 0
+
     view->start = NULL;
     view->end = NULL;
 
+#endif
+
+
+
     view->first = 0;
     view->last = 0;
 
-    view->tracker = NULL;
-
 }
 
 
@@ -181,11 +148,13 @@ static void g_buffer_view_init(GBufferView *view)
 static void g_buffer_view_dispose(GBufferView *view)
 {
     g_clear_object(&view->cache);
+    g_clear_object(&view->tracker);
+    g_clear_object(&view->style);
 
+#if 0
     g_clear_object(&view->start);
     g_clear_object(&view->end);
-
-    g_clear_object(&view->tracker);
+#endif
 
     G_OBJECT_CLASS(g_buffer_view_parent_class)->dispose(G_OBJECT(view));
 
@@ -206,9 +175,6 @@ static void g_buffer_view_dispose(GBufferView *view)
 
 static void g_buffer_view_finalize(GBufferView *view)
 {
-    if (view->highlighted != NULL)
-        unref_segment_content_list(view->highlighted);
-
     G_OBJECT_CLASS(g_buffer_view_parent_class)->finalize(G_OBJECT(view));
 
 }
@@ -216,38 +182,25 @@ static void g_buffer_view_finalize(GBufferView *view)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : buffer      = tampon à représenter à l'écran.                *
-*                highlighted = gestionnaire de surbrillance pour segments.    *
+*  Paramètres  : cache = cache de lignes à présenter à la vue.                *
+*                style = modèles de rendus pour tous les types de bribes.     *
 *                                                                             *
-*  Description : Crée une nouvelle vue d'un tampon pour code désassemblé.     *
+*  Description : Crée une nouvelle vue d'un tampon de texte.                  *
 *                                                                             *
-*  Retour      : Composant GTK créé.                                          *
+*  Retour      : Vue de tampon mise en place ou NULL en cas d'erreur.         *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-GBufferView *g_buffer_view_new(GBufferCache *cache, segcnt_list *highlighted)
+GBufferView *g_buffer_view_new(GBufferCache *cache, GTokenStyle *style)
 {
     GBufferView *result;                    /* Composant à retourner       */
 
     result = g_object_new(G_TYPE_BUFFER_VIEW, NULL);
 
-    result->cache = cache;
-    g_object_ref_sink(G_OBJECT(cache));
-
-    g_buffer_view_restrict(result, NULL, NULL);
-
-    g_signal_connect(cache, "size-changed", G_CALLBACK(on_buffer_cache_size_changed), result);
-    g_signal_connect(cache, "line-updated", G_CALLBACK(on_buffer_cache_line_updated), result);
-
-    if (highlighted != NULL)
-    {
-        ref_segment_content_list(highlighted);
-        result->highlighted = highlighted;
-    }
-    else
-        result->highlighted = init_segment_content_list();
+    if (!g_buffer_view_create(result, cache, style))
+        g_clear_object(&result);
 
     return result;
 
@@ -256,21 +209,50 @@ GBufferView *g_buffer_view_new(GBufferCache *cache, segcnt_list *highlighted)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : cache = tampon de lignes cohérentes à manipuler.             *
-*                index = indice de la première ligne actualisée.              *
+*  Paramètres  : view  = vue de tampon à initialiser.                         *
+*                cache = cache de lignes à présenter à la vue.                *
+*                style = modèles de rendus pour tous les types de bribes.     *
 *                                                                             *
-*  Description : Réagit à la modification d'une ligne du tampon.              *
+*  Description : Met en place une nouvelle vue pour un tampon de texte.       *
 *                                                                             *
-*  Retour      : -                                                            *
+*  Retour      : Bilan de l'opération.                                        *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static void on_buffer_cache_line_updated(const GBufferCache *cache, size_t index, GBufferView *view)
+bool g_buffer_view_create(GBufferView *view, GBufferCache *cache, GTokenStyle *style)
 {
-    if (view->first <= index && index <= view->last)
-        g_signal_emit_by_name(view, "need-redraw");
+    bool result;                            /* Bilan à retourner           */
+
+    result = true;
+
+    view->cache = cache;
+    ref_object(cache);
+
+    view->tracker = g_width_tracker_new(cache);
+
+    view->style = style;
+    ref_object(style);
+
+    g_buffer_view_restrict(view, NULL, NULL);
+
+    g_signal_connect(cache, "size-changed", G_CALLBACK(on_buffer_cache_size_changed), view);
+
+
+#if 0
+    g_signal_connect(cache, "line-updated", G_CALLBACK(on_buffer_cache_line_updated), result);
+
+    if (highlighted != NULL)
+    {
+        ref_segment_content_list(highlighted);
+        result->highlighted = highlighted;
+    }
+    else
+        result->highlighted = init_segment_content_list();
+#endif
+
+    return result;
 
 }
 
@@ -411,7 +393,32 @@ GBufferCache *g_buffer_view_get_cache(const GBufferView *view)
 
     result = view->cache;
 
-    g_object_ref(G_OBJECT(result));
+    ref_object(result);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : view = visualisateur à consulter.                            *
+*                                                                             *
+*  Description : Fournit le collecteur de largeurs associé au tampon lié.     *
+*                                                                             *
+*  Retour      : Collecteur de largeurs des lignes du tampon représenté.      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GWidthTracker *g_buffer_view_get_tracker(const GBufferView *view)
+{
+    GWidthTracker *result;                  /* Instance à retourner        */
+
+    result = view->tracker;
+
+    ref_object(result);
 
     return result;
 
@@ -432,10 +439,10 @@ GBufferCache *g_buffer_view_get_cache(const GBufferView *view)
 *                                                                             *
 ******************************************************************************/
 
-void g_buffer_view_restrict(GBufferView *view, GLineCursor *start, GLineCursor *end)
+void g_buffer_view_restrict(GBufferView *view, /*GLineCursor*/void *start, /*GLineCursor*/void *end)
 {
     bool state;                             /* Nouvel état à proclamer     */
-    GWidthTracker *template;                /* Suivi déjà en place         */
+    //GWidthTracker *template;                /* Suivi déjà en place         */
 
     state = (start == NULL || end == NULL);
 
@@ -443,11 +450,11 @@ void g_buffer_view_restrict(GBufferView *view, GLineCursor *start, GLineCursor *
     {
         view->unrestricted = state;
 
-        template = g_buffer_cache_get_width_tracker(view->cache);
+        //template = g_buffer_cache_get_width_tracker(view->cache);
 
         /* Vérification pour le cas particulier du démarrage */
-        if (view->tracker != NULL)
-            g_object_unref(G_OBJECT(view->tracker));
+        //if (view->tracker != NULL)
+        //    g_object_unref(G_OBJECT(view->tracker));
 
         g_buffer_cache_rlock(view->cache);
 
@@ -456,12 +463,14 @@ void g_buffer_view_restrict(GBufferView *view, GLineCursor *start, GLineCursor *
             view->first = 0;
             view->last = g_buffer_cache_count_lines(view->cache) - 1;
 
-            view->tracker = template;
+            //view->tracker = template;
 
         }
 
         else
         {
+            /*
+
             g_object_ref_sink(G_OBJECT(start));
             g_object_ref_sink(G_OBJECT(end));
 
@@ -475,6 +484,8 @@ void g_buffer_view_restrict(GBufferView *view, GLineCursor *start, GLineCursor *
 
             g_object_unref(G_OBJECT(template));
 
+            */
+
         }
 
         g_buffer_cache_runlock(view->cache);
@@ -484,6 +495,156 @@ void g_buffer_view_restrict(GBufferView *view, GLineCursor *start, GLineCursor *
 }
 
 
+
+
+
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : view   = visualisation à consulter.                          *
+*                style  = style de rendu pour les bribes de texte.            *
+*                width  = largeur requise pour un affichage complet. [OUT]    *
+*                height = hauteur requise pour un affichage complet. [OUT]    *
+*                                                                             *
+*  Description : Détermine la taille nécessaire à une représentation complète.*
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_buffer_view_compute_size(const GBufferView *view, int *width, int *height)
+{
+    size_t last;                            /* Dernière ligne à dessiner   */
+
+    /* Largeur de l'ensemble des colonnes */
+
+    g_width_tracker_compute_width(view->tracker, width);
+
+    /* Hauteur de l'ensemble des lignes */
+
+    *height = g_token_style_get_line_height(view->style) * (view->last + 1);
+
+}
+
+
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : view     = visualisation à représenter.                      *
+*                cr       = contexte graphique dédié à la procédure.          *
+*                column   = (première) colonne à traiter.                     *
+*                virt_top = ordonnée présentée au point 0 à l'écran.          *
+*                height   = hauteur disponible pour les représentations.      *
+*                                                                             *
+*  Description : Imprime la visualisation du tampon de lignes quelconques.    *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_buffer_view_draw(const GBufferView *view, cairo_t *cr, size_t column, int virt_top, int height)
+{
+    int line_height;                        /* Hauteur d'une ligne         */
+    gint cr_y;                              /* Ordonnée pour le dessin     */
+    size_t first;                           /* Première ligne visée        */
+    size_t last;                            /* Dernière ligne visée        */
+
+    line_height = g_token_style_get_line_height(view->style);
+
+    /* Indice et point de départ */
+
+    first = view->first;
+    first += (virt_top / line_height);
+
+    cr_y = -(virt_top % line_height);
+
+    /* Indice de d'arrivée */
+
+    last = first + (height / line_height);
+    if (height % line_height > 0) last++;
+
+    last = MIN(last, view->last);
+
+    /* Phase de dessin ! */
+
+    g_buffer_cache_draw(view->cache, cr, column, cr_y, first, last, view->style);
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+#if 0
+
+#include <assert.h>
+
+
+
+
+/* Accompagne une variation de la quantité de lignes du tampon. */
+//static void on_buffer_cache_size_changed(const GBufferCache *, bool, size_t, size_t, GBufferView *);
+
+/* Réagit à la modification d'une ligne du tampon. */
+static void on_buffer_cache_line_updated(const GBufferCache *, size_t, GBufferView *);
+
+/* Calcule la position idéale de curseur pour un point donné. */
+static bool _g_buffer_view_compute_caret_full(GBufferView *, gint, GBufferLine *, size_t, const GDisplayOptions *, cairo_rectangle_int_t *, GLineCursor **);
+
+/* Fournit la ligne présente à une ordonnée donnée. */
+static GBufferLine *g_buffer_view_find_line_at(GBufferView *, gint, size_t *);
+
+/* Déplace le curseur au sein d'une vue de tampon. */
+static bool _g_buffer_view_move_caret(GBufferView *, const GBufferLine *, size_t, cairo_rectangle_int_t *, bool, GdkScrollDirection, const GDisplayOptions *);
+
+
+
+
+
+
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : cache = tampon de lignes cohérentes à manipuler.             *
+*                index = indice de la première ligne actualisée.              *
+*                                                                             *
+*  Description : Réagit à la modification d'une ligne du tampon.              *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void on_buffer_cache_line_updated(const GBufferCache *cache, size_t index, GBufferView *view)
+{
+    if (view->first <= index && index <= view->last)
+        g_signal_emit_by_name(view, "need-redraw");
+
+}
+
+
+
+
+
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : view  = visualisateur à consulter.                           *
@@ -1313,3 +1474,44 @@ bool g_buffer_view_get_cursor_coordinates(GBufferView *view, const GLineCursor *
     return result;
 
 }
+
+
+
+#endif
+
+
+
+
+
+#if 0
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : view   = visualisation à consulter.                          *
+*                cursor = emplacement à présenter à l'écran.                  *
+*                code   = s'arrête si possible à une ligne avec code.         *
+*                x      = position horizontale au sein du composant. [OUT]    *
+*                y      = position verticale au sein du composant. [OUT]      *
+*                                                                             *
+*  Description : Indique la position d'affichage d'une adresse donnée.        *
+*                                                                             *
+*  Retour      : true si l'adresse fait partie du composant, false sinon.     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_buffer_view_allocate_widths(GBufferView *view, int width, int height, int fill, int *out)
+{
+
+
+
+
+
+
+}
+
+
+
+#endif
diff --git a/src/glibext/bufferview.h b/src/glibext/bufferview.h
index 43e6293..d5af6d1 100644
--- a/src/glibext/bufferview.h
+++ b/src/glibext/bufferview.h
@@ -2,7 +2,7 @@
 /* Chrysalide - Outil d'analyse de fichiers binaires
  * bufferview.h - prototypes pour l'affichage d'une vue particulière d'un tampon de lignes
  *
- * Copyright (C) 2016-2019 Cyrille Bagard
+ * Copyright (C) 2016-2024 Cyrille Bagard
  *
  *  This file is part of Chrysalide.
  *
@@ -25,6 +25,48 @@
 #define _GLIBEXT_BUFFERVIEW_H
 
 
+#include "buffercache.h"
+#include "helpers.h"
+#include "tokenstyle.h"
+#include "widthtracker.h"
+
+
+
+#define G_TYPE_BUFFER_VIEW (g_buffer_view_get_type())
+
+DECLARE_GTYPE(GBufferView, g_buffer_view, G, BUFFER_VIEW);
+
+
+/* Crée une nouvelle vue d'un tampon de texte. */
+GBufferView *g_buffer_view_new(GBufferCache *, GTokenStyle *);
+
+/* Fournit le tampon de code lié à un visualisateur donné. */
+GBufferCache *g_buffer_view_get_cache(const GBufferView *);
+
+/* Fournit le collecteur de largeurs associé au tampon lié. */
+GWidthTracker *g_buffer_view_get_tracker(const GBufferView *);
+
+/* Restreint le champ d'application de l'affichage. */
+void g_buffer_view_restrict(GBufferView *, /*GLineCursor*/void *, /*GLineCursor*/void *);
+
+
+
+/* Détermine la taille nécessaire à une représentation complète. */
+void g_buffer_view_compute_size(const GBufferView *, int *, int *);
+
+
+
+/* Imprime la visualisation du tampon de lignes quelconques. */
+void g_buffer_view_draw(const GBufferView *, cairo_t *, size_t, int, int);
+
+
+
+
+
+
+
+#if 0
+
 #include <glib-object.h>
 
 
@@ -52,13 +94,13 @@ typedef struct _GBufferViewClass GBufferViewClass;
 GType g_buffer_view_get_type(void);
 
 /* Crée une nouvelle vue d'un tampon pour lignes générées. */
-GBufferView *g_buffer_view_new(GBufferCache *, segcnt_list *);
+//GBufferView *g_buffer_view_new(GBufferCache *, segcnt_list *);
 
 /* Fournit le tampon de code lié à un visualisateur donné. */
-GBufferCache *g_buffer_view_get_cache(const GBufferView *);
+//GBufferCache *g_buffer_view_get_cache(const GBufferView *);
 
 /* Restreint le champ d'application de l'affichage. */
-void g_buffer_view_restrict(GBufferView *, GLineCursor *, GLineCursor *);
+//void g_buffer_view_restrict(GBufferView *, GLineCursor *, GLineCursor *);
 
 /* Indique le champ d'application de l'affichage. */
 bool g_buffer_view_get_restrictions(const GBufferView *, GLineCursor **, GLineCursor **);
@@ -110,6 +152,9 @@ bool g_buffer_view_get_cursor_coordinates(GBufferView *, const GLineCursor *, bo
 
 
 
+#endif
+
+
 
 
 #endif  /* _GLIBEXT_BUFFERVIEW_H */
diff --git a/src/glibext/generator-int.h b/src/glibext/generator-int.h
index 6952f69..8b7e28d 100644
--- a/src/glibext/generator-int.h
+++ b/src/glibext/generator-int.h
@@ -1,8 +1,8 @@
 
 /* Chrysalide - Outil d'analyse de fichiers binaires
- * linegen-int.h - définitions internes propres aux intermédiaires de génération de lignes
+ * generator-int.h - définitions internes propres aux intermédiaires de génération de lignes à partir de bribres de texte
  *
- * Copyright (C) 2016-2018 Cyrille Bagard
+ * Copyright (C) 2016-2024 Cyrille Bagard
  *
  *  This file is part of Chrysalide.
  *
@@ -21,47 +21,52 @@
  */
 
 
-#ifndef _GLIBEXT_LINEGEN_INT_H
-#define _GLIBEXT_LINEGEN_INT_H
+#ifndef _GLIBEXT_GENERATOR_INT_H
+#define _GLIBEXT_GENERATOR_INT_H
 
 
-#include "linegen.h"
+#include "generator.h"
 
 
 
 /* Indique le nombre de ligne prêtes à être générées. */
-typedef size_t (* linegen_count_lines_fc) (const GLineGenerator *);
+typedef size_t (* count_tokgen_lines_fc) (const GTokenGenerator *);
+
+/* Renseigne sur les propriétés liées à un générateur. */
+typedef BufferLineFlags (* get_tokgen_flags_fc) (const GTokenGenerator *, size_t, size_t);
+
+/* Imprime dans une ligne de rendu le contenu représenté. */
+typedef void (* populate_tokgen_line_fc) (const GTokenGenerator *, size_t, size_t, GBufferLine *, void *);
+
+#if 0
 
 /* Retrouve l'emplacement correspondant à une position donnée. */
-typedef void (* linegen_compute_fc) (const GLineGenerator *, gint, size_t, size_t, GLineCursor **);
+typedef void (* compute_tokgen_fc) (const GTokenGenerator *, gint, size_t, size_t, GLineCursor **);
 
 /* Détermine si le conteneur s'inscrit dans une plage donnée. */
-typedef int (* linegen_contain_fc) (const GLineGenerator *, size_t, size_t, const GLineCursor *);
+typedef int (* contain_tokgen_fc) (const GTokenGenerator *, size_t, size_t, const GLineCursor *);
 
-/* Renseigne sur les propriétés liées à un générateur. */
-typedef BufferLineFlags (* linegen_get_flags_fc) (const GLineGenerator *, size_t, size_t);
-
-/* Imprime dans une ligne de rendu le contenu représenté. */
-typedef void (* linegen_print_fc) (GLineGenerator *, GBufferLine *, size_t, size_t, const GBinContent *);
+#endif
 
 
 /* Intermédiaire pour la génération de lignes (interface) */
-struct _GLineGeneratorIface
+struct _GTokenGeneratorInterface
 {
     GTypeInterface base_iface;              /* A laisser en premier        */
 
-    linegen_count_lines_fc count;           /* Décompte des lignes         */
-    linegen_compute_fc compute;             /* Calcul d'emplacement        */
-    linegen_contain_fc contain;             /* Inclusion de positions      */
-    linegen_get_flags_fc get_flags;         /* Récupération des drapeaux   */
-    linegen_print_fc print;                 /* Impression d'une ligne      */
+    count_tokgen_lines_fc count;            /* Décompte des lignes         */
+    get_tokgen_flags_fc get_flags;          /* Récupération des drapeaux   */
+    populate_tokgen_line_fc populate;       /* Impression d'une ligne      */
 
-};
+#if 0
 
+    compute_tokgen_fc compute;              /* Calcul d'emplacement        */
+    contain_tokgen_fc contain;              /* Inclusion de positions      */
 
-/* Redéfinition */
-typedef GLineGeneratorIface GLineGeneratorInterface;
+#endif
+
+};
 
 
 
-#endif  /* _GLIBEXT_LINEGEN_INT_H */
+#endif  /* _GLIBEXT_GENERATOR_INT_H */
diff --git a/src/glibext/generator.c b/src/glibext/generator.c
index c5291ab..2d3d349 100644
--- a/src/glibext/generator.c
+++ b/src/glibext/generator.c
@@ -1,8 +1,8 @@
 
 /* Chrysalide - Outil d'analyse de fichiers binaires
- * linegen.c - intermédiaires de génération de lignes
+ * generator.c - intermédiaires de génération de lignes à partir de bribres de texte
  *
- * Copyright (C) 2016-2018 Cyrille Bagard
+ * Copyright (C) 2016-2024 Cyrille Bagard
  *
  *  This file is part of Chrysalide.
  *
@@ -21,23 +21,26 @@
  */
 
 
-#include "linegen.h"
+#include "generator.h"
 
 
 #include <assert.h>
 
 
-#include "linegen-int.h"
+#include "generator-int.h"
 
 
 
 /* Procède à l'initialisation de l'interface de génération. */
-static void g_line_generator_default_init(GLineGeneratorInterface *);
+static void g_token_generator_default_init(GTokenGeneratorInterface *);
+
+/* Indique le nombre de ligne prêtes à être générées. */
+static size_t _g_token_generator_count_one_line(const GTokenGenerator *);
 
 
 
 /* Détermine le type d'une interface pour la mise en place de lignes. */
-G_DEFINE_INTERFACE(GLineGenerator, g_line_generator, G_TYPE_OBJECT)
+G_DEFINE_INTERFACE(GTokenGenerator, g_token_generator, G_TYPE_OBJECT)
 
 
 /******************************************************************************
@@ -52,8 +55,32 @@ G_DEFINE_INTERFACE(GLineGenerator, g_line_generator, G_TYPE_OBJECT)
 *                                                                             *
 ******************************************************************************/
 
-static void g_line_generator_default_init(GLineGeneratorInterface *iface)
+static void g_token_generator_default_init(GTokenGeneratorInterface *iface)
+{
+    iface->count = _g_token_generator_count_one_line;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : generator = générateur à consulter.                          *
+*                                                                             *
+*  Description : Indique le nombre de ligne prêtes à être générées.           *
+*                                                                             *
+*  Retour      : Nombre de lignes devant apparaître au final.                 *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static size_t _g_token_generator_count_one_line(const GTokenGenerator *generator)
 {
+    size_t result;                          /* Décompte à retourner        */
+
+    result = 1;
+
+    return result;
 
 }
 
@@ -70,12 +97,12 @@ static void g_line_generator_default_init(GLineGeneratorInterface *iface)
 *                                                                             *
 ******************************************************************************/
 
-size_t g_line_generator_count_lines(const GLineGenerator *generator)
+size_t g_token_generator_count_lines(const GTokenGenerator *generator)
 {
     size_t result;                          /* Décompte à retourner        */
-    GLineGeneratorIface *iface;             /* Interface utilisée          */
+    GTokenGeneratorInterface *iface;        /* Interface utilisée          */
 
-    iface = G_LINE_GENERATOR_GET_IFACE(generator);
+    iface = G_TOKEN_GENERATOR_GET_IFACE(generator);
 
     result = iface->count(generator);
 
@@ -87,31 +114,29 @@ size_t g_line_generator_count_lines(const GLineGenerator *generator)
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : generator = générateur à consulter.                          *
-*                x         = position géographique sur la ligne concernée.    *
 *                index     = indice de cette même ligne dans le tampon global.*
 *                repeat    = indice d'utilisations successives du générateur. *
 *                                                                             *
-*  Description : Retrouve l'emplacement correspondant à une position donnée.  *
+*  Description : Renseigne sur les propriétés liées à un générateur.          *
 *                                                                             *
-*  Retour      : Emplacement constitué.                                       *
+*  Retour      : Propriétés particulières associées.                          *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-GLineCursor *g_line_generator_compute_cursor(const GLineGenerator *generator, gint x, size_t index, size_t repeat)
+BufferLineFlags g_token_generator_get_flags(const GTokenGenerator *generator, size_t index, size_t repeat)
 {
-    GLineCursor *result;                    /* Emplacement à renvoyer      */
-    GLineGeneratorIface *iface;             /* Interface utilisée          */
+    BufferLineFlags result;                 /* Fanions à retourner         */
+    GTokenGeneratorInterface *iface;        /* Interface utilisée          */
 
-    iface = G_LINE_GENERATOR_GET_IFACE(generator);
+    iface = G_TOKEN_GENERATOR_GET_IFACE(generator);
 
 #ifndef NDEBUG
-    if (iface->count != NULL)
-        assert(repeat < g_line_generator_count_lines(generator));
+    assert(repeat < g_token_generator_count_lines(generator));
 #endif
 
-    iface->compute(generator, x, index, repeat, &result);
+    result = iface->get_flags(generator, index, repeat);
 
     return result;
 
@@ -120,65 +145,65 @@ GLineCursor *g_line_generator_compute_cursor(const GLineGenerator *generator, gi
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : generator = générateur à consulter.                          *
+*  Paramètres  : generator = générateur à utiliser pour l'impression.         *
 *                index     = indice de cette même ligne dans le tampon global.*
 *                repeat    = indice d'utilisations successives du générateur. *
-*                cursor    = emplacement à analyser.                          *
+*                line      = ligne de rendu à compléter.                      *
+*                data      = éventuelle donnée complémentaire fournie.        *
 *                                                                             *
-*  Description : Détermine si le conteneur s'inscrit dans une plage donnée.   *
+*  Description : Etablit dans une ligne de rendu le contenu représenté.       *
 *                                                                             *
-*  Retour      : Bilan de la détermination, utilisable en comparaisons.       *
+*  Retour      : -                                                            *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-int g_line_generator_contain_cursor(const GLineGenerator *generator, size_t index, size_t repeat, const GLineCursor *cursor)
+void g_token_generator_populate_line(const GTokenGenerator *generator, size_t index, size_t repeat, GBufferLine *line, void *data)
 {
-    int result;                             /* Bilan d'analyse à retourner */
-    GLineGeneratorIface *iface;             /* Interface utilisée          */
+    GTokenGeneratorInterface *iface;        /* Interface utilisée          */
 
-    iface = G_LINE_GENERATOR_GET_IFACE(generator);
+    iface = G_TOKEN_GENERATOR_GET_IFACE(generator);
 
 #ifndef NDEBUG
-    if (iface->count != NULL)
-        assert(repeat < g_line_generator_count_lines(generator));
+    assert(repeat < g_token_generator_count_lines(generator));
 #endif
 
-    result = iface->contain(generator, index, repeat, cursor);
-
-    return result;
+    iface->populate(generator, index, repeat, line, data);
 
 }
 
 
+#if 0
+
+
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : generator = générateur à consulter.                          *
+*                x         = position géographique sur la ligne concernée.    *
 *                index     = indice de cette même ligne dans le tampon global.*
 *                repeat    = indice d'utilisations successives du générateur. *
 *                                                                             *
-*  Description : Renseigne sur les propriétés liées à un générateur.          *
+*  Description : Retrouve l'emplacement correspondant à une position donnée.  *
 *                                                                             *
-*  Retour      : Propriétés particulières associées.                          *
+*  Retour      : Emplacement constitué.                                       *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-BufferLineFlags g_line_generator_get_flags(const GLineGenerator *generator, size_t index, size_t repeat)
+GLineCursor *g_token_generator_compute_cursor(const GTokenGenerator *generator, gint x, size_t index, size_t repeat)
 {
-    BufferLineFlags result;                 /* Fanions à retourner         */
-    GLineGeneratorIface *iface;             /* Interface utilisée          */
+    GLineCursor *result;                    /* Emplacement à renvoyer      */
+    GTokenGeneratorInterface *iface;        /* Interface utilisée          */
 
-    iface = G_LINE_GENERATOR_GET_IFACE(generator);
+    iface = G_TOKEN_GENERATOR_GET_IFACE(generator);
 
 #ifndef NDEBUG
-    if (iface->count != NULL)
-        assert(repeat < g_line_generator_count_lines(generator));
+    assert(repeat < g_token_generator_count_lines(generator));
 #endif
 
-    result = iface->get_flags(generator, index, repeat);
+    iface->compute(generator, x, index, repeat, &result);
 
     return result;
 
@@ -187,31 +212,35 @@ BufferLineFlags g_line_generator_get_flags(const GLineGenerator *generator, size
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : generator = générateur à utiliser pour l'impression.         *
-*                line      = ligne de rendu à compléter.                      *
+*  Paramètres  : generator = générateur à consulter.                          *
 *                index     = indice de cette même ligne dans le tampon global.*
 *                repeat    = indice d'utilisations successives du générateur. *
-*                content   = éventuel contenu binaire brut à imprimer.        *
+*                cursor    = emplacement à analyser.                          *
 *                                                                             *
-*  Description : Imprime dans une ligne de rendu le contenu représenté.       *
+*  Description : Détermine si le conteneur s'inscrit dans une plage donnée.   *
 *                                                                             *
-*  Retour      : -                                                            *
+*  Retour      : Bilan de la détermination, utilisable en comparaisons.       *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-void g_line_generator_print(GLineGenerator *generator, GBufferLine *line, size_t index, size_t repeat, const GBinContent *content)
+int g_token_generator_contain_cursor(const GTokenGenerator *generator, size_t index, size_t repeat, const GLineCursor *cursor)
 {
-    GLineGeneratorIface *iface;             /* Interface utilisée          */
+    int result;                             /* Bilan d'analyse à retourner */
+    GTokenGeneratorInterface *iface;        /* Interface utilisée          */
 
-    iface = G_LINE_GENERATOR_GET_IFACE(generator);
+    iface = G_TOKEN_GENERATOR_GET_IFACE(generator);
 
 #ifndef NDEBUG
-    if (iface->count != NULL)
-        assert(repeat < g_line_generator_count_lines(generator));
+    assert(repeat < g_token_generator_count_lines(generator));
 #endif
 
-    iface->print(generator, line, index, repeat, content);
+    result = iface->contain(generator, index, repeat, cursor);
+
+    return result;
 
 }
+
+
+#endif
diff --git a/src/glibext/generator.h b/src/glibext/generator.h
index d40a598..c93e0a0 100644
--- a/src/glibext/generator.h
+++ b/src/glibext/generator.h
@@ -1,8 +1,8 @@
 
 /* Chrysalide - Outil d'analyse de fichiers binaires
- * linegen.h - prototypes pour les intermédiaires de génération de lignes
+ * generator.h - prototypes pour les intermédiaires de génération de lignes à partir de bribres de texte
  *
- * Copyright (C) 2016-2018 Cyrille Bagard
+ * Copyright (C) 2016-2024 Cyrille Bagard
  *
  *  This file is part of Chrysalide.
  *
@@ -21,52 +21,43 @@
  */
 
 
-#ifndef _GLIBEXT_LINEGEN_H
-#define _GLIBEXT_LINEGEN_H
-
-
-#include <glib-object.h>
+#ifndef _GLIBEXT_GENERATOR_H
+#define _GLIBEXT_GENERATOR_H
 
 
 #include "bufferline.h"
+#include "helpers.h"
+/*
 #include "glinecursor.h"
-#include "../analysis/content.h"
+*/
 
 
 
-#define G_TYPE_LINE_GENERATOR               g_line_generator_get_type()
-#define G_LINE_GENERATOR(obj)               (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_LINE_GENERATOR, GLineGenerator))
-#define G_LINE_GENERATOR_CLASS(vtable)      (G_TYPE_CHECK_CLASS_CAST((vtable), G_TYPE_LINE_GENERATOR, GLineGeneratorIface))
-#define GTK_IS_LINE_GENERATOR(obj)          (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_LINE_GENERATOR))
-#define GTK_IS_LINE_GENERATOR_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE((vtable), G_TYPE_LINE_GENERATOR))
-#define G_LINE_GENERATOR_GET_IFACE(inst)    (G_TYPE_INSTANCE_GET_INTERFACE((inst), G_TYPE_LINE_GENERATOR, GLineGeneratorIface))
+#define G_TYPE_TOKEN_GENERATOR (g_token_generator_get_type())
 
+DECLARE_INTERFACE(GTokenGenerator, g_token_generator, G, TOKEN_GENERATOR);
 
-/* Intermédiaire pour la génération de lignes (coquille vide) */
-typedef struct _GLineGenerator GLineGenerator;
 
-/* Intermédiaire pour la génération de lignes (interface) */
-typedef struct _GLineGeneratorIface GLineGeneratorIface;
 
+/* Indique le nombre de ligne prêtes à être générées. */
+size_t g_token_generator_count_lines(const GTokenGenerator *);
 
-/* Détermine le type d'une interface pour la mise en place de lignes. */
-GType g_line_generator_get_type(void) G_GNUC_CONST;
+/* Renseigne sur les propriétés liées à un générateur. */
+BufferLineFlags g_token_generator_get_flags(const GTokenGenerator *, size_t, size_t);
 
-/* Indique le nombre de ligne prêtes à être générées. */
-size_t g_line_generator_count_lines(const GLineGenerator *);
+/* Etablit dans une ligne de rendu le contenu représenté. */
+void g_token_generator_populate_line(const GTokenGenerator *, size_t, size_t, GBufferLine *, void *);
 
-/* Retrouve l'emplacement correspondant à une position donnée. */
-GLineCursor *g_line_generator_compute_cursor(const GLineGenerator *, gint, size_t, size_t);
 
-/* Détermine si le conteneur s'inscrit dans une plage donnée. */
-int g_line_generator_contain_cursor(const GLineGenerator *, size_t, size_t, const GLineCursor *);
+#if 0
 
-/* Renseigne sur les propriétés liées à un générateur. */
-BufferLineFlags g_line_generator_get_flags(const GLineGenerator *, size_t, size_t);
+/* Retrouve l'emplacement correspondant à une position donnée. */
+GLineCursor *g_token_generator_compute_cursor(const GTokenGenerator *, gint, size_t, size_t);
 
-/* Imprime dans une ligne de rendu le contenu représenté. */
-void g_line_generator_print(GLineGenerator *, GBufferLine *, size_t, size_t, const GBinContent *);
+/* Détermine si le conteneur s'inscrit dans une plage donnée. */
+int g_token_generator_contain_cursor(const GTokenGenerator *, size_t, size_t, const GLineCursor *);
 
+#endif
 
 
-#endif  /* _GLIBEXT_LINEGEN_H */
+#endif  /* _GLIBEXT_GENERATOR_H */
diff --git a/src/glibext/generators/Makefile.am b/src/glibext/generators/Makefile.am
index a332498..e95618f 100644
--- a/src/glibext/generators/Makefile.am
+++ b/src/glibext/generators/Makefile.am
@@ -3,17 +3,14 @@ noinst_LTLIBRARIES  = libglibextgenerators.la
 
 
 libglibextgenerators_la_SOURCES =			\
-	prologue.h prologue.c					\
-	rborder.h rborder.c
+	hex.h hex.c
 
-if BUILD_GTK_SUPPORT
 
-libglibextgenerators_la_SOURCES +=			\
-	hex.h hex.c
 
-endif
+# prologue.h prologue.c					\
+# rborder.h rborder.c
 
-libglibextgenerators_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS)
+libglibextgenerators_la_CFLAGS = $(TOOLKIT_CFLAGS)
 
 
 devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%)
diff --git a/src/glibext/generators/hex.c b/src/glibext/generators/hex.c
index 668ebae..6058825 100644
--- a/src/glibext/generators/hex.c
+++ b/src/glibext/generators/hex.c
@@ -28,14 +28,26 @@
 #include <ctype.h>
 
 
+#include "../generator-int.h"
+#include "../options/hex.h"
+
+
+
+
+#if 0
+
+//#include <ctype.h>
+
+
 #include "../bufferline.h"
 #include "../gbinarycursor.h"
-#include "../linegen-int.h"
 #include "../linesegment.h"
 #include "../../core/columns.h"
 #include "../../core/params.h"
 #include "../../gtkext/hexdisplay.h"
 
+#endif
+
 
 
 /* --------------------------- RENDU AMIQUE D'HEXADECIMAL --------------------------- */
@@ -48,9 +60,13 @@ struct _GHexGenerator
 
     GBinContent *content;                   /* Contenu à représenter       */
 
+#if 0
+
     gint left_start;                        /* Abscisse des impressions    */
     gint padding;                           /* Bourrage supplémentaire     */
 
+#endif
+
     phys_t bytes_per_line;                  /* Nombre d'octets par ligne   */
 
 };
@@ -60,11 +76,15 @@ struct _GHexGeneratorClass
 {
     GObjectClass parent;                    /* A laisser en premier        */
 
+#if 0
+
     gint addr_width;                        /* Largeur des positions       */
     gint byte_width;                        /* Largeur d'un octet brut     */
     gint sep_width;                         /* Largeur de séparation       */
     gint char_width;                        /* Largeur d'un caractère      */
 
+#endif
+
 };
 
 
@@ -75,7 +95,7 @@ static void g_hex_generator_class_init(GHexGeneratorClass *);
 static void g_hex_generator_init(GHexGenerator *);
 
 /* Procède à l'initialisation de l'interface de génération. */
-static void g_hex_generator_interface_init(GLineGeneratorInterface *);
+static void g_hex_generator_token_generator_iface_init(GTokenGeneratorInterface *);
 
 /* Supprime toutes les références externes. */
 static void g_hex_generator_dispose(GHexGenerator *);
@@ -91,6 +111,13 @@ static void g_hex_generator_finalize(GHexGenerator *);
 /* Indique le nombre de ligne prêtes à être générées. */
 static size_t g_hex_generator_count_lines(const GHexGenerator *);
 
+/* Etablit dans une ligne de rendu le contenu représenté. */
+static void g_hex_generator_populate_line(const GHexGenerator *, size_t, size_t, GBufferLine *, void *);
+
+
+
+
+#if 0
 #ifdef INCLUDE_GTK_SUPPORT
 
 /* Retrouve l'emplacement correspondant à une position donnée. */
@@ -106,6 +133,7 @@ static BufferLineFlags g_hex_generator_get_flags(const GHexGenerator *, size_t,
 
 /* Imprime dans une ligne de rendu le contenu représenté. */
 static void g_hex_generator_print(GHexGenerator *, GBufferLine *, size_t, size_t);
+#endif
 
 
 
@@ -116,7 +144,7 @@ static void g_hex_generator_print(GHexGenerator *, GBufferLine *, size_t, size_t
 
 /* Détermine le type du générateur de lignes hexadécimales à la volée. */
 G_DEFINE_TYPE_WITH_CODE(GHexGenerator, g_hex_generator, G_TYPE_OBJECT,
-                        G_IMPLEMENT_INTERFACE(G_TYPE_LINE_GENERATOR, g_hex_generator_interface_init));
+                        G_IMPLEMENT_INTERFACE(G_TYPE_TOKEN_GENERATOR, g_hex_generator_token_generator_iface_init));
 
 
 /******************************************************************************
@@ -134,13 +162,15 @@ G_DEFINE_TYPE_WITH_CODE(GHexGenerator, g_hex_generator, G_TYPE_OBJECT,
 static void g_hex_generator_class_init(GHexGeneratorClass *class)
 {
     GObjectClass *object;                   /* Autre version de la classe  */
-    line_segment *segment;                  /* Segment de test pour mesure */
+    //line_segment *segment;                  /* Segment de test pour mesure */
 
     object = G_OBJECT_CLASS(class);
 
     object->dispose = (GObjectFinalizeFunc/* ! */)g_hex_generator_dispose;
     object->finalize = (GObjectFinalizeFunc)g_hex_generator_finalize;
 
+#if 0
+
     /* Mesure de quelques dimensions */
 
     segment = get_new_line_segment(RTT_PHYS_ADDR, "0x00000000", 10);
@@ -167,6 +197,8 @@ static void g_hex_generator_class_init(GHexGeneratorClass *class)
 
     release_line_segment(segment);
 
+#endif
+
 }
 
 
@@ -184,7 +216,7 @@ static void g_hex_generator_class_init(GHexGeneratorClass *class)
 
 static void g_hex_generator_init(GHexGenerator *generator)
 {
-    generator->bytes_per_line = 4;
+    generator->bytes_per_line = 0;
 
 }
 
@@ -201,15 +233,20 @@ static void g_hex_generator_init(GHexGenerator *generator)
 *                                                                             *
 ******************************************************************************/
 
-static void g_hex_generator_interface_init(GLineGeneratorInterface *iface)
+static void g_hex_generator_token_generator_iface_init(GTokenGeneratorInterface *iface)
 {
-    iface->count = (linegen_count_lines_fc)g_hex_generator_count_lines;
+    iface->count = (count_tokgen_lines_fc)g_hex_generator_count_lines;
+
+    iface->populate = (populate_tokgen_line_fc)g_hex_generator_populate_line;
+
+#if 0
 #ifdef INCLUDE_GTK_SUPPORT
     iface->compute = (linegen_compute_fc)g_hex_generator_compute_cursor;
     iface->contain = (linegen_contain_fc)g_hex_generator_contain_cursor;
 #endif
     iface->get_flags = (linegen_get_flags_fc)g_hex_generator_get_flags;
     iface->print = (linegen_print_fc)g_hex_generator_print;
+#endif
 
 }
 
@@ -228,8 +265,7 @@ static void g_hex_generator_interface_init(GLineGeneratorInterface *iface)
 
 static void g_hex_generator_dispose(GHexGenerator *generator)
 {
-    if (generator->content != NULL)
-        g_object_unref(G_OBJECT(generator->content));
+    g_clear_object(&generator->content);
 
     G_OBJECT_CLASS(g_hex_generator_parent_class)->dispose(G_OBJECT(generator));
 
@@ -274,8 +310,239 @@ GHexGenerator *g_hex_generator_new(GBinContent *content)
     result = g_object_new(G_TYPE_HEX_GENERATOR, NULL);
 
     result->content = content;
+    ref_object(content);
+
+    return result;
+
+}
+
+
+// TODO create...
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : generator = générateur à consulter.                          *
+*                                                                             *
+*  Description : Fournit le contenu associé au générateur de lignes hexa.     *
+*                                                                             *
+*  Retour      : Contenu dans lequel puise le générateur pour les lignes.     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GBinContent *g_hex_generator_get_content(const GHexGenerator *generator)
+{
+    GBinContent *result;                    /* Référence à retourner       */
+
+    result = generator->content;
+
+    ref_object(result);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : generator = générateur à ajuster.                            *
+*                options   = options d'affichage des colonnes.                *
+*                style     = style de rendus des bribes de texte.             *
+*                width     = largeur disponible pour les différentes colonnes.*
+*                                                                             *
+*  Description : Détermine la hauteur idéale d'un contenu lié à une largeur.  *
+*                                                                             *
+*  Retour      : Hauteur nécessaire pour les lignes induites.                 *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+int g_hex_generator_mesure_height_for_width(GHexGenerator *generator, const GDisplayOptions *options, const GTokenStyle *style, int width)
+{
+    int result;                             /* Taille à retourner          */
+    vmpa2t end;                             /* Position terminale          */
+    bool status;                            /* Bilan d'une opération       */
+    int off_size;                           /* Taille des emplacements     */
+    int byte_width;                         /* Largeur d'un octet brut     */
+    int sep_width;                          /* Largeur de séparation       */
+    int char_width;                         /* Largeur d'un caractère      */
+    phys_t i;                               /* Boucle de parcours          */
+    phys_t block_count;                     /* Nombre de blocs d'octets    */
+    int requested;                          /* Espace requis pour X octets */
+    phys_t size;                            /* Taille du contenu binaire   */
+    phys_t line_count;                      /* Nombre de lignes requises   */
+
+    result = -1;
+
+    /* Largeur des positions */
+
+    if (g_display_options_get(options, HCO_OFFSET))
+    {
+        status = g_binary_content_compute_end_pos(generator->content, &end);
+        assert(status);
+        if (!status) goto done;
+
+        off_size = g_token_style_compute_location_width(style, end.physical, false);
+
+        width -= off_size;
+
+    }
+
+    /* Détermination des tailles basiques */
+
+    byte_width = g_token_style_measure_width(style, TRT_RAW_CODE, 2 /* 00 */);
+
+    sep_width = g_token_style_measure_width(style, TRT_RAW_CODE, TAB_SIZE /* \t */);
+
+    char_width = g_token_style_measure_width(style, TRT_RAW_CODE, 1 /* 0 */);
+
+    for (i = 4; ; i += 4)
+    {
+        block_count = (i / 4);
+
+        requested  = i * byte_width + 3 * block_count * char_width;
+        requested += (block_count > 1 ? block_count - 1 : 0) * sep_width;
+
+        requested += i * char_width;
+
+        /* Limite atteinte ? */
+        if (requested > width)
+        {
+            i -= 4;
+            break;
+        }
+
+    }
+
+    if (i == 0)
+        i = 4;
+
+    /* Détermination de la taille pour un nombre de lignes donné */
+
+    size = g_binary_content_compute_size(generator->content);
+
+    line_count = size / i;
+
+    if (size % i > 0)
+        line_count++;
+
+    result = line_count * g_token_style_get_line_height(style);
+
+ done:
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : generator = générateur à ajuster.                            *
+*                options   = options d'affichage des colonnes.                *
+*                style     = style de rendus des bribes de texte.             *
+*                width     = largeur disponible pour les différentes colonnes.*
+*                columns   = largeurs adaptées pour les colonnes. [OUT]       *
+*                                                                             *
+*  Description : Détermine les différentes largeurs de colonnes requises.     *
+*                                                                             *
+*  Retour      : true si un changement de contenu a été déterminé.            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_hex_generator_allocate(GHexGenerator *generator, const GDisplayOptions *options, const GTokenStyle *style, int width, int *columns)
+{
+    bool result;                            /* Variation d'état à remonter */
+    vmpa2t end;                             /* Position terminale          */
+    bool status;                            /* Bilan d'une opération       */
+    int byte_width;                         /* Largeur d'un octet brut     */
+    int sep_width;                          /* Largeur de séparation       */
+    int char_width;                         /* Largeur d'un caractère      */
+    phys_t i;                               /* Boucle de parcours          */
+    phys_t block_count;                     /* Nombre de blocs d'octets    */
+    int requested;                          /* Espace requis pour X octets */
+
+    result = false;
+
+    /* Largeur des positions */
+
+    status = g_binary_content_compute_end_pos(generator->content, &end);
+    assert(status);
+    if (!status) goto done;
+
+    columns[HCO_OFFSET] = g_token_style_compute_location_width(style, end.physical, false);
+
+    if (g_display_options_get(options, HCO_OFFSET))
+        width -= columns[HCO_OFFSET];
+
+    /* Détermination des tailles basiques */
+
+    byte_width = g_token_style_measure_width(style, TRT_RAW_CODE, 2 /* 00 */);
+
+    sep_width = g_token_style_measure_width(style, TRT_RAW_CODE, TAB_SIZE /* \t */);
+
+    char_width = g_token_style_measure_width(style, TRT_RAW_CODE, 1 /* 0 */);
+
+    for (i = 4; ; i += 4)
+    {
+        block_count = (i / 4);
+
+        requested  = i * byte_width + 3 * block_count * char_width;
+        requested += (block_count > 1 ? block_count - 1 : 0) * sep_width;
+
+        requested += i * char_width;
+
+        /* Limite atteinte ? */
+        if (requested > width)
+        {
+            i -= 4;
+            break;
+        }
+
+    }
+
+    if (i == 0)
+        i = 4;
+
+    /* Détermination des largeurs de colonnes principales */
+
+    columns[HCO_COUNT + 0]  = i * byte_width + 3 * block_count * char_width;
+    columns[HCO_COUNT + 0] += (block_count > 1 ? block_count - 1 : 0) * sep_width;
+
+    columns[HCO_COUNT + 1] = i * char_width;
+
+    result = (generator->bytes_per_line != i);
+
+    generator->bytes_per_line = i;
+
+ done:
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : generator = générateur à consulter.                          *
+*                                                                             *
+*  Description : Indique le nombre d'octets programmés constituer une ligne.  *
+*                                                                             *
+*  Retour      : Nombre d'octets représentés sur chaque ligne.                *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
 
-    g_object_ref(G_OBJECT(result->content));
+phys_t g_hex_generator_get_bytes_per_line(const GHexGenerator *generator)
+{
+    phys_t result;                          /* Quantité d'octets à renvoyer*/
+
+    result = generator->bytes_per_line;
 
     return result;
 
@@ -317,6 +584,136 @@ static size_t g_hex_generator_count_lines(const GHexGenerator *generator)
 }
 
 
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : generator = générateur à utiliser pour l'impression.         *
+*                index     = indice de cette même ligne dans le tampon global.*
+*                repeat    = indice d'utilisations successives du générateur. *
+*                line      = ligne de rendu à compléter.                      *
+*                data      = éventuelle donnée complémentaire fournie.        *
+*                                                                             *
+*  Description : Etablit dans une ligne de rendu le contenu représenté.       *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_hex_generator_populate_line(const GHexGenerator *generator, size_t index, size_t repeat, GBufferLine *line, void *data)
+{
+
+
+    //GGenConfig *config;                     /* Configuration à consulter   */
+    bool upper_case;                        /* Casse des données en hexa   */
+#ifndef NDEBUG
+    bool status;                            /* Bilan de la consultation    */
+#endif
+    const char *hexa;                       /* Chaîne à considérer #0      */
+    const char *ff;                         /* Chaîne à considérer #1      */
+    vmpa2t pos;                             /* Position définie à la volée */
+    phys_t got;                             /* Quantité affichable         */
+    const bin_t *raw;                       /* Accès direct et brut        */
+    phys_t i;                               /* Boucle de parcours          */
+    bin_t byte;                             /* Copie pour confort          */
+    char tmp[2];                            /* Représentation d'un octet   */
+
+    static const char hexa_lower[] = "0123456789abcdef";
+    static const char hexa_upper[] = "0123456789ABCDEF";
+    static const char ff_lower[] = "ff";
+    static const char ff_upper[] = "FF";
+
+    /*
+    config = get_main_configuration();
+
+#ifndef NDEBUG
+    status = g_generic_config_get_value(config, MPK_HEX_UPPER_CASE, &upper_case);
+    assert(status);
+#else
+    g_generic_config_get_value(config, MPK_HEX_UPPER_CASE, &upper_case);
+#endif
+    */
+
+    upper_case = true;
+
+    if (upper_case)
+    {
+        hexa = hexa_upper;
+        ff = ff_upper;
+    }
+    else
+    {
+        hexa = hexa_lower;
+        ff = ff_lower;
+    }
+
+    /* Position physique */
+
+    init_vmpa(&pos, generator->bytes_per_line * index, VMPA_NO_VIRTUAL);
+
+    //g_buffer_line_fill_phys(line, HLC_PHYSICAL, MDS_32_BITS_UNSIGNED, &pos);
+
+    /* Contenu brut */
+
+    got = g_binary_content_compute_size(generator->content) - get_phy_addr(&pos);
+
+    if (got > generator->bytes_per_line)
+        got = generator->bytes_per_line;
+
+    raw = g_binary_content_get_raw_access(generator->content, &pos, got);
+
+    for (i = 0; i < got; i++)
+    {
+        /* Séparation ? */
+
+        if (i > 0)
+        {
+            if (i % 4 == 0)
+                g_buffer_line_append_text(line, HCO_COUNT + 0, TRT_NONE, "\t", 1, NULL, NULL);
+            else
+                g_buffer_line_append_text(line, HCO_COUNT + 0, TRT_NONE, " ", 1, NULL, NULL);
+        }
+
+        /* Binaire brut */
+
+        byte = raw[i];
+
+        if (byte == 0x00)
+            g_buffer_line_append_text(line, HCO_COUNT + 0, TRT_RAW_NULL, "00", 2, NULL, NULL);
+
+        else if (byte == 0xff)
+            g_buffer_line_append_text(line, HCO_COUNT + 0, TRT_RAW_FULL, ff, 2, NULL, NULL);
+
+        else
+        {
+            tmp[1] = hexa[byte & 0xf];
+            tmp[0] = hexa[(byte >> 4) & 0xf];
+
+            if (isgraph(byte) || byte == ' ')
+                g_buffer_line_append_text(line, HCO_COUNT + 0, TRT_RAW_PRINTABLE, tmp, 2, NULL, NULL);
+            else
+                g_buffer_line_append_text(line, HCO_COUNT + 0, TRT_RAW_NOT_PRINTABLE, tmp, 2, NULL, NULL);
+
+        }
+
+        /* Représentation humaine ? */
+
+        if (isgraph(byte) || byte == ' ')
+            g_buffer_line_append_text(line, HCO_COUNT + 1, TRT_CHR_PRINTABLE, (char *)raw + i, 1, NULL, NULL);
+        else
+            g_buffer_line_append_text(line, HCO_COUNT + 1, TRT_CHR_NOT_PRINTABLE, ".", 1, NULL, NULL);
+
+    }
+
+}
+
+
+
+
+
+
+
+#if 0
 #ifdef INCLUDE_GTK_SUPPORT
 
 
@@ -538,9 +935,9 @@ static void g_hex_generator_print(GHexGenerator *generator, GBufferLine *line, s
         if (i > 0)
         {
             if (i % 4 == 0)
-                g_buffer_line_append_text(line, HLC_BINARY, "\t", 1, RTT_RAW, NULL);
+                g_buffer_line_append_text(line, HCO_COUNT + 0, "\t", 1, RTT_RAW, NULL);
             else
-                g_buffer_line_append_text(line, HLC_BINARY, " ", 1, RTT_RAW, NULL);
+                g_buffer_line_append_text(line, HCO_COUNT + 0, " ", 1, RTT_RAW, NULL);
         }
 
         /* Binaire brut */
@@ -548,17 +945,17 @@ static void g_hex_generator_print(GHexGenerator *generator, GBufferLine *line, s
         byte = raw[i];
 
         if (byte == 0x00)
-            g_buffer_line_append_text(line, HLC_BINARY, "00", 2, RTT_RAW_NULL, NULL);
+            g_buffer_line_append_text(line, HCO_COUNT + 0, "00", 2, RTT_RAW_NULL, NULL);
 
         else if (byte == 0xff)
-            g_buffer_line_append_text(line, HLC_BINARY, ff, 2, RTT_RAW_FULL, NULL);
+            g_buffer_line_append_text(line, HCO_COUNT + 0, ff, 2, RTT_RAW_FULL, NULL);
 
         else
         {
             tmp[1] = hexa[byte & 0xf];
             tmp[0] = hexa[(byte >> 4) & 0xf];
 
-            g_buffer_line_append_text(line, HLC_BINARY, tmp, 2, RTT_RAW, NULL);
+            g_buffer_line_append_text(line, HCO_COUNT + 0, tmp, 2, RTT_RAW, NULL);
 
         }
 
@@ -574,30 +971,6 @@ static void g_hex_generator_print(GHexGenerator *generator, GBufferLine *line, s
 }
 
 
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : generator = générateur à consulter.                          *
-*                                                                             *
-*  Description : Fournit le contenu associé au générateur de lignes hexa.     *
-*                                                                             *
-*  Retour      : Contenu dans lequel puise le générateur pour les lignes.     *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-GBinContent *g_hex_generator_get_content(const GHexGenerator *generator)
-{
-    GBinContent *result;                    /* Référence à retourner       */
-
-    result = generator->content;
-
-    g_object_ref(G_OBJECT(result));
-
-    return result;
-
-}
-
 
 /******************************************************************************
 *                                                                             *
@@ -665,20 +1038,4 @@ bool g_hex_generator_auto_fit(GHexGenerator *generator, gint left, bool show_pos
 }
 
 
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : generator = générateur à consulter.                          *
-*                                                                             *
-*  Description : Indique le nombre d'octets programmés constituer une ligne.  *
-*                                                                             *
-*  Retour      : Nombre d'octets représentés sur chaque ligne.                *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-phys_t g_hex_generator_get_bytes_per_line(const GHexGenerator *generator)
-{
-    return generator->bytes_per_line;
-
-}
+#endif
diff --git a/src/glibext/generators/hex.h b/src/glibext/generators/hex.h
index f4aeb03..e404adf 100644
--- a/src/glibext/generators/hex.h
+++ b/src/glibext/generators/hex.h
@@ -25,30 +25,17 @@
 #define _GLIBEXT_GENERATORS_HEX_H
 
 
-#include <glib-object.h>
-
-
+#include "../helpers.h"
+#include "../options.h"
+#include "../tokenstyle.h"
 #include "../../analysis/content.h"
 
 
 
-#define G_TYPE_HEX_GENERATOR            (g_hex_generator_get_type())
-#define G_HEX_GENERATOR(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_HEX_GENERATOR, GHexGenerator))
-#define G_IS_HEX_GENERATOR(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_HEX_GENERATOR))
-#define G_HEX_GENERATOR_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_HEX_GENERATOR, GHexGeneratorClass))
-#define G_IS_HEX_GENERATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_HEX_GENERATOR))
-#define G_HEX_GENERATOR_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_HEX_GENERATOR, GHexGeneratorClass))
-
+#define G_TYPE_HEX_GENERATOR (g_hex_generator_get_type())
 
-/* Tampon pour générateur de lignes hexadécimales (instance) */
-typedef struct _GHexGenerator GHexGenerator;
+DECLARE_GTYPE(GHexGenerator, g_hex_generator, G, HEX_GENERATOR);
 
-/* Tampon pour générateur de lignes hexadécimales (classe) */
-typedef struct _GHexGeneratorClass GHexGeneratorClass;
-
-
-/* Détermine le type du générateur de lignes hexadécimales à la volée. */
-GType g_hex_generator_get_type(void);
 
 /* Crée un nouveau générateur de lignes hexadécimales. */
 GHexGenerator *g_hex_generator_new(GBinContent *);
@@ -56,8 +43,11 @@ GHexGenerator *g_hex_generator_new(GBinContent *);
 /* Fournit le contenu associé au générateur de lignes hexa. */
 GBinContent *g_hex_generator_get_content(const GHexGenerator *);
 
-/* Ajuste la génération à une nouvelle largeur de rendu. */
-bool g_hex_generator_auto_fit(GHexGenerator *, gint, bool, gint, gint);
+/* Détermine la hauteur idéale d'un contenu lié à une largeur. */
+int g_hex_generator_mesure_height_for_width(GHexGenerator *, const GDisplayOptions *, const GTokenStyle *, int);
+
+/* Détermine les différentes largeurs de colonnes requises. */
+bool g_hex_generator_allocate(GHexGenerator *, const GDisplayOptions *, const GTokenStyle *, int, int *);
 
 /* Indique le nombre d'octets programmés constituer une ligne. */
 phys_t g_hex_generator_get_bytes_per_line(const GHexGenerator *);
diff --git a/src/glibext/helpers.h b/src/glibext/helpers.h
index 71a7269..04e51ad 100644
--- a/src/glibext/helpers.h
+++ b/src/glibext/helpers.h
@@ -90,6 +90,36 @@
 
 
 /**
+ * Bis repetita pour les interfaces...
+ */
+
+#define DECLARE_INTERFACE(TN, t_n, MOD, NAME)                                               \
+                                                                                            \
+    GType t_n##_get_type(void) G_GNUC_CONST;                                                \
+                                                                                            \
+    /* Coquille vide */                                                                     \
+    typedef struct _##TN TN;                                                                \
+    /* Interface */                                                                         \
+    typedef struct _##TN##Interface TN##Interface;                                          \
+                                                                                            \
+    G_GNUC_UNUSED static inline TN *MOD##_##NAME(gconstpointer obj)                         \
+    {                                                                                       \
+        return G_TYPE_CHECK_INSTANCE_CAST(obj, MOD##_TYPE_##NAME, TN);                      \
+    }                                                                                       \
+                                                                                            \
+    G_GNUC_UNUSED static inline gboolean MOD##_IS_##NAME(gconstpointer obj)                 \
+    {                                                                                       \
+        return G_TYPE_CHECK_INSTANCE_TYPE(obj, MOD##_TYPE_##NAME);                          \
+    }                                                                                       \
+                                                                                            \
+    G_GNUC_UNUSED static inline TN##Interface *MOD##_##NAME##_GET_IFACE(gconstpointer obj)  \
+    {                                                                                       \
+        return G_TYPE_INSTANCE_GET_INTERFACE(obj, MOD##_TYPE_##NAME, TN##Interface);        \
+    }
+
+
+
+/**
  * Les principales fonctions incrémentant ou réduisant le nombre de références
  * attachées à un objet acceptent de simples pointeurs génériques (cf. définitions
  * du fichier <glib-2.80>/gobject/gobject.h :
@@ -143,7 +173,7 @@
         assert(__inst != NULL);                                                     \
         g_object_ref(ip);                                                           \
     }                                                                               \
-    while (0);
+    while (0)
 
 #   define unref_object(ip)                                                         \
     do                                                                              \
@@ -153,7 +183,7 @@
         assert(__inst != NULL);                                                     \
         g_object_unref(ip);                                                         \
     }                                                                               \
-    while (0);
+    while (0)
 
 #else
 
diff --git a/src/glibext/linecolumn.c b/src/glibext/linecolumn.c
index 35f7698..22ff2a4 100644
--- a/src/glibext/linecolumn.c
+++ b/src/glibext/linecolumn.c
@@ -24,13 +24,9 @@
 #include "linecolumn.h"
 
 
-#include <assert.h>
 #include <malloc.h>
 
 
-#include "../common/extstr.h"
-
-
 
 /******************************************************************************
 *                                                                             *
@@ -44,14 +40,12 @@
 *                                                                             *
 ******************************************************************************/
 
-void init_line_column(line_column *column)
+void init_line_column(line_column_t *column)
 {
-    column->segments = NULL;
+    column->tokens = NULL;
     column->count = 0;
 
-#ifdef INCLUDE_GTK_SUPPORT
     column->max_width = 0;
-#endif
 
 }
 
@@ -68,114 +62,162 @@ void init_line_column(line_column *column)
 *                                                                             *
 ******************************************************************************/
 
-void reset_line_column(line_column *column)
+void reset_line_column(line_column_t *column)
 {
     size_t i;                               /* Boucle de parcours          */
 
     for (i = 0; i < column->count; i++)
-        release_line_segment(column->segments[i]);
+        release_line_token(column->tokens[i]);
 
-    if (column->segments != NULL)
+    if (column->tokens != NULL)
     {
-        free(column->segments);
-        column->segments = NULL;
+        free(column->tokens);
+        column->tokens = NULL;
     }
 
     column->count = 0;
 
-#ifdef INCLUDE_GTK_SUPPORT
     column->max_width = 0;
-#endif
 
 }
 
 
-#ifdef INCLUDE_GTK_SUPPORT
+
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : column = colonne de ligne à mettre à jour.                   *
+*  Paramètres  : column = colonne de ligne à venir compléter.                 *
+*                tag    = propriétés de la zone de texte.                     *
+*                text   = chaîne de caractères à traiter.                     *
+*                length = quantité de ces caractères.                         *
+*                style  = gestionnaire de paramètres de rendu à consulter.    *
 *                                                                             *
-*  Description : Recalcule la largeur d'une colonne de segments.              *
+*  Description : Ajoute un fragment de texte à une colonne de ligne.          *
 *                                                                             *
-*  Retour      : -                                                            *
+*  Retour      : Indice du point d'insertion.                                 *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-void refresh_line_column_width(line_column *column)
+size_t append_text_to_line_column(line_column_t *column, TokenRenderingTag tag, const char *text, size_t length, const GTokenStyle *style)
 {
-    size_t i;                               /* Boucle de parcours          */
+    size_t result;                          /* Indice à retourner          */
+    line_token_t *token;                    /* Contenu à représenter       */
 
-    column->max_width = 0;
+    result = column->count;
 
-    for (i = 0; i < column->count; i++)
-        column->max_width += get_line_segment_width(column->segments[i]);
+    token = get_new_line_token(tag, text, length);
+
+    column->tokens = realloc(column->tokens, ++column->count * sizeof(line_token_t *));
+
+    column->tokens[result] = token;
+
+    //column->max_width += g_token_style_measure_width(style, tag, length);
+
+    return result;
 
 }
 
 
+
+
+
+
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : column  = colonne de ligne à consulter.                      *
+*  Paramètres  : column = colonne de ligne de texte à manipuler.              *
+*                cr     = contexte graphique à utiliser pour les pinceaux.    *
+*                x      = abscisse du point d'impression (à maj). [OUT]       *
+*                y      = ordonnée du point d'impression.                     *
+*                style  = style de rendu pour les bribes de texte.            *
 *                                                                             *
-*  Description : Fournit la quantité de pixels requise pour l'impression.     *
+*  Description : Imprime le contenu d'une colonne de ligne de texte.          *
 *                                                                             *
-*  Retour      : Largeur requise par la colonne, en pixel.                    *
+*  Retour      : -                                                            *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-gint get_column_width(const line_column *column)
+void draw_line_column(const line_column_t *column, cairo_t *cr, int *x, int y, const GTokenStyle *style)
 {
-    return column->max_width;
+    size_t i;                               /* Boucle de parcours          */
+
+    for (i = 0; i < column->count; i++)
+        draw_line_token(column->tokens[i], cr, x, y, style);
 
 }
 
 
-#endif
+
+
+
+
+#if 0
+
+#include <assert.h>
+#include <malloc.h>
+
+
+#include "../common/extstr.h"
+
+
+
+
+
+#ifdef INCLUDE_GTK_SUPPORT
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : column  = colonne de ligne à venir compléter.                *
-*                text    = texte à insérer dans l'existant.                   *
-*                length  = taille du texte à traiter.                         *
-*                type    = type de décorateur à utiliser.                     *
+*  Paramètres  : column = colonne de ligne à mettre à jour.                   *
 *                                                                             *
-*  Description : Ajoute un fragment de texte à une colonne de ligne.          *
+*  Description : Recalcule la largeur d'une colonne de segments.              *
 *                                                                             *
-*  Retour      : Indice du point d'insertion.                                 *
+*  Retour      : -                                                            *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-size_t append_text_to_line_column(line_column *column, const char *text, size_t length, RenderingTagType type)
+void refresh_line_column_width(line_column *column)
 {
-    size_t result;                          /* Indice à retourner          */
-    line_segment *segment;                  /* Contenu à représenter       */
+    size_t i;                               /* Boucle de parcours          */
 
-    result = column->count;
+    column->max_width = 0;
 
-    segment = get_new_line_segment(type, text, length);
+    for (i = 0; i < column->count; i++)
+        column->max_width += get_line_segment_width(column->segments[i]);
 
-    column->segments = realloc(column->segments, ++column->count * sizeof(line_segment *));
+}
 
-    column->segments[result] = segment;
 
-#ifdef INCLUDE_GTK_SUPPORT
-    column->max_width += get_line_segment_width(segment);
-#endif
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : column  = colonne de ligne à consulter.                      *
+*                                                                             *
+*  Description : Fournit la quantité de pixels requise pour l'impression.     *
+*                                                                             *
+*  Retour      : Largeur requise par la colonne, en pixel.                    *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
 
-    return result;
+gint get_column_width(const line_column *column)
+{
+    return column->max_width;
 
 }
 
 
+#endif
+
+
+
+
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : column  = colonne de ligne à venir compléter.                *
@@ -202,7 +244,7 @@ void replace_text_in_line_column(line_column *column, size_t index, const char *
 
     segment = column->segments[index];
 
-    type = get_line_segment_type(segment);
+    type = get_line_token_type(segment);
 
     release_line_segment(segment);
 
@@ -544,3 +586,5 @@ void export_line_column_segments(const line_column *column, buffer_export_contex
     }
 
 }
+
+#endif
diff --git a/src/glibext/linecolumn.h b/src/glibext/linecolumn.h
index 6dd50f6..a1757f9 100644
--- a/src/glibext/linecolumn.h
+++ b/src/glibext/linecolumn.h
@@ -25,39 +25,58 @@
 #define _GLIBEXT_LINECOLUMN_H
 
 
-#include <stdbool.h>
-#include <glib-object.h>
-#ifdef INCLUDE_GTK_SUPPORT
-#   include <gdk/gdk.h>
-#endif
+#include <sys/types.h>
 
 
-#include "linesegment.h"
+#include "linetoken.h"
 
 
 
 /* Informations sur le contenu d'une colonne */
-typedef struct _line_column line_column;
-
-
-/* Informations sur le contenu d'une colonne */
-struct _line_column
+typedef struct _line_column_t
 {
-    line_segment **segments;                /* Liste des segments contenus */
+    line_token_t **tokens;                  /* Liste des segments contenus */
     size_t count;                           /* Taille de cette liste       */
 
-#ifdef INCLUDE_GTK_SUPPORT
     int max_width;                          /* Largeur max. de l'espace    */
-#endif
 
-};
+} line_column_t;
+
 
 
 /* Initialise une colonne de ligne. */
-void init_line_column(line_column *);
+void init_line_column(line_column_t *);
 
 /* Réinitialise une colonne de ligne. */
-void reset_line_column(line_column *);
+void reset_line_column(line_column_t *);
+
+/* Ajoute un fragment de texte à une colonne de ligne. */
+size_t append_text_to_line_column(line_column_t *, TokenRenderingTag, const char *, size_t, const GTokenStyle *);
+
+
+
+
+/* Imprime le contenu d'une colonne de ligne de texte. */
+void draw_line_column(const line_column_t *, cairo_t *, int *, int, const GTokenStyle *);
+
+
+
+
+#if 0
+
+#include <stdbool.h>
+#include <glib-object.h>
+#ifdef INCLUDE_GTK_SUPPORT
+#   include <gdk/gdk.h>
+#endif
+
+
+#include "linesegment.h"
+
+
+
+/* Réinitialise une colonne de ligne. */
+//void reset_line_column(line_column *);
 
 #ifdef INCLUDE_GTK_SUPPORT
 
@@ -70,7 +89,7 @@ gint get_column_width(const line_column *);
 #endif
 
 /* Ajoute un fragment de texte à une colonne de ligne. */
-size_t append_text_to_line_column(line_column *, const char *, size_t, RenderingTagType);
+//size_t append_text_to_line_column(line_column *, const char *, size_t, RenderingTagType);
 
 /* Remplace un fragment de texte dans une colonne de ligne. */
 void replace_text_in_line_column(line_column *, size_t, const char *, size_t);
@@ -104,5 +123,8 @@ char *get_line_column_text(const line_column *, bool);
 void export_line_column_segments(const line_column *, buffer_export_context *, BufferExportType, int);
 
 
+#endif
+
+
 
 #endif  /* _GLIBEXT_LINECOLUMN_H */
diff --git a/src/glibext/linetoken.c b/src/glibext/linetoken.c
index 192e030..6caa7df 100644
--- a/src/glibext/linetoken.c
+++ b/src/glibext/linetoken.c
@@ -1,6 +1,6 @@
 
 /* Chrysalide - Outil d'analyse de fichiers binaires
- * linesegment.c - concentration d'un fragment de caractères aux propriétés communes
+ * linetoken.c - concentration d'un fragment de caractères aux propriétés communes
  *
  * Copyright (C) 2016-2019 Cyrille Bagard
  *
@@ -21,173 +21,137 @@
  */
 
 
-#include "linesegment.h"
+#include "linetoken.h"
 
 
-#include <assert.h>
-#include <limits.h>
+#include <glib.h>
 #include <malloc.h>
-#include <stdbool.h>
-#include <stdlib.h>
 #include <string.h>
 
 
-#include "../common/extstr.h"
 #include "../common/fnv1a.h"
-#include "../core/paths.h"
-#ifdef INCLUDE_GTK_SUPPORT
-#   include "../gtkext/rendering.h"
-#endif
 
 
 
-/* ------------------------ NATURE POUR UN FRAGMENT DE TEXTE ------------------------ */
+/* -------------------- NATURE DE BASE POUR UN FRAGMENT DE TEXTE -------------------- */
 
 
-/* Nom des éléments CSS */
+/* Fragment de caractères aux propriétés potentiellement partagées */
+struct _line_token_t
+{
+    gint ref_count;                         /* Compteur de références      */
 
-#define SEGMENT_NAME(s) "token-" s
+    TokenRenderingTag tag;                  /* Type de rendu attendu       */
 
-static const char *_segment_names[RTT_COUNT] = {
+    fnv64_t hash;                           /* Empreinte pour comparaisons */
 
-    [RTT_NONE]          = SEGMENT_NAME("none"),
-    [RTT_RAW]           = SEGMENT_NAME("raw"),
-    [RTT_RAW_FULL]      = SEGMENT_NAME("raw-full"),
-    [RTT_RAW_NULL]      = SEGMENT_NAME("raw-null"),
-    [RTT_PRINTABLE]     = SEGMENT_NAME("printable"),
-    [RTT_NOT_PRINTABLE] = SEGMENT_NAME("not-printable"),
-    [RTT_COMMENT]       = SEGMENT_NAME("comment"),
-    [RTT_INDICATION]    = SEGMENT_NAME("indication"),
-    [RTT_PHYS_ADDR_PAD] = SEGMENT_NAME("phys-addr-padding"),
-    [RTT_PHYS_ADDR]     = SEGMENT_NAME("phys-addr"),
-    [RTT_VIRT_ADDR_PAD] = SEGMENT_NAME("virt-addr-padding"),
-    [RTT_VIRT_ADDR]     = SEGMENT_NAME("virt-addr"),
-    [RTT_RAW_CODE]      = SEGMENT_NAME("raw-code"),
-    [RTT_RAW_CODE_NULL] = SEGMENT_NAME("raw-code-null"),
-    [RTT_LABEL]         = SEGMENT_NAME("label"),
-    [RTT_INSTRUCTION]   = SEGMENT_NAME("instruction"),
-    [RTT_IMMEDIATE]     = SEGMENT_NAME("immediate"),
-    [RTT_REGISTER]      = SEGMENT_NAME("register"),
-    [RTT_PUNCT]         = SEGMENT_NAME("punct"),
-    [RTT_HOOK]          = SEGMENT_NAME("hooks"),
-    [RTT_SIGNS]         = SEGMENT_NAME("signs"),
-    [RTT_LTGT]          = SEGMENT_NAME("ltgt"),
-    [RTT_SECTION]       = SEGMENT_NAME("section"),
-    [RTT_SEGMENT]       = SEGMENT_NAME("segment"),
-    [RTT_STRING]        = SEGMENT_NAME("string"),
-    [RTT_VAR_NAME]      = SEGMENT_NAME("var-name"),
-    [RTT_KEY_WORD]      = SEGMENT_NAME("keyword"),
-    [RTT_ERROR]         = SEGMENT_NAME("error"),
+    size_t length;                          /* Taille du texte brut        */
+    char text[0];                           /* Texte brut conservé         */
 
 };
 
+/* Fournit l'empreinte d'une bribe de texte pour rendu. */
+static guint hash_line_token(const line_token_t *);
 
-#ifdef INCLUDE_GTK_SUPPORT
-
-/* Compléments à Cairo */
-
-#define CAIRO_FONT_SLANT_COUNT  3
-#define CAIRO_FONT_WEIGHT_COUNT 2
+/* Détermine si deux fragments de texte sont identiques. */
+static bool is_line_token_equal(const line_token_t *, const line_token_t *);
 
-#define CAIRO_FONTS_COUNT (CAIRO_FONT_SLANT_COUNT * CAIRO_FONT_WEIGHT_COUNT)
-#define CAIRO_FONT_INDEX(s, w) ((s) + (w) * CAIRO_FONT_WEIGHT_COUNT)
-
-
-/* Propriétés de rendu */
-typedef struct _segment_rendering
-{
-    rendering_color_t selection_bg;         /* Fond d'impression           */
 
-    cairo_t *font_ctxts[CAIRO_FONTS_COUNT]; /* Contextes de police         */
-    double x_advances[CAIRO_FONTS_COUNT];   /* Largeurs par caractère      */
 
-    rendering_pattern_t patterns[RTT_COUNT];/* Modèles d'impression        */
+/* ----------------------- ISOLATION DE CONTENUS PARTAGEABLES ----------------------- */
 
-} segment_rendering;
 
+/* Conservation de toutes les créations partagées */
+static GHashTable *_token_htable;
+G_LOCK_DEFINE_STATIC(_token_mutex);
 
-/* Configuration globale des rendus */
-static segment_rendering _seg_params;
+/* Fournit l'adresse d'un fragment de texte unique. */
+static line_token_t *get_shared_line_token(const line_token_t *);
 
-#endif
+/* Abandonne un contenu pour segments. */
+static void release_shared_line_token(line_token_t *);
 
 
 
-/* ----------------------- ISOLATION DE CONTENUS PARTAGEABLES ----------------------- */
+/* ---------------------------------------------------------------------------------- */
+/*                      NATURE DE BASE POUR UN FRAGMENT DE TEXTE                      */
+/* ---------------------------------------------------------------------------------- */
 
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : tag    = propriétés de la zone de texte.                     *
+*                text   = chaîne de caractères à traiter.                     *
+*                length = quantité de ces caractères.                         *
+*                                                                             *
+*  Description : Crée un nouveau fragment de texte avec des propriétés.       *
+*                                                                             *
+*  Retour      : Elément créé ou recyclé.                                     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
 
-/* Fragment de caractères aux propriétés potentiellement partagées */
-struct _line_segment
+line_token_t *get_new_line_token(TokenRenderingTag tag, const char *text, size_t length)
 {
-    gint ref_count;                         /* Compteur de références      */
-
-#ifdef INCLUDE_GTK_SUPPORT
-   rendering_pattern_t *pattern;           /* Propriétés du rendu         */
-#else
-    RenderingTagType type;                  /* Type de rendu attendu       */
-#endif
-
-    fnv64_t hash;                           /* Empreinte pour comparaisons */
-    char text[0];                           /* Texte brut conservé         */
+    line_token_t *result;                   /* Elément à retourner         */
+    char atmp[sizeof(line_token_t) + 128];  /* Allocation static facile    */
+    line_token_t *template;                 /* Contenu à mettre en place ? */
 
-};
+    assert(length > 0);
 
+    /**
+     * L'octet nul final est attendu par la fonction cairo_show_text()
+     * pour le rendu.
+     */
 
-/* Conservation de toutes les créations partagées */
-static GHashTable *_segcnt_htable;
-G_LOCK_DEFINE_STATIC(_segcnt_mutex);
+    if ((length + 1) < (sizeof(atmp) - sizeof(line_token_t)))
+        template = (line_token_t *)atmp;
+    else
+        template = malloc(sizeof(line_token_t) + length + 1);
 
+    template->tag = tag;
 
-/* Fournit l'empreinte d'un contenu pour segments. */
-static guint get_line_segment_hash(const line_segment *);
+    template->hash = fnv_64a_hash(text);
 
-/* Détermine si deux contenus pour segments sont identiques. */
-static bool is_line_segment_equal(const line_segment *, const line_segment *);
+    template->length = length;
 
-/* Détermine si deux contenus pour segments sont identiques. */
-static line_segment *get_shared_segment_content(const line_segment *);
+    memcpy(template->text, text, length);
+    template->text[length] = '\0';
 
-/* Abandonne un contenu pour segments. */
-static void release_shared_segment_content(line_segment *);
+    result = get_shared_line_token(template);
 
+    if (template != (line_token_t *)atmp)
+        free(template);
 
+    return result;
 
-/* -------------------- GESTION OPTIMALE D'UNE LISTE DE CONTENUS -------------------- */
+}
 
 
-#ifdef INCLUDE_GTK_SUPPORT
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : token = fragment de texte à traiter.                         *
+*                                                                             *
+*  Description : Augmente le compteur de références d'un fragment de texte.   *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
 
-/* Liste identifiant un ensemble de segments */
-struct _segcnt_list
+void ref_line_token(line_token_t *token)
 {
-    fnv64_t *hashes;                        /* Empreinte pour comparaisons */
-    size_t count;                           /* Nommbre de ces empreintes   */
-
-    unsigned int ref_count;                 /* Compteur de références      */
-
-};
-
-
-/* Indique si le contenu d'un segment est notable ou non. */
-bool selection_list_has_segment_content(const segcnt_list *, const line_segment *);
-
-#endif
+    g_atomic_int_inc(&token->ref_count);
 
-
-
-/* ---------------------------------------------------------------------------------- */
-/*                          NATURE POUR UN FRAGMENT DE TEXTE                          */
-/* ---------------------------------------------------------------------------------- */
-
-
-#ifdef INCLUDE_GTK_SUPPORT
+}
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : -                                                            *
+*  Paramètres  : token = fragment de texte à libérer de la mémoire.           *
 *                                                                             *
-*  Description : Procède à l'initialisation des paramètres de rendu de texte. *
+*  Description : Retire une utilisation à un fragment de texte.               *
 *                                                                             *
 *  Retour      : -                                                            *
 *                                                                             *
@@ -195,164 +159,152 @@ bool selection_list_has_segment_content(const segcnt_list *, const line_segment
 *                                                                             *
 ******************************************************************************/
 
-bool load_segment_rendering_parameters(void)
+void release_line_token(line_token_t *token)
 {
-    cairo_font_slant_t s;                   /* Boucle de parcours #1       */
-    cairo_font_weight_t w;                  /* Boucle de parcours #2       */
-    cairo_t **cr;                           /* Contexte à créer            */
-    cairo_surface_t *surface;               /* Surface pour dessin Cairo   */
-    cairo_text_extents_t extents;           /* Couverture des caractères   */
-    RenderingTagType i;                     /* Boucle de parcours          */
+    release_shared_line_token(token);
 
-    /* Contextes pour les mesures initiales */
+}
 
-    for (s = CAIRO_FONT_SLANT_NORMAL; s < CAIRO_FONT_SLANT_COUNT; s++)
-        for (w = CAIRO_FONT_WEIGHT_NORMAL; w < CAIRO_FONT_WEIGHT_COUNT; w++)
-        {
-            cr = &_seg_params.font_ctxts[CAIRO_FONT_INDEX(s, w)];
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : token = fragment de texte à consulter.                       *
+*                                                                             *
+*  Description : Fournit l'empreinte d'une bribe de texte pour rendu.         *
+*                                                                             *
+*  Retour      : Empreinte de lu contenu représenté.                          *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
 
-            surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 1, 1);
-            *cr = cairo_create(surface);
-            cairo_surface_destroy(surface);
+static guint hash_line_token(const line_token_t *token)
+{
+    return token->hash;
 
-            cairo_select_font_face(*cr, "mono", s, w);
-            cairo_set_font_size(*cr, 13);
+}
 
-            cairo_text_extents(*cr, "A", &extents);
-            _seg_params.x_advances[CAIRO_FONT_INDEX(s, w)] = extents.x_advance;
 
-        }
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : token = premier fragment de texte à analyser.                *
+*                other = second fragment de texte à analyser.                 *
+*                                                                             *
+*  Description : Détermine si deux fragments de texte sont identiques.        *
+*                                                                             *
+*  Retour      : Bilan de la comparaison.                                     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
 
-    /* Fond d'impression */
+static bool is_line_token_equal(const line_token_t *token, const line_token_t *other)
+{
+    bool result;                            /* Résultat à retourner        */
 
-    _seg_params.selection_bg.has_color = true;
-    _seg_params.selection_bg.color.red = 0.5;
-    _seg_params.selection_bg.color.green = 0.5;
-    _seg_params.selection_bg.color.blue = 0.5;
-    _seg_params.selection_bg.color.alpha = 1.0;
+    result = (cmp_fnv_64a(token->hash, other->hash) == 0);
 
-    /* Chargement des définitions utiles */
+    if (result)
+        result = (token->length == other->length);
 
-    for (i = 0; i < RTT_COUNT; i++)
-        load_rendering_pattern(_segment_names[i], &_seg_params.patterns[i]);
+    if (result)
+        result = (token->tag == other->tag);
 
-    return true;
+    if (result)
+        result = (strncmp(token->text, other->text, token->length) == 0);
+
+    return result;
 
 }
 
 
-#endif
 
 
 
-/* ---------------------------------------------------------------------------------- */
-/*                         ISOLATION DE CONTENUS PARTAGEABLES                         */
-/* ---------------------------------------------------------------------------------- */
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : -                                                            *
+*  Paramètres  : token = fragment de texte à manipuler.                       *
+*                cr    = contexte graphique à utiliser pour les pinceaux.     *
+*                x     = abscisse du point d'impression (à maj). [OUT]        *
+*                y     = ordonnée du point d'impression.                      *
+*                style = style de rendu pour les bribes de texte.             *
 *                                                                             *
-*  Description : Initialise la table mémorisant les contenus pour segments.   *
+*  Description : Imprime le fragment de texte représenté.                     *
 *                                                                             *
-*  Retour      : Bilan de l'opération.                                        *
+*  Retour      : -                                                            *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-bool init_segment_content_hash_table(void)
+void draw_line_token(const line_token_t *token, cairo_t *cr, int *x, int y, const GTokenStyle *style)
 {
-    _segcnt_htable = g_hash_table_new_full((GHashFunc)get_line_segment_hash,
-                                           (GEqualFunc)is_line_segment_equal,
-                                           free, NULL);
-
-    return (_segcnt_htable != NULL);
+    g_token_style_draw_text(style, token->tag, cr, x, y, token->text, token->length);
 
 }
 
 
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : -                                                            *
-*                                                                             *
-*  Description : Organise la sortie de la table des contenus pour segments.   *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
 
-void exit_segment_content_hash_table(void)
-{
-    assert(g_hash_table_size(_segcnt_htable) == 0);
 
-    g_hash_table_unref(_segcnt_htable);
 
-}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                         ISOLATION DE CONTENUS PARTAGEABLES                         */
+/* ---------------------------------------------------------------------------------- */
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : content = contenu pour segment à consulter.                  *
+*  Paramètres  : -                                                            *
 *                                                                             *
-*  Description : Fournit l'empreinte d'un contenu pour segments.              *
+*  Description : Initialise la table mémorisant les contenus pour segments.   *
 *                                                                             *
-*  Retour      : Empreinte de lu contenu représenté.                          *
+*  Retour      : Bilan de l'opération.                                        *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static guint get_line_segment_hash(const line_segment *content)
+bool init_segment_content_hash_table(void)
 {
-    return content->hash;
+    _token_htable = g_hash_table_new_full((GHashFunc)hash_line_token,
+                                           (GEqualFunc)is_line_token_equal,
+                                           free, NULL);
+
+    return (_token_htable != NULL);
 
 }
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : content = premier contenu pour segment à analyser.           *
-*                other   = second contenu pour segment à analyser.            *
+*  Paramètres  : -                                                            *
 *                                                                             *
-*  Description : Détermine si deux contenus pour segments sont identiques.    *
+*  Description : Organise la sortie de la table des contenus pour segments.   *
 *                                                                             *
-*  Retour      : Bilan de la comparaison.                                     *
+*  Retour      : -                                                            *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static bool is_line_segment_equal(const line_segment *content, const line_segment *other)
+void exit_segment_content_hash_table(void)
 {
-    bool result;                            /* Résultat à retourner        */
-
-#ifdef INCLUDE_GTK_SUPPORT
-    result = (content->pattern == other->pattern);
-#else
-    result = (content->type == other->type);
-#endif
+    assert(g_hash_table_size(_token_htable) == 0);
 
-    if (result)
-        result = (cmp_fnv_64a(content->hash, other->hash) == 0);
-
-    if (result)
-        result = (strcmp(content->text, other->text) == 0);
-
-    return result;
+    g_hash_table_unref(_token_htable);
 
 }
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : content = premier contenu pour segment à analyser.           *
-*                other   = second contenu pour segment à analyser.            *
+*  Paramètres  : template = premier contenu pour segment à rechercher.        *
 *                                                                             *
-*  Description : Détermine si deux contenus pour segments sont identiques.    *
+*  Description : Fournit l'adresse d'un fragment de texte unique.             *
 *                                                                             *
 *  Retour      : Bilan de la comparaison.                                     *
 *                                                                             *
@@ -360,34 +312,34 @@ static bool is_line_segment_equal(const line_segment *content, const line_segmen
 *                                                                             *
 ******************************************************************************/
 
-static line_segment *get_shared_segment_content(const line_segment *content)
+static line_token_t *get_shared_line_token(const line_token_t *template)
 {
-    line_segment *result;                    /* Contenu partagé à renvoyer  */
+    line_token_t *result;                   /* Contenu partagé à renvoyer  */
     gboolean found;                         /* Le contenu existe déjà ?    */
     size_t allocated;                       /* Besoin complet en mémoire   */
 #ifndef NDEBUG
     gboolean created;                       /* Validation de mise en place */
 #endif
 
-    G_LOCK(_segcnt_mutex);
+    G_LOCK(_token_mutex);
 
-    found = g_hash_table_lookup_extended(_segcnt_htable, content, (gpointer *)&result, NULL);
+    found = g_hash_table_lookup_extended(_token_htable, template, (gpointer *)&result, NULL);
 
     if (!found)
     {
-        allocated = sizeof(line_segment) + strlen(content->text) + 1;
+        allocated = sizeof(line_token_t) + template->length + 1;
 
-        result = (line_segment *)malloc(allocated);
+        result = malloc(allocated);
 
-        memcpy(result, content, allocated);
+        memcpy(result, template, allocated);
 
         g_atomic_int_set(&result->ref_count, 1);
 
 #ifndef NDEBUG
-        created = g_hash_table_insert(_segcnt_htable, result, result);
+        created = g_hash_table_insert(_token_htable, result, result);
         assert(created);
 #else
-        g_hash_table_insert(_segcnt_htable, result, result);
+        g_hash_table_insert(_token_htable, result, result);
 #endif
 
     }
@@ -400,7 +352,7 @@ static line_segment *get_shared_segment_content(const line_segment *content)
 
     }
 
-    G_UNLOCK(_segcnt_mutex);
+    G_UNLOCK(_token_mutex);
 
     return result;
 
@@ -409,7 +361,7 @@ static line_segment *get_shared_segment_content(const line_segment *content)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : content = contenu pour segments à délaisser.                 *
+*  Paramètres  : token = fragment de texte à délaisser.                       *
 *                                                                             *
 *  Description : Abandonne un contenu pour segments.                          *
 *                                                                             *
@@ -419,24 +371,24 @@ static line_segment *get_shared_segment_content(const line_segment *content)
 *                                                                             *
 ******************************************************************************/
 
-static void release_shared_segment_content(line_segment *content)
+static void release_shared_line_token(line_token_t *token)
 {
 #ifndef NDEBUG
     gboolean deleted;                       /* Validation de suppression   */
 #endif
 
-    if (g_atomic_int_dec_and_test(&content->ref_count))
+    if (g_atomic_int_dec_and_test(&token->ref_count))
     {
-        G_LOCK(_segcnt_mutex);
+        G_LOCK(_token_mutex);
 
 #ifndef NDEBUG
-        deleted = g_hash_table_remove(_segcnt_htable, content);
+        deleted = g_hash_table_remove(_token_htable, token);
         assert(deleted);
 #else
-        g_hash_table_remove(_segcnt_htable, content);
+        g_hash_table_remove(_token_htable, token);
 #endif
 
-        G_UNLOCK(_segcnt_mutex);
+        G_UNLOCK(_token_mutex);
 
     }
 
@@ -445,59 +397,240 @@ static void release_shared_segment_content(line_segment *content)
 
 
 
+
+
+
+
+
+
+
+
+
+
+#if 0
+
+#include <assert.h>
+#include <limits.h>
+#include <malloc.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+#include "../common/extstr.h"
+//#include "../common/fnv1a.h"
+#include "../core/paths.h"
+#ifdef INCLUDE_GTK_SUPPORT
+#   include "../gtkext/rendering.h"
+#endif
+
+
+
+/* ------------------------ NATURE POUR UN FRAGMENT DE TEXTE ------------------------ */
+
+
+/* Nom des éléments CSS */
+
+#define SEGMENT_NAME(s) "token-" s
+
+static const char *_segment_names[RTT_COUNT] = {
+
+    [RTT_NONE]          = SEGMENT_NAME("none"),
+    [RTT_RAW]           = SEGMENT_NAME("raw"),
+    [RTT_RAW_FULL]      = SEGMENT_NAME("raw-full"),
+    [RTT_RAW_NULL]      = SEGMENT_NAME("raw-null"),
+    [RTT_PRINTABLE]     = SEGMENT_NAME("printable"),
+    [RTT_NOT_PRINTABLE] = SEGMENT_NAME("not-printable"),
+    [RTT_COMMENT]       = SEGMENT_NAME("comment"),
+    [RTT_INDICATION]    = SEGMENT_NAME("indication"),
+    [RTT_PHYS_ADDR_PAD] = SEGMENT_NAME("phys-addr-padding"),
+    [RTT_PHYS_ADDR]     = SEGMENT_NAME("phys-addr"),
+    [RTT_VIRT_ADDR_PAD] = SEGMENT_NAME("virt-addr-padding"),
+    [RTT_VIRT_ADDR]     = SEGMENT_NAME("virt-addr"),
+    [RTT_RAW_CODE]      = SEGMENT_NAME("raw-code"),
+    [RTT_RAW_CODE_NULL] = SEGMENT_NAME("raw-code-null"),
+    [RTT_LABEL]         = SEGMENT_NAME("label"),
+    [RTT_INSTRUCTION]   = SEGMENT_NAME("instruction"),
+    [RTT_IMMEDIATE]     = SEGMENT_NAME("immediate"),
+    [RTT_REGISTER]      = SEGMENT_NAME("register"),
+    [RTT_PUNCT]         = SEGMENT_NAME("punct"),
+    [RTT_HOOK]          = SEGMENT_NAME("hooks"),
+    [RTT_SIGNS]         = SEGMENT_NAME("signs"),
+    [RTT_LTGT]          = SEGMENT_NAME("ltgt"),
+    [RTT_SECTION]       = SEGMENT_NAME("section"),
+    [RTT_SEGMENT]       = SEGMENT_NAME("segment"),
+    [RTT_STRING]        = SEGMENT_NAME("string"),
+    [RTT_VAR_NAME]      = SEGMENT_NAME("var-name"),
+    [RTT_KEY_WORD]      = SEGMENT_NAME("keyword"),
+    [RTT_ERROR]         = SEGMENT_NAME("error"),
+
+};
+
+
+#ifdef INCLUDE_GTK_SUPPORT
+
+/* Compléments à Cairo */
+
+#define CAIRO_FONT_SLANT_COUNT  3
+#define CAIRO_FONT_WEIGHT_COUNT 2
+
+#define CAIRO_FONTS_COUNT (CAIRO_FONT_SLANT_COUNT * CAIRO_FONT_WEIGHT_COUNT)
+#define CAIRO_FONT_INDEX(s, w) ((s) + (w) * CAIRO_FONT_WEIGHT_COUNT)
+
+
+/* Propriétés de rendu */
+typedef struct _segment_rendering
+{
+    rendering_color_t selection_bg;         /* Fond d'impression           */
+
+    cairo_t *font_ctxts[CAIRO_FONTS_COUNT]; /* Contextes de police         */
+    double x_advances[CAIRO_FONTS_COUNT];   /* Largeurs par caractère      */
+
+    rendering_pattern_t patterns[RTT_COUNT];/* Modèles d'impression        */
+
+} segment_rendering;
+
+
+/* Configuration globale des rendus */
+static segment_rendering _seg_params;
+
+#endif
+
+
+
+/* ----------------------- ISOLATION DE CONTENUS PARTAGEABLES ----------------------- */
+
+
+/* Fragment de caractères aux propriétés potentiellement partagées */
+struct _line_segment
+{
+    gint ref_count;                         /* Compteur de références      */
+
+#ifdef INCLUDE_GTK_SUPPORT
+   rendering_pattern_t *pattern;           /* Propriétés du rendu         */
+#else
+    RenderingTagType type;                  /* Type de rendu attendu       */
+#endif
+
+    fnv64_t hash;                           /* Empreinte pour comparaisons */
+    char text[0];                           /* Texte brut conservé         */
+
+};
+
+
+
+/* Détermine si deux contenus pour segments sont identiques. */
+static line_segment *get_shared_segment_content(const line_segment *);
+
+/* Abandonne un contenu pour segments. */
+static void release_shared_segment_content(line_segment *);
+
+
+
+/* -------------------- GESTION OPTIMALE D'UNE LISTE DE CONTENUS -------------------- */
+
+
+#ifdef INCLUDE_GTK_SUPPORT
+
+/* Liste identifiant un ensemble de segments */
+struct _segcnt_list
+{
+    fnv64_t *hashes;                        /* Empreinte pour comparaisons */
+    size_t count;                           /* Nommbre de ces empreintes   */
+
+    unsigned int ref_count;                 /* Compteur de références      */
+
+};
+
+
+/* Indique si le contenu d'un segment est notable ou non. */
+bool selection_list_has_segment_content(const segcnt_list *, const line_segment *);
+
+#endif
+
+
+
 /* ---------------------------------------------------------------------------------- */
-/*                      NATURE DE BASE POUR UN FRAGMENT DE TEXTE                      */
+/*                          NATURE POUR UN FRAGMENT DE TEXTE                          */
 /* ---------------------------------------------------------------------------------- */
 
 
+#ifdef INCLUDE_GTK_SUPPORT
+
+
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : type   = propriétés de la zone de texte.                     *
-*                text   = chaîne de caractères à traiter.                     *
-*                length = quantité de ces caractères.                         *
+*  Paramètres  : -                                                            *
 *                                                                             *
-*  Description : Crée un nouveau fragment de texte avec des propriétés.       *
+*  Description : Procède à l'initialisation des paramètres de rendu de texte. *
 *                                                                             *
-*  Retour      : Elément créé ou recyclé.                                     *
+*  Retour      : -                                                            *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-line_segment *get_new_line_segment(RenderingTagType type, const char *text, size_t length)
+bool load_segment_rendering_parameters(void)
 {
-    line_segment *result;                   /* Elément à retourner         */
-    char atmp[sizeof(line_segment) + 128];  /* Allocation static facile    */
-    line_segment *content;                  /* Contenu à mettre en place ? */
+    cairo_font_slant_t s;                   /* Boucle de parcours #1       */
+    cairo_font_weight_t w;                  /* Boucle de parcours #2       */
+    cairo_t **cr;                           /* Contexte à créer            */
+    cairo_surface_t *surface;               /* Surface pour dessin Cairo   */
+    cairo_text_extents_t extents;           /* Couverture des caractères   */
+    RenderingTagType i;                     /* Boucle de parcours          */
 
-    assert(length > 0);
+    /* Contextes pour les mesures initiales */
 
-    if (length < (sizeof(atmp) - sizeof(line_segment)))
-        content = (line_segment *)atmp;
-    else
-        content = (line_segment *)malloc(sizeof(line_segment) + length + 1);
+    for (s = CAIRO_FONT_SLANT_NORMAL; s < CAIRO_FONT_SLANT_COUNT; s++)
+        for (w = CAIRO_FONT_WEIGHT_NORMAL; w < CAIRO_FONT_WEIGHT_COUNT; w++)
+        {
+            cr = &_seg_params.font_ctxts[CAIRO_FONT_INDEX(s, w)];
 
-#ifdef INCLUDE_GTK_SUPPORT
-    content->pattern = &_seg_params.patterns[type];
-#else
-    content->type = type;
-#endif
+            surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 1, 1);
+            *cr = cairo_create(surface);
+            cairo_surface_destroy(surface);
 
-    content->hash = fnv_64a_hash(text);
+            cairo_select_font_face(*cr, "mono", s, w);
+            cairo_set_font_size(*cr, 13);
 
-    memcpy(content->text, text, length);
-    content->text[length] = '\0';
+            cairo_text_extents(*cr, "A", &extents);
+            _seg_params.x_advances[CAIRO_FONT_INDEX(s, w)] = extents.x_advance;
 
-    result = get_shared_segment_content(content);
+        }
 
-    if (content != (line_segment *)atmp)
-        free(content);
+    /* Fond d'impression */
 
-    return result;
+    _seg_params.selection_bg.has_color = true;
+    _seg_params.selection_bg.color.red = 0.5;
+    _seg_params.selection_bg.color.green = 0.5;
+    _seg_params.selection_bg.color.blue = 0.5;
+    _seg_params.selection_bg.color.alpha = 1.0;
+
+    /* Chargement des définitions utiles */
+
+    for (i = 0; i < RTT_COUNT; i++)
+        load_rendering_pattern(_segment_names[i], &_seg_params.patterns[i]);
+
+    return true;
 
 }
 
 
+#endif
+
+
+
+
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                      NATURE DE BASE POUR UN FRAGMENT DE TEXTE                      */
+/* ---------------------------------------------------------------------------------- */
+
+
+
+
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : segment = fragment de texte à traiter.                       *
@@ -555,7 +688,7 @@ RenderingTagType get_line_segment_type(const line_segment *segment)
 #ifdef INCLUDE_GTK_SUPPORT
     result = (RenderingTagType)(segment->pattern - _seg_params.patterns);
 #else
-    result = segment->type;
+    result = segment->tag;
 #endif
 
     return result;
@@ -1204,3 +1337,5 @@ bool selection_list_has_segment_content(const segcnt_list *list, const line_segm
 
 
 #endif
+
+#endif
diff --git a/src/glibext/linetoken.h b/src/glibext/linetoken.h
index 4e06f8c..25c93ed 100644
--- a/src/glibext/linetoken.h
+++ b/src/glibext/linetoken.h
@@ -1,6 +1,6 @@
 
 /* Chrysalide - Outil d'analyse de fichiers binaires
- * linesegment.h - prototypes pour la concentration d'un fragment de caractères aux propriétés communes
+ * linetoken.h - prototypes pour la concentration d'un fragment de caractères aux propriétés communes
  *
  * Copyright (C) 2016-2019 Cyrille Bagard
  *
@@ -21,12 +21,61 @@
  */
 
 
-#ifndef _GLIBEXT_LINESEGMENT_H
-#define _GLIBEXT_LINESEGMENT_H
+#ifndef _GLIBEXT_LINETOKEN_H
+#define _GLIBEXT_LINETOKEN_H
 
 
-#include <glib-object.h>
 #include <stdbool.h>
+
+
+#include "tokenstyle.h"
+
+
+
+/* -------------------- NATURE DE BASE POUR UN FRAGMENT DE TEXTE -------------------- */
+
+
+/* Fragment de caractères aux propriétés potentiellement partagées */
+typedef struct _line_token_t line_token_t;
+
+
+/* Crée un nouveau fragment de texte avec des propriétés. */
+line_token_t *get_new_line_token(TokenRenderingTag, const char *, size_t);
+
+/* Augmente le compteur de références d'un fragment de texte. */
+void ref_line_token(line_token_t *);
+
+/* Retire une utilisation à un fragment de texte. */
+void release_line_token(line_token_t *);
+
+
+
+
+
+
+
+/* ----------------------- ISOLATION DE CONTENUS PARTAGEABLES ----------------------- */
+
+
+/* Initialise la table mémorisant les contenus pour segments. */
+bool init_segment_content_hash_table(void);
+
+/* Organise la sortie de la table des contenus pour segments. */
+void exit_segment_content_hash_table(void);
+
+
+
+/* Imprime le fragment de texte représenté. */
+void draw_line_token(const line_token_t *, cairo_t *, int *, int, const GTokenStyle *);
+
+
+
+
+
+
+#if 0
+
+#include <glib-object.h>
 #ifdef INCLUDE_GTK_SUPPORT
 #   include <gdk/gdk.h>
 #   include <pango/pango.h>
@@ -58,14 +107,14 @@ bool load_segment_rendering_parameters(void);
 
 
 /* Fragment de caractères aux propriétés potentiellement partagées */
-typedef struct _line_segment line_segment;
+//typedef struct _line_segment line_segment;
 
 
 /* Initialise la table mémorisant les contenus pour segments. */
-bool init_segment_content_hash_table(void);
+//bool init_segment_content_hash_table(void);
 
 /* Organise la sortie de la table des contenus pour segments. */
-void exit_segment_content_hash_table(void);
+//void exit_segment_content_hash_table(void);
 
 
 
@@ -74,13 +123,13 @@ void exit_segment_content_hash_table(void);
 
 
 /* Crée un nouveau fragment de texte avec des propriétés. */
-line_segment *get_new_line_segment(RenderingTagType, const char *, size_t);
+//line_segment *get_new_line_segment(RenderingTagType, const char *, size_t);
 
 /* Augmente le compteur de références d'un fragment de texte. */
-void ref_line_segment(line_segment *);
+//void ref_line_segment(line_segment *);
 
 /* Retire une utilisation à un fragment de texte. */
-void release_line_segment(line_segment *);
+//void release_line_segment(line_segment *);
 
 /* Indique le type de rendu associé à un segment de ligne. */
 RenderingTagType get_line_segment_type(const line_segment *);
@@ -100,7 +149,7 @@ gint get_caret_position_from_line_segment(const line_segment *, gint);
 bool move_caret_on_line_segment(const line_segment *, gint *, bool, GdkScrollDirection);
 
 /* Imprime le fragment de texte représenté. */
-void draw_line_segment(const line_segment *, cairo_t *, gint *, gint, const segcnt_list *);
+//void draw_line_segment(const line_segment *, cairo_t *, gint *, gint, const segcnt_list *);
 
 #endif
 
@@ -174,6 +223,7 @@ bool add_segment_content_to_selection_list(segcnt_list *, const line_segment *);
 
 #endif
 
+#endif
 
 
-#endif  /* _GLIBEXT_LINESEGMENT_H */
+#endif  /* _GLIBEXT_LINETOKEN_H */
diff --git a/src/glibext/options/hex.c b/src/glibext/options/hex.c
index 5804a57..ab461a7 100644
--- a/src/glibext/options/hex.c
+++ b/src/glibext/options/hex.c
@@ -101,7 +101,7 @@ static void g_hex_options_init(GHexOptions *options)
 #endif
                              (const char *[]) { _("Offset") },
                              (const bool []) { true },
-                             1);
+                             HCO_COUNT);
 
     assert(status);
 
diff --git a/src/glibext/options/hex.h b/src/glibext/options/hex.h
index 48ce942..0d187dc 100644
--- a/src/glibext/options/hex.h
+++ b/src/glibext/options/hex.h
@@ -29,6 +29,16 @@
 
 
 
+/* Liste des colonnes en options */
+typedef enum _HexColumnOptions
+{
+    HCO_OFFSET,                             /* Position                    */
+
+    HCO_COUNT
+
+} HexColumnOptions;
+
+
 #define G_TYPE_HEX_OPTIONS (g_hex_options_get_type())
 
 DECLARE_GTYPE(GHexOptions, g_hex_options, G, HEX_OPTIONS);
diff --git a/src/glibext/tokenstyle.c b/src/glibext/tokenstyle.c
index e797856..df1d42a 100644
--- a/src/glibext/tokenstyle.c
+++ b/src/glibext/tokenstyle.c
@@ -25,6 +25,7 @@
 #include "tokenstyle.h"
 
 
+#include <math.h>
 #include <string.h>
 
 
@@ -60,34 +61,35 @@ static void g_token_style_finalize(GTokenStyle *);
 
 static const char *_token_names[TRT_COUNT] = {
 
-    [TRT_NONE]          = SEGMENT_NAME("none"),
-    [TRT_RAW]           = SEGMENT_NAME("raw"),
-    [TRT_RAW_FULL]      = SEGMENT_NAME("raw-full"),
-    [TRT_RAW_NULL]      = SEGMENT_NAME("raw-null"),
-    [TRT_PRINTABLE]     = SEGMENT_NAME("printable"),
-    [TRT_NOT_PRINTABLE] = SEGMENT_NAME("not-printable"),
-    [TRT_COMMENT]       = SEGMENT_NAME("comment"),
-    [TRT_INDICATION]    = SEGMENT_NAME("indication"),
-    [TRT_PHYS_ADDR_PAD] = SEGMENT_NAME("phys-addr-padding"),
-    [TRT_PHYS_ADDR]     = SEGMENT_NAME("phys-addr"),
-    [TRT_VIRT_ADDR_PAD] = SEGMENT_NAME("virt-addr-padding"),
-    [TRT_VIRT_ADDR]     = SEGMENT_NAME("virt-addr"),
-    [TRT_RAW_CODE]      = SEGMENT_NAME("raw-code"),
-    [TRT_RAW_CODE_NULL] = SEGMENT_NAME("raw-code-null"),
-    [TRT_LABEL]         = SEGMENT_NAME("label"),
-    [TRT_INSTRUCTION]   = SEGMENT_NAME("instruction"),
-    [TRT_IMMEDIATE]     = SEGMENT_NAME("immediate"),
-    [TRT_REGISTER]      = SEGMENT_NAME("register"),
-    [TRT_PUNCT]         = SEGMENT_NAME("punct"),
-    [TRT_HOOK]          = SEGMENT_NAME("hooks"),
-    [TRT_SIGNS]         = SEGMENT_NAME("signs"),
-    [TRT_LTGT]          = SEGMENT_NAME("ltgt"),
-    [TRT_SECTION]       = SEGMENT_NAME("section"),
-    [TRT_SEGMENT]       = SEGMENT_NAME("segment"),
-    [TRT_STRING]        = SEGMENT_NAME("string"),
-    [TRT_VAR_NAME]      = SEGMENT_NAME("var-name"),
-    [TRT_KEY_WORD]      = SEGMENT_NAME("keyword"),
-    [TRT_ERROR]         = SEGMENT_NAME("error"),
+    [TRT_NONE]              = SEGMENT_NAME("none"),
+    [TRT_RAW_PRINTABLE]     = SEGMENT_NAME("raw-printable"),
+    [TRT_RAW_NOT_PRINTABLE] = SEGMENT_NAME("raw-not-printable"),
+    [TRT_RAW_FULL]          = SEGMENT_NAME("raw-full"),
+    [TRT_RAW_NULL]          = SEGMENT_NAME("raw-null"),
+    [TRT_CHR_PRINTABLE]     = SEGMENT_NAME("chr-printable"),
+    [TRT_CHR_NOT_PRINTABLE] = SEGMENT_NAME("chr-not-printable"),
+    [TRT_COMMENT]           = SEGMENT_NAME("comment"),
+    [TRT_INDICATION]        = SEGMENT_NAME("indication"),
+    [TRT_PHYS_ADDR_PAD]     = SEGMENT_NAME("phys-addr-padding"),
+    [TRT_PHYS_ADDR]         = SEGMENT_NAME("phys-addr"),
+    [TRT_VIRT_ADDR_PAD]     = SEGMENT_NAME("virt-addr-padding"),
+    [TRT_VIRT_ADDR]         = SEGMENT_NAME("virt-addr"),
+    [TRT_RAW_CODE]          = SEGMENT_NAME("raw-code"),
+    [TRT_RAW_CODE_NULL]     = SEGMENT_NAME("raw-code-null"),
+    [TRT_LABEL]             = SEGMENT_NAME("label"),
+    [TRT_INSTRUCTION]       = SEGMENT_NAME("instruction"),
+    [TRT_IMMEDIATE]         = SEGMENT_NAME("immediate"),
+    [TRT_REGISTER]          = SEGMENT_NAME("register"),
+    [TRT_PUNCT]             = SEGMENT_NAME("punct"),
+    [TRT_HOOK]              = SEGMENT_NAME("hooks"),
+    [TRT_SIGNS]             = SEGMENT_NAME("signs"),
+    [TRT_LTGT]              = SEGMENT_NAME("ltgt"),
+    [TRT_SECTION]           = SEGMENT_NAME("section"),
+    [TRT_SEGMENT]           = SEGMENT_NAME("segment"),
+    [TRT_STRING]            = SEGMENT_NAME("string"),
+    [TRT_VAR_NAME]          = SEGMENT_NAME("var-name"),
+    [TRT_KEY_WORD]          = SEGMENT_NAME("keyword"),
+    [TRT_ERROR]             = SEGMENT_NAME("error"),
 
 };
 
@@ -272,12 +274,35 @@ bool g_token_style_create(GTokenStyle *style, GtkWidget *target)
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : style  = gestionnaire de paramètres de rendu à consulter.    *
+*                                                                             *
+*  Description : Fournit la quantité de pixels requise pour une ligne.        *
+*                                                                             *
+*  Retour      : Hauteur de chaque ligne de rendu, en pixels.                 *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+int g_token_style_get_line_height(const GTokenStyle *style)
+{
+    int result;                             /* Hauteur à retourner         */
+
+    result = style->font_extents.height;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : style  = gestionnaire de paramètres de rendu à consulter.    *
 *                tag    = type de rendu sollicité.                            *
 *                length = nombre de caractères à mesurer.                     *
 *                                                                             *
 *  Description : Fournit la quantité de pixels requise pour l'impression.     *
 *                                                                             *
-*  Retour      : Largeur requise par la colonne, en pixel.                    *
+*  Retour      : Largeur requise par la colonne, en pixels.                   *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
@@ -325,6 +350,13 @@ void g_token_style_draw_text(const GTokenStyle *style, TokenRenderingTag tag, ca
     cairo_operator_t old;                   /* Sauvegarde avant changement */
     const rendering_property_t *prop;       /* Motif de rendu visé         */
 
+    /* Cas particulier d'une tabulation */
+    if (length == 1 && (text[0] == '\t' || text[0] == ' '))
+    {
+        width = g_token_style_measure_width(style, tag, text[0] == '\t' ? TAB_SIZE : 1);
+        goto small_sep;
+    }
+
     selected = false;//selection_list_has_segment_content(list, segment);
 
     width = g_token_style_measure_width(style, tag, length);
@@ -378,6 +410,8 @@ void g_token_style_draw_text(const GTokenStyle *style, TokenRenderingTag tag, ca
 
     cairo_show_text(cr, text);
 
+ small_sep:
+
     *x += width;
 
 }
@@ -467,6 +501,56 @@ char *g_token_style_append_markup(const GTokenStyle *style, char *base, TokenRen
 }
 
 
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : style = gestionnaire de paramètres de rendu à consulter.     *
+*                max   = valeur maximale atteignable.                         *
+*                virt  = indique une position virtuelle et non physique.      *
+*                                                                             *
+*  Description : Détermine une taille de localisation, physique ou virtuelle. *
+*                                                                             *
+*  Retour      : Largeur minimale à observer en pixels.                       *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+int g_token_style_compute_location_width(const GTokenStyle *style, uint64_t max, bool virt)
+{
+    int result;                             /* Taille à retourner          */
+    double n;                               /* Nombre de chiffres hexa     */
+    double c;                               /* Valeur ajustée              */
+    TokenRenderingTag tag;                  /* Type de représentation      */
+
+    /**
+     * Les situations suivantes ont été évaluées :
+     *
+     *          max        |     n    |  c
+     *   -----------------------------------
+     *                   0 |  0       |  0
+     *                   1 |  0,25    |  1
+     *                   f |  1       |  1
+     *                  10 |  1,02187 |  2
+     *                  11 |  1,04248 |  2
+     *                  ff |  2       |  2
+     *                 100 |  2,00141 |  3
+     *            ffffffff |  8       |  8
+     *    ffffffffffffffff | 16       | 16
+     */
+
+    n = log1p(max) / log(16);
+
+    c = ceil(n);
+
+    tag = virt ? TRT_VIRT_ADDR : TRT_PHYS_ADDR;
+
+    result = g_token_style_measure_width(style, tag, c);
+
+    return result;
+
+}
+
+
 
 /* ---------------------------------------------------------------------------------- */
 /*                          RECEPTACLES DE SIGNAUX CONNECTES                          */
diff --git a/src/glibext/tokenstyle.css b/src/glibext/tokenstyle.css
index 0cf9f37..6fb78aa 100644
--- a/src/glibext/tokenstyle.css
+++ b/src/glibext/tokenstyle.css
@@ -6,21 +6,30 @@
 }
 
 
+.token-raw-printable,
+.token-chr-printable {
 
+    color: white;
+
+}
+
+.token-raw-not-printable,
+.token-chr-not-printable {
+
+    color: #bbbbbb;
+
+}
 
 .token-raw-full {
 
     color: white;
 
-    font-style: italic;
     font-weight: bold;
 
 }
 
 .token-raw-null {
 
-    color: black;
-
-    background-color: pink;
+    color: #666666;
 
 }
diff --git a/src/glibext/tokenstyle.h b/src/glibext/tokenstyle.h
index 923b725..2e19b51 100644
--- a/src/glibext/tokenstyle.h
+++ b/src/glibext/tokenstyle.h
@@ -26,6 +26,8 @@
 #define _GLIBEXT_TOKENSTYLE_H
 
 
+#include <stdbool.h>
+#include <stdint.h>
 #include <gtk/gtk.h>
 
 
@@ -38,11 +40,12 @@ typedef enum _TokenRenderingTag
 {
     TRT_NONE,                               /* Espace ou tabulation        */
 
-    TRT_RAW,                                /* Contenu brut                */
+    TRT_RAW_PRINTABLE,                      /* Contenu brut                */
+    TRT_RAW_NOT_PRINTABLE,                  /* Contenu brut                */
     TRT_RAW_FULL,                           /* Contenu brut et complet     */
     TRT_RAW_NULL,                           /* Contenu brut et nul         */
-    TRT_PRINTABLE,                          /* Caractère imprimable        */
-    TRT_NOT_PRINTABLE,                      /* Caractère non imprimable    */
+    TRT_CHR_PRINTABLE,                      /* Caractère imprimable        */
+    TRT_CHR_NOT_PRINTABLE,                  /* Caractère non imprimable    */
 
     TRT_COMMENT,                            /* Commentaire                 */
     TRT_INDICATION,                         /* Aide à la lecture           */
@@ -82,6 +85,10 @@ typedef enum _TokenRenderingTag
 } TokenRenderingTag;
 
 
+/* Caractères par tabulation */
+#define TAB_SIZE 2
+
+
 #define G_TYPE_TOKEN_STYLE (g_token_style_get_type())
 
 DECLARE_GTYPE(GTokenStyle, g_token_style, G, TOKEN_STYLE);
@@ -90,6 +97,9 @@ DECLARE_GTYPE(GTokenStyle, g_token_style, G, TOKEN_STYLE);
 /* Crée un gestionnaire de style pour le rendu des lignes. */
 GTokenStyle *g_token_style_new(GtkWidget *);
 
+/* Fournit la quantité de pixels requise pour une ligne. */
+int g_token_style_get_line_height(const GTokenStyle *);
+
 /* Fournit la quantité de pixels requise pour l'impression. */
 int g_token_style_measure_width(const GTokenStyle *, TokenRenderingTag, size_t);
 
@@ -102,6 +112,9 @@ char *g_token_style_build_markup(const GTokenStyle *, TokenRenderingTag, const c
 /* Ajoute du texte enjolivé selon un élément de thème. */
 char *g_token_style_append_markup(const GTokenStyle *, char *, TokenRenderingTag, const char *);
 
+/* Détermine une taille de localisation, physique ou virtuelle. */
+int g_token_style_compute_location_width(const GTokenStyle *, uint64_t, bool);
+
 
 
 #endif  /* _GLIBEXT_TOKENSTYLE_H */
diff --git a/src/glibext/widthtracker-int.h b/src/glibext/widthtracker-int.h
new file mode 100644
index 0000000..50f5757
--- /dev/null
+++ b/src/glibext/widthtracker-int.h
@@ -0,0 +1,80 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * widthtracker-int.h - prototypes internes pour le suivi des largeurs associées à un ensemble de lignes
+ *
+ * Copyright (C) 2016-2024 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Chrysalide is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GLIBEXT_WIDTHTRACKER_INT_H
+#define _GLIBEXT_WIDTHTRACKER_INT_H
+
+
+#include "widthtracker.h"
+
+
+
+/* Portions de largeurs communes */
+typedef struct _common_metrics_t
+{
+    size_t first;                           /* Premier indice de portion   */
+    size_t last;                            /* Dernier indice de portion   */
+
+    size_t merging_index;                   /* Indice de colonne de fusion */
+
+    int *summary;                           /* Compilation de largeurs     */
+    bool cached;                            /* Mise en cache des calculs   */
+
+} common_metrics_t;
+
+
+/* Gestionnaire de largeurs associées aux lignes (instance) */
+struct _GWidthTracker
+{
+    GObject parent;                         /* A laisser en premier        */
+
+    GBufferCache *cache;                    /* Ensemble complet de lignes  */
+    size_t opt_count;                       /* Qté de colonnes en option   */
+    size_t reg_count;                       /* Nombre de colonnes normales */
+#ifndef NDEBUG
+    size_t col_count;                       /* Nombre maximum de colonnes  */
+#endif
+
+    common_metrics_t *locals;               /* Portions représentées       */
+    size_t count;                           /* Quantité de ces portions    */
+
+    int *min_widths;                        /* Largeurs requises suivies   */
+    bool *fixed;                            /* Indication d'impositions    */
+    bool cached;                            /* Mise en cache des calculs   */
+
+};
+
+/* Gestionnaire de largeurs associées aux lignes (classe) */
+struct _GWidthTrackerClass
+{
+    GObjectClass parent;                    /* A laisser en premier        */
+
+};
+
+
+/* Met en place un nouveau suivi de largeurs au sein de lignes. */
+bool g_width_tracker_create(GWidthTracker *, GBufferCache *);
+
+
+
+#endif  /* _GLIBEXT_WIDTHTRACKER_INT_H */
diff --git a/src/glibext/widthtracker.c b/src/glibext/widthtracker.c
index bfeb32c..7e06578 100644
--- a/src/glibext/widthtracker.c
+++ b/src/glibext/widthtracker.c
@@ -26,6 +26,331 @@
 
 #include <assert.h>
 #include <malloc.h>
+
+
+#include "widthtracker-int.h"
+
+
+
+/* ---------------------------- PRISE DE MESURES LOCALES ---------------------------- */
+
+
+/* Supprime de la mémoire une collecte de mesures locales. */
+static void delete_common_metrics(common_metrics_t *);
+
+
+
+/* ---------------------------- RASSEMBLEMENT DE MESURES ---------------------------- */
+
+
+/* Procède à l'initialisation d'une classe de suivi de largeurs. */
+static void g_width_tracker_class_init(GWidthTrackerClass *);
+
+/* Procède à l'initialisation d'un suivi de largeurs de lignes. */
+static void g_width_tracker_init(GWidthTracker *);
+
+/* Supprime toutes les références externes. */
+static void g_width_tracker_dispose(GWidthTracker *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_width_tracker_finalize(GWidthTracker *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                              PRISE DE MESURES LOCALES                              */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : metrics = mesures locales conservées.                        *
+*                                                                             *
+*  Description : Supprime de la mémoire une collecte de mesures locales.      *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void delete_common_metrics(common_metrics_t *metrics)
+{
+    free(metrics->summary);
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                              RASSEMBLEMENT DE MESURES                              */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Détermine le type du gestionnaire de largeurs associées aux lignes. */
+G_DEFINE_TYPE(GWidthTracker, g_width_tracker, G_TYPE_OBJECT);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : class = classe de composant GLib à initialiser.              *
+*                                                                             *
+*  Description : Procède à l'initialisation d'une classe de suivi de largeurs.*
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_width_tracker_class_init(GWidthTrackerClass *class)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+
+    object = G_OBJECT_CLASS(class);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_width_tracker_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_width_tracker_finalize;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : tracker = composant GLib à initialiser.                      *
+*                                                                             *
+*  Description : Procède à l'initialisation d'un suivi de largeurs de lignes. *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_width_tracker_init(GWidthTracker *tracker)
+{
+    tracker->cache = NULL;
+    tracker->opt_count = 0;
+    tracker->reg_count = 0;
+
+    tracker->locals = NULL;
+    tracker->count = 0;
+
+    tracker->min_widths = NULL;
+    tracker->fixed = NULL;
+    tracker->cached = false;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : tracker = instance d'objet GLib à traiter.                   *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_width_tracker_dispose(GWidthTracker *tracker)
+{
+    g_clear_object(&tracker->cache);
+
+    G_OBJECT_CLASS(g_width_tracker_parent_class)->dispose(G_OBJECT(tracker));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : tracker = instance d'objet GLib à traiter.                   *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_width_tracker_finalize(GWidthTracker *tracker)
+{
+    size_t i;                               /* Boucle de parcours          */
+
+    for (i = 0; i < tracker->count; i++)
+        delete_common_metrics(&tracker->locals[i]);
+
+    if (tracker->locals != NULL)
+        free(tracker->locals);
+
+    if (tracker->min_widths != NULL)
+        free(tracker->min_widths);
+
+    if (tracker->fixed != NULL)
+        free(tracker->fixed);
+
+    G_OBJECT_CLASS(g_width_tracker_parent_class)->finalize(G_OBJECT(tracker));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : cache = tampon de lignes à lier au futur collecteur.         *
+*                                                                             *
+*  Description : Crée un nouveau suivi de largeurs au sein de lignes.         *
+*                                                                             *
+*  Retour      : Composant GLib créé.                                         *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GWidthTracker *g_width_tracker_new(GBufferCache *cache)
+{
+    GWidthTracker *result;                  /* Composant à retourner       */
+
+    result = g_object_new(G_TYPE_WIDTH_TRACKER, NULL);
+
+    if (!g_width_tracker_create(result, cache))
+        g_clear_object(&result);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : tracker = collecteur de largeur à initialiser pleinement.    *
+*                cache   = tampon de lignes à lier au futur élément.          *
+*                                                                             *
+*  Description : Met en place un nouveau suivi de largeurs au sein de lignes. *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_width_tracker_create(GWidthTracker *tracker, GBufferCache *cache)
+{
+    bool result;                            /* Bilen à retourner           */
+    size_t col_count;                       /* Nombre maximum de colonnes  */
+
+    result = true;
+
+    tracker->cache = cache;
+    ref_object(cache);
+
+    g_buffer_cache_count_columns(cache, &tracker->opt_count, &tracker->reg_count);
+
+    col_count = tracker->opt_count + tracker->reg_count;
+
+#ifndef NDEBUG
+    tracker->col_count = col_count;
+#endif
+
+    tracker->min_widths = malloc(col_count * sizeof(int));
+    tracker->fixed = calloc(col_count, sizeof(bool));
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : tracker = gestionnaire de largeurs de lignes à mettre jour.  *
+*                col     = indice de colonne visée.                           *
+*                                                                             *
+*  Description : Indique la largeur minimale pour une colonne donnée.         *
+*                                                                             *
+*  Retour      : Largeur minimale à imposée, nulle ou positive.               *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+int g_width_tracker_get_column_min_width(const GWidthTracker *tracker, size_t col)
+{
+    int result;                             /* Largeur à renvoyer          */
+
+    assert(col < tracker->col_count);
+
+    result = tracker->min_widths[col];
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : tracker = gestionnaire de largeurs de lignes à mettre jour.  *
+*                col     = indice de colonne visée.                           *
+*                width   = largeur minimale à imposer.                        *
+*                                                                             *
+*  Description : Impose une largeur minimale pour une colonne donnée.         *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_width_tracker_set_column_min_width(GWidthTracker *tracker, size_t col, int width)
+{
+    assert(col < tracker->col_count);
+
+    if (width < 0)
+        width = 0;
+
+    tracker->min_widths[col] = width;
+    tracker->fixed[col] = true;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : tracker = gestionnaire de largeurs de lignes à consulter.    *
+*                width   = largeur requise pour un affichage complet. [OUT]   *
+*                                                                             *
+*  Description : Détermine la largeur nécessaire à une pleine représentation. *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_width_tracker_compute_width(const GWidthTracker *tracker, int *width)
+{
+    size_t i;                               /* Boucle de parcours          */
+
+    *width = 0;
+
+    // FIX access to col_count
+
+    for (i = 0; i < tracker->col_count; i++)
+        *width += tracker->min_widths[i];
+
+}
+
+
+
+
+
+
+#if 0
+
+
+//#include <assert.h>
+//#include <malloc.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -33,7 +358,7 @@
 #include <i18n.h>
 
 
-#include "buffercache.h"
+//#include "buffercache.h"
 #include "delayed-int.h"
 #include "../core/global.h"
 #include "../core/nproc.h"
@@ -104,56 +429,7 @@ static void g_width_update_collect(GWidthUpdate *, line_width_summary *);
 /* ---------------------------- RASSEMBLEMENT DE MESURES ---------------------------- */
 
 
-/* Portions de largeurs communes */
-typedef struct _common_metrics
-{
-    size_t first;                           /* Premier indice de portion   */
-    size_t last;                            /* Dernier indice de portion   */
-
-    line_width_summary summary;             /* Compilation de largeurs     */
-    bool cached;                            /* Mise en cache des calculs   */
-
-} common_metrics;
-
-
-/* Gestionnaire de largeurs associées aux lignes (instance) */
-struct _GWidthTracker
-{
-    GObject parent;                         /* A laisser en premier        */
-
-    GBufferCache *cache;                    /* Ensemble complet de lignes  */
-    size_t col_count;                       /* Nombre maximum de colonnes  */
-    size_t opt_count;                       /* Qté de colonnes en option   */
-
-    common_metrics *portions;               /* Portions représentées       */
-    size_t count;                           /* Quantité de ces portions    */
-
-    gint *min_widths;                       /* Largeurs min. à respecter   */
-
-    line_width_summary summary;             /* Largeurs requises suivies   */
-    bool cached;                            /* Mise en cache des calculs   */
-
-};
-
-/* Gestionnaire de largeurs associées aux lignes (classe) */
-struct _GWidthTrackerClass
-{
-    GObjectClass parent;                    /* A laisser en premier        */
-
-};
-
-
-/* Procède à l'initialisation d'une classe de suivi de largeurs. */
-static void g_width_tracker_class_init(GWidthTrackerClass *);
-
-/* Procède à l'initialisation d'un suivi de largeurs de lignes. */
-static void g_width_tracker_init(GWidthTracker *);
 
-/* Supprime toutes les références externes. */
-static void g_width_tracker_dispose(GWidthTracker *);
-
-/* Procède à la libération totale de la mémoire. */
-static void g_width_tracker_finalize(GWidthTracker *);
 
 /* Recherche la portion contenant un indice de ligne donné. */
 static size_t g_width_tracker_find_metrics(const GWidthTracker *, size_t);
@@ -375,131 +651,6 @@ static void g_width_update_collect(GWidthUpdate *update, line_width_summary *glo
 /* ---------------------------------------------------------------------------------- */
 
 
-/* Détermine le type du gestionnaire de largeurs associées aux lignes. */
-G_DEFINE_TYPE(GWidthTracker, g_width_tracker, G_TYPE_OBJECT);
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : class = classe de composant GTK à initialiser.               *
-*                                                                             *
-*  Description : Procède à l'initialisation d'une classe de suivi de largeurs.*
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void g_width_tracker_class_init(GWidthTrackerClass *class)
-{
-    GObjectClass *object;                   /* Autre version de la classe  */
-
-    object = G_OBJECT_CLASS(class);
-
-    object->dispose = (GObjectFinalizeFunc/* ! */)g_width_tracker_dispose;
-    object->finalize = (GObjectFinalizeFunc)g_width_tracker_finalize;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : tracker = composant GLib à initialiser.                      *
-*                                                                             *
-*  Description : Procède à l'initialisation d'un suivi de largeurs de lignes. *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void g_width_tracker_init(GWidthTracker *tracker)
-{
-    tracker->portions = NULL;
-    tracker->count = 0;
-
-    memset(&tracker->summary, 0, sizeof(line_width_summary));
-    tracker->cached = false;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : tracker = instance d'objet GLib à traiter.                   *
-*                                                                             *
-*  Description : Supprime toutes les références externes.                     *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void g_width_tracker_dispose(GWidthTracker *tracker)
-{
-    g_object_unref(G_OBJECT(tracker->cache));
-
-    G_OBJECT_CLASS(g_width_tracker_parent_class)->dispose(G_OBJECT(tracker));
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : tracker = instance d'objet GLib à traiter.                   *
-*                                                                             *
-*  Description : Procède à la libération totale de la mémoire.                *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void g_width_tracker_finalize(GWidthTracker *tracker)
-{
-    if (tracker->min_widths != NULL)
-        free(tracker->min_widths);
-
-    G_OBJECT_CLASS(g_width_tracker_parent_class)->finalize(G_OBJECT(tracker));
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : cache     = tampon de lignes à lier au futur élément.        *
-*                col_count = quantité maximale de colonnes à considérer.      *
-*                opt_count = quantité de colonnes optionnelles.               *
-*                                                                             *
-*  Description : Crée un nouveau suivi de largeurs au sein de lignes.         *
-*                                                                             *
-*  Retour      : Composant GLib créé.                                         *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-GWidthTracker *g_width_tracker_new(GBufferCache *cache, size_t col_count, size_t opt_count)
-{
-    GWidthTracker *result;                  /* Composant à retourner       */
-
-    result = g_object_new(G_TYPE_WIDTH_TRACKER, NULL);
-
-    g_object_ref(G_OBJECT(cache));
-    result->cache = cache;
-
-    result->col_count = col_count;
-    result->opt_count = opt_count;
-
-    result->min_widths = calloc(col_count, sizeof(gint));
-
-    return result;
-
-}
 
 
 /******************************************************************************
@@ -588,57 +739,6 @@ size_t g_width_tracker_count_columns(const GWidthTracker *tracker)
 }
 
 
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : tracker = gestionnaire de largeurs de lignes à mettre jour.  *
-*                col     = indice de colonne visée.                           *
-*                                                                             *
-*  Description : Indique la largeur minimale pour une colonne donnée.         *
-*                                                                             *
-*  Retour      : Largeur minimale à imposée, nulle ou positive.               *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-gint g_width_tracker_get_column_min_width(GWidthTracker *tracker, size_t col)
-{
-    gint result;                            /* Largeur à renvoyer          */
-
-    assert(col < tracker->col_count);
-
-    result = tracker->min_widths[col];
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : tracker = gestionnaire de largeurs de lignes à mettre jour.  *
-*                col     = indice de colonne visée.                           *
-*                width   = largeur minimale à imposer.                        *
-*                                                                             *
-*  Description : Impose une largeur minimale pour une colonne donnée.         *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-void g_width_tracker_set_column_min_width(GWidthTracker *tracker, size_t col, gint width)
-{
-    assert(col < tracker->col_count);
-
-    if (width < 0)
-        width = 0;
-
-    tracker->min_widths[col] = width;
-
-}
-
 
 /******************************************************************************
 *                                                                             *
@@ -1367,3 +1467,7 @@ gint g_width_tracker_get_local_column_width(GWidthTracker *tracker, size_t index
     return result;
 
 }
+
+
+#endif
+
diff --git a/src/glibext/widthtracker.h b/src/glibext/widthtracker.h
index ce0aa93..c67e335 100644
--- a/src/glibext/widthtracker.h
+++ b/src/glibext/widthtracker.h
@@ -25,6 +25,34 @@
 #define _GLIBEXT_WIDTHTRACKER_H
 
 
+#include "buffercache.h"
+#include "helpers.h"
+
+
+
+#define G_TYPE_WIDTH_TRACKER (g_width_tracker_get_type())
+
+DECLARE_GTYPE(GWidthTracker, g_width_tracker, G, WIDTH_TRACKER);
+
+
+/* Crée un nouveau suivi de largeurs au sein de lignes. */
+GWidthTracker *g_width_tracker_new(GBufferCache *);
+
+/* Indique la largeur minimale pour une colonne donnée. */
+int g_width_tracker_get_column_min_width(const GWidthTracker *, size_t);
+
+/* Impose une largeur minimale pour une colonne donnée. */
+void g_width_tracker_set_column_min_width(GWidthTracker *, size_t, int);
+
+/* Détermine la largeur nécessaire à une pleine représentation. */
+void g_width_tracker_compute_width(const GWidthTracker *, int *);
+
+
+
+
+#if 0
+
+
 #include <glib-object.h>
 #include <stdbool.h>
 
@@ -74,7 +102,7 @@ typedef struct _GWidthTrackerClass GWidthTrackerClass;
 GType g_width_tracker_get_type(void);
 
 /* Crée un nouveau suivi de largeurs au sein de lignes. */
-GWidthTracker *g_width_tracker_new(GBufferCache *, size_t, size_t);
+//GWidthTracker *g_width_tracker_new(GBufferCache *, size_t, size_t);
 
 /* Crée un nouveau suivi de largeurs au sein de lignes. */
 GWidthTracker *g_width_tracker_new_restricted(const GWidthTracker *, size_t, size_t);
@@ -82,12 +110,6 @@ GWidthTracker *g_width_tracker_new_restricted(const GWidthTracker *, size_t, siz
 /* Indique le nombre de colonnes prises en compte. */
 size_t g_width_tracker_count_columns(const GWidthTracker *);
 
-/* Indique la largeur minimale pour une colonne donnée. */
-gint g_width_tracker_get_column_min_width(GWidthTracker *, size_t);
-
-/* Impose une largeur minimale pour une colonne donnée. */
-void g_width_tracker_set_column_min_width(GWidthTracker *, size_t, gint);
-
 /* Prend acte d'un changement sur une ligne pour les largeurs. */
 void g_width_tracker_update(GWidthTracker *, size_t);
 
@@ -110,5 +132,8 @@ gint g_width_tracker_get_margin(GWidthTracker *, const GDisplayOptions *);
 gint g_width_tracker_get_local_column_width(GWidthTracker *, size_t, size_t, size_t);
 
 
+#endif
+
+
 
 #endif  /* _GLIBEXT_WIDTHTRACKER_H */
diff --git a/src/gtkext/Makefile.am b/src/gtkext/Makefile.am
index e33e09e..c9445e6 100644
--- a/src/gtkext/Makefile.am
+++ b/src/gtkext/Makefile.am
@@ -11,8 +11,6 @@ libgtkext_la_SOURCES =						\
 	easygtk.h easygtk.c						\
 	gtkbinarystrip.h gtkbinarystrip.c		\
 	gtkblockdisplay.h gtkblockdisplay.c		\
-	gtkbufferdisplay-int.h					\
-	gtkbufferdisplay.h gtkbufferdisplay.c	\
 	gtkdockable-int.h						\
 	gtkdockable.h gtkdockable.c				\
 	gtkdockstation.h gtkdockstation.c		\
@@ -39,8 +37,11 @@ RES_FILES =									\
 libgtkext4_la_SOURCES =						\
 	area-int.h								\
 	area.h area.c							\
+	bufferview-int.h						\
+	bufferview.h bufferview.c				\
 	contentview-int.h						\
 	contentview.h contentview.c				\
+	hexview-int.h							\
 	hexview.h hexview.c						\
 	resources.h resources.c
 
diff --git a/src/gtkext/bufferview-int.h b/src/gtkext/bufferview-int.h
index d02aa37..7c9c8e1 100644
--- a/src/gtkext/bufferview-int.h
+++ b/src/gtkext/bufferview-int.h
@@ -1,8 +1,8 @@
 
 /* Chrysalide - Outil d'analyse de fichiers binaires
- * gtkbufferdisplay-int.h - prototypes internes pour l'affichage de tampons de lignes
+ * bufferview-int.h - prototypes internes pour l'affichage de tampons de lignes
  *
- * Copyright (C) 2016-2019 Cyrille Bagard
+ * Copyright (C) 2016-2024 Cyrille Bagard
  *
  *  This file is part of Chrysalide.
  *
@@ -21,27 +21,38 @@
  */
 
 
-#ifndef _GTK_BUFFERDISPLAY_INT_H
-#define _GTK_BUFFERDISPLAY_INT_H
+#ifndef _GTKEXT_BUFFERVIEW_INT_H
+#define _GTKEXT_BUFFERVIEW_INT_H
 
 
-#include "gtkbufferdisplay.h"
+#include "bufferview.h"
+#include "contentview-int.h"
 
 
-#include "gtkdisplaypanel-int.h"
-
 
 
+#if 0
 /* Réagit à un déplacement de curseur. */
-typedef bool (* notify_caret_relocation_fc) (GtkBufferDisplay *, const GdkRectangle *);
+typedef bool (* notify_caret_relocation_fc) (GtkBufferView *, const GdkRectangle *);
+#endif
+
+
 
 
 /* Composant d'affichage de tampon de lignes (instance) */
-struct _GtkBufferDisplay
+struct _GtkBufferView
 {
-    GtkDisplayPanel parent;                 /* A laisser en premier        */
+    GtkContentView parent;                  /* A laisser en premier        */
+
+    GBufferView *view;                      /* Vue choisie sur un tampon   */
+    GTokenStyle *style;                     /* Centralisation des styles   */
+
+    int virt_top;                           /* Première ordonnée affichée  */
+
 
-    GBufferView *view;                      /* Vue sur le contenu affiché  */
+
+
+#if 0
 
     cairo_rectangle_int_t caret;            /* Emplacement du curseur #1   */
     GLineCursor *cursor;                    /* Emplacement du curseur #2   */
@@ -51,23 +62,29 @@ struct _GtkBufferDisplay
     GtkBuilder *builder;                    /* Constructeur à manipuler    */
     GtkWidget *bar;                         /* Barre d'outils intégrée     */
 
+#endif
+
 };
 
 /* Composant d'affichage de tampon de lignes (classe) */
-struct _GtkBufferDisplayClass
+struct _GtkBufferViewClass
 {
-    GtkDisplayPanelClass parent;            /* A laisser en premier        */
+    GtkContentViewClass parent;             /* A laisser en premier        */
+
+#if 0
 
     notify_caret_relocation_fc notify_caret;/* Accompagne un déplacement   */
 
     /* Signaux */
 
-    void (* reach_limit) (GtkBufferDisplay *, GdkScrollDirection);
+    void (* reach_limit) (GtkBufferView *, GdkScrollDirection);
+
+    void (* prepare_collapsing) (GtkBufferView *, gboolean);
 
-    void (* prepare_collapsing) (GtkBufferDisplay *, gboolean);
+#endif
 
 };
 
 
 
-#endif  /* _GTK_BUFFERDISPLAY_INT_H */
+#endif  /* _GTKEXT_BUFFERVIEW_INT_H */
diff --git a/src/gtkext/bufferview.c b/src/gtkext/bufferview.c
index 4566cc5..4a700c3 100644
--- a/src/gtkext/bufferview.c
+++ b/src/gtkext/bufferview.c
@@ -1,8 +1,8 @@
 
 /* Chrysalide - Outil d'analyse de fichiers binaires
- * gtkbufferdisplay.c - affichage de tampons de lignes
+ * bufferview.c - affichage de tampons de lignes
  *
- * Copyright (C) 2016-2019 Cyrille Bagard
+ * Copyright (C) 2016-2024 Cyrille Bagard
  *
  *  This file is part of Chrysalide.
  *
@@ -21,9 +21,418 @@
  */
 
 
-#include "gtkbufferdisplay.h"
+#include "bufferview.h"
 
 
+#include "bufferview-int.h"
+
+
+
+
+
+/* ------------------------- BASES D'UN COMPOSANT GRAPHIQUE ------------------------- */
+
+
+/* Procède à l'initialisation de l'afficheur de tampons. */
+static void gtk_buffer_view_class_init(GtkBufferViewClass *);
+
+/* Procède à l'initialisation de l'afficheur de tampons. */
+static void gtk_buffer_view_init(GtkBufferView *);
+
+/* Supprime toutes les références externes. */
+static void gtk_buffer_view_dispose(GtkBufferView *);
+
+/* Procède à la libération totale de la mémoire. */
+static void gtk_buffer_view_finalize(GtkBufferView *);
+
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Prend acte de la taille allouée au composant d'affichage. */
+static void gtk_buffer_view_size_allocate(GtkWidget *, int, int, int);
+
+/* Réagit à un défilement chez une barre associée au composant. */
+static void gtk_buffer_view_adjust_scroll_value(GtkBufferView *, GtkOrientation, GtkAdjustment *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                           BASES D'UN COMPOSANT GRAPHIQUE                           */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Détermine le type du composant d'affichage générique. */
+G_DEFINE_TYPE(GtkBufferView, gtk_buffer_view, GTK_TYPE_CONTENT_VIEW);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : class = classe GTK à initialiser.                            *
+*                                                                             *
+*  Description : Procède à l'initialisation de l'afficheur de tampons.        *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void gtk_buffer_view_class_init(GtkBufferViewClass *class)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+    GtkWidgetClass *widget;                 /* Classe version Widget       */
+    GtkContentViewClass *content;           /* Base d'affichage            */
+
+    object = G_OBJECT_CLASS(class);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)gtk_buffer_view_dispose;
+    object->finalize = (GObjectFinalizeFunc)gtk_buffer_view_finalize;
+
+    widget = GTK_WIDGET_CLASS(class);
+
+    widget->size_allocate = gtk_buffer_view_size_allocate;
+
+    content = GTK_CONTENT_VIEW_CLASS(class);
+
+    content->adjust = (adjust_scroll_value_fc)gtk_buffer_view_adjust_scroll_value;
+
+
+
+#if 0
+
+    widget_class->focus_in_event = gtk_buffer_view_focus;
+    widget_class->focus_out_event = gtk_buffer_view_focus;
+    widget_class->button_press_event = gtk_buffer_view_button_press;
+    widget_class->draw = gtk_buffer_view_draw;
+    widget_class->key_press_event = gtk_buffer_view_key_press;
+
+    panel_class = GTK_DISPLAY_PANEL_CLASS(class);
+
+    panel_class->compute_size = (compute_requested_size_fc)gtk_buffer_view_compute_requested_size;
+    panel_class->compute_inc = (compute_scroll_inc_fc)gtk_buffer_view_compute_scroll_inc;
+    panel_class->adjust = (adjust_scroll_value_fc)gtk_buffer_view_adjust_scroll_value;
+    panel_class->get_coordinates = (get_coordinates_fc)gtk_buffer_view_get_cursor_coordinates;
+    panel_class->get_active = (get_active_object_fc)gtk_buffer_view_get_active_object;
+    panel_class->move_caret_to = (move_caret_to_fc)_gtk_buffer_view_move_caret_to;
+    panel_class->cache_glance = (cache_glance_fc)gtk_buffer_view_cache_glance;
+
+    panel_class->get_cursor = (get_cursor_fc)gtk_buffer_view_get_cursor;
+
+    /* Signaux */
+
+    g_signal_new("reach-limit",
+                 GTK_TYPE_BUFFER_DISPLAY,
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET(GtkBufferViewClass, reach_limit),
+                 NULL, NULL,
+                 g_cclosure_marshal_VOID__ENUM,
+                 G_TYPE_NONE, 1, GTK_TYPE_SCROLL_TYPE);
+
+    g_signal_new("prepare-collapsing",
+                 GTK_TYPE_BUFFER_DISPLAY,
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET(GtkBufferViewClass, prepare_collapsing),
+                 NULL, NULL,
+                 g_cclosure_marshal_VOID__BOOLEAN,
+                 G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
+
+#endif
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : display = composant GTK à initialiser.                       *
+*                                                                             *
+*  Description : Procède à l'initialisation de l'afficheur de tampons.        *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void gtk_buffer_view_init(GtkBufferView *view)
+{
+    view->view = NULL;
+    view->style = g_token_style_new(GTK_WIDGET(view));
+
+    view->virt_top = 0;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : display = instance d'objet GLib à traiter.                   *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void gtk_buffer_view_dispose(GtkBufferView *view)
+{
+#if 0
+
+    if (display->caret_timer != 0)
+    {
+        g_source_remove(display->caret_timer);
+        display->caret_timer = 0;
+    }
+
+    g_clear_object(&display->cursor);
+
+    g_clear_object(&display->builder);
+    g_clear_object(&display->bar);
+
+#endif
+
+
+
+
+    g_clear_object(&view->view);
+    g_clear_object(&view->style);
+
+    G_OBJECT_CLASS(gtk_buffer_view_parent_class)->dispose(G_OBJECT(view));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : display = instance d'objet Gtk à traiter.                    *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void gtk_buffer_view_finalize(GtkBufferView *view)
+{
+    G_OBJECT_CLASS(gtk_buffer_view_parent_class)->finalize(G_OBJECT(view));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : view = composant GTK à consulter.                            *
+*                                                                             *
+*  Description : Fournit la vue associée au tampon de lignes courant.         *
+*                                                                             *
+*  Retour      : Vue mise en place.                                           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GBufferView *gtk_buffer_view_get_view(const GtkBufferView *view)
+{
+    GBufferView *result;                    /* Instance à retourner        */
+
+    result = view->view;
+
+    ref_object(result);
+
+    return result;
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : widget = composant GTK à examiner.                           *
+*                width  = largeur affectée au composant graphique.            *
+*                height = hauteur affectée au composant graphique.            *
+*                baseline = ligne de base affectée au composant graphique.    *
+*                                                                             *
+*  Description : Prend acte de la taille allouée au composant d'affichage.    *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void gtk_buffer_view_size_allocate(GtkWidget *widget, int width, int height, int baseline)
+{
+    GtkContentView *base;                   /* Version de base             */
+    GtkBufferView *view;                    /* Version spécialisée         */
+    int full_width;                         /* Largeur idéale complète     */
+    int full_height;                        /* Hauteur idéale complète     */
+    int *min_widths;                        /* Largeurs minimales imposées */
+    int *min_heights;                       /* Hauteurs minimales imposées */
+    size_t i;                               /* Boucle de parcours          */
+    int upper;                              /* Valeur maximale retenue     */
+    GtkAdjustment *adj;                     /* Ajustement à mettre à jour  */
+    int line_height;                        /* Hauteur d'une ligne unique  */
+    int lines_per_page;                     /* Nombre de lignes sur l'écran*/
+    GtkAllocation allocated;                /* Zone allouée                */
+    GWidthTracker *tracker;                 /* Collecteur de largeurs      */
+
+    base = GTK_CONTENT_VIEW(widget);
+    view = GTK_BUFFER_VIEW(widget);
+
+    /* Détermination de la surface idéale à afficher */
+
+    g_buffer_view_compute_size(view->view, &full_width, &full_height);
+
+    min_widths = alloca(base->sub_count * sizeof(int));
+    min_heights = alloca(base->sub_count * sizeof(int));
+
+    for (i = 0; i < base->sub_count; i++)
+    {
+        gtk_widget_measure(base->sub_children[i], GTK_ORIENTATION_HORIZONTAL, -1,
+                           &min_widths[i], NULL, NULL, NULL);
+        full_width += min_widths[i];
+
+        gtk_widget_measure(base->sub_children[i], GTK_ORIENTATION_VERTICAL, -1,
+                           &min_heights[i], NULL, NULL, NULL);
+        full_height += min_heights[i];
+
+    }
+
+    /* Définition des besoins en défilement */
+
+    upper = MAX(width, full_width);
+
+    adj = base->adjustments[GTK_ORIENTATION_HORIZONTAL];
+
+    gtk_adjustment_configure(adj,
+                             gtk_adjustment_get_value(adj),
+                             0, upper,
+                             0.1 * width,
+                             0.9 * width,
+                             width);
+
+    upper = MAX(height, full_height);
+
+    line_height = g_token_style_get_line_height(view->style);
+
+    lines_per_page = height / line_height;
+    if (lines_per_page == 0) lines_per_page = 1;
+
+    adj = base->adjustments[GTK_ORIENTATION_VERTICAL];
+
+    gtk_adjustment_configure(adj,
+                             gtk_adjustment_get_value(adj),
+                             0, upper,
+                             line_height * lines_per_page,
+                             line_height * lines_per_page * 10,
+                             height);
+
+    /* Placement des composants d'affichage */
+
+    tracker = g_buffer_view_get_tracker(view->view);
+
+    allocated.x = 0;
+    allocated.y = 0;
+    allocated.height = height;
+
+    for (i = 0; i < base->sub_count; i++)
+    {
+        allocated.width = g_width_tracker_get_column_min_width(tracker, i);
+
+        if ((i + 1) == base->sub_count && allocated.width < (width - allocated.x))
+            allocated.width = width - allocated.x;
+
+        gtk_widget_size_allocate(base->sub_children[i], &allocated, baseline);
+
+        allocated.x += allocated.width;
+
+    }
+
+    unref_object(tracker);
+
+    /* Mise à jour des éléments plus internes */
+
+    GTK_WIDGET_CLASS(gtk_buffer_view_parent_class)->size_allocate(widget, width, height, baseline);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : view        = panneau d'affichage concerné.                  *
+*                orientation = indication sur le défilement à traiter.        *
+*                adj         = nouvel ajustement à prendre en compte.         *
+*                                                                             *
+*  Description : Réagit à un défilement chez une barre associée au composant. *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void gtk_buffer_view_adjust_scroll_value(GtkBufferView *view, GtkOrientation orientation, GtkAdjustment *adj)
+{
+    GtkContentView *base;                   /* Version de base             */
+    size_t i;                               /* Boucle de parcours          */
+
+    base = GTK_CONTENT_VIEW(view);
+
+    if (orientation == GTK_ORIENTATION_HORIZONTAL)
+        printf("TODO...\n");
+
+    else
+    {
+        view->virt_top = gtk_adjustment_get_value(adj);
+
+        for (i = 0; i < base->sub_count; i++)
+            gtk_widget_queue_draw(base->sub_children[i]);
+
+    }
+
+}
+
+
+
+
+
+
+
+
+#if 0
+
 #include <assert.h>
 
 
@@ -38,16 +447,16 @@
 
 
 /* Procède à l'initialisation de l'afficheur de tampons. */
-static void gtk_buffer_display_class_init(GtkBufferDisplayClass *);
+//static void gtk_buffer_display_class_init(GtkBufferDisplayClass *);
 
 /* Procède à l'initialisation de l'afficheur de tampons. */
-static void gtk_buffer_display_init(GtkBufferDisplay *);
+//static void gtk_buffer_display_init(GtkBufferDisplay *);
 
 /* Supprime toutes les références externes. */
-static void gtk_buffer_display_dispose(GtkBufferDisplay *);
+//static void gtk_buffer_display_dispose(GtkBufferDisplay *);
 
 /* Procède à la libération totale de la mémoire. */
-static void gtk_buffer_display_finalize(GtkBufferDisplay *);
+//static void gtk_buffer_display_finalize(GtkBufferDisplay *);
 
 /* Intègre le focus dans le rendu du composant. */
 static gboolean gtk_buffer_display_focus(GtkWidget *, GdkEventFocus *);
@@ -882,30 +1291,6 @@ static GLineCursor *gtk_buffer_display_get_cursor(const GtkBufferDisplay *displa
 }
 
 
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : display = composant GTK à consulter.                         *
-*                                                                             *
-*  Description : Fournit la vue associée au tampon de lignes courant.         *
-*                                                                             *
-*  Retour      : Vue mise en place.                                           *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-GBufferView *gtk_buffer_display_get_view(const GtkBufferDisplay *display)
-{
-    GBufferView *result;                    /* Instance à retourner        */
-
-    result = display->view;
-
-    g_object_ref(G_OBJECT(result));
-
-    return result;
-
-}
-
 
 
 /* ---------------------------------------------------------------------------------- */
@@ -1437,3 +1822,5 @@ static gboolean on_block_bar_collapsing_leave(GtkWidget *widget, GdkEventCrossin
     return FALSE;
 
 }
+
+#endif
diff --git a/src/gtkext/bufferview.h b/src/gtkext/bufferview.h
index 8f2d63c..1bdfc80 100644
--- a/src/gtkext/bufferview.h
+++ b/src/gtkext/bufferview.h
@@ -1,8 +1,8 @@
 
 /* Chrysalide - Outil d'analyse de fichiers binaires
- * gtkbufferdisplay.h - prototypes pour l'affichage de tampons de lignes
+ * bufferview.h - prototypes pour l'affichage de tampons de lignes
  *
- * Copyright (C) 2016-2019 Cyrille Bagard
+ * Copyright (C) 2016-2024 Cyrille Bagard
  *
  *  This file is part of Chrysalide.
  *
@@ -21,41 +21,36 @@
  */
 
 
-#ifndef _GTKEXT_GTKBUFFER_DISPLAY_H
-#define _GTKEXT_GTKBUFFER_DISPLAY_H
+#ifndef _GTKEXT_BUFFERVIEW_H
+#define _GTKEXT_BUFFERVIEW_H
 
 
-#include <glib-object.h>
 #include <gtk/gtk.h>
 
 
 #include "../glibext/bufferview.h"
+#include "../glibext/helpers.h"
 
 
 
-#define GTK_TYPE_BUFFER_DISPLAY             (gtk_buffer_display_get_type())
-#define GTK_BUFFER_DISPLAY(obj)             (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_BUFFER_DISPLAY, GtkBufferDisplay))
-#define GTK_BUFFER_DISPLAY_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST((klass), GTK_TYPE_BUFFER_DISPLAY, GtkBufferDisplayClass))
-#define GTK_IS_BUFFER_DISPLAY(obj)          (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_BUFFER_DISPLAY))
-#define GTK_IS_BUFFER_DISPLAY_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE((klass), GTK_TYPE_BUFFER_DISPLAY))
-#define GTK_BUFFER_DISPLAY_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_BUFFER_VIEW, GtkBufferDisplayClass))
+#define GTK_TYPE_BUFFER_VIEW (gtk_buffer_view_get_type())
 
+DECLARE_GTYPE(GtkBufferView, gtk_buffer_view, GTK, BUFFER_VIEW);
 
-/* Composant d'affichage de tampon de lignes (instance) */
-typedef struct _GtkBufferDisplay GtkBufferDisplay;
 
-/* Composant d'affichage de tampon de lignes (classe) */
-typedef struct _GtkBufferDisplayClass GtkBufferDisplayClass;
+
+/* Fournit la vue associée au tampon de lignes courant. */
+GBufferView *gtk_buffer_view_get_view(const GtkBufferView *);
+
 
 
-/* Détermine le type du composant d'affichage de tampon de lignes. */
-GType gtk_buffer_display_get_type(void);
 
-/* Fournit la vue associée au tampon de lignes courant. */
-GBufferView *gtk_buffer_display_get_view(const GtkBufferDisplay *);
 
 
 
+
+#if 0
+
 /* ------------------------------ ANIMATION DU CURSEUR ------------------------------ */
 
 
@@ -73,6 +68,9 @@ bool gtk_buffer_display_move_caret_to(GtkBufferDisplay *, bool, gint *);
 /* Ajoute une nouvelle barre d'outils pour bloc au composant. */
 void gtk_buffer_display_add_block_bar(GtkBufferDisplay *);
 
+#endif
+
+
 
 
-#endif  /* _GTKEXT_GTKBUFFER_DISPLAY_H */
+#endif  /* _GTKEXT_BUFFERVIEW_H */
diff --git a/src/gtkext/contentview-int.h b/src/gtkext/contentview-int.h
index 25c9ddb..01c0c7a 100644
--- a/src/gtkext/contentview-int.h
+++ b/src/gtkext/contentview-int.h
@@ -28,11 +28,19 @@
 #include "contentview.h"
 
 
+#include "../glibext/bufferview.h"
 #include "../glibext/tokenstyle.h"
 
 
 
 
+/* Réagit à un défilement chez une barre associée au composant. */
+typedef void (* adjust_scroll_value_fc) (GtkContentView *, GtkOrientation, GtkAdjustment *);
+
+
+
+
+
 #if 0
 
 #include <stdbool.h>
@@ -52,10 +60,10 @@
 typedef void (* compute_requested_size_fc) (GtkDisplayPanel *, gint *, gint *);
 
 /* Détermine la taille des bonds lors de défilements. */
-typedef void (* compute_scroll_inc_fc) (GtkDisplayPanel *, gint, GtkOrientation, gdouble *, gdouble *);
+//typedef void (* compute_scroll_inc_fc) (GtkDisplayPanel *, gint, GtkOrientation, gdouble *, gdouble *);
 
 /* Réagit à un défilement chez une barre associée au composant. */
-typedef void (* adjust_scroll_value_fc) (GtkDisplayPanel *, GtkAdjustment *, GtkOrientation);
+//typedef void (* adjust_scroll_value_fc) (GtkDisplayPanel *, GtkAdjustment *, GtkOrientation);
 
 /* Ajuste au besoin la zone affichée pour un curseur. */
 typedef void (* prepare_for_cursor_fc) (GtkDisplayPanel *, const GLineCursor *);
@@ -94,15 +102,18 @@ struct _GtkContentView
 {
     GtkWidget parent;                       /* A laisser en premier        */
 
+    GtkAdjustment *adjustments[2];          /* Barres de défilement h. & v.*/
+    GtkScrollablePolicy scroll_policies[2]; /* Politiques de défilement    */
+
     GDisplayOptions *options;               /* Options de rendu            */
-    GTokenStyle *style;                     /* Centralisation des styles   */
 
-#if 0
+    /* Propriété des implémentations */
 
-    GtkAdjustment *hadjustment;             /* Barre de défilement horiz.  */
-    GtkAdjustment *vadjustment;             /* Barre de défilement vert.   */
-    GtkScrollablePolicy hscroll_policy;     /* Politique horizontale       */           
-    GtkScrollablePolicy vscroll_policy;     /* Politique verticale         */           
+    GtkWidget * const *sub_children;        /* Composants embarqués        */
+    size_t sub_count;                       /* Quantité de ces composants  */
+
+
+#if 0
 
     double scale;                           /* Echelle de l'affichage      */
 
@@ -121,13 +132,14 @@ struct _GtkContentView
 /* Composant d'affichage générique (classe) */
 struct _GtkContentViewClass
 {
-    GtkFixedClass parent;                   /* A laisser en premier        */
+    GtkWidgetClass parent;                  /* A laisser en premier        */
 
 #if 0
-
     compute_requested_size_fc compute_size; /* Calcul de la taille requise */
-    compute_scroll_inc_fc compute_inc;      /* Calcul des bonds            */
+#endif
     adjust_scroll_value_fc adjust;          /* Réaction à un défilement    */
+
+#if 0
     prepare_for_cursor_fc prepare;          /* Préparation de zone affichée*/
     get_coordinates_fc get_coordinates;     /* Conversion adresse <-> pos. */
     get_active_object_fc get_active;        /* Infos sur l'objet actif     */
@@ -149,20 +161,20 @@ struct _GtkContentViewClass
 };
 
 
-#if 0
-
 /* Propriétés propres au composant d'affichage */
-typedef enum _ViewPanelProps
+typedef enum _ContentViewProps
 {
-    VPP_0,
-    VPP_HADJUSTMENT,
-    VPP_VADJUSTMENT,
-    VPP_HSCROLL_POLICY,
-    VPP_VSCROLL_POLICY
+    CVP_0,
+    CVP_HADJUSTMENT,
+    CVP_VADJUSTMENT,
+    CVP_HSCROLL_POLICY,
+    CVP_VSCROLL_POLICY
 
-} ViewPanelProps;
+} ContentViewProps;
 
 
+#if 0
+
 /* Définit un chemin décrivant la bordure autour du panneau. */
 void gtk_display_panel_define_border_path(GtkDisplayPanel *, cairo_t *, const GtkAllocation *);
 
diff --git a/src/gtkext/contentview.c b/src/gtkext/contentview.c
index 4b7f79d..77bbb7b 100644
--- a/src/gtkext/contentview.c
+++ b/src/gtkext/contentview.c
@@ -59,22 +59,51 @@ static void gtk_content_view_dispose(GtkContentView *);
 /* Procède à la libération totale de la mémoire. */
 static void gtk_content_view_finalize(GtkContentView *);
 
+
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Définit une propriété du composant d'affichage. */
+static void gtk_content_view_set_property(GObject *, guint, const GValue *, GParamSpec *);
+
+/* Se débarrsse d'un ajustement pour un défilement donné. */
+static void _gtk_content_view_disconnect_adjustment(GtkContentView *, GtkOrientation);
+
+/* S'associe à un ajustement pour un défilement donné. */
+static void _gtk_content_view_set_adjustment(GtkContentView *, GtkOrientation, GtkAdjustment *);
+
+/* Réagit à un défilement chez une barre associée au composant. */
+static void _gtk_content_view_adjustment_value_changed(GtkAdjustment *, GtkContentView *);
+
+/* Fournit une propriété du composant d'affichage. */
+static void gtk_content_view_get_property(GObject *, guint, GValue *, GParamSpec *);
+
+/* Fournit les mesures mainimale et idéale du composant. */
+static void gtk_content_view_measure(GtkWidget *, GtkOrientation, int, int *, int *, int *, int *);
+
+
+
+
+
 #if 0
 
 /* Définit une propriété du composant d'affichage. */
-static void gtk_display_panel_set_property(GObject *, guint, const GValue *, GParamSpec *);
+//static void gtk_display_panel_set_property(GObject *, guint, const GValue *, GParamSpec *);
 
 /* Fournit une propriété du composant d'affichage. */
-static void gtk_display_panel_get_property(GObject *, guint, GValue *, GParamSpec *);
+//static void gtk_display_panel_get_property(GObject *, guint, GValue *, GParamSpec *);
 
 /* Détruit un composant d'affichage. */
-static void gtk_display_panel_destroy(GtkWidget *);
+//static void gtk_display_panel_destroy(GtkWidget *);
 
 /* Encadre la construction graphique initiale de l'affichage. */
 static void gtk_display_panel_realize(GtkWidget *);
 
 /* S'adapte à la surface concédée par le composant parent. */
-static void gtk_display_panel_size_allocate(GtkWidget *, GtkAllocation *);
+//static void gtk_display_panel_size_allocate(GtkWidget *, GtkAllocation *);
 
 /* Fournit la hauteur idéale pour le composant d'affichage. */
 static void gtk_display_panel_get_preferred_height(GtkWidget *, gint *, gint *);
@@ -83,22 +112,22 @@ static void gtk_display_panel_get_preferred_height(GtkWidget *, gint *, gint *);
 static void gtk_display_panel_get_preferred_width(GtkWidget *, gint *, gint *);
 
 /* Détermine la taille des bonds lors de défilements. */
-static void gtk_display_panel_compute_scroll_inc(GtkDisplayPanel *, gint, GtkOrientation, gdouble *, gdouble *);
+//static void gtk_display_panel_compute_scroll_inc(GtkDisplayPanel *, gint, GtkOrientation, gdouble *, gdouble *);
 
 /* Détermine la taille allouée pour le contenu. */
 static void gtk_display_panel_compute_allocation(GtkDisplayPanel *, GtkAllocation *);
 
 /* Se débarrsse d'un ajustement pour un défilement donné. */
-static void gtk_display_panel_disconnect_adjustment(GtkDisplayPanel *, GtkOrientation);
+//static void gtk_display_panel_disconnect_adjustment(GtkDisplayPanel *, GtkOrientation);
 
 /* S'associe à un ajustement pour un défilement donné. */
-static void gtk_display_panel_set_adjustment(GtkDisplayPanel *, GtkOrientation, GtkAdjustment *);
+//static void gtk_display_panel_set_adjustment(GtkDisplayPanel *, GtkOrientation, GtkAdjustment *);
 
 /* Ajuste les paramètres de défilement du composant. */
-static void gtk_display_panel_update_adjustment(GtkDisplayPanel *, GtkOrientation);
+//static void gtk_display_panel_update_adjustment(GtkDisplayPanel *, GtkOrientation);
 
 /* Réagit à un défilement chez une barre associée au composant.*/
-static void gtk_display_panel_adjustment_value_changed(GtkAdjustment *, GtkDisplayPanel *);
+//static void gtk_display_panel_adjustment_value_changed(GtkAdjustment *, GtkDisplayPanel *);
 
 
 
@@ -136,8 +165,8 @@ G_DEFINE_TYPE_WITH_CODE(GtkDisplayPanel, gtk_display_panel, GTK_TYPE_FIXED,
 
 
 /* Détermine le type du composant d'affichage générique. */
-G_DEFINE_TYPE(GtkContentView, gtk_content_view, GTK_TYPE_WIDGET);
-
+G_DEFINE_TYPE_WITH_CODE(GtkContentView, gtk_content_view, GTK_TYPE_WIDGET,
+                        G_IMPLEMENT_INTERFACE(GTK_TYPE_SCROLLABLE, NULL));
 
 
 /******************************************************************************
@@ -155,35 +184,43 @@ G_DEFINE_TYPE(GtkContentView, gtk_content_view, GTK_TYPE_WIDGET);
 static void gtk_content_view_class_init(GtkContentViewClass *class)
 {
     GObjectClass *object;                   /* Plus haut niveau équivalent */
-    //GtkWidgetClass *widget;                 /* Classe de haut niveau       */
-    //GtkContentViewClass *panel;            /* Classe de lus bas niveau    */
+    GtkWidgetClass *widget;                 /* Classe de haut niveau       */
 
     object = G_OBJECT_CLASS(class);
 
+    object->set_property = gtk_content_view_set_property;
+    object->get_property = gtk_content_view_get_property;
     object->dispose = (GObjectFinalizeFunc/* ! */)gtk_content_view_dispose;
     object->finalize = (GObjectFinalizeFunc)gtk_content_view_finalize;
 
+    /* Implémentation de l'interface "GtkScrollable" */
+    g_object_class_override_property(object, CVP_HADJUSTMENT, "hadjustment");
+    g_object_class_override_property(object, CVP_VADJUSTMENT, "vadjustment");
+    g_object_class_override_property(object, CVP_HSCROLL_POLICY, "hscroll-policy");
+    g_object_class_override_property(object, CVP_VSCROLL_POLICY, "vscroll-policy");
+
+
+
+
+
+    widget = GTK_WIDGET_CLASS(class);
+
+    widget->measure = gtk_content_view_measure;
+
+
+
+
 #if 0
-    object->set_property = gtk_display_panel_set_property;
-    object->get_property = gtk_display_panel_get_property;
 
-    /* Implémentation de l'interface "GtkScrollable" */
-    g_object_class_override_property(object, VPP_HADJUSTMENT, "hadjustment");
-    g_object_class_override_property(object, VPP_VADJUSTMENT, "vadjustment");
-    g_object_class_override_property(object, VPP_HSCROLL_POLICY, "hscroll-policy");
-    g_object_class_override_property(object, VPP_VSCROLL_POLICY, "vscroll-policy");
 
     widget = GTK_WIDGET_CLASS(class);
 
-    widget->destroy = gtk_display_panel_destroy;
+    //widget->destroy = gtk_display_panel_destroy;
     widget->realize = gtk_display_panel_realize;
     widget->size_allocate = gtk_display_panel_size_allocate;
     widget->get_preferred_height = gtk_display_panel_get_preferred_height;
     widget->get_preferred_width = gtk_display_panel_get_preferred_width;
 
-    panel = GTK_DISPLAY_PANEL_CLASS(class);
-
-    panel->compute_inc = gtk_display_panel_compute_scroll_inc;
 
     /* Signaux */
 
@@ -214,8 +251,13 @@ static void gtk_content_view_class_init(GtkContentViewClass *class)
 
 static void gtk_content_view_init(GtkContentView *view)
 {
+    view->adjustments[GTK_ORIENTATION_HORIZONTAL] = NULL;
+    view->adjustments[GTK_ORIENTATION_VERTICAL] = NULL;
+
+    view->scroll_policies[GTK_ORIENTATION_HORIZONTAL] = GTK_POLICY_AUTOMATIC;
+    view->scroll_policies[GTK_ORIENTATION_VERTICAL] = GTK_POLICY_AUTOMATIC;
+
     view->options = NULL;
-    view->style = g_token_style_new(GTK_WIDGET(view));
 
 
 
@@ -272,13 +314,16 @@ static void gtk_display_panel_loaded_interface_init(GLoadedPanelInterface *iface
 
 static void gtk_content_view_dispose(GtkContentView *view)
 {
+    _gtk_content_view_disconnect_adjustment(view, GTK_ORIENTATION_HORIZONTAL);
+    _gtk_content_view_disconnect_adjustment(view, GTK_ORIENTATION_VERTICAL);
+
+    g_clear_object(&view->adjustments[GTK_ORIENTATION_HORIZONTAL]);
+    g_clear_object(&view->adjustments[GTK_ORIENTATION_VERTICAL]);
+
     g_clear_object(&view->options);
-    g_clear_object(&view->style);
 
 
     /*
-    g_clear_object(&panel->hadjustment);
-    g_clear_object(&panel->vadjustment);
 
     g_clear_object(&panel->options);
 
@@ -309,7 +354,16 @@ static void gtk_content_view_finalize(GtkContentView *view)
 }
 
 
-#if 0
+
+
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */
+/* ---------------------------------------------------------------------------------- */
+
+
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : object  = instance de composant GTK à manipuler.             *
@@ -325,25 +379,25 @@ static void gtk_content_view_finalize(GtkContentView *view)
 *                                                                             *
 ******************************************************************************/
 
-static void gtk_display_panel_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+static void gtk_content_view_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
 {
-    GtkDisplayPanel *panel;                 /* Autre vision de l'instance  */
+    GtkContentView *view;                   /* Autre vision de l'instance  */
 
-    panel = GTK_DISPLAY_PANEL(object);
+    view = GTK_CONTENT_VIEW(object);
 
     switch (prop_id)
     {
-        case VPP_HADJUSTMENT:
-            gtk_display_panel_set_adjustment(panel, GTK_ORIENTATION_HORIZONTAL, g_value_get_object(value));
+        case CVP_HADJUSTMENT:
+            _gtk_content_view_set_adjustment(view, GTK_ORIENTATION_HORIZONTAL, g_value_get_object(value));
             break;
-        case VPP_VADJUSTMENT:
-            gtk_display_panel_set_adjustment(panel, GTK_ORIENTATION_VERTICAL, g_value_get_object(value));
+        case CVP_VADJUSTMENT:
+            _gtk_content_view_set_adjustment(view, GTK_ORIENTATION_VERTICAL, g_value_get_object(value));
             break;
-        case VPP_HSCROLL_POLICY:
+        case CVP_HSCROLL_POLICY:
             //viewport->priv->hscroll_policy = g_value_get_enum (value);
             //gtk_widget_queue_resize (GTK_WIDGET (viewport));
             break;
-        case VPP_VSCROLL_POLICY:
+        case CVP_VSCROLL_POLICY:
             //viewport->priv->vscroll_policy = g_value_get_enum (value);
             //gtk_widget_queue_resize (GTK_WIDGET (viewport));
             break;
@@ -357,6 +411,105 @@ static void gtk_display_panel_set_property(GObject *object, guint prop_id, const
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : view        = composant GTK d'affichage à mettre à jour.     *
+*                orientation = indication sur le défilement à traiter.        *
+*                                                                             *
+*  Description : Se débarrsse d'un ajustement pour un défilement donné.       *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void _gtk_content_view_disconnect_adjustment(GtkContentView *view, GtkOrientation orientation)
+{
+    GtkAdjustment **adjp;                   /* Ajustement à manipuler      */
+
+    adjp = &view->adjustments[orientation];
+
+    if (*adjp != NULL)
+    {
+        g_signal_handlers_disconnect_by_func(*adjp, _gtk_content_view_adjustment_value_changed, view);
+        g_clear_object(adjp);
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : view        = composant GTK d'affichage à mettre à jour.     *
+*                orientation = indication sur le défilement à traiter.        *
+*                adj         = nouvel ajustement à prendre en compte.         *
+*                                                                             *
+*  Description : S'associe à un ajustement pour un défilement donné.          *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void _gtk_content_view_set_adjustment(GtkContentView *view, GtkOrientation orientation, GtkAdjustment *adj)
+{
+    GtkAdjustment **adjp;                   /* Ajustement à manipuler      */
+
+    adjp = &view->adjustments[orientation];
+
+    /* S'il n'y a rien à faire... */
+    if (adj != NULL && adj == *adjp)
+        return;
+
+    if (adj == NULL)
+        adj = gtk_adjustment_new(0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
+    else
+        ref_object(adj);
+
+    _gtk_content_view_disconnect_adjustment(view, orientation);
+
+    *adjp = adj;
+
+    g_signal_connect(adj, "value-changed", G_CALLBACK(_gtk_content_view_adjustment_value_changed), view);
+
+    gtk_widget_queue_allocate(GTK_WIDGET(view));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : adj  = défilement dont une valeur a changé.                  *
+*                view = panneau d'affichage concerné.                         *
+*                                                                             *
+*  Description : Réagit à un défilement chez une barre associée au composant. *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void _gtk_content_view_adjustment_value_changed(GtkAdjustment *adj, GtkContentView *view)
+{
+    GtkOrientation orientation;             /* Indification de la barre    */
+    GtkContentViewClass *class;             /* Classe de l'instance        */
+
+    if (adj == view->adjustments[GTK_ORIENTATION_HORIZONTAL])
+        orientation = GTK_ORIENTATION_HORIZONTAL;
+    else
+        orientation = GTK_ORIENTATION_VERTICAL;
+
+    class = GTK_CONTENT_VIEW_GET_CLASS(view);
+
+    if (class->adjust != NULL)
+        class->adjust(view, orientation, adj);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : object  = instance de composant GTK à manipuler.             *
 *                prop_id = identifiant de la propriété concernée.             *
 *                value   = valeur à renvoyer.                                 *
@@ -370,25 +523,25 @@ static void gtk_display_panel_set_property(GObject *object, guint prop_id, const
 *                                                                             *
 ******************************************************************************/
 
-static void gtk_display_panel_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+static void gtk_content_view_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
 {
-    GtkDisplayPanel *panel;                 /* Autre vision de l'instance  */
+    GtkContentView *view;                   /* Autre vision de l'instance  */
 
-    panel = GTK_DISPLAY_PANEL(object);
+    view = GTK_CONTENT_VIEW(object);
 
     switch (prop_id)
     {
-        case VPP_HADJUSTMENT:
-            g_value_set_object(value, panel->hadjustment);
+        case CVP_HADJUSTMENT:
+            g_value_set_object(value, view->adjustments[GTK_ORIENTATION_HORIZONTAL]);
             break;
-        case VPP_VADJUSTMENT:
-            g_value_set_object(value, panel->vadjustment);
+        case CVP_VADJUSTMENT:
+            g_value_set_object(value, view->adjustments[GTK_ORIENTATION_VERTICAL]);
             break;
-        case VPP_HSCROLL_POLICY:
-            g_value_set_enum(value, panel->hscroll_policy);
+        case CVP_HSCROLL_POLICY:
+            g_value_set_enum(value, view->scroll_policies[GTK_ORIENTATION_HORIZONTAL]);
             break;
-        case VPP_VSCROLL_POLICY:
-            g_value_set_enum(value, panel->vscroll_policy);
+        case CVP_VSCROLL_POLICY:
+            g_value_set_enum(value, view->scroll_policies[GTK_ORIENTATION_VERTICAL]);
             break;
         default:
             G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
@@ -400,6 +553,88 @@ static void gtk_display_panel_get_property(GObject *object, guint prop_id, GValu
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : widget       = composant GTK à examiner.                     *
+*                orientation  = direction à observer pour les calculs.        *
+*                for_size     = taille de la direction opposée.               *
+*                minimum      = taille minimale pour le composant. [OUT]      *
+*                natural      = taille idéale pour le composant. [OUT]        *
+*                min_baseline = ligne de base minimale. [OUT]                 *
+*                nat_baseline = ligne de base idéale. [OUT]                   *
+*                                                                             *
+*  Description : Fournit les mesures mainimale et idéale du composant.        *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void gtk_content_view_measure(GtkWidget *widget, GtkOrientation orientation, int for_size, int *minimum, int *natural, int *min_baseline, int *nat_baseline)
+{
+    GtkContentView *view;                   /* Version spécialisée         */
+    size_t i;                               /* Boucle de parcours          */
+    int min;                                /* Valeur minimale locale      */
+    int nat;                                /* Valeur idéale locale        */
+
+    view = GTK_CONTENT_VIEW(widget);
+
+    if (minimum != NULL) *minimum = 0;
+    if (natural != NULL) *natural = 0;
+
+    /* Demande de hauteur minimale / idéale */
+    if (orientation == GTK_ORIENTATION_VERTICAL)
+    {
+        for (i = 0; i < view->sub_count; i++)
+        {
+            gtk_widget_measure(view->sub_children[i], GTK_ORIENTATION_VERTICAL, -1, &min, &nat, NULL, NULL);
+
+            if (minimum != NULL && min > *minimum)
+                *minimum = min;
+
+            if (natural != NULL && nat > *natural)
+                *natural = nat;
+
+        }
+
+    }
+
+    /* Demande de largeur minimale / idéale */
+    else
+    {
+        for (i = 0; i < view->sub_count; i++)
+        {
+            gtk_widget_measure(view->sub_children[i], GTK_ORIENTATION_HORIZONTAL, -1, &min, &nat, NULL, NULL);
+
+            if (minimum != NULL) *minimum += min;
+            if (natural != NULL) *natural += nat;
+
+        }
+
+    }
+
+    if (min_baseline != NULL) *min_baseline = -1;
+    if (nat_baseline != NULL) *nat_baseline = -1;
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#if 0
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : widget = composant GTK à détruire.                           *
 *                                                                             *
 *  Description : Détruit un composant d'affichage.                            *
@@ -416,8 +651,11 @@ static void gtk_display_panel_destroy(GtkWidget *widget)
 
     panel = GTK_DISPLAY_PANEL(widget);
 
-    gtk_display_panel_disconnect_adjustment(panel, GTK_ORIENTATION_HORIZONTAL);
-    gtk_display_panel_disconnect_adjustment(panel, GTK_ORIENTATION_VERTICAL);
+    GtkContentView *view;                   /* Autre vision de l'instance  */
+
+    view = GTK_CONTENT_VIEW(widget);
+
+
 
     GTK_WIDGET_CLASS(gtk_display_panel_parent_class)->destroy(widget);
 
@@ -471,32 +709,6 @@ static void gtk_display_panel_realize(GtkWidget *widget)
 }
 
 
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : widget     = composant GTK à mettre à jour.                  *
-*                allocation = étendue accordée à la vue.                      *
-*                                                                             *
-*  Description : S'adapte à la surface concédée par le composant parent.      *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void gtk_display_panel_size_allocate(GtkWidget *widget, GtkAllocation *allocation)
-{
-    GtkDisplayPanel *panel;                 /* Autre version du composant  */
-
-    GTK_WIDGET_CLASS(gtk_display_panel_parent_class)->size_allocate(widget, allocation);
-
-    panel = GTK_DISPLAY_PANEL(widget);
-
-    gtk_display_panel_update_adjustment(panel, GTK_ORIENTATION_HORIZONTAL);
-    gtk_display_panel_update_adjustment(panel, GTK_ORIENTATION_VERTICAL);
-
-}
-
 
 /******************************************************************************
 *                                                                             *
@@ -560,29 +772,6 @@ static void gtk_display_panel_get_preferred_width(GtkWidget *widget, gint *minim
 }
 
 
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : panel       = composant GTK d'affichage à mettre à jour.     *
-*                size        = taille de l'espace dans la direction donnée.   *
-*                orientation = indication sur le défilement à traiter.        *
-*                step        = valeur d'un petit pas de défilement. [OUT]     *
-*                page        = valeur d'un grand pas de défilement. [OUT]     *
-*                                                                             *
-*  Description : Détermine la taille des bonds lors de défilements.           *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void gtk_display_panel_compute_scroll_inc(GtkDisplayPanel *panel, gint size, GtkOrientation orientation, gdouble *step, gdouble *page)
-{
-    *step = size * 0.1;
-    *page = size * 0.9;
-
-}
-
 
 /******************************************************************************
 *                                                                             *
@@ -653,151 +842,8 @@ static void gtk_display_panel_compute_allocation(GtkDisplayPanel *panel, GtkAllo
 }
 
 
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : panel       = composant GTK d'affichage à mettre à jour.     *
-*                orientation = indication sur le défilement à traiter.        *
-*                                                                             *
-*  Description : Se débarrsse d'un ajustement pour un défilement donné.       *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void gtk_display_panel_disconnect_adjustment(GtkDisplayPanel *panel, GtkOrientation orientation)
-{
-    GtkAdjustment **adjp;                   /* Ajustement à manipuler      */
-
-    adjp = orientation == GTK_ORIENTATION_HORIZONTAL ? &panel->hadjustment : &panel->vadjustment;
-
-    if (*adjp != NULL)
-    {
-        g_signal_handlers_disconnect_by_func(*adjp, gtk_display_panel_adjustment_value_changed, panel);
-        g_object_unref(G_OBJECT(*adjp));
-        *adjp = NULL;
-    }
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : panel       = composant GTK d'affichage à mettre à jour.     *
-*                orientation = indication sur le défilement à traiter.        *
-*                adj         = nouvel ajustement à prendre en compte.         *
-*                                                                             *
-*  Description : S'associe à un ajustement pour un défilement donné.          *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void gtk_display_panel_set_adjustment(GtkDisplayPanel *panel, GtkOrientation orientation, GtkAdjustment *adj)
-{
-    GtkAdjustment **adjp;                   /* Ajustement à manipuler      */
 
-    adjp = orientation == GTK_ORIENTATION_HORIZONTAL ? &panel->hadjustment : &panel->vadjustment;
 
-    /* S'il n'y a rien à faire... */
-    if (adj != NULL && adj == *adjp)
-        return;
-
-    if (!adj)
-        adj = gtk_adjustment_new(0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
-
-    gtk_display_panel_disconnect_adjustment(panel, orientation);
-
-    *adjp = adj;
-    g_object_ref_sink(adj);
-
-    gtk_display_panel_update_adjustment(panel, orientation);
-
-    g_signal_connect(adj, "value-changed", G_CALLBACK(gtk_display_panel_adjustment_value_changed), panel);
-
-    gtk_display_panel_adjustment_value_changed(adj, panel);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : panel       = composant GTK d'affichage à mettre à jour.     *
-*                orientation = indication sur le défilement à traiter.        *
-*                                                                             *
-*  Description : Ajuste les paramètres de défilement du composant.            *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void gtk_display_panel_update_adjustment(GtkDisplayPanel *panel, GtkOrientation orientation)
-{
-    GtkAllocation allocation;               /* Emplacement du contenu      */
-    GtkAdjustment *adj;                     /* Ajustement à manipuler      */
-    gint req;                               /* Dimension requise           */
-    gint allocated;                         /* Dimension allouée           */
-    gdouble step_inc;                       /* Pas de défilement           */
-    gdouble page_inc;                       /* ENjambée de défilement      */
-
-    gtk_display_panel_compute_allocation(panel, &allocation);
-
-    if (orientation == GTK_ORIENTATION_HORIZONTAL)
-    {
-        adj = panel->hadjustment;
-
-        gtk_widget_get_preferred_width(GTK_WIDGET(panel), &req, NULL);
-        allocated = allocation.width;
-
-    }
-    else
-    {
-        adj = panel->vadjustment;
-
-        gtk_widget_get_preferred_height(GTK_WIDGET(panel), &req, NULL);
-        allocated = allocation.height;
-
-    }
-
-    GTK_DISPLAY_PANEL_GET_CLASS(panel)->compute_inc(panel, allocated, orientation, &step_inc, &page_inc);
-
-    gtk_adjustment_configure(adj, gtk_adjustment_get_value(adj),
-                             0, MAX(req, allocated),
-                             step_inc,
-                             page_inc,
-                             allocated);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : adj   = défilement dont une valeur a changé.                 *
-*                panel = panneau d'affichage concerné.                        *
-*                                                                             *
-*  Description : Réagit à un défilement chez une barre associée au composant. *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void gtk_display_panel_adjustment_value_changed(GtkAdjustment *adj, GtkDisplayPanel *panel)
-{
-    GtkOrientation orientation;             /* Indification de la barre    */
-
-    orientation = (adj == panel->hadjustment ? GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL);
-
-    if (GTK_DISPLAY_PANEL_GET_CLASS(panel)->adjust != NULL)
-        GTK_DISPLAY_PANEL_GET_CLASS(panel)->adjust(panel, adj, orientation);
-
-}
 
 
 /******************************************************************************
diff --git a/src/gtkext/hexview-int.h b/src/gtkext/hexview-int.h
new file mode 100644
index 0000000..2b1c570
--- /dev/null
+++ b/src/gtkext/hexview-int.h
@@ -0,0 +1,71 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * hexview-int.h - définitions internes pour l'affichage de contenus de binaire
+ *
+ * Copyright (C) 2016-2024 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Chrysalide is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GTKEXT_HEXVIEW_INT_H
+#define _GTKEXT_HEXVIEW_INT_H
+
+
+#include "bufferview-int.h"
+#include "hexview.h"
+#include "../glibext/generators/hex.h"
+
+
+
+/* Composant d'affichage d'octets bruts et imprimables (instance) */
+struct _GtkHexView
+{
+    GtkBufferView parent;                   /* A laisser en premier        */
+
+    union
+    {
+#define _CHILDREN_COUNT 3
+
+        GtkWidget *children[_CHILDREN_COUNT];/* Sous-composants d'affichage*/
+
+        struct
+        {
+            GtkWidget *offsets;             /* Affichage des positions     */
+            GtkWidget *hex;                 /* Affichage des octets brut   */
+            GtkWidget *ascii;               /* Affichage des imprimables   */
+        };
+
+    };
+
+    GHexGenerator *generator;               /* Générateur unique dédié     */
+
+};
+
+/* Composant d'affichage d'octets bruts et imprimables (classe) */
+struct _GtkHexViewClass
+{
+    GtkBufferViewClass parent;              /* A laisser en premier        */
+
+};
+
+
+/* Met en place un nouveau composant d'affichage d'octets bruts. */
+bool gtk_hex_view_create(GtkHexView *, GBinContent *);
+
+
+
+#endif  /* _GTKEXT_HEXVIEW_INT_H */
diff --git a/src/gtkext/hexview.c b/src/gtkext/hexview.c
index 717c1bc..7363079 100644
--- a/src/gtkext/hexview.c
+++ b/src/gtkext/hexview.c
@@ -24,45 +24,17 @@
 #include "hexview.h"
 
 
-#include "area.h"
-#include "contentview-int.h"
-
-
-
-/* ------------------------- BASES D'UN COMPOSANT GRAPHIQUE ------------------------- */
-
+#include <alloca.h>
+#include <sys/param.h>
 
-/* Composant d'affichage d'octets bruts et imprimables (instance) */
-struct _GtkHexView
-{
-    GtkContentView parent;                  /* A laisser en premier        */
-
-    union
-    {
-#define _CHILDREN_COUNT 4
-
-        GtkWidget *children[_CHILDREN_COUNT];/* Sous-composants d'affichage*/
-
-        struct
-        {
-            GtkWidget *offsets;             /* Affichage des positions     */
-            GtkWidget *hex;                 /* Affichage des octets brut   */
-            GtkWidget *ascii;               /* Affichage des imprimables   */
-            GtkWidget *vscroll;             /* Barre de défilement         */
-        };
 
-    };
-
-    bool need_vscrolling;                   /* Besoin de défilement ?      */
+#include "area.h"
+#include "hexview-int.h"
+#include "../glibext/options/hex.h"
 
-};
 
-/* Composant d'affichage d'octets bruts et imprimables (classe) */
-struct _GtkHexViewClass
-{
-    GtkContentViewClass parent;             /* A laisser en premier        */
 
-};
+/* ------------------------- BASES D'UN COMPOSANT GRAPHIQUE ------------------------- */
 
 
 /* Procède à l'initialisation de l'afficheur générique. */
@@ -77,6 +49,12 @@ static void gtk_hex_view_dispose(GtkHexView *);
 /* Procède à la libération totale de la mémoire. */
 static void gtk_hex_view_finalize(GtkHexView *);
 
+/* Procède à l'actualisation de l'affichage d'un sous-composant. */
+static void gtk_hex_view_dispatch_sub_snapshot(GtkWidget *, GtkSnapshot *, GtkWidget *);
+
+/* Adapte le cache de lignes hexadécimales à la taille courante. */
+static void gtk_hex_view_populate_cache(GtkHexView *);
+
 
 
 void demo_snapshot (GtkWidget *widget, GtkSnapshot *snapshot, GtkWidget *parent);
@@ -105,7 +83,7 @@ static void gtk_hex_view_measure(GtkWidget *, GtkOrientation, int, int *, int *,
 
 
 /* Détermine le type du composant d'affichage générique. */
-G_DEFINE_TYPE(GtkHexView, gtk_hex_view, GTK_TYPE_CONTENT_VIEW);
+G_DEFINE_TYPE(GtkHexView, gtk_hex_view, GTK_TYPE_BUFFER_VIEW);
 
 
 /******************************************************************************
@@ -141,7 +119,6 @@ static void gtk_hex_view_class_init(GtkHexViewClass *class)
     gtk_widget_class_bind_template_child(widget, GtkHexView, offsets);
     gtk_widget_class_bind_template_child(widget, GtkHexView, hex);
     gtk_widget_class_bind_template_child(widget, GtkHexView, ascii);
-    gtk_widget_class_bind_template_child(widget, GtkHexView, vscroll);
 
     widget->size_allocate = gtk_hex_view_size_allocate;
     widget->get_request_mode = gtk_hex_view_get_request_mode;
@@ -164,15 +141,31 @@ static void gtk_hex_view_class_init(GtkHexViewClass *class)
 
 static void gtk_hex_view_init(GtkHexView *view)
 {
+    GtkContentView *base;                   /* Base d'instance supérieure  */
+
+    /* Niveau supérieur */
+
+    base = GTK_CONTENT_VIEW(view);
+
+    base->options = G_DISPLAY_OPTIONS(g_hex_options_new());
+
+    base->sub_children = view->children;
+    base->sub_count = _CHILDREN_COUNT;
+
+    /* Instance courante */
+
     gtk_widget_init_template(GTK_WIDGET(view));
 
-    g_raw_scan_cache_register_snapshot(GTK_COMPOSING_AREA(view->offsets), demo_snapshot, GTK_WIDGET(view));
+    g_raw_scan_cache_register_snapshot(GTK_COMPOSING_AREA(view->offsets),
+                                       gtk_hex_view_dispatch_sub_snapshot, GTK_WIDGET(view));
 
-    g_raw_scan_cache_register_snapshot(GTK_COMPOSING_AREA(view->hex), demo_snapshot, GTK_WIDGET(view));
+    g_raw_scan_cache_register_snapshot(GTK_COMPOSING_AREA(view->hex),
+                                       gtk_hex_view_dispatch_sub_snapshot, GTK_WIDGET(view));
 
-    g_raw_scan_cache_register_snapshot(GTK_COMPOSING_AREA(view->ascii), demo_snapshot, GTK_WIDGET(view));
+    g_raw_scan_cache_register_snapshot(GTK_COMPOSING_AREA(view->ascii),
+                                       gtk_hex_view_dispatch_sub_snapshot, GTK_WIDGET(view));
 
-    view->need_vscrolling = true;
+    view->generator = NULL;
 
 }
 
@@ -193,6 +186,8 @@ static void gtk_hex_view_dispose(GtkHexView *view)
 {
     gtk_widget_dispose_template(GTK_WIDGET(view), GTK_TYPE_HEX_VIEW);
 
+    g_clear_object(&view->generator);
+
     G_OBJECT_CLASS(gtk_hex_view_parent_class)->dispose(G_OBJECT(view));
 
 }
@@ -217,130 +212,225 @@ static void gtk_hex_view_finalize(GtkHexView *view)
 }
 
 
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : content = contenu binaire à exposer de façon brute.          *
+*                                                                             *
+*  Description : Crée un composant d'affichage d'octets bruts et imprimables. *
+*                                                                             *
+*  Retour      : Centralisateur mis en place pour un composant GTK donné.     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
 
+GtkHexView *gtk_hex_view_new(GBinContent *content)
+{
+    GtkHexView *result;                     /* Nouvelle instance à renvoyer*/
 
+    result = g_object_new(GTK_TYPE_HEX_VIEW, NULL);
 
+    if (!gtk_hex_view_create(result, content))
+        g_clear_object(&result);
 
+    return result;
 
+}
 
 
-void demo_snapshot (GtkWidget *widget, GtkSnapshot *snapshot, GtkWidget *parent)
-{
-  GdkRGBA red, green, yellow, blue;
-  float w, h;
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : view    = composant d'affichage à initialiser pleinement.    *
+*                content = contenu binaire à exposer de façon brute.          *
+*                                                                             *
+*  Description : Met en place un nouveau composant d'affichage d'octets bruts.*
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
 
-  gdk_rgba_parse (&red, "red");
-  gdk_rgba_parse (&green, "green");
-  gdk_rgba_parse (&yellow, "yellow");
-  gdk_rgba_parse (&blue, "blue");
+bool gtk_hex_view_create(GtkHexView *view, GBinContent *content)
+{
+    bool result;                            /* Bilan à retourner           */
+    GtkBufferView *parent;                  /* Version parente du composant*/
+    GBufferCache *cache;                    /* Tampon à représenter        */
 
-  w = gtk_widget_get_width (widget) / 2.0;
-  h = gtk_widget_get_height (widget) / 2.0;
+    result = true;
 
-  h /= 2.0;
+    assert(g_display_options_count(GTK_CONTENT_VIEW(view)->options) == 1);
 
-  gtk_snapshot_append_color (snapshot, &red,
-                             &GRAPHENE_RECT_INIT(0, 0, w, h));
-  gtk_snapshot_append_color (snapshot, &green,
-                             &GRAPHENE_RECT_INIT(w, 0, w, h));
-  gtk_snapshot_append_color (snapshot, &yellow,
-                             &GRAPHENE_RECT_INIT(0, h, w, h));
-  gtk_snapshot_append_color (snapshot, &blue,
-                             &GRAPHENE_RECT_INIT(w, h, w, h));
+    parent = GTK_BUFFER_VIEW(view);
 
+    cache = g_buffer_cache_new(1, 2);
 
+    parent->view = g_buffer_view_new(cache, parent->style);
 
+    unref_object(cache);
 
-  cairo_t *cr;
-  int x;
+    view->generator = g_hex_generator_new(content);
 
-  x = 0;
+    return result;
 
-  cr = gtk_snapshot_append_cairo(snapshot, &GRAPHENE_RECT_INIT(0, 0, w * 2, h * 2));
+}
 
-  g_token_style_draw_text(GTK_CONTENT_VIEW(parent)->style,
-                          TRT_RAW_FULL,
-                          cr,
-                          &x, 0,
-                          "A.A", 3);
 
-  g_token_style_draw_text(GTK_CONTENT_VIEW(parent)->style,
-                          TRT_RAW_NULL,
-                          cr,
-                          &x, 0,
-                          "A.A", 3);
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : widget   = composant GTK à redessiner.                       *
+*                snapshot = gestionnaire de noeuds de rendu à solliciter.     *
+*                parent   = composant GTK parent et cadre de l'appel.         *
+*                                                                             *
+*  Description : Procède à l'actualisation de l'affichage d'un sous-composant.*
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
 
-  cairo_destroy(cr);
+static void gtk_hex_view_dispatch_sub_snapshot(GtkWidget *widget, GtkSnapshot *snapshot, GtkWidget *parent)
+{
+    GtkHexView *view;                       /* Version spécialisée         */
+    size_t column;                          /* Indice de colonne à traiter */
+    int width;                              /* Largeur à disposition       */
+    int height;                             /* Hauteur à disposition       */
+    cairo_t *cr;                            /* Pinceau pour les dessins    */
 
+    view = GTK_HEX_VIEW(parent);
 
+    if (widget == view->offsets)
+        column = HCO_OFFSET;
 
-}
+    else if (widget == view->hex)
+        column = HCO_COUNT + 0;
 
+    else
+    {
+        assert(widget == view->ascii);
+        column = HCO_COUNT + 1;
+    }
 
+    width = gtk_widget_get_width(widget);
+    height = gtk_widget_get_height(widget);
 
+    cr = gtk_snapshot_append_cairo(snapshot, &GRAPHENE_RECT_INIT(0, 0, width, height));
 
+    g_buffer_view_draw(GTK_BUFFER_VIEW(parent)->view, cr, column, GTK_BUFFER_VIEW(parent)->virt_top, height);
 
+    cairo_destroy(cr);
 
+}
 
 
-bool g_buffer_view_allocate_widths(void *ptr, int width, int height, int fill, int *out);
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : view = composant GTK à mettre à jour.                        *
+*                                                                             *
+*  Description : Adapte le cache de lignes hexadécimales à la taille courante.*
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
 
-bool g_buffer_view_allocate_widths(void *ptr, int width, int height, int fill, int *out)
+static void gtk_hex_view_populate_cache(GtkHexView *view)
 {
+    GBinContent *content;                   /* Contenu binaire affiché     */
+    phys_t full;                            /* Taille totale à représenter */
+    phys_t line;                            /* Taille représentée par ligne*/
+    size_t needed;                          /* Nombre de lignes nécessaires*/
+    GBufferCache *cache;                    /* Tampon à représenter        */
+    size_t count;                           /* Nombre actuel de lignes     */
 
-    int i;                                  /* Boucle de parcours          */
+    /* Détermination du besoin */
 
+    content = g_hex_generator_get_content(view->generator);
 
-    for (i = 0; i < fill; i++)
-    {
+    full = g_binary_content_compute_size(content);
 
-        if (i == 0)
-        {
-            out[0] = 40;
-        }
+    unref_object(content);
 
-        else if ((i + 1) == fill)
-        {
-            out[i] = width;
-        }
+    line = g_hex_generator_get_bytes_per_line(view->generator);
 
-        else
-        {
-            out[i] = 230;
-        }
+    needed = full / line;
 
+    if (full % line > 0)
+        needed++;
 
-        width -= out[i];
+    /* Adaptation du tampon interne ? */
 
+    cache = g_buffer_view_get_cache(GTK_BUFFER_VIEW(view)->view);
 
+    g_buffer_cache_wlock(cache);
 
-    }
+    count = g_buffer_cache_count_lines(cache);
+
+    if (needed < count)
+        g_buffer_cache_truncate(cache, needed);
+
+    else if (needed > count)
+        g_buffer_cache_extend_with(cache, needed, G_TOKEN_GENERATOR(view->generator));
 
-    return false;
+    g_buffer_cache_wunlock(cache);
 
+    unref_object(cache);
+
+    /* Mise à jour de l'affichage ? */
+
+    if (needed != count)
+        gtk_widget_queue_resize(GTK_WIDGET(view));
 
 }
 
-int g_buffer_view_measure_height(void *ptr, int width);
 
-int g_buffer_view_measure_height(void *ptr, int width)
+
+
+
+
+
+void demo_snapshot (GtkWidget *widget, GtkSnapshot *snapshot, GtkWidget *parent)
 {
-    int result;                             /* Mesure à retourner          */
+  GdkRGBA red, green, yellow, blue;
+  float w, h;
 
-    if (width == -1)
-        result = 1;
+  gdk_rgba_parse (&red, "red");
+  gdk_rgba_parse (&green, "green");
+  gdk_rgba_parse (&yellow, "yellow");
+  gdk_rgba_parse (&blue, "blue");
 
-    else
-        result = 5000 / width;
+  w = gtk_widget_get_width (widget) / 2.0;
+  h = gtk_widget_get_height (widget) / 2.0;
+
+  h /= 2.0;
+
+  gtk_snapshot_append_color (snapshot, &red,
+                             &GRAPHENE_RECT_INIT(0, 0, w, h));
+  gtk_snapshot_append_color (snapshot, &green,
+                             &GRAPHENE_RECT_INIT(w, 0, w, h));
+  gtk_snapshot_append_color (snapshot, &yellow,
+                             &GRAPHENE_RECT_INIT(0, h, w, h));
+  gtk_snapshot_append_color (snapshot, &blue,
+                             &GRAPHENE_RECT_INIT(w, h, w, h));
 
-    result *= 16;
 
-    return result;
 
 }
 
 
 
+
+
+
+
+
+
+
+
+
+
 /* ---------------------------------------------------------------------------------- */
 /*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */
 /* ---------------------------------------------------------------------------------- */
@@ -364,68 +454,56 @@ int g_buffer_view_measure_height(void *ptr, int width)
 static void gtk_hex_view_size_allocate(GtkWidget *widget, int width, int height, int baseline)
 {
     GtkHexView *view;                       /* Version spécialisée         */
-    int vscroll_width;                      /* Largeur idéale de la barre  */
-
-    GtkAllocation allocated;                /* Zone allouée                */
+    int *min_widths;                        /* Tailles minimales imposées  */
+    int *final_widths;                      /* Tailles finales retenues    */
     size_t i;                               /* Boucle de parcours          */
-    int sub_widths[_CHILDREN_COUNT - 1];    /* Sous-largeurs calculées     */
+    int available;                          /* Largeur disponible          */
+    bool changed;                           /* Détection de variation      */
+    GWidthTracker *tracker;                 /* Collecteur de largeurs      */
 
     view = GTK_HEX_VIEW(widget);
 
-    allocated.y = 0;
-    allocated.height = height;
-
-    /* Barre de défilement ? */
-
-    view->need_vscrolling = g_buffer_view_allocate_widths(NULL, width, height, _CHILDREN_COUNT - 1, sub_widths);
+    min_widths = alloca(_CHILDREN_COUNT * sizeof(int));
+    final_widths = alloca(_CHILDREN_COUNT * sizeof(int));
 
-    gtk_widget_set_visible(view->vscroll, view->need_vscrolling);
+    for (i = 0; i < _CHILDREN_COUNT; i++)
+        gtk_widget_measure(view->children[i], GTK_ORIENTATION_HORIZONTAL, -1, &min_widths[i], NULL, NULL, NULL);
 
-    if (view->need_vscrolling)
-    {
-        gtk_widget_remove_css_class(widget, "without_vscroll");
-        gtk_widget_add_css_class(widget, "with_vscroll");
-    }
-    else
-    {
-        gtk_widget_remove_css_class(widget, "with_vscroll");
-        gtk_widget_add_css_class(widget, "without_vscroll");
-    }
+    /* Passe 1 : tentative sans défilement vertical */
 
-    /**
-     * Validité de la consistence des feuilles CSS : le changement de classe
-     * ne doit pas faire évoluer les tailles.
-     */
-    assert(view->need_vscrolling == g_buffer_view_allocate_widths(NULL, width, height, _CHILDREN_COUNT - 1, sub_widths));
+    available = width;
 
-    if (view->need_vscrolling)
-    {
-        gtk_widget_measure(view->vscroll, GTK_ORIENTATION_HORIZONTAL, height, &vscroll_width, NULL, NULL, NULL);
+    for (i = 0; i < _CHILDREN_COUNT; i++)
+        available -= min_widths[i];
 
-        allocated.x = width - vscroll_width;
-        allocated.width = vscroll_width;
+    changed = g_hex_generator_allocate(view->generator,
+                                       GTK_CONTENT_VIEW(view)->options,
+                                       GTK_BUFFER_VIEW(view)->style,
+                                       available, final_widths);
 
-        gtk_widget_size_allocate(view->vscroll, &allocated, baseline);
+    /* Application des largeurs calculées */
 
-        width -= vscroll_width;
+    if (changed)
+    {
+        gtk_hex_view_populate_cache(view);
 
-    }
+        tracker = g_buffer_view_get_tracker(GTK_BUFFER_VIEW(view)->view);
 
-    /* Placement des composants d'affichage */
+        for (i = 0; i < _CHILDREN_COUNT; i++)
+        {
+            final_widths[i] += min_widths[i];
 
-    g_buffer_view_allocate_widths(NULL, width, height, _CHILDREN_COUNT - 1, sub_widths);
+            g_width_tracker_set_column_min_width(tracker, i, final_widths[i]);
 
-    allocated.x = 0;
+        }
 
-    for (i = 0; i < (_CHILDREN_COUNT - 1); i++)
-    {
-        allocated.width = sub_widths[i];
+        unref_object(tracker);
 
-        gtk_widget_size_allocate(view->children[i], &allocated, baseline);
+    }
 
-        allocated.x += sub_widths[i];
+    /* Mise à jour des éléments plus internes */
 
-    }
+    GTK_WIDGET_CLASS(gtk_hex_view_parent_class)->size_allocate(widget, width, height, baseline);
 
 }
 
@@ -453,6 +531,17 @@ static GtkSizeRequestMode gtk_hex_view_get_request_mode(GtkWidget *widget)
 }
 
 
+
+
+
+
+
+
+
+
+
+
+
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : widget       = composant GTK à examiner.                     *
@@ -473,54 +562,60 @@ static GtkSizeRequestMode gtk_hex_view_get_request_mode(GtkWidget *widget)
 
 static void gtk_hex_view_measure(GtkWidget *widget, GtkOrientation orientation, int for_size, int *minimum, int *natural, int *min_baseline, int *nat_baseline)
 {
+    bool processed;                         /* Calcul de hauteur effectué  */
     GtkHexView *view;                       /* Version spécialisée         */
     int requested;                          /* Taille requise à priori     */
     size_t i;                               /* Boucle de parcours          */
     int min;                                /* Valeur minimale locale      */
     int nat;                                /* Valeur idéale locale        */
 
-    view = GTK_HEX_VIEW(widget);
+    processed = false;
 
     /* Demande de hauteur minimale / idéale */
-    if (orientation == GTK_ORIENTATION_VERTICAL)
+    if (orientation == GTK_ORIENTATION_VERTICAL && for_size != -1)
     {
-        requested = g_buffer_view_measure_height(NULL, for_size);
+        view = GTK_HEX_VIEW(widget);
 
-        if (minimum != NULL) *minimum = requested;
-        if (natural != NULL) *natural = requested;
+        requested = 0;
 
         for (i = 0; i < _CHILDREN_COUNT; i++)
         {
-            gtk_widget_measure(view->children[i], GTK_ORIENTATION_VERTICAL, -1, &min, &nat, NULL, NULL);
+            gtk_widget_measure(view->children[i], GTK_ORIENTATION_HORIZONTAL, -1, &min, NULL, NULL, NULL);
+            requested += min;
+        }
 
-            if (minimum != NULL && min > *minimum)
-                *minimum = min;
+        for_size -= requested;
 
-            if (natural != NULL && nat > *natural)
-                *natural = nat;
+        if (for_size > 0)
+        {
+            requested = g_hex_generator_mesure_height_for_width(view->generator,
+                                                                GTK_CONTENT_VIEW(view)->options,
+                                                                GTK_BUFFER_VIEW(view)->style,
+                                                                for_size);
 
-        }
+            if (minimum != NULL) *minimum = 0;
+            if (natural != NULL) *natural = requested;
 
-    }
+            for (i = 0; i < _CHILDREN_COUNT; i++)
+            {
+                gtk_widget_measure(view->children[i], GTK_ORIENTATION_VERTICAL, -1, &min, &nat, NULL, NULL);
 
-    /* Demande de largeur minimale / idéale */
-    else
-    {
-        if (minimum != NULL) *minimum = 0;
-        if (natural != NULL) *natural = 0;
+                if (minimum != NULL && min > *minimum)
+                    *minimum = min;
 
-        for (i = 0; i < _CHILDREN_COUNT; i++)
-        {
-            gtk_widget_measure(view->children[i], GTK_ORIENTATION_HORIZONTAL, -1, &min, &nat, NULL, NULL);
+                if (natural != NULL && nat > *natural)
+                    *natural = nat;
+
+            }
 
-            if (minimum != NULL) *minimum += min;
-            if (natural != NULL) *natural += nat;
+            processed = true;
 
         }
 
     }
 
-    if (min_baseline != NULL) *min_baseline = -1;
-    if (nat_baseline != NULL) *nat_baseline = -1;
+    if (!processed)
+        GTK_WIDGET_CLASS(gtk_hex_view_parent_class)->measure(widget, orientation, for_size,
+                                                           minimum, natural, min_baseline, nat_baseline);
 
 }
diff --git a/src/gtkext/hexview.h b/src/gtkext/hexview.h
index 8d3129d..2199786 100644
--- a/src/gtkext/hexview.h
+++ b/src/gtkext/hexview.h
@@ -28,6 +28,7 @@
 #include <gtk/gtk.h>
 
 
+#include "../analysis/content.h"
 #include "../glibext/helpers.h"
 
 
@@ -37,11 +38,8 @@
 DECLARE_GTYPE(GtkHexView, gtk_hex_view, GTK, HEX_VIEW);
 
 
-
-
-
-
-
+/* Crée un composant d'affichage d'octets bruts et imprimables. */
+GtkHexView *gtk_hex_view_new(GBinContent *);
 
 
 
diff --git a/src/gtkext/hexview.ui b/src/gtkext/hexview.ui
index df657ca..ae4586c 100644
--- a/src/gtkext/hexview.ui
+++ b/src/gtkext/hexview.ui
@@ -1,5 +1,5 @@
 <interface>
-  <template class="GtkHexView" parent="GtkContentView">
+  <template class="GtkHexView" parent="GtkBufferView">
     <property name="css-name">GtkHexView</property>
     <child>
       <object class="GtkComposingArea" id="offsets">
@@ -23,10 +23,5 @@
         </style>
       </object>
     </child>
-    <child>
-      <object class="GtkScrollbar" id="vscroll">
-        <property name="orientation">1</property>
-      </object>
-    </child>
   </template>
 </interface>
diff --git a/src/gui/core/Makefile.am b/src/gui/core/Makefile.am
index c219655..96ef578 100644
--- a/src/gui/core/Makefile.am
+++ b/src/gui/core/Makefile.am
@@ -13,7 +13,6 @@ RES_FILES =								\
 	../../../pixmaps/snapshot_current.png
 
 libguicore_la_SOURCES =					\
-	core.h core.c						\
 	global.h global.c					\
 	items.h items.c						\
 	panels.h panels.c					\
@@ -23,7 +22,8 @@ libguicore_la_SOURCES =					\
 libguicore_la_CFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS)
 
 
-libguicore4_la_SOURCES =				\
+libguicore4_la_SOURCES =					\
+	core.h core.c							\
 	logs.h logs.c
 
 libguicore4_la_CFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS)
diff --git a/src/gui/core/core.c b/src/gui/core/core.c
index 6bebfe2..2d47dc9 100644
--- a/src/gui/core/core.c
+++ b/src/gui/core/core.c
@@ -24,6 +24,80 @@
 #include "core.h"
 
 
+#include "../../glibext/linetoken.h"
+
+
+
+/* Statuts de chargement */
+static AvailableGuiComponent __loaded = AGC_NONE;
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : flags = liste d'éléments à charger.                          *
+*                                                                             *
+*  Description : Charge les éléments graphiques de l'éditeur.                 *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool load_gui_components(AvailableGuiComponent flags)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    result = true;
+
+    if ((flags & AGC_BUFFER_FEATURES) != 0 && (__loaded & AGC_BUFFER_FEATURES) == 0)
+    {
+        result = init_segment_content_hash_table();
+        if (!result) goto done;
+
+        __loaded |= AGC_BUFFER_FEATURES;
+
+    }
+
+ done:
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : flags = liste d'éléments à décharger.                        *
+*                                                                             *
+*  Description : Décharge les éléments graphiques de l'éditeur.               *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void unload_gui_components(AvailableGuiComponent flags)
+{
+    if ((flags & AGC_BUFFER_FEATURES) != 0 && (__loaded & AGC_BUFFER_FEATURES) == 0)
+    {
+        exit_segment_content_hash_table();
+
+        __loaded &= ~AGC_BUFFER_FEATURES;
+
+    }
+
+}
+
+
+
+
+
+
+
+#if 0
+
 #include "global.h"
 #include "items.h"
 #include "panels.h"
@@ -201,3 +275,5 @@ void unload_all_gui_components(void)
     unload_all_themes();
 
 }
+
+#endif
diff --git a/src/gui/core/core.h b/src/gui/core/core.h
index c043434..bcb5433 100644
--- a/src/gui/core/core.h
+++ b/src/gui/core/core.h
@@ -25,10 +25,34 @@
 #define _GUI_CORE_CORE_H
 
 
-#include <glib-object.h>
 #include <stdbool.h>
 
 
+
+/* Eléments à (dé)charger disponibles */
+typedef enum _AvailableGuiComponent
+{
+    AGC_NONE            = (0 << 0),         /* Statut initial              */
+    AGC_BUFFER_FEATURES = (1 << 0),         /* Tampons de bribes de texte  */
+
+} AvailableGuiComponent;
+
+/* Charge les éléments graphiques de l'éditeur. */
+bool load_gui_components(AvailableGuiComponent);
+
+/* Décharge les éléments graphiques de l'éditeur. */
+void unload_gui_components(AvailableGuiComponent);
+
+
+
+
+
+
+#if 0
+
+#include <glib-object.h>
+
+
 #include "../../glibext/configuration.h"
 
 
@@ -43,5 +67,8 @@ bool complete_loading_of_all_gui_components(GGenConfig *);
 void unload_all_gui_components(void);
 
 
+#endif
+
+
 
 #endif  /* _GUI_CORE_CORE_H */
-- 
cgit v0.11.2-87-g4458