From 19516ffcca14abb082c5109125b7249bdc7fc199 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Thu, 23 Jul 2020 13:21:16 +0200
Subject: Renamed some files.

---
 plugins/pychrysalide/glibext/buffercache.c |    4 +-
 plugins/pychrysalide/glibext/bufferline.c  |    4 +-
 plugins/pychrysalide/glibext/bufferview.c  |    4 +-
 plugins/pychrysalide/glibext/constants.c   |    2 +-
 src/analysis/binary.h                      |    2 +-
 src/analysis/block.h                       |    2 +-
 src/analysis/db/items/comment.h            |    2 +-
 src/analysis/disass/output.h               |    2 +-
 src/arch/operand.h                         |    2 +-
 src/arch/operands/feeder.h                 |    2 +-
 src/arch/register.h                        |    2 +-
 src/glibext/Makefile.am                    |   12 +-
 src/glibext/buffercache-int.h              |   96 ++
 src/glibext/buffercache.c                  | 1725 ++++++++++++++++++++++++++++
 src/glibext/buffercache.h                  |  133 +++
 src/glibext/bufferline.c                   | 1558 +++++++++++++++++++++++++
 src/glibext/bufferline.h                   |  218 ++++
 src/glibext/bufferview.c                   | 1285 +++++++++++++++++++++
 src/glibext/bufferview.h                   |  115 ++
 src/glibext/gbuffercache-int.h             |   96 --
 src/glibext/gbuffercache.c                 | 1725 ----------------------------
 src/glibext/gbuffercache.h                 |  133 ---
 src/glibext/gbufferline.c                  | 1558 -------------------------
 src/glibext/gbufferline.h                  |  218 ----
 src/glibext/gbufferview.c                  | 1285 ---------------------
 src/glibext/gbufferview.h                  |  115 --
 src/glibext/generators/hex.c               |    2 +-
 src/glibext/generators/prologue.c          |    2 +-
 src/glibext/generators/rborder.c           |    2 +-
 src/glibext/gwidthtracker.c                | 1271 --------------------
 src/glibext/gwidthtracker.h                |   95 --
 src/glibext/linegen.h                      |    2 +-
 src/glibext/widthtracker.c                 | 1271 ++++++++++++++++++++
 src/glibext/widthtracker.h                 |   95 ++
 src/gtkext/gtkblockdisplay.h               |    2 +-
 src/gtkext/gtkbufferdisplay.h              |    2 +-
 36 files changed, 6522 insertions(+), 6522 deletions(-)
 create mode 100644 src/glibext/buffercache-int.h
 create mode 100644 src/glibext/buffercache.c
 create mode 100644 src/glibext/buffercache.h
 create mode 100644 src/glibext/bufferline.c
 create mode 100644 src/glibext/bufferline.h
 create mode 100644 src/glibext/bufferview.c
 create mode 100644 src/glibext/bufferview.h
 delete mode 100644 src/glibext/gbuffercache-int.h
 delete mode 100644 src/glibext/gbuffercache.c
 delete mode 100644 src/glibext/gbuffercache.h
 delete mode 100644 src/glibext/gbufferline.c
 delete mode 100644 src/glibext/gbufferline.h
 delete mode 100644 src/glibext/gbufferview.c
 delete mode 100644 src/glibext/gbufferview.h
 delete mode 100644 src/glibext/gwidthtracker.c
 delete mode 100644 src/glibext/gwidthtracker.h
 create mode 100644 src/glibext/widthtracker.c
 create mode 100644 src/glibext/widthtracker.h

diff --git a/plugins/pychrysalide/glibext/buffercache.c b/plugins/pychrysalide/glibext/buffercache.c
index fec5844..019d981 100644
--- a/plugins/pychrysalide/glibext/buffercache.c
+++ b/plugins/pychrysalide/glibext/buffercache.c
@@ -1,6 +1,6 @@
 
 /* Chrysalide - Outil d'analyse de fichiers binaires
- * buffercache.c - équivalent Python du fichier "glibext/gbuffercache.c"
+ * buffercache.c - équivalent Python du fichier "glibext/buffercache.c"
  *
  * Copyright (C) 2018-2019 Cyrille Bagard
  *
@@ -28,7 +28,7 @@
 #include <pygobject.h>
 
 
-#include <glibext/gbuffercache-int.h>
+#include <glibext/buffercache-int.h>
 #include <plugins/dt.h>
 
 
diff --git a/plugins/pychrysalide/glibext/bufferline.c b/plugins/pychrysalide/glibext/bufferline.c
index af3cf1d..dc59b85 100644
--- a/plugins/pychrysalide/glibext/bufferline.c
+++ b/plugins/pychrysalide/glibext/bufferline.c
@@ -1,6 +1,6 @@
 
 /* Chrysalide - Outil d'analyse de fichiers binaires
- * bufferline.c - équivalent Python du fichier "glibext/gbufferline.h"
+ * bufferline.c - équivalent Python du fichier "glibext/bufferline.h"
  *
  * Copyright (C) 2018-2019 Cyrille Bagard
  *
@@ -31,7 +31,7 @@
 
 
 #include <i18n.h>
-#include <glibext/gbufferline.h>
+#include <glibext/bufferline.h>
 #include <plugins/dt.h>
 
 
diff --git a/plugins/pychrysalide/glibext/bufferview.c b/plugins/pychrysalide/glibext/bufferview.c
index 725dd1a..98cc10a 100644
--- a/plugins/pychrysalide/glibext/bufferview.c
+++ b/plugins/pychrysalide/glibext/bufferview.c
@@ -1,6 +1,6 @@
 
 /* Chrysalide - Outil d'analyse de fichiers binaires
- * bufferview.c - équivalent Python du fichier "glibext/gbufferview.c"
+ * bufferview.c - équivalent Python du fichier "glibext/bufferview.c"
  *
  * Copyright (C) 2019 Cyrille Bagard
  *
@@ -28,7 +28,7 @@
 #include <pygobject.h>
 
 
-#include <glibext/gbufferview.h>
+#include <glibext/bufferview.h>
 
 
 #include "../access.h"
diff --git a/plugins/pychrysalide/glibext/constants.c b/plugins/pychrysalide/glibext/constants.c
index a7938cb..3f657e2 100644
--- a/plugins/pychrysalide/glibext/constants.c
+++ b/plugins/pychrysalide/glibext/constants.c
@@ -26,9 +26,9 @@
 
 
 #include <i18n.h>
+#include <glibext/bufferline.h>
 #include <glibext/linesegment.h>
 #include <glibext/gbinportion.h>
-#include <glibext/gbufferline.h>
 #include <glibext/gloadedpanel.h>
 
 
diff --git a/src/analysis/binary.h b/src/analysis/binary.h
index 178d186..194ccd0 100644
--- a/src/analysis/binary.h
+++ b/src/analysis/binary.h
@@ -36,7 +36,7 @@
 #include "../arch/processor.h"
 #include "../format/debuggable.h"
 #include "../format/executable.h"
-#include "../glibext/gbuffercache.h"
+#include "../glibext/buffercache.h"
 
 
 
diff --git a/src/analysis/block.h b/src/analysis/block.h
index f902db0..63f0be0 100644
--- a/src/analysis/block.h
+++ b/src/analysis/block.h
@@ -33,7 +33,7 @@
 #include "../arch/instruction.h"
 #include "../arch/vmpa.h"
 #include "../common/bits.h"
-#include "../glibext/gbufferview.h"
+#include "../glibext/bufferview.h"
 #include "../glibext/linesegment.h"
 
 
diff --git a/src/analysis/db/items/comment.h b/src/analysis/db/items/comment.h
index 4eb1160..7049b28 100644
--- a/src/analysis/db/items/comment.h
+++ b/src/analysis/db/items/comment.h
@@ -30,7 +30,7 @@
 
 
 #include "../../../arch/vmpa.h"
-#include "../../../glibext/gbufferline.h"
+#include "../../../glibext/bufferline.h"
 
 
 
diff --git a/src/analysis/disass/output.h b/src/analysis/disass/output.h
index 6b00250..20729d2 100644
--- a/src/analysis/disass/output.h
+++ b/src/analysis/disass/output.h
@@ -28,7 +28,7 @@
 #include "../binary.h"
 #include "../human/lang.h"
 #include "../../format/preload.h"
-#include "../../glibext/gbuffercache.h"
+#include "../../glibext/buffercache.h"
 #include "../../gtkext/gtkstatusstack.h"
 
 
diff --git a/src/arch/operand.h b/src/arch/operand.h
index 5789169..faeab49 100644
--- a/src/arch/operand.h
+++ b/src/arch/operand.h
@@ -30,7 +30,7 @@
 
 #include "../common/packed.h"
 #include "../format/format.h"
-#include "../glibext/gbufferline.h"
+#include "../glibext/bufferline.h"
 
 
 
diff --git a/src/arch/operands/feeder.h b/src/arch/operands/feeder.h
index 7cea504..d2b2cff 100644
--- a/src/arch/operands/feeder.h
+++ b/src/arch/operands/feeder.h
@@ -31,7 +31,7 @@
 
 #include "../../common/packed.h"
 #include "../../format/format.h"
-#include "../../glibext/gbufferline.h"
+#include "../../glibext/bufferline.h"
 
 
 
diff --git a/src/arch/register.h b/src/arch/register.h
index 48e8eff..10fa428 100644
--- a/src/arch/register.h
+++ b/src/arch/register.h
@@ -29,7 +29,7 @@
 #include <stdbool.h>
 
 
-#include "../glibext/gbufferline.h"
+#include "../glibext/bufferline.h"
 
 
 
diff --git a/src/glibext/Makefile.am b/src/glibext/Makefile.am
index 4739fef..118ca39 100644
--- a/src/glibext/Makefile.am
+++ b/src/glibext/Makefile.am
@@ -4,6 +4,10 @@ BUILT_SOURCES = chrysamarshal.h chrysamarshal.c
 noinst_LTLIBRARIES  = libglibext.la
 
 libglibext_la_SOURCES =					\
+	buffercache-int.h					\
+	buffercache.h buffercache.c			\
+	bufferline.h bufferline.c			\
+	bufferview.h bufferview.c			\
 	chrysamarshal.h chrysamarshal.c		\
 	configuration.h configuration.c		\
 	delayed-int.h						\
@@ -11,17 +15,12 @@ libglibext_la_SOURCES =					\
 	gbinarycursor.h gbinarycursor.c		\
 	gbinportion-int.h					\
 	gbinportion.h gbinportion.c			\
-	gbuffercache-int.h					\
-	gbuffercache.h gbuffercache.c		\
-	gbufferline.h gbufferline.c			\
-	gbufferview.h gbufferview.c			\
 	gdisplayoptions.h gdisplayoptions.c	\
 	glinecursor-int.h					\
 	glinecursor.h glinecursor.c			\
 	gloadedpanel-int.h					\
 	gloadedpanel.h gloadedpanel.c		\
 	gnhash.h gnhash.c					\
-	gwidthtracker.h gwidthtracker.c		\
 	linecolumn.h linecolumn.c			\
 	linegen-int.h						\
 	linegen.h linegen.c					\
@@ -29,7 +28,8 @@ libglibext_la_SOURCES =					\
 	objhole.h							\
 	proto.h								\
 	seq.h seq.c							\
-	signal.h signal.c
+	signal.h signal.c					\
+	widthtracker.h widthtracker.c
 
 libglibext_la_LIBADD = 					\
 	generators/libglibextgenerators.la
diff --git a/src/glibext/buffercache-int.h b/src/glibext/buffercache-int.h
new file mode 100644
index 0000000..3dfd5e2
--- /dev/null
+++ b/src/glibext/buffercache-int.h
@@ -0,0 +1,96 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * buffercache-int.h - définitions internes d'affichage à la demande d'un ensemble de lignes
+ *
+ * Copyright (C) 2020 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_BUFFERCACHE_INT_H
+#define _GLIBEXT_BUFFERCACHE_INT_H
+
+
+#include "buffercache.h"
+
+
+
+/* --------------------- FONCTIONS AUXILIAIRES DE MANIPULATIONS --------------------- */
+
+
+/* Informations rattachées à la génération d'une ligne */
+typedef struct _generator_link
+{
+    GLineGenerator *instance;               /* Fournisseur de contenu      */
+    size_t repeat;                          /* Compteur de successions     */
+
+} generator_link;
+
+/* Suivi interne de l'état d'une ligne */
+typedef struct _cache_info
+{
+    union
+    {
+        generator_link generator;           /* Générateur unique           */
+        generator_link *generators;         /* Liste de générateurs        */
+    };
+    size_t count;                           /* Taille de cette liste       */
+
+    GBufferLine *line;                      /* Ligne en place ou NULL      */
+
+    BufferLineFlags extra_flags;            /* Propriétés supplémentaires  */
+
+} cache_info;
+
+
+
+/* -------------------------- TAMPON POUR CODE DESASSEMBLE -------------------------- */
+
+
+/* Tampon pour gestion de lignes optimisée (instance) */
+struct _GBufferCache
+{
+    GObject parent;                         /* A laisser en premier        */
+
+    GBinContent *content;                   /* Contenu binaire global      */
+
+    cache_info *lines;                      /* Liste des lignes intégrées  */
+    size_t count;                           /* Quantité en cache           */
+    size_t used;                            /* Quantité utilisée           */
+
+    GWidthTracker *tracker;                 /* Suivi des largeurs          */
+
+};
+
+/* Tampon pour gestion de lignes optimisée (classe) */
+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);
+
+};
+
+
+
+#endif  /* _GLIBEXT_BUFFERCACHE_INT_H */
diff --git a/src/glibext/buffercache.c b/src/glibext/buffercache.c
new file mode 100644
index 0000000..16d96dc
--- /dev/null
+++ b/src/glibext/buffercache.c
@@ -0,0 +1,1725 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * buffercache.c - affichage à la demande d'un ensemble de lignes
+ *
+ * Copyright (C) 2016-2019 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Chrysalide is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "buffercache.h"
+
+
+#include <assert.h>
+#include <malloc.h>
+#include <stdlib.h>
+
+
+#include "buffercache-int.h"
+#include "chrysamarshal.h"
+
+
+
+/* --------------------- 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);
+
+/* Libère la mémoire occupée par des informations sur une ligne. */
+static void release_cache_info(cache_info *);
+
+/* Ajoute un générateur aux informations sur une ligne. */
+static void extend_cache_info(cache_info *, GLineGenerator *, BufferLineFlags);
+
+/* Retire un générateur aux informations d'une ligne. */
+static void remove_from_cache_info(cache_info *, 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);
+
+/* Fournit la ligne de tampon correspondant aux générateurs. */
+static GBufferLine *get_cache_info_line(cache_info *, size_t, const GBinContent *);
+
+/* 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 *);
+
+
+
+/* -------------------------- TAMPON POUR CODE DESASSEMBLE -------------------------- */
+
+
+/* Taille des allocations de masse */
+#define LINE_ALLOC_BULK 1000
+
+
+/* Procède à l'initialisation d'une classe de tampon de lignes. */
+static void g_buffer_cache_class_init(GBufferCacheClass *);
+
+/* Procède à l'initialisation d'un tampon de gestion de lignes. */
+static void g_buffer_cache_init(GBufferCache *);
+
+/* Supprime toutes les références externes. */
+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 *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                       FONCTIONS AUXILIAIRES DE MANIPULATIONS                       */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : info      = informations concernant une ligne à constituer.  *
+*                generator = générateur à associer à toutes les lignes.       *
+*                repeat    = compteur de répétition entre les lignes.         *
+*                flags     = propriétés supplémentaires à associer à la ligne.*
+*                                                                             *
+*  Description : Met en place un nouvel ensemble d'information sur une ligne. *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void init_cache_info(cache_info *info, GLineGenerator *generator, size_t repeat, BufferLineFlags flags)
+{
+    info->generator.instance = generator;
+    info->generator.repeat = repeat;
+
+    g_object_ref(G_OBJECT(generator));
+
+    info->count = 1;
+
+    info->line = NULL;
+
+    info->extra_flags = flags;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : info = informations concernant une ligne à constituer.       *
+*                                                                             *
+*  Description : Libère la mémoire occupée par des informations sur une ligne.*
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void release_cache_info(cache_info *info)
+{
+    size_t i;                               /* Boucle de parcours          */
+
+    if (info->count == 1)
+        g_object_unref(G_OBJECT(info->generator.instance));
+
+    else
+        for (i = 0; i < info->count; i++)
+            g_object_unref(G_OBJECT(info->generators[i].instance));
+
+    reset_cache_info_line(info);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  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.*
+*                                                                             *
+*  Description : Ajoute un générateur aux informations sur une ligne.         *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void extend_cache_info(cache_info *info, GLineGenerator *generator, BufferLineFlags flags)
+{
+    generator_link first;                   /* Générateur déjà en place    */
+    generator_link *new;                    /* Nouveau générateur placé    */
+
+    if (info->count == 1)
+    {
+        first = info->generator;
+
+        info->generators = (generator_link *)calloc(2, sizeof(generator_link));
+
+        info->generators[0] = first;
+        info->count = 2;
+
+        new = &info->generators[1];
+
+    }
+    else
+    {
+        info->generators = (generator_link *)realloc(info->generators,
+                                                     ++info->count * sizeof(generator_link));
+
+        new = &info->generators[info->count - 1];
+
+    }
+
+    new->instance = generator;
+    new->repeat = 0;
+
+    g_object_ref(G_OBJECT(generator));
+
+    reset_cache_info_line(info);
+
+    /**
+     * On peut rajouter des indications, mais, en cas de retrait d'un générateur,
+     * on ne saura pas forcément lesquelles retirer puisque qu'on ne trace pas
+     * leur origine.
+     *
+     * On considère donc que seul le premier générateur (le principal) a le
+     * droit de poser des fanions.
+     */
+
+    assert(flags == BLF_NONE);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : info      = informations concernant une ligne à actualiser.  *
+*                generator = générateur à dissocier de toutes les lignes.     *
+*                                                                             *
+*  Description : Retire un générateur aux informations d'une ligne.           *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void remove_from_cache_info(cache_info *info, GLineGenerator *generator)
+{
+    generator_link *link;                   /* Accès simplifié             */
+    size_t i;                               /* Boucle de parcours          */
+    generator_link *old;                    /* Mémorisation avant opérat°  */
+
+    if (info->count == 1)
+    {
+        link = &info->generator;
+
+        assert(link->instance == generator);
+
+        g_object_unref(G_OBJECT(generator));
+
+        info->count = 0;
+
+    }
+
+    else
+    {
+        for (i = 0; i < info->count; i++)
+        {
+            link = &info->generators[i];
+
+            if (link->instance == generator)
+            {
+                if ((i + 1) < info->count)
+                    memmove(&info->generators[i], &info->generators[i + 1],
+                            (info->count - i - 1) * sizeof(generator_link));
+
+                if (info->count == 2)
+                {
+                    old = info->generators;
+
+                    info->count = 1;
+                    info->generator = info->generators[0];
+
+                    free(old);
+
+                }
+                else
+                    info->generators = (generator_link *)realloc(info->generators,
+                                                                 --info->count * sizeof(generator_link));
+
+                g_object_unref(G_OBJECT(generator));
+
+                break;
+
+            }
+
+        }
+
+#ifndef NDEBUG
+
+        /**
+         * Attention : si l'élément était en dernière position,
+         * l'indice de parcours est désormais égal au nombre de générateurs présents !
+         */
+        assert(i <= info->count);
+
+        for ( ; i < info->count; i++)
+        {
+            link = &info->generators[i];
+
+            assert(link->instance != generator);
+
+        }
+
+#endif
+
+    }
+
+    reset_cache_info_line(info);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : info   = informations sur une ligne à venir consulter.       *
+*                index  = indice de la ligne visée par la consultation.       *
+*                x      = position géographique sur la ligne concernée.       *
+*                cursor = emplacement à constituer. [OUT]                     *
+*                                                                             *
+*  Description : Retrouve l'emplacement correspondant à une position de ligne.*
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void get_cache_info_cursor(const cache_info *info, size_t index, gint x, GLineCursor **cursor)
+{
+    const generator_link *generator;        /* Générateur retenu           */
+
+    if (info->count == 1)
+        generator = &info->generator;
+    else
+        generator = &info->generators[0];
+
+    *cursor = g_line_generator_compute_cursor(generator->instance, x, index, generator->repeat);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  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 *info, GBufferLine *line, gboolean last)
+{
+    if (last)
+    {
+        G_LOCK(_line_update);
+
+        assert(info->line != NULL);
+
+        _reset_cache_info_line_unlocked(info);
+
+        G_UNLOCK(_line_update);
+
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : info    = informations sur une ligne à venir manipuler.      *
+*                index   = indice de la ligne à constituer.                   *
+*                content = éventuel contenu binaire brut à imprimer.          *
+*                                                                             *
+*  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 *info, size_t index, const GBinContent *content)
+{
+    GBufferLine *result;                    /* Construction à retourner    */
+    size_t i;                               /* Boucle de parcours          */
+
+    G_LOCK(_line_update);
+
+    result = info->line;
+
+    if (result == NULL)
+    {
+        result = g_buffer_line_new(UNUSED_MRANGE_PTR, 0/* !! */);
+
+        g_object_add_toggle_ref(G_OBJECT(result), (GToggleNotify)on_line_ref_toggle, info);
+
+        if (info->count == 1)
+            g_line_generator_print(info->generator.instance, result, index,
+                                   info->generator.repeat, content);
+
+        else
+            for (i = 0; i < info->count; i++)
+                g_line_generator_print(info->generators[i].instance, result, index,
+                                       info->generators[i].repeat, content);
+
+        info->line = result;
+
+    }
+
+    else
+        g_object_ref(G_OBJECT(result));
+
+    G_UNLOCK(_line_update);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  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_unlocked(cache_info *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.         *
+*                                                                             *
+*  Description : Force la réinitialisation d'une éventuelle ligne cachée.     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void reset_cache_info_line(cache_info *info)
+{
+    G_LOCK(_line_update);
+
+    _reset_cache_info_line_unlocked(info);
+
+    G_UNLOCK(_line_update);
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                            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  : class = classe de composant GLib à initialiser.              *
+*                                                                             *
+*  Description : Procède à l'initialisation d'une classe de tampon de lignes. *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_buffer_cache_class_init(GBufferCacheClass *class)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+
+    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;
+
+    /* 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);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : cache = composant GLib à initialiser.                        *
+*                                                                             *
+*  Description : Procède à l'initialisation d'un tampon de gestion de lignes. *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_buffer_cache_init(GBufferCache *cache)
+{
+    cache->content = NULL;
+
+    cache->lines = NULL;
+    cache->count = 0;
+    cache->used = 0;
+
+    cache->tracker = g_width_tracker_new(cache);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  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)
+{
+    size_t i;                               /* Boucle de parcours #1       */
+    cache_info *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_clear_object(&info->generator.instance);
+
+        else
+            for (j = 0; j < info->count; j++)
+                g_clear_object(&info->generators[j].instance);
+
+        g_clear_object(&info->line);
+
+    }
+
+    g_clear_object(&cache->tracker);
+
+    G_OBJECT_CLASS(g_buffer_cache_parent_class)->dispose(G_OBJECT(cache));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : cache = instance d'objet GLib à traiter.                     *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_buffer_cache_finalize(GBufferCache *cache)
+{
+    size_t i;                               /* Boucle de parcours          */
+    cache_info *info;                       /* Accès direct à une ligne    */
+
+    for (i = 0; i < cache->used; i++)
+    {
+        info = &cache->lines[i];
+
+        if (info->count > 1)
+            free(info->generators);
+
+    }
+
+    if (cache->lines != NULL)
+        free(cache->lines);
+
+    G_OBJECT_CLASS(g_buffer_cache_parent_class)->finalize(G_OBJECT(cache));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : content = éventuel contenu binaire brut à référencer.        *
+*                                                                             *
+*  Description : Crée un nouveau composant de tampon pour code désassemblé.   *
+*                                                                             *
+*  Retour      : Composant GLib créé.                                         *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GBufferCache *g_buffer_cache_new(GBinContent *content)
+{
+    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));
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : cache = tampon de lignes à consulter.                        *
+*                                                                             *
+*  Description : Fournit la hauteur d'impression d'une ligne visualisée.      *
+*                                                                             *
+*  Retour      : Hauteur de ligne en pixels.                                  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+gint g_buffer_cache_get_line_height(const GBufferCache *cache)
+{
+    GBufferCacheClass *class;               /* Classe des tampons          */
+
+    class = G_BUFFER_CACHE_GET_CLASS(cache);
+
+    return class->line_height;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : cache = tampon de lignes à consulter.                        *
+*                                                                             *
+*  Description : Indique l'éventuel contenu binaire associé au cache.         *
+*                                                                             *
+*  Retour      : Eventuel contenu renseigné ou NULL.                          *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GBinContent *g_buffer_cache_get_content(const GBufferCache *cache)
+{
+    GBinContent *result;                    /* Contenu à retourner         */
+
+    result = cache->content;
+
+    if (result != NULL)
+        g_object_ref(G_OBJECT(result));
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : cache = tampon de lignes à consulter.                        *
+*                                                                             *
+*  Description : Fournit la taille réservée pour la marge gauche.             *
+*                                                                             *
+*  Retour      : Largeur en pixels.                                           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+gint g_buffer_cache_get_left_margin(const GBufferCache *cache)
+{
+    GBufferCacheClass *class;               /* Classe des tampons          */
+
+    class = G_BUFFER_CACHE_GET_CLASS(cache);
+
+    return class->left_margin;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : cache = tampon de lignes à consulter.                        *
+*                                                                             *
+*  Description : Fournit la position de départ pour l'impression de texte.    *
+*                                                                             *
+*  Retour      : Position en pixels.                                          *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+gint g_buffer_cache_get_text_position(const GBufferCache *cache)
+{
+    GBufferCacheClass *class;               /* Classe des tampons          */
+
+    class = G_BUFFER_CACHE_GET_CLASS(cache);
+
+    return class->text_pos;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  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(const GBufferCache *cache)
+{
+    return cache->used;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : cache = composant GLib à consulter.                          *
+*                                                                             *
+*  Description : Fournit un lien vers la structure de suivi de largeurs.      *
+*                                                                             *
+*  Retour      : Gestionnaire de largeurs de lignes.                          *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GWidthTracker *g_buffer_cache_get_width_tracker(const GBufferCache *cache)
+{
+    GWidthTracker *result;                  /* Instance à retourner    *   */
+
+    result = cache->tracker;
+
+    g_object_ref(G_OBJECT(result));
+
+    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;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : cache     = instance GLib à modifier.                        *
+*                index     = point d'insertion, puis de sauvegarde.           *
+*                generator = générateur à insérer dans les lignes.            *
+*                flags     = propriétés supplémentaires à associer à la ligne.*
+*                before    = précise l'emplacement final des nouvelles lignes.*
+*                after     = précise l'emplacement final des nouvelles lignes.*
+*                                                                             *
+*  Description : Insère un générateur dans des lignes à une position donnée.  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_buffer_cache_insert_at(GBufferCache *cache, size_t index, GLineGenerator *generator, BufferLineFlags flags, bool before, bool after)
+{
+#ifndef NDEBUG
+    GLineCursor *gen_cursor;                /* Position du générateur      */
+    GLineCursor *line_cursor;               /* Position de la ligne        */
+    int ret;                                /* Bilan de comparaison        */
+#endif
+    size_t needed;                          /* Emplacements nécessaires    */
+    size_t i;                               /* Boucle de parcours          */
+
+    assert(index < cache->used);
+
+    assert(!(before && after));
+
+#ifndef NDEBUG
+
+    if (!before && !after)
+    {
+        gen_cursor = g_line_generator_compute_cursor(generator, 0, index, 0);
+
+        get_cache_info_cursor(&cache->lines[index], index, 0, &line_cursor);
+
+        ret = g_line_cursor_compare(gen_cursor, line_cursor);
+
+        g_object_unref(G_OBJECT(line_cursor));
+        g_object_unref(G_OBJECT(gen_cursor));
+
+        assert(ret == 0);
+
+    }
+
+#endif
+
+    /* Cas particulier d'ajout en fin de cache... */
+    if (after && (index + 1) == cache->used)
+    {
+        g_buffer_cache_append(cache, generator, flags);
+        goto gbcia_done;
+    }
+
+    /* Adaptation de l'espace */
+
+    needed = g_line_generator_count_lines(generator);
+
+    if (before || after)
+    {
+        if ((cache->used + needed) >= cache->count)
+        {
+            cache->count += needed + LINE_ALLOC_BULK;
+            cache->lines = (cache_info *)realloc(cache->lines, cache->count * sizeof(cache_info));
+        }
+    }
+
+    else if (needed > 1)
+    {
+        if ((cache->used + needed - 1) >= cache->count)
+        {
+            cache->count += needed - 1 + LINE_ALLOC_BULK;
+            cache->lines = (cache_info *)realloc(cache->lines, cache->count * sizeof(cache_info));
+        }
+    }
+
+    /* Insertion du générateur */
+
+    if (after)
+        index++;
+
+    if (before || after)
+    {
+        memmove(&cache->lines[index + needed], &cache->lines[index], (cache->used - index) * sizeof(cache_info));
+
+        for (i = 0; i < needed; i++)
+            init_cache_info(&cache->lines[index + i], generator, i, flags);
+
+        cache->used += needed;
+
+        g_width_tracker_update_added(cache->tracker, index, needed);
+
+        g_signal_emit_by_name(cache, "size-changed", true, index, needed);
+
+    }
+
+    else
+    {
+        extend_cache_info(&cache->lines[index], generator, flags);
+
+        g_width_tracker_update(cache->tracker, index);
+
+        if (needed > 1)
+        {
+            /* On déborde sur les lignes suivantes, donc on crée de l'espace ! */
+
+            memmove(&cache->lines[index + 1],
+                    &cache->lines[index + 1 + needed - 1], (cache->used - index - 1) * sizeof(cache_info));
+
+            for (i = 1; i < needed; i++)
+                init_cache_info(&cache->lines[index + i], generator, i, BLF_NONE);
+
+            cache->used += needed - 1;
+
+            g_width_tracker_update_added(cache->tracker, index + 1, needed - 1);
+
+        }
+
+        g_signal_emit_by_name(cache, "size-changed", true, index, needed - 1);
+
+    }
+
+ gbcia_done:
+
+    ;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : cache = instance GLib à modifier.                            *
+*                index = point de suppression.                                *
+*                                                                             *
+*  Description : Retire une ligne du tampon.                                  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_buffer_cache_delete_at(GBufferCache *cache, size_t index)
+{
+    cache_info *info;                       /* Accès direct à une ligne    */
+
+    assert(index < cache->used);
+
+    info = &cache->lines[index];
+
+    release_cache_info(info);
+
+    if ((index + 1) < cache->used)
+        memmove(&cache->lines[index], &cache->lines[index + 1],
+                (cache->used - index - 1) * sizeof(cache_info));
+
+    cache->used--;
+
+    g_width_tracker_update_deleted(cache->tracker, index, index);
+
+    g_signal_emit_by_name(cache, "size-changed", false, index, 1);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : cache  = instance GLib à modifier.                           *
+*                index  = point d'insertion, puis de sauvegarde.              *
+*                type   = type de générateurs à retirer des lignes visées.    *
+*                before = précise l'emplacement final de l'élément visé.      *
+*                after  = précise l'emplacement final de l'élément visé.      *
+*                                                                             *
+*  Description : Retire un type de générateur de lignes.                      *
+*                                                                             *
+*  Retour      : Générateur éventuellement trouvé ou NULL si aucun.           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+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    */
+    generator_link *link;                   /* Accès simplifié             */
+    size_t i;                               /* Boucle de parcours          */
+    size_t count;                           /* Emplacements occupés        */
+    size_t delete;                          /* Indice de suppression       */
+
+    assert(index < cache->used);
+
+    assert(!(before && after));
+
+    result = NULL;
+
+    /* Recherche d'un générateur correspondant */
+
+    if (before)
+        info = &cache->lines[index - 1];
+    else if (after)
+        info = &cache->lines[index + 1];
+    else
+        info = &cache->lines[index];
+
+    if (info->count == 1)
+    {
+        link = &info->generator;
+
+        if (G_OBJECT_TYPE(link->instance) == type)
+            result = link->instance;
+
+    }
+
+    else
+        for (i = 0; i < info->count && result == NULL; i++)
+        {
+            link = &info->generators[i];
+
+            if (G_OBJECT_TYPE(link->instance) == type)
+                result = link->instance;
+
+        }
+
+    /* Retrait de l'instance trouvée */
+
+    if (result != NULL)
+    {
+        count = g_line_generator_count_lines(result);
+
+#ifndef NDEBUG
+        if (!before && !after)
+            assert(count == 1);
+#endif
+
+        g_object_ref(G_OBJECT(result));
+
+        /* Suppression de l'élément */
+
+        for (i = 0; i < count; i++)
+        {
+            if (before)
+                info = &cache->lines[index - 1 - i];
+            else if (after)
+                info = &cache->lines[index + 1 + i];
+            else
+                info = &cache->lines[index];
+
+            remove_from_cache_info(info, result);
+
+        }
+
+        /* Suppression des lignes associées */
+
+        for (i = 0; i < count; i++)
+        {
+            if (before)
+                delete = index - 1;
+            else if (after)
+                delete = index + 1;
+            else
+                delete = index;
+
+            info = &cache->lines[delete];
+
+            if (info->count == 0)
+            {
+                release_cache_info(info);
+
+                if ((delete + 1) < cache->used)
+                    memmove(&cache->lines[delete], &cache->lines[delete + 1],
+                            (cache->used - delete - 1) * sizeof(cache_info));
+
+                cache->used--;
+
+                g_width_tracker_update_deleted(cache->tracker, delete, delete);
+
+                g_signal_emit_by_name(cache, "size-changed", false, delete, 1);
+
+            }
+
+        }
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : cache     = instance GLib à modifier.                        *
+*                generator = générateur à associer à toutes les lignes.       *
+*                flags     = propriétés supplémentaires à associer à la ligne.*
+*                                                                             *
+*  Description : Ajoute en fin de tampon un générateur de lignes.             *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_buffer_cache_append(GBufferCache *cache, GLineGenerator *generator, BufferLineFlags flags)
+{
+    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    */
+
+    count = g_line_generator_count_lines(generator);
+
+    assert(count > 0);
+
+    assert((flags != BLF_NONE && count == 1) || flags == BLF_NONE);
+
+    if ((cache->used + count) > cache->count)
+    {
+        cache->count += count + LINE_ALLOC_BULK;
+        cache->lines = (cache_info *)realloc(cache->lines, cache->count * sizeof(cache_info));
+    }
+
+    index = cache->used;
+
+    for (i = 0; i < count; i++)
+    {
+        info = &cache->lines[index + i];
+
+        info->generator.instance = generator;
+        info->generator.repeat = g_buffer_cache_compute_repetition(cache, index + i, generator);
+
+        g_object_ref(G_OBJECT(generator));
+
+        info->count = 1;
+
+        info->line = NULL;
+
+        info->extra_flags = flags;
+
+    }
+
+    cache->used += count;
+
+    g_width_tracker_update_added(cache->tracker, index, count);
+
+    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 added;                           /* Nombre d'ajouts effectués   */
+
+    assert(count >= cache->used);
+
+    if (count > cache->count)
+    {
+        cache->lines = (cache_info *)realloc(cache->lines, count * sizeof(cache_info));
+        cache->count = count;
+    }
+
+    index = cache->used;
+
+    for (i = index; i < count; i++)
+    {
+        info = &cache->lines[i];
+
+        info->generator.instance = generator;
+        info->generator.repeat = g_buffer_cache_compute_repetition(cache, i, generator);
+
+        g_object_ref(G_OBJECT(generator));
+
+        info->count = 1;
+
+        info->line = NULL;
+
+    }
+
+    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 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*/
+
+    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;
+
+        g_width_tracker_update_deleted(cache->tracker, max, max + removed - 1);
+
+        g_signal_emit_by_name(cache, "size-changed", false, max, removed);
+
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : cache  = tampon de lignes à venir consulter.                 *
+*                index  = indice de la ligne visée par la consultation.       *
+*                x      = position géographique sur la ligne concernée.       *
+*                cursor = emplacement à constituer. [OUT]                     *
+*                                                                             *
+*  Description : Retrouve l'emplacement correspondant à une position de ligne.*
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_buffer_cache_get_line_cursor(const GBufferCache *cache, size_t index, gint x, GLineCursor **cursor)
+{
+    assert(index < cache->used);
+
+    get_cache_info_cursor(&cache->lines[index], index, x, cursor);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : cache = tampon de lignes à venir consulter.                  *
+*                index = indice de la ligne visée par la consultation.        *
+*                                                                             *
+*  Description : Détermine l'ensemble des propriétés attachées à une ligne.   *
+*                                                                             *
+*  Retour      : Somme de toutes les propriétés enregistrées.                 *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+BufferLineFlags g_buffer_cache_get_line_flags(const GBufferCache *cache, size_t index)
+{
+    BufferLineFlags result;                 /* Somme à renvoyer            */
+    cache_info *info;                       /* Accès direct à une ligne    */
+    const generator_link *generator;        /* Générateur retenu           */
+    size_t i;                               /* Boucle de parcours          */
+
+    // TODO : check lock
+
+    assert(index < cache->used);
+
+    info = &cache->lines[index];
+
+    result = info->extra_flags;
+
+    if (info->count == 1)
+    {
+        generator = &info->generator;
+        result |= g_line_generator_get_flags(generator->instance, index, generator->repeat);
+    }
+
+    else
+        for (i = 0; i < info->count; i++)
+        {
+            generator = &info->generators[i];
+            result |= g_line_generator_get_flags(generator->instance, index, generator->repeat);
+        }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : cache = tampon de lignes à consulter.                        *
+*                index = indice de la ligne recherchée.                       *
+*                                                                             *
+*  Description : Retrouve une ligne au sein d'un tampon avec un indice.       *
+*                                                                             *
+*  Retour      : Line retrouvée ou NULL en cas d'échec.                       *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GBufferLine *g_buffer_cache_find_line_by_index(const GBufferCache *cache, size_t index)
+{
+    GBufferLine *result;                    /* Ligne trouvée à retourner   */
+
+    if (index < cache->used)
+        result = get_cache_info_line(&cache->lines[index], index, cache->content);
+    else
+        result = NULL;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : cache   = tampon de lignes à venir consulter.                *
+*                index   = indice de la ligne à mesurer.                      *
+*                summary = largeurs maximales à faire évoluer.                *
+*                                                                             *
+*  Description : Fait remonter les largeurs requises par une ligne donnée.    *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_buffer_cache_collect_widths(GBufferCache *cache, size_t index, line_width_summary *summary)
+{
+    GBufferLine *line;                      /* Ligne éphémère à mesurer    */
+
+    line = get_cache_info_line(&cache->lines[index], index, cache->content);
+
+    g_buffer_line_collect_widths(line, summary);
+
+    g_object_unref(G_OBJECT(line));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : cache    = visualisation à représenter.                      *
+*                cr       = contexte graphique dédié à la procédure.          *
+*                first    = première ligne à dessiner.                        *
+*                last     = dernière ligne à dessiner.                        *
+*                area     = position et surface à traiter.                    *
+*                options  = règles d'affichage des colonnes modulables.       *
+*                offsets  = décalages supplémentaires à appliquer.            *
+*                selected = ordonnée d'une ligne sélectionnée ou NULL.        *
+*                list     = liste de contenus à mettre en évidence.           *
+*                                                                             *
+*  Description : Imprime une partie choisie du tampon contenant des lignes.   *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_buffer_cache_draw(const GBufferCache *cache, cairo_t *cr, size_t first, size_t last, const cairo_rectangle_int_t *area, const GDisplayOptions *options, const line_width_summary *offsets, const gint *selected, const segcnt_list *list)
+{
+    GBufferCacheClass *class;               /* Classe des tampons          */
+    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    */
+    line_width_summary summary;             /* Résumé concis des largeurs  */
+    GBufferLine *line;                      /* Ligne à venir dessiner      */
+
+    class = G_BUFFER_CACHE_GET_CLASS(cache);
+
+    y = 0;
+
+    wait_selection = true;
+
+    if (cache->used > 0)
+        for (i = first; i <= last; i++)
+        {
+            /* Si sélection, on sousligne la ligne concernée */
+            if (wait_selection && selected != NULL && *selected == y)
+            {
+                cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.05);
+
+                cairo_rectangle(cr, area->x, y, area->width, class->line_height);
+                cairo_fill(cr);
+
+                wait_selection = false;
+
+            }
+
+            info = &cache->lines[i];
+
+            if (i == first || (g_buffer_cache_get_line_flags(cache, i) & BLF_WIDTH_MANAGER))
+                g_width_tracker_get_local_width_summary(cache->tracker, i, &summary);
+
+            line = get_cache_info_line(info, i, cache->content);
+
+            g_buffer_line_draw(line, cr, &summary, class->text_pos, y, options, offsets, list);
+
+            g_object_unref(G_OBJECT(line));
+
+            y += class->line_height;
+
+        }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : cache  = tampon de lignes à consulter.                       *
+*                cursor = emplacement à retrouver dans le tampon.             *
+*                first  = indique si on l'arrête à la première ou la dernière.*
+*                start  = borne inférieure des recherches (incluse).          *
+*                end    = borne supérieure des recherches (incluse).          *
+*                                                                             *
+*  Description : Indique l'indice correspondant à une adresse donnée.         *
+*                                                                             *
+*  Retour      : Indice des infos à l'adresse demandée, ou nombre de lignes.  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+size_t _g_buffer_cache_find_index_by_cursor(const 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é     */
+
+    int find_containing_generator(const GLineCursor *c, const cache_info *i)
+    {
+        const generator_link *generator;    /* Générateur retenu           */
+
+        if (i->count == 1)
+            generator = &i->generator;
+        else
+            generator = &i->generators[0];
+
+        return g_line_generator_contain_cursor(generator->instance,
+                                                i - cache->lines, generator->repeat, c);
+
+    }
+
+    found = (cache_info *)bsearch(cursor, &cache->lines[start], end - start + 1,
+                                  sizeof(cache_info), (__compar_fn_t)find_containing_generator);
+
+    if (found == NULL)
+        result = cache->used;
+
+    else
+    {
+        result = (found - cache->lines);
+        assert(start <= result && result <= end);
+
+        /* On s'assure d'un arrêt sur la bonne ligne */
+
+        if (first)
+            for (; result > start; result--)
+            {
+                found = &cache->lines[result - 1];
+
+                if (find_containing_generator(cursor, found) != 0)
+                    break;
+
+            }
+
+        else
+            for (; result < end; result++)
+            {
+                found = &cache->lines[result + 1];
+
+                if (find_containing_generator(cursor, found) != 0)
+                    break;
+
+            }
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : cache  = tampon de lignes à consulter.                       *
+*                cursor = emplacement à retrouver dans le tampon.             *
+*                first  = indique si on l'arrête à la première ou la dernière.*
+*                                                                             *
+*  Description : Indique l'indice correspondant à une adresse donnée.         *
+*                                                                             *
+*  Retour      : Indice des infos à l'adresse demandée, ou nombre de lignes.  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+size_t g_buffer_cache_find_index_by_cursor(const GBufferCache *cache, const GLineCursor *cursor, bool first)
+{
+    size_t result;                          /* Indice à retourner          */
+
+    if (cache->used == 0)
+        result = 0;
+    else
+        result = _g_buffer_cache_find_index_by_cursor(cache, cursor, first, 0, cache->used - 1);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : cache = tampon de lignes à consulter.                        *
+*                start = point de départ du parcours.                         *
+*                flag  = propriétés à retrouver si possible.                  *
+*                                                                             *
+*  Description : Avance autant que possible vers une ligne idéale.            *
+*                                                                             *
+*  Retour      : Indice de la ligne recherchée, si elle existe.               *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+size_t g_buffer_cache_look_for_flag(const GBufferCache *cache, size_t start, BufferLineFlags flag)
+{
+    size_t result;                          /* Indice de ligne à retourner */
+    GLineCursor *init;                      /* Localisation de départ      */
+    size_t i;                               /* Boucle de parcours          */
+    GLineCursor *next;                      /* Localisation suivante       */
+    int ret;                                /* Bilan de comparaison        */
+
+    // TODO : check lock
+
+    assert(start < cache->used);
+
+    result = start;
+
+    get_cache_info_cursor(&cache->lines[start], start, 0, &init);
+
+    for (i = start + 1; i < cache->used; i++)
+    {
+        get_cache_info_cursor(&cache->lines[i], i, 0, &next);
+
+        ret = g_line_cursor_compare(init, next);
+
+        g_object_unref(G_OBJECT(next));
+
+        if (ret != 0)
+            break;
+
+        if ((g_buffer_cache_get_line_flags(cache, i) & flag) != 0)
+        {
+            result = i;
+            break;
+        }
+
+    }
+
+    g_object_unref(G_OBJECT(init));
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : cache  = tampon de lignes à consulter.                       *
+*                cursor = emplacement à présenter à l'écran.                  *
+*                first  = borne inférieure des recherches (incluse).          *
+*                last   = borne supérieure des recherches (incluse).          *
+*                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_cache_get_cursor_coordinates(const GBufferCache *cache, const GLineCursor *cursor, size_t first, size_t last, bool code, gint *x, gint *y)
+{
+    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 generator_link *generator;        /* Générateur retenu           */
+
+    index = _g_buffer_cache_find_index_by_cursor(cache, cursor, true, first, last);
+
+    result = (index < cache->used);
+
+    if (result)
+    {
+        lheight = G_BUFFER_CACHE_GET_CLASS(cache)->line_height;
+
+        *x = 0;
+        *y = (index - first) * G_BUFFER_CACHE_GET_CLASS(cache)->line_height;
+
+        for (; code && index <= last; index++)
+        {
+            if (g_buffer_cache_get_line_flags(cache, index) & BLF_HAS_CODE)
+                break;
+
+            if (index == last)
+                break;
+
+            info = &cache->lines[index + 1];
+
+            if (info->count == 1)
+                generator = &info->generator;
+            else
+                generator = &info->generators[0];
+
+            if (!g_line_generator_contain_cursor(generator->instance, index + 1, generator->repeat, cursor))
+                break;
+
+            *y += lheight;
+
+        }
+
+    }
+
+    return result;
+
+}
diff --git a/src/glibext/buffercache.h b/src/glibext/buffercache.h
new file mode 100644
index 0000000..5094b53
--- /dev/null
+++ b/src/glibext/buffercache.h
@@ -0,0 +1,133 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * buffercache.h - prototypes pour l'affichage à la demande d'un ensemble de lignes
+ *
+ * Copyright (C) 2016-2019 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Chrysalide is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GLIBEXT_BUFFERCACHE_H
+#define _GLIBEXT_BUFFERCACHE_H
+
+
+#include <glib-object.h>
+#include <stdbool.h>
+#include <gdk/gdk.h>
+
+
+#include "gdisplayoptions.h"
+#include "linegen.h"
+#include "widthtracker.h"
+
+
+
+/* -------------------------- TAMPON POUR CODE DESASSEMBLE -------------------------- */
+
+
+#define G_TYPE_BUFFER_CACHE            g_buffer_cache_get_type()
+#define G_BUFFER_CACHE(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_BUFFER_CACHE, GBufferCache))
+#define G_BUFFER_CACHE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_BUFFER_CACHE, GBufferCacheClass))
+#define G_IS_BUFFER_CACHE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_BUFFER_CACHE))
+#define G_IS_BUFFER_CACHE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_BUFFER_CACHE))
+#define G_BUFFER_CACHE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_BUFFER_CACHE, GBufferCacheClass))
+
+
+/* Tampon pour gestion de lignes optimisée (instance) */
+typedef struct _GBufferCache GBufferCache;
+
+/* Tampon pour gestion de lignes optimisée (classe) */
+typedef struct _GBufferCacheClass GBufferCacheClass;
+
+
+/* Détermine le type du composant de tampon pour gestion de lignes optimisée. */
+GType g_buffer_cache_get_type(void);
+
+/* Crée un nouveau composant de tampon pour code désassemblé. */
+GBufferCache *g_buffer_cache_new(GBinContent *);
+
+/* Indique l'éventuel contenu binaire associé au cache. */
+GBinContent *g_buffer_cache_get_content(const GBufferCache *);
+
+/* Fournit la hauteur d'impression d'une ligne visualisée. */
+gint g_buffer_cache_get_line_height(const GBufferCache *);
+
+/* Fournit la taille réservée pour la marge gauche. */
+gint g_buffer_cache_get_left_margin(const GBufferCache *);
+
+/* Fournit la position de départ pour l'impression de texte. */
+gint g_buffer_cache_get_text_position(const GBufferCache *);
+
+/* Compte le nombre de lignes rassemblées dans un tampon. */
+size_t g_buffer_cache_count_lines(const GBufferCache *);
+
+/* Fournit un lien vers la structure de suivi de largeurs. */
+GWidthTracker *g_buffer_cache_get_width_tracker(const 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);
+
+/* Retire une ligne du tampon. */
+void g_buffer_cache_delete_at(GBufferCache *, size_t);
+
+/* Retire un type de générateur de lignes. */
+GLineGenerator *g_buffer_cache_delete_type_at(GBufferCache *, size_t, GType, bool, bool);
+
+/* Ajoute en fin de tampon un générateur de lignes. */
+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 *);
+
+/* Réduit le tampon à une quantité de lignes précise. */
+void g_buffer_cache_truncate(GBufferCache *, size_t);
+
+/* Retrouve l'emplacement correspondant à une position de ligne. */
+void g_buffer_cache_get_line_cursor(const GBufferCache *, size_t, gint, GLineCursor **);
+
+/* Détermine l'ensemble des propriétés attachées à une ligne. */
+BufferLineFlags g_buffer_cache_get_line_flags(const GBufferCache *, size_t);
+
+#define g_buffer_cache_lock(c)
+#define g_buffer_cache_unlock(c)
+
+#define g_buffer_cache_throw_update_at_index(c, i) // check locked
+
+/* Retrouve une ligne au sein d'un tampon avec un indice. */
+GBufferLine *g_buffer_cache_find_line_by_index(const GBufferCache *, size_t);
+
+/* Fait remonter les largeurs requises par une ligne donnée. */
+void g_buffer_cache_collect_widths(GBufferCache *, size_t, line_width_summary *);
+
+/* 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 line_width_summary *, const gint *, const segcnt_list *);
+
+/* Indique l'indice correspondant à une adresse donnée. */
+size_t _g_buffer_cache_find_index_by_cursor(const GBufferCache *, const GLineCursor *, bool, size_t, size_t);
+
+/* Indique l'indice correspondant à une adresse donnée. */
+size_t g_buffer_cache_find_index_by_cursor(const GBufferCache *, const GLineCursor *, bool);
+
+/* Avance autant que possible vers une ligne idéale. */
+size_t g_buffer_cache_look_for_flag(const GBufferCache *, size_t, BufferLineFlags);
+
+/* Indique la position d'affichage d'une adresse donnée. */
+bool g_buffer_cache_get_cursor_coordinates(const GBufferCache *, const GLineCursor *, size_t, size_t, bool, gint *, gint *);
+
+
+
+#endif  /* _GLIBEXT_BUFFERCACHE_H */
diff --git a/src/glibext/bufferline.c b/src/glibext/bufferline.c
new file mode 100644
index 0000000..b9413e2
--- /dev/null
+++ b/src/glibext/bufferline.c
@@ -0,0 +1,1558 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * bufferline.c - représentation de fragments de texte en ligne
+ *
+ * Copyright (C) 2010-2019 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Chrysalide is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "bufferline.h"
+
+
+#include <assert.h>
+#include <malloc.h>
+#include <string.h>
+
+
+#include "chrysamarshal.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        */
+
+    mrange_t range;                         /* Couverture geographique     */
+    BufferLineColumn main_column;           /* Colonne principale          */
+
+    line_column columns[BLC_COUNT];         /* Répartition du texte        */
+    BufferLineColumn merge_start;           /* Début de la zone globale    */
+    BufferLineColumn last_used;             /* Dernière colonne utilisée   */
+
+    BufferLineFlags flags;                  /* Drapeaux particuliers       */
+
+    content_origin *origins;                /* Mémorisation des origines   */
+    size_t ocount;                          /* Nombre de ces mémorisations */
+
+    union
+    {
+        struct
+        {
+            gint max_widths[BLC_COUNT];     /* Taille cachée des colonnes  */
+            gint merged_width;              /* Largeur cumulée avant fusion*/
+        };
+    };
+
+};
+
+/* Représentation de fragments de texte en ligne (classe) */
+struct _GBufferLineClass
+{
+    GObjectClass parent;                    /* A laisser en premier        */
+
+    cairo_surface_t *entrypoint_img;        /* Image pour les entrées      */
+    cairo_surface_t *bookmark_img;          /* Image pour les signets      */
+
+    /* Signaux */
+
+    void (* content_changed) (GBufferLine *, line_segment *);
+
+    void (* flip_flag) (GBufferLine *, BufferLineFlags, BufferLineFlags);
+
+};
+
+
+/* Procède à l'initialisation d'une classe de représentation. */
+static void g_buffer_line_class_init(GBufferLineClass *);
+
+/* Procède à l'initialisation d'une représentation de fragments. */
+static void g_buffer_line_init(GBufferLine *);
+
+/* Supprime toutes les références externes. */
+static void g_buffer_line_dispose(GBufferLine *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_buffer_line_finalize(GBufferLine *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                              GESTION DE LINE COMPLETE                              */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Détermine le type de la représentation de fragments de texte en ligne. */
+G_DEFINE_TYPE(GBufferLine, g_buffer_line, G_TYPE_OBJECT);
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : class = classe de composant GTK à initialiser.               *
+*                                                                             *
+*  Description : Procède à l'initialisation d'une classe de représentation.   *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_buffer_line_class_init(GBufferLineClass *class)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+    gchar *filename;                        /* Chemin d'accès à utiliser   */
+
+    object = G_OBJECT_CLASS(class);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_buffer_line_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_buffer_line_finalize;
+
+    filename = find_pixmap_file("entrypoint.png");
+    assert(filename != NULL);
+
+    class->entrypoint_img = cairo_image_surface_create_from_png(filename);
+
+    g_free(filename);
+
+    filename = find_pixmap_file("bookmark.png");
+    assert(filename != NULL);
+
+    class->bookmark_img = cairo_image_surface_create_from_png(filename);
+
+    g_free(filename);
+
+    g_signal_new("content-changed",
+                 G_TYPE_BUFFER_LINE,
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET(GBufferLineClass, content_changed),
+                 NULL, NULL,
+                 g_cclosure_marshal_VOID__OBJECT,
+                 G_TYPE_NONE, 1, G_TYPE_OBJECT);
+
+    g_signal_new("flip-flag",
+                 G_TYPE_BUFFER_LINE,
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET(GBufferLineClass, flip_flag),
+                 NULL, NULL,
+                 g_cclosure_user_marshal_VOID__ENUM_ENUM,
+                 G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : line = composant GTK à initialiser.                          *
+*                                                                             *
+*  Description : Procède à l'initialisation d'une représentation de fragments.*
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_buffer_line_init(GBufferLine *line)
+{
+    BufferLineColumn i;                     /* Boucle de parcours          */
+
+    for (i = 0; i < BLC_COUNT; i++)
+        init_line_column(&line->columns[i]);
+
+    line->merge_start = BLC_COUNT;
+    line->last_used = BLC_COUNT;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : line = instance d'objet GLib à traiter.                      *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_buffer_line_dispose(GBufferLine *line)
+{
+    size_t i;                               /* Boucle de parcours          */
+
+    for (i = 0; i < line->ocount; i++)
+        g_object_unref(G_OBJECT(line->origins[i].creator));
+
+    G_OBJECT_CLASS(g_buffer_line_parent_class)->dispose(G_OBJECT(line));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : line = instance d'objet GLib à traiter.                      *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_buffer_line_finalize(GBufferLine *line)
+{
+    BufferLineColumn i;                     /* Boucle de parcours          */
+
+    for (i = 0; i < BLC_COUNT; i++)
+        reset_line_column(&line->columns[i]);
+
+    if (line->origins != NULL)
+        free(line->origins);
+
+    G_OBJECT_CLASS(g_buffer_line_parent_class)->finalize(G_OBJECT(line));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : range = emplacement où va se situer la ligne.                *
+*                main  = colonne à référencer comme étant la principale.      *
+*                                                                             *
+*  Description : Crée une nouvelle représentation de fragments de texte.      *
+*                                                                             *
+*  Retour      : Composant GTK créé.                                          *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GBufferLine *g_buffer_line_new(const mrange_t *range, BufferLineColumn main)
+{
+    GBufferLine *result;                    /* Composant à retourner       */
+
+    result = g_object_new(G_TYPE_BUFFER_LINE, NULL);
+
+    copy_mrange(&result->range, range);
+    result->main_column = main;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : line = ligne à venir consulter.                              *
+*                                                                             *
+*  Description : Indique la zone mémoire où se situe la ligne.                *
+*                                                                             *
+*  Retour      : Emplacement mémoire virtuel ou physique.                     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+const mrange_t *g_buffer_line_get_range(const GBufferLine *line)
+{
+    return &line->range;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : line = ligne à venir compléter.                              *
+*                size = taille souhaitée de l'impression des positions.       *
+*                addr = localisation physique à venir représenter.            *
+*                                                                             *
+*  Description : Construit le tronc commun d'une ligne autour de sa position. *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_buffer_line_fill_phys(GBufferLine *line, MemoryDataSize size, const vmpa2t *addr)
+{
+    VMPA_BUFFER(position);                  /* Emplacement au format texte */
+    size_t len;                             /* Taille de l'élément inséré  */
+    size_t i;                               /* Boucle de parcours #1       */
+
+    vmpa2_phys_to_string(addr, size, position, &len);
+
+    for (i = 2; i < len; i++)
+        if (position[i] != '0') break;
+
+    if (i == len)
+        i = len - 1;
+
+    if (i > 0)
+        g_buffer_line_append_text(line, BLC_PHYSICAL, position, i, RTT_PHYS_ADDR_PAD, NULL);
+
+    g_buffer_line_append_text(line, BLC_PHYSICAL, &position[i], len - i, RTT_PHYS_ADDR, NULL);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : line = ligne à venir compléter.                              *
+*                size = taille souhaitée de l'impression des positions.       *
+*                addr = localisation virtuelle à venir représenter.           *
+*                                                                             *
+*  Description : Construit le tronc commun d'une ligne autour de sa position. *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_buffer_line_fill_virt(GBufferLine *line, MemoryDataSize size, const vmpa2t *addr)
+{
+    VMPA_BUFFER(position);                  /* Emplacement au format texte */
+    size_t len;                             /* Taille de l'élément inséré  */
+    size_t i;                               /* Boucle de parcours #1       */
+
+    vmpa2_virt_to_string(addr, size, position, &len);
+
+    if (has_virt_addr(addr))
+    {
+        for (i = 2; i < len; i++)
+            if (position[i] != '0') break;
+
+        if (i == len)
+            i = len - 1;
+
+        if (i > 0)
+            g_buffer_line_append_text(line, BLC_VIRTUAL, position, i, RTT_VIRT_ADDR_PAD, NULL);
+
+        g_buffer_line_append_text(line, BLC_VIRTUAL, &position[i], len - i, RTT_VIRT_ADDR, NULL);
+
+    }
+
+    else
+        g_buffer_line_append_text(line, BLC_VIRTUAL, position, len, RTT_VIRT_ADDR_PAD, NULL);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : line  = ligne à venir compléter.                             *
+*                addr  = localisation à afficher.                             *
+*                psize = taille souhaitée de l'impression des positions.      *
+*                vsize = taille souhaitée de l'impression des adresses.       *
+*                                                                             *
+*  Description : Construit le tronc commun d'une ligne autour de sa position. *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_buffer_line_fill_vmpa(GBufferLine *line, const vmpa2t *addr, MemoryDataSize psize, MemoryDataSize vsize)
+{
+    g_buffer_line_fill_phys(line, psize, addr);
+
+    g_buffer_line_fill_virt(line, vsize, addr);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : line    = ligne à venir compléter.                           *
+*                content = contenu binaire global à venir lire.               *
+*                range   = localisation des données à venir lire et présenter.*
+*                max     = taille maximale de la portion binaire en octets.   *
+*                                                                             *
+*  Description : Construit le tronc commun d'une ligne autour de son contenu. *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_buffer_line_fill_content(GBufferLine *line, const GBinContent *content, const mrange_t *range, phys_t max)
+{
+    phys_t length;                          /* Taille de la couverture     */
+    bool truncated;                         /* Indique si le code est coupé*/
+    size_t required;                        /* Taille de traitement requise*/
+    char static_buffer[64];                 /* Petit tampon local rapide   */
+    char *bin_code;                         /* Tampon utilisé pour le code */
+    vmpa2t pos;                             /* Boucle de parcours #1       */
+    phys_t i;                               /* Boucle de parcours #2       */
+    char *iter;                             /* Boucle de parcours #3       */
+    int ret;                                /* Progression dans l'écriture */
+    uint8_t byte;                           /* Octet à représenter         */
+
+    static const char *charset = "0123456789abcdef";
+
+    /* Détermination du réceptacle */
+
+    length = get_mrange_length(range);
+
+    truncated = (max != VMPA_NO_PHYSICAL && length > max);
+
+    if (truncated)
+    {
+        length = max;
+        required = length * 3 + 4 /* "..." */ + 1;
+    }
+    else
+        required = length * 3 + 1;
+
+    if (required <= sizeof(static_buffer))
+        bin_code = static_buffer;
+    else
+        bin_code = (char *)calloc(required, sizeof(char));
+
+    /* Code brut */
+
+    copy_vmpa(&pos, get_mrange_addr(range));
+
+    for (i = 0, iter = bin_code; i < length; i++, iter += ret)
+    {
+        if (i == 0)
+            ret = 0;
+        else
+        {
+            iter[0] = ' ';
+            ret = 1;
+        }
+
+        if (!g_binary_content_read_u8(content, &pos, &byte))
+        {
+            iter[ret + 0] = '?';
+            iter[ret + 1] = '?';
+        }
+        else
+        {
+            iter[ret + 0] = charset[byte >> 4];
+            iter[ret + 1] = charset[byte & 0x0f];
+        }
+
+        ret += 2;
+
+    }
+
+    if (truncated)
+    {
+        strcpy(iter, "...");
+        iter += 3;
+    }
+    else
+        *iter = '\0';
+
+    /* Conclusion */
+
+    g_buffer_line_append_text(line, BLC_BINARY, bin_code, iter - bin_code, RTT_RAW_CODE, NULL);
+
+    if (bin_code != static_buffer)
+        free(bin_code);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : line   = ligne à venir consulter.                            *
+*                column = indice de la colonne visée par les recherches.      *
+*                                                                             *
+*  Description : Recherche le premier créateur enregistré dans des segments.  *
+*                                                                             *
+*  Retour      : Créateur trouvé à déréférencer par la suite ou NULL si échec.*
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GObject *g_buffer_line_find_first_segment_creator(const GBufferLine *line, BufferLineColumn column)
+{
+    GObject *result;                        /* Trouvaille à retourner      */
+    size_t i;                               /* Boucle de parcours          */
+
+    assert(column < BLC_COUNT);
+
+    result = NULL;
+
+    for (i = 0; i < line->ocount && result == NULL; i++)
+    {
+        if (line->origins[i].coord.column == column)
+            result = line->origins[i].creator;
+    }
+
+    if (result != NULL)
+        g_object_ref(G_OBJECT(result));
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : line    = ligne à venir compléter.                           *
+*                column  = colonne de la ligne visée par l'insertion.         *
+*                text    = texte à insérer dans l'existant.                   *
+*                length  = taille du texte à traiter.                         *
+*                type    = type de décorateur à utiliser.                     *
+*                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, const char *text, size_t length, RenderingTagType type, GObject *creator)
+{
+    size_t index;                           /* Indice d'insertion          */
+    content_origin *origin;                 /* Définition d'une origine    */
+
+    assert(length > 0);
+
+    if (column == -1)
+        column = BLC_LAST_USED;
+
+    if (column == BLC_MAIN)
+        column = BLC_ASSEMBLY;//line->main_column;
+
+    if (column == BLC_LAST_USED)
+        column = line->last_used;
+    else
+        line->last_used = column;
+
+    index = append_text_to_line_column(&line->columns[column], text, length, type);
+
+    if (creator != NULL)
+    {
+        line->origins = (content_origin *)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 à venir compléter.                           *
+*                creator = instance GLib quelconque identifiant un segment.   *
+*                text    = texte à insérer dans l'existant.                   *
+*                length  = taille du texte à traiter.                         *
+*                                                                             *
+*  Description : Remplace du texte dans une ligne donnée.                     *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_buffer_line_replace_text(GBufferLine *line, const GObject *creator, const char *text, size_t length)
+{
+    bool result;                            /* Bilan à retourner            */
+    size_t i;                               /* Boucle de parcours          */
+    const col_coord_t *coord;               /* Emplacement du contenu visé */
+
+    result = false;
+
+    for (i = 0; i < line->ocount && !result; i++)
+    {
+        if (line->origins[i].creator == creator)
+        {
+            coord = &line->origins[i].coord;
+
+            replace_text_in_line_column(&line->columns[coord->column], coord->index, text, length);
+
+            g_signal_emit_by_name(line, "content-changed", NULL);
+
+            result = true;
+
+        }
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : line   = ligne à venir consulter.                            *
+*                first  = première colonne à parcourir.                       *
+*                end    = colonne de fin de parcours.                         *
+*                                                                             *
+*  Description : Indique si du texte est présent dans une ligne de tampon.    *
+*                                                                             *
+*  Retour      : true pour indiquer la présence de texte, false pour du vide. *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_buffer_line_has_text(const GBufferLine *line, BufferLineColumn first, BufferLineColumn end)
+{
+    bool result;                            /* Bilan à retourner           */
+    BufferLineColumn i;                     /* Boucle de parcours          */
+
+    result = false;
+
+    assert(first < end);
+
+    for (i = first; i < end && !result; i++)
+        result = (line->columns[i].count > 0);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : line   = ligne à venir consulter.                            *
+*                first  = première colonne à parcourir.                       *
+*                end    = colonne de fin de parcours.                         *
+*                markup = indique si le texte doit être décoré ou non.        *
+*                                                                             *
+*  Description : Donne le texte représenté par une ligne de tampon.           *
+*                                                                             *
+*  Retour      : Texte à libérer de la mémoire après usage.                   *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+char *g_buffer_line_get_text(const GBufferLine *line, BufferLineColumn first, BufferLineColumn end, bool markup)
+{
+    char *result;                           /* Construction à retourner    */
+    BufferLineColumn i;                     /* Boucle de parcours          */
+    char *extra;                            /* Contenu à intégrer au texte */
+
+    result = NULL;
+
+    assert(first < end);
+
+    for (i = first; i < end; i++)
+    {
+        if (i > first && result != NULL)
+            result = stradd(result, " ");
+
+        extra = get_line_column_text(&line->columns[i], markup);
+
+        /* Si la colonne était vide, suivante ! */
+        if (extra == NULL) continue;
+
+        if (result == NULL)
+            result = extra;
+
+        else
+        {
+            result = stradd(result, extra);
+            free(extra);
+        }
+
+    }
+
+    return result;
+
+}
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : line  = ligne à venir modifier.                              *
+*                first = première colonne à parcourir.                        *
+*                end   = colonne de fin de parcours.                          *
+*                                                                             *
+*  Description : Supprime du texte représenté par une ligne de tampon.        *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_buffer_line_delete_text(GBufferLine *line, BufferLineColumn first, BufferLineColumn end)
+{
+    BufferLineColumn i;                     /* Boucle de parcours #1       */
+
+    assert(first < end);
+
+    for (i = first; i < end; i++)
+        reset_line_column(&line->columns[i]);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : line = ligne à venir consulter.                              *
+*                                                                             *
+*  Description : Fournit la colonne à partir de laquelle une fusion opère.    *
+*                                                                             *
+*  Retour      : Début de la première (et unique) zone globale.               *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+BufferLineColumn g_buffer_line_get_merge_start(const GBufferLine *line)
+{
+    return line->merge_start;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : line  = ligne à venir compléter.                             *
+*                start = début de la première (et unique) zone globale.       *
+*                                                                             *
+*  Description : Définit la colonne à partir de laquelle la fusion opère.     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_buffer_line_start_merge_at(GBufferLine *line, BufferLineColumn start)
+{
+    if (start == BLC_LAST_USED)
+        line->merge_start = line->last_used;
+    else
+        line->merge_start = start;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : line = ligne à venir compléter.                              *
+*                flag = propriété à intégrer.                                 *
+*                                                                             *
+*  Description : Ajoute une propriété particulière à une ligne donnée.        *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_buffer_line_add_flag(GBufferLine *line, BufferLineFlags flag)
+{
+    if ((line->flags & flag) == 0)
+    {
+        g_signal_emit_by_name(line, "flip-flag", line->flags, flag);
+
+        line->flags |= flag;
+
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : line = ligne à venir consulter.                              *
+*                                                                             *
+*  Description : Renseigne sur les propriétés particulières liées à une ligne.*
+*                                                                             *
+*  Retour      : Propriétés intégrées.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+BufferLineFlags g_buffer_line_get_flags(const GBufferLine *line)
+{
+    return line->flags;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : line = ligne à venir compléter.                              *
+*                flag = propriété à supprimer.                                *
+*                                                                             *
+*  Description : Retire une propriété particulière à une ligne donnée.        *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_buffer_line_remove_flag(GBufferLine *line, BufferLineFlags flag)
+{
+    if ((line->flags & flag) != 0)
+    {
+        g_signal_emit_by_name(line, "flip-flag", line->flags, flag);
+
+        line->flags &= ~flag;
+
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : line    = ligne de texte à manipuler.                        *
+*                ctx     = éléments à disposition pour l'exportation.         *
+*                type    = type d'exportation attendue.                       *
+*                display = règles d'affichage des colonnes modulables.        *
+*                                                                             *
+*  Description : Exporte la ligne de texte représentée.                       *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_buffer_line_export(GBufferLine *line, buffer_export_context *ctx, BufferExportType type, const bool *display)
+{
+    BufferLineColumn i;                     /* Boucle de parcours          */
+    int col_span;                           /* Fusion de colonnes ?        */
+
+    switch (type)
+    {
+        case BET_HTML:
+            dprintf(ctx->fd, "\t<TR>\n");
+            break;
+        default:
+            break;
+    }
+
+    for (i = 0; i < BLC_COUNT; i++)
+    {
+        if (i < BLC_DISPLAY && !display[i]) continue;
+
+        switch (type)
+        {
+            case BET_TEXT:
+                if (i > 0) dprintf(ctx->fd, "%s", ctx->sep);
+                break;
+            default:
+                break;
+        }
+
+        /**
+         * Pour la signification des différentes valeurs assignées,
+         * se référer au code de export_line_column_segments().
+         *
+         * En gros :
+         *   - 1  = rien de spécial.
+         *   - >1 = il s'agit de la première cellule fusionnée de la ligne.
+         *   - 0  = fusion déjà faite, on ne peut que rajouter du contenu dedans.
+         *   - <1 = il s'agit de la dernière cellule fusionnée de la ligne.
+         *
+         * On considère qu'une fusion ne peut pas se réaliser sur la dernière
+         * cellule uniquement (ce qui a du sens : c'est inutile).
+         */
+
+        if (i < line->merge_start)
+            col_span = 1;
+
+        else if (i == line->merge_start)
+            col_span = BLC_COUNT - i;
+
+        else
+            col_span = ((i + 1) == BLC_COUNT ? -1 : 0);
+
+        export_line_column_segments(&line->columns[i], ctx, type, col_span);
+
+    }
+
+    switch (type)
+    {
+        case BET_TEXT:
+            dprintf(ctx->fd, "\n");
+            break;
+        case BET_HTML:
+            dprintf(ctx->fd, "</TR>\n");
+            break;
+        default:
+            break;
+    }
+
+}
+
+
+
+/*----------------------------------------------------------------------------------- */
+/*                         MANIPULATION DES LARGEURS REQUISES                         */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : line    = ligne à venir consulter.                           *
+*                summary = largeurs maximales à faire évoluer.                *
+*                                                                             *
+*  Description : Fait remonter les largeurs requises par une ligne donnée.    *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_buffer_line_collect_widths(GBufferLine *line, line_width_summary *summary)
+{
+    gint merged_width;                      /* Largeur cumulée avant fusion*/
+    BufferLineColumn i;                     /* Boucle de parcours          */
+    gint width;                             /* Largeur d'une colonne       */
+
+    merged_width = 0;
+
+    for (i = 0; i < BLC_COUNT; i++)
+    {
+        width = get_column_width(&line->columns[i]);
+
+        if (i < line->merge_start)
+            summary->max_widths[i] = MAX(summary->max_widths[i], width);
+
+        if (i >= BLC_DISPLAY)
+        {
+            merged_width += width;
+
+            if (i < line->merge_start && (i + 1) < BLC_COUNT)
+                merged_width += COL_MARGIN;
+
+        }
+
+    }
+
+    if (line->merge_start != BLC_COUNT)
+        summary->merged_width = MAX(summary->merged_width, merged_width);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : line    = ligne à venir consulter.                           *
+*                index   = indice de la colonne visée.                        *
+*                summary = résumé des largeurs maximales.                     *
+*                offsets = décalages supplémentaires à appliquer.             *
+*                                                                             *
+*  Description : Fournit la largeur d'une colonne finalement appliquée.       *
+*                                                                             *
+*  Retour      : Largeur globale ou spécifique, selon l'indice communiqué.    *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+gint g_buffer_line_compute_max_width(const GBufferLine *line, BufferLineColumn index, const line_width_summary *summary, const line_width_summary *offsets)
+{
+    gint result;                            /* Largeur à retourner         */
+
+    assert(index < BLC_COUNT);
+
+    if (index >= line->merge_start)
+        result = get_column_width(&line->columns[index]);
+
+    else
+        result = summary->max_widths[index];
+
+    if (result < offsets->max_widths[index])
+        result = offsets->max_widths[index];
+
+    return result;
+
+}
+
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : line  = ligne à venir consulter.                             *
+*                coord = coordonnées interne du segment à retrouver.          *
+*                                                                             *
+*  Description : Fournit le segment présent à une position donnée.            *
+*                                                                             *
+*  Retour      : Segment trouvé ou NULL si hors borne.                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+line_segment *g_buffer_line_get_segment_from_coord(const GBufferLine *line, const col_coord_t *coord)
+{
+    line_segment *result;                   /* Trouvaille à retourner      */
+
+    if (coord->column < BLC_COUNT)
+        result = get_line_column_content_from_index(&line->columns[coord->column], coord->index);
+    else
+        result = NULL;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : line    = ligne à venir consulter.                           *
+*                summary = résumé des largeurs maximales.                     *
+*                options = règles d'affichage des colonnes modulables.        *
+*                offsets = décalages supplémentaires à appliquer.             *
+*                base    = position jusqu'au segment trouvé. [OUT]            *
+*                offset  = position à la colonne visée. [OUT]                 *
+*                dir     = direction d'un éventuel déplacement en cours.      *
+*                force   = accepte les segments en bordure au pire.           *
+*                coord   = cordonnées à usage interne à renseigner. [OUT]     *
+*                                                                             *
+*  Description : Fournit les coordonnées correspondant à une abscisse donnée. *
+*                                                                             *
+*  Retour      : true si des coordonnées valides ont été renseignées.         *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_buffer_line_get_coord_at(const GBufferLine *line, const line_width_summary *summary, const GDisplayOptions *options, const line_width_summary *offsets, gint *base, gint *offset, GdkScrollDirection dir, bool force, col_coord_t *coord)
+{
+    bool result;                            /* Bilan à retourner           */
+    BufferLineColumn last;                  /* Dernière colonne remplie    */
+    gint last_base;                         /* Dernière abscisse associée  */
+    size_t count;                           /* Qté de colonnes en option   */
+    size_t i;                               /* Boucle de parcours          */
+    gint width;                             /* Largeur d'une colonne donnée*/
+    gint limit;                             /* Limite d'appartenance       */
+    gint consumed;                          /* Distance vers le segment    */
+    gint old_base;                          /* Somme de toutes les largeurs*/
+
+    result = false;
+
+    *base = 0;
+
+    last = BLC_COUNT;
+    last_base = 0;
+
+    /* On cible déjà la colonne idéale */
+
+    count = g_display_options_count(options);
+
+    for (i = 0; i < BLC_COUNT; i++)
+    {
+        if (i < count)
+        {
+            if (!g_display_options_get(options, i))
+                continue;
+        }
+
+        /* Mémorisation de la dernière colonne contenant quelque chose... */
+        if (get_column_width(&line->columns[i]) > 0)
+        {
+            last = i;
+            last_base = *base;
+        }
+
+        if (i < line->merge_start)
+        {
+            width = g_buffer_line_compute_max_width(line, i, summary, offsets);
+
+            /* Si la colonne n'est absolument pas visible, on ne s'arrête pas dessus ! */
+            if (width == 0) continue;
+
+            if ((i + 1) < BLC_COUNT) limit = width + COL_MARGIN / 2;
+            else limit = width;
+
+            if (*offset <= limit) break;
+            else
+            {
+                *offset -= width + COL_MARGIN;
+                *base += width + COL_MARGIN;
+            }
+
+        }
+        else
+        {
+            width = get_column_width(&line->columns[i]);
+
+            if (*offset <= width) break;
+            else
+            {
+                *offset -= width;
+                *base += width;
+            }
+
+        }
+
+
+    }
+
+    /* Si l'abscisse fournie tombe encore dans une colonne... */
+
+    if (i < BLC_COUNT)
+    {
+        /* Il y a bien du contenu dans cette colonne */
+
+        if (get_column_width(&line->columns[i]) > 0)
+        {
+            /**
+             * Si la position était au milieu d'une marge, la sélection a pu pousser
+             * jusqu'à la colonne suivante, plus proche.
+             * Relativment à la base de cette dernière, la position est donc devenue négative.
+             */
+            if (*offset < 0) *offset = 0;
+
+            result = get_line_column_content_index_at(&line->columns[i], offset, dir, &consumed, &coord->index);
+
+            if (result)
+            {
+                coord->column = i;
+
+                *base += consumed;
+
+            }
+
+        }
+
+        /* La position fournie tombe dans une colonne vide ! */
+
+        else
+        {
+            if (force || get_column_width(&line->columns[i]) == 0)
+            {
+                result = false;
+                *offset = 0;
+
+                old_base = *base;
+
+                for (i++; i < BLC_COUNT && !result; i++)
+                {
+                    if ((i - 1) < line->merge_start)
+                    {
+                        width = g_buffer_line_compute_max_width(line, i - 1, summary, offsets);
+
+                        if (width > 0)
+                            *base += (width + COL_MARGIN);
+
+                    }
+                    else
+                        *base += get_column_width(&line->columns[i - 1]);
+
+                    result = get_line_column_first_content_index(&line->columns[i], &coord->index);
+
+                    if (result)
+                        coord->column = i;
+
+                }
+
+                if (!result)
+                {
+                    *base = old_base;
+                    goto use_right_border;
+                }
+
+            }
+
+        }
+
+    }
+
+    else /* if (i == BLC_COUNT) */
+    {
+        if (force)
+        {
+ use_right_border:
+
+            if (last != BLC_COUNT)
+            {
+                result = get_line_column_last_content_index(&line->columns[last], &coord->index);
+
+                if (result)
+                {
+                    coord->column = last;
+
+                    *base = last_base;
+                    *offset = get_column_width(&line->columns[last]);
+
+                }
+
+            }
+
+            /* Il n'y a rien sur la ligne ! */
+            else
+            {
+                result = true;
+
+                *base = 0;
+                *offset = 0;
+
+                coord->column = BLC_COUNT;
+                coord->index = -1;
+
+            }
+
+        }
+        else
+            result = false;
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : line    = ligne à venir consulter.                           *
+*                summary = résumé des largeurs maximales.                     *
+*                options = règles d'affichage des colonnes modulables.        *
+*                offsets = décalages supplémentaires à appliquer.             *
+*                base    = position jusqu'au segment trouvé. [OUT]            *
+*                offset  = position à la colonne visée. [OUT]                 *
+*                dir     = direction d'un éventuel déplacement en cours.      *
+*                force   = accepte les segments en bordure au pire.           *
+*                                                                             *
+*  Description : Donne le segment présent à une abscisse donnée.              *
+*                                                                             *
+*  Retour      : Segment trouvé ou NULL si hors borne.                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+line_segment *g_buffer_line_get_segment_at(const GBufferLine *line, const line_width_summary *summary, const GDisplayOptions *options, const line_width_summary *offsets, gint *base, gint *offset, GdkScrollDirection dir, bool force)
+{
+    line_segment *result;                   /* Trouvaille à retourner      */
+    col_coord_t coord;                      /* Emplacement du contenu visé */
+    bool status;                            /* Bilan de la localisation    */
+
+    status = g_buffer_line_get_coord_at(line, summary, options, offsets, base, offset, dir, force, &coord);
+
+    if (status)
+        result = g_buffer_line_get_segment_from_coord(line, &coord);
+    else
+        result = NULL;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : line    = ligne à venir consulter.                           *
+*                summary = résumé des largeurs maximales.                     *
+*                options = règles d'affichage des colonnes modulables.        *
+*                offsets = décalages supplémentaires à appliquer.             *
+*                base    = position jusqu'au segment trouvé. [OUT]            *
+*                offset  = position à la colonne visée. [OUT]                 *
+*                dir     = direction d'un éventuel déplacement en cours.      *
+*                force   = accepte les segments en bordure au pire.           *
+*                                                                             *
+*  Description : Donne le créateur présent à une abscisse donnée.             *
+*                                                                             *
+*  Retour      : Créateur trouvé ou NULL si hors borne.                       *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GObject *g_buffer_line_get_creator_at(const GBufferLine *line, const line_width_summary *summary, const GDisplayOptions *options, const line_width_summary *offsets, gint *base, gint *offset, GdkScrollDirection dir, bool force)
+{
+    GObject *result;                        /* Trouvaille à retourner      */
+    col_coord_t target;                     /* Emplacement du contenu visé */
+    bool status;                            /* Bilan de la localisation    */
+    size_t i;                               /* Boucle de parcours          */
+    const col_coord_t *coord;               /* Emplacement du contenu visé */
+
+    result = NULL;
+
+    status = g_buffer_line_get_coord_at(line, summary, options, offsets, base, offset, dir, force, &target);
+
+    if (status)
+    {
+        for (i = 0; i < line->ocount && result == NULL; i++)
+        {
+            coord = &line->origins[i].coord;
+
+            if (coord->column == target.column && coord->index == target.index)
+                result = line->origins[i].creator;
+
+        }
+
+        if (result != NULL)
+            g_object_ref(G_OBJECT(result));
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : line    = ligne à venir consulter.                           *
+*                coord   = cordonnées à consulter puis renseigner. [OUT]      *
+*                summary = résumé des largeurs maximales.                     *
+*                options = règles d'affichage des colonnes modulables.        *
+*                offsets = décalages supplémentaires à appliquer.             *
+*                dir     = orientation des recherches.                        *
+*                offset  = décalage pour amener à l'extrémité nouvelle. [OUT] *
+*                                                                             *
+*  Description : Fournit des coordonnées voisines selon une direction donnée. *
+*                                                                             *
+*  Retour      : true si des coordonnées valides ont été renseignées.         *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_buffer_line_find_near_coord(const GBufferLine *line, col_coord_t *coord, const line_width_summary *summary, const GDisplayOptions *options, const line_width_summary *offsets, GdkScrollDirection dir, gint *offset)
+{
+    bool result;                            /* Bilan à retourner           */
+    size_t count;                           /* Qté de colonnes en option   */
+    size_t i;                               /* Boucle de parcours #1       */
+    bool displayed;                         /* Confort de lecture          */
+    size_t k;                               /* Boucle de parcours #2       */
+    gint width;                             /* Largeur d'une colonne donnée*/
+
+    result = false;
+
+    /* Recherche dans la colonne de départ */
+
+    i = coord->column;
+
+    if (i == BLC_COUNT) return false;
+
+    result = find_near_segment(&line->columns[i], &coord->index, dir);
+
+    /* Recherche dans la direction des colonnes voisines */
+
+    count = g_display_options_count(options);
+
+    if (!result)
+        switch (dir)
+        {
+            case GDK_SCROLL_LEFT:
+
+                /* Si on a atteint la première colonne sans trouver... */
+                if (i == 0) break;
+
+                /* On s'assure que la colonne précédente est visible et peuplée */
+                for (; i > BLC_FIRST && !result; i--)
+                {
+                    displayed = (i <= count ? g_display_options_get(options, i - 1) : true);
+
+                    if (displayed)
+                    {
+                        result = get_line_column_first_content_index(&line->columns[i - 1], &coord->index);
+
+                        if (result)
+                            coord->column = i - 1;
+
+                    }
+
+                }
+
+                break;
+
+            case GDK_SCROLL_RIGHT:
+
+                /* On s'assure que la colonne suivante est visible et peuplée */
+                for (; (i + 1) < BLC_COUNT && !result; i++)
+                {
+                    displayed = ((i + 1) < count ? g_display_options_get(options, i + 1) : true);
+
+                    if (displayed)
+                    {
+                        result = get_line_column_first_content_index(&line->columns[i + 1], &coord->index);
+
+                        if (result)
+                            coord->column = i + 1;
+
+                    }
+
+                }
+
+                break;
+
+        default:
+            break;
+
+    }
+
+    /* Calcul de la position finale */
+
+    if (result)
+    {
+        *offset = 0;
+
+        for (k = 0; k < i; k++)
+        {
+            displayed = (k < count ? g_display_options_get(options, k) : true);
+
+            if (displayed)
+            {
+                width = g_buffer_line_compute_max_width(line, k, summary, offsets);
+
+                if (width > 0)
+                {
+                    *offset += width;
+                    if (k < line->merge_start) *offset += COL_MARGIN;
+                }
+
+            }
+
+        }
+
+        switch (dir)
+        {
+            case GDK_SCROLL_LEFT:
+                *offset += get_column_width(&line->columns[i]);
+                break;
+
+            case GDK_SCROLL_RIGHT:
+                /**offset += 0;*/
+                break;
+
+            default:
+                break;
+
+        }
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : line    = ligne de texte à manipuler.                        *
+*                cairo   = contexte graphique à utiliser pour les pinceaux.   *
+*                summary = résumé des largeurs maximales.                     *
+*                x_init  = abscisse du point d'impression de départ.          *
+*                y       = ordonnée du point d'impression.                    *
+*                options = règles d'affichage des colonnes modulables.        *
+*                offsets = décalages supplémentaires à appliquer.             *
+*                list    = liste de contenus à mettre en évidence.            *
+*                                                                             *
+*  Description : Imprime la ligne de texte représentée.                       *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_buffer_line_draw(GBufferLine *line, cairo_t *cairo, const line_width_summary *summary, gint x_init, gint y, const GDisplayOptions *options, const line_width_summary *offsets, const segcnt_list *list)
+{
+    GBufferLineClass *class;                /* Stockage de briques de base */
+    bool has_src_surface;                   /* Note une présence définie   */
+    gint x;                                 /* Point de départ d'impression*/
+    size_t count;                           /* Qté de colonnes en option   */
+    size_t i;                               /* Boucle de parcours          */
+    gint max_width;                         /* Largeur maximale de colonne */
+
+    if (line->flags != BLF_NONE && line->flags != BLF_HAS_CODE)
+    {
+        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);
+
+    }
+
+    x = x_init;
+
+    count = g_display_options_count(options);
+
+    for (i = 0; i < BLC_COUNT; i++)
+    {
+        if (i < count)
+        {
+            if (!g_display_options_get(options, i))
+                continue;
+        }
+
+        draw_line_column_segments(&line->columns[i], cairo, x, y, list);
+
+        if (i < line->merge_start)
+        {
+            max_width = g_buffer_line_compute_max_width(line, i, summary, offsets);
+
+            if (max_width > 0)
+                x += max_width + COL_MARGIN;
+
+        }
+
+    }
+
+}
diff --git a/src/glibext/bufferline.h b/src/glibext/bufferline.h
new file mode 100644
index 0000000..95db203
--- /dev/null
+++ b/src/glibext/bufferline.h
@@ -0,0 +1,218 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * bufferline.h - prototypes pour la représentation de fragments de texte en ligne
+ *
+ * Copyright (C) 2010-2018 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_H
+#define _GLIBEXT_BUFFERLINE_H
+
+
+#include <glib-object.h>
+#include <stdbool.h>
+
+
+#include "gdisplayoptions.h"
+#include "linesegment.h"
+#include "../analysis/content.h"
+#include "../arch/vmpa.h"
+
+
+
+#define G_TYPE_BUFFER_LINE            g_buffer_line_get_type()
+#define G_BUFFER_LINE(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_BUFFER_LINE, GBufferLine))
+#define G_BUFFER_LINE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_BUFFER_LINE, GBufferLineClass))
+#define G_IS_BUFFER_LINE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_BUFFER_LINE))
+#define G_IS_BUFFER_LINE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_BUFFER_LINE))
+#define G_BUFFER_LINE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_BUFFER_LINE, GBufferLineClass))
+
+
+/* Représentation de fragments de texte en ligne (instance) */
+typedef struct _GBufferLine GBufferLine;
+
+/* Représentation de fragments de texte en ligne (classe) */
+typedef struct _GBufferLineClass GBufferLineClass;
+
+
+/* Désignation des colonnes d'une ligne */
+typedef enum _BufferLineColumn
+{
+    BLC_PHYSICAL,                           /* Position physique           */
+    BLC_VIRTUAL,                            /* Adresse virtuelle           */
+    BLC_BINARY,                             /* Contenu sous forme binaire  */
+    BLC_ASSEMBLY_LABEL,                     /* Etiquette dans les données  */
+    BLC_ASSEMBLY_HEAD,                      /* Instruction pour assembleur */
+    BLC_ASSEMBLY,                           /* Code pour assembleur        */
+    BLC_COMMENTS,                           /* Commentaires éventuels      */
+
+    BLC_COUNT,
+
+    BLC_LAST_USED,                          /* Dernière colonne utilisée   */
+    BLC_INVALID,                            /* Valeur de non-initialisation*/
+    BLC_MAIN                                /* Colonne principale (cf. imm)*/
+
+} BufferLineColumn;
+
+/* Première colonne de l'ensemble */
+#define BLC_FIRST BLC_PHYSICAL
+
+/* Première colonne toujours affichée */
+#define BLC_DISPLAY BLC_ASSEMBLY_LABEL
+
+
+/* Confort pour l'insertion de texte */
+#define SL(str) str, strlen(str)
+
+/* Espace entre les colonnes */
+#define COL_MARGIN 23
+
+
+/* Propriétés particulières supplémentaires */
+typedef enum _BufferLineFlags
+{
+    BLF_NONE            = 0 << 0,           /* Aucune                      */
+    BLF_HAS_CODE        = 1 << 0,           /* La ligne contient du code   */
+    BLF_IS_LABEL        = 1 << 1,           /* Etiquette pour symbole      */
+    BLF_ENTRYPOINT      = 1 << 2,           /* Représentation d'une entrée */
+    BLF_BOOKMARK        = 1 << 3,           /* Signet associé              */
+    BLF_WIDTH_MANAGER   = 1 << 4,           /* Début de groupe des largeurs*/
+
+    BLF_ALL             = ((1 << 5) - 1)
+
+} 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(const mrange_t *, BufferLineColumn);
+
+/* Indique la zone mémoire où se situe la ligne. */
+const mrange_t *g_buffer_line_get_range(const GBufferLine *);
+
+/* Construit le tronc commun d'une ligne autour de sa position. */
+void g_buffer_line_fill_phys(GBufferLine *, MemoryDataSize, const vmpa2t *);
+
+/* Construit le tronc commun d'une ligne autour de sa position. */
+void g_buffer_line_fill_virt(GBufferLine *, MemoryDataSize, const vmpa2t *);
+
+/* Construit le tronc commun d'une ligne autour de sa position. */
+void g_buffer_line_fill_vmpa(GBufferLine *, const vmpa2t *, MemoryDataSize, MemoryDataSize);
+
+/* Construit le tronc commun d'une ligne autour de son contenu. */
+void g_buffer_line_fill_content(GBufferLine *, const GBinContent *, const mrange_t *, phys_t);
+
+/* Recherche le premier créateur enregistré dans des segments. */
+GObject *g_buffer_line_find_first_segment_creator(const GBufferLine *, BufferLineColumn);
+
+/* Ajoute du texte à formater dans une ligne donnée. */
+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);
+
+/* Indique si du texte est présent dans une ligne de tampon. */
+bool g_buffer_line_has_text(const GBufferLine *, BufferLineColumn, BufferLineColumn);
+
+/* Donne le texte représenté par une ligne de tampon. */
+char *g_buffer_line_get_text(const GBufferLine *, BufferLineColumn, BufferLineColumn, bool);
+
+/* Supprime du texte représenté par une ligne de tampon. */
+void g_buffer_line_delete_text(GBufferLine *, BufferLineColumn, BufferLineColumn);
+
+/* Fournit la colonne à partir de laquelle une fusion opère. */
+BufferLineColumn g_buffer_line_get_merge_start(const GBufferLine *);
+
+/* Définit la colonne à partir de laquelle la fusion opère. */
+void g_buffer_line_start_merge_at(GBufferLine *, BufferLineColumn);
+
+/* Ajoute une propriété particulière à une ligne donnée. */
+void g_buffer_line_add_flag(GBufferLine *, BufferLineFlags);
+
+/* Renseigne sur les propriétés particulières liées à une ligne. */
+BufferLineFlags g_buffer_line_get_flags(const GBufferLine *);
+
+/* Retire une propriété particulière à une ligne donnée. */
+void g_buffer_line_remove_flag(GBufferLine *, BufferLineFlags);
+
+/* Exporte la ligne de texte représentée. */
+void g_buffer_line_export(GBufferLine *, buffer_export_context *, BufferExportType, const bool *);
+
+
+/* Petite aide pour la détection de commentaire */
+#define g_buffer_line_has_comment(ln)                                       \
+    ({                                                                      \
+        bool __result;                                                      \
+        __result = g_buffer_line_has_text(ln, BLC_COMMENTS, BLC_COUNT);     \
+        __result |= (g_buffer_line_get_merge_start(ln) == BLC_DISPLAY       \
+                     && !(g_buffer_line_get_flags(ln) & BLF_IS_LABEL));     \
+        __result;                                                           \
+    })
+
+
+
+/* ----------------------- MANIPULATION DES LARGEURS REQUISES ----------------------- */
+
+
+/* Mémorisation des largeurs pour un groupe de lignes */
+typedef struct _line_width_summary
+{
+    gint max_widths[BLC_COUNT];             /* Taille cachée des colonnes  */
+    gint merged_width;                      /* Largeur cumulée avant fusion*/
+
+} line_width_summary;
+
+/* Identification d'un contenu de colonne */
+typedef struct _col_coord_t
+{
+    BufferLineColumn column;                /* Colonne concernée           */
+    size_t index;                           /* Indice d'insertion          */
+
+} col_coord_t;
+
+
+/* Fait remonter les largeurs requises par une ligne donnée. */
+void g_buffer_line_collect_widths(GBufferLine *, line_width_summary *);
+
+/* Fournit la largeur d'une colonne finalement appliquée. */
+gint g_buffer_line_compute_max_width(const GBufferLine *, BufferLineColumn, const line_width_summary *, const line_width_summary *);
+
+/* Fournit le segment présent à une position donnée. */
+line_segment *g_buffer_line_get_segment_from_coord(const GBufferLine *, const col_coord_t *);
+
+/* Fournit les coordonnées correspondant à une abscisse donnée. */
+bool g_buffer_line_get_coord_at(const GBufferLine *, const line_width_summary *, const GDisplayOptions *, const line_width_summary *, gint *, gint *, GdkScrollDirection, bool, col_coord_t *);
+
+/* Donne le segment présent à une abscisse donnée. */
+line_segment *g_buffer_line_get_segment_at(const GBufferLine *, const line_width_summary *, const GDisplayOptions *, const line_width_summary *, gint *, gint *, GdkScrollDirection, bool);
+
+/* Donne le créateur présent à une abscisse donnée. */
+GObject *g_buffer_line_get_creator_at(const GBufferLine *, const line_width_summary *, const GDisplayOptions *, const line_width_summary *, gint *, gint *, GdkScrollDirection, bool);
+
+/* Fournit des coordonnées voisines selon une direction donnée. */
+bool g_buffer_line_find_near_coord(const GBufferLine *, col_coord_t *, const line_width_summary *, const GDisplayOptions *, const line_width_summary *, GdkScrollDirection, gint *);
+
+/* Imprime la ligne de texte représentée. */
+void g_buffer_line_draw(GBufferLine *, cairo_t *, const line_width_summary *, gint, gint, const GDisplayOptions *, const line_width_summary *, const segcnt_list *);
+
+
+
+#endif  /* _GLIBEXT_BUFFERLINE_H */
diff --git a/src/glibext/bufferview.c b/src/glibext/bufferview.c
new file mode 100644
index 0000000..e40715e
--- /dev/null
+++ b/src/glibext/bufferview.c
@@ -0,0 +1,1285 @@
+
+/* 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
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Chrysalide is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "bufferview.h"
+
+
+#include <assert.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 *);
+
+};
+
+
+/* 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. */
+static void g_buffer_view_init(GBufferView *);
+
+/* Supprime toutes les références externes. */
+static void g_buffer_view_dispose(GBufferView *);
+
+/* Procède à la libération totale de la mémoire. */
+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 *);
+
+/* Calcule la position idéale de curseur pour un point donné. */
+bool _g_buffer_view_compute_caret_full(GBufferView *, gint, GBufferLine *, size_t, const GDisplayOptions *, const line_width_summary *, cairo_rectangle_int_t *, GLineCursor **);
+
+/* 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 *, const line_width_summary *);
+
+
+/* Fournit la ligne présente à une ordonnée donnée. */
+static GBufferLine *g_buffer_view_find_line_at(GBufferView *, gint, size_t *);
+
+
+
+
+
+
+
+/* Détermine le type de la vue d'un tampon pour code désassemblé. */
+G_DEFINE_TYPE(GBufferView, g_buffer_view, G_TYPE_OBJECT);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : class = classe de composant GTK à initialiser.               *
+*                                                                             *
+*  Description : Procède à l'initialisation d'une classe de vue de tampon.    *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_buffer_view_class_init(GBufferViewClass *class)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+
+    object = G_OBJECT_CLASS(class);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_buffer_view_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_buffer_view_finalize;
+
+    /* Sigaux */
+
+    g_signal_new("need-redraw",
+                 G_TYPE_BUFFER_VIEW,
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET(GBufferViewClass, need_redraw),
+                 NULL, NULL,
+                 g_cclosure_marshal_VOID__VOID,
+                 G_TYPE_NONE, 0);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : view = composant GLib à initialiser.                         *
+*                                                                             *
+*  Description : Procède à l'initialisation d'une vue d'un tampon pour code.  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_buffer_view_init(GBufferView *view)
+{
+    view->cache = NULL;
+
+    view->highlighted = NULL;
+
+    /**
+     * Inversion du statut pour forcer l'actualisation lors de la création.
+     */
+    view->unrestricted = false;
+
+    view->start = NULL;
+    view->end = NULL;
+
+    view->first = 0;
+    view->last = 0;
+
+    view->tracker = NULL;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : view = instance d'objet GLib à traiter.                      *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_buffer_view_dispose(GBufferView *view)
+{
+    g_clear_object(&view->cache);
+
+    g_clear_object(&view->start);
+    g_clear_object(&view->end);
+
+    g_clear_object(&view->tracker);
+
+    G_OBJECT_CLASS(g_buffer_view_parent_class)->dispose(G_OBJECT(view));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : view = instance d'objet GLib à traiter.                      *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+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));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : buffer      = tampon à représenter à l'écran.                *
+*                highlighted = gestionnaire de surbrillance pour segments.    *
+*                                                                             *
+*  Description : Crée une nouvelle vue d'un tampon pour code désassemblé.     *
+*                                                                             *
+*  Retour      : Composant GTK créé.                                          *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GBufferView *g_buffer_view_new(GBufferCache *cache, segcnt_list *highlighted)
+{
+    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);
+
+    if (highlighted != NULL)
+    {
+        ref_segment_content_list(highlighted);
+        result->highlighted = highlighted;
+    }
+    else
+        result->highlighted = init_segment_content_list();
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : cache = tampon de lignes cohérentes à manipuler.             *
+*                added = indication sur la variation de la taille du tampon.  *
+*                index = indice de la première ligne à traiter.               *
+*                count = nombre de lignes à traiter.                          *
+*                view  = vue active du tampon de lignes concerné.             *
+*                                                                             *
+*  Description : Accompagne une variation de la quantité de lignes du tampon. *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void on_buffer_cache_size_changed(const GBufferCache *cache, bool added, size_t index, size_t count, GBufferView *view)
+{
+    //size_t i;                               /* Boucle de parcours          */
+    //GBufferLine *line;                      /* Ligne à manipuler           */
+    //const vmpa2t *addr;                     /* Localisation de ligne       */
+
+    /**
+     * Il n'y a pas besoin de verrou ici car la fonction est appelée directement par le tampon.
+     * D'autre part, on considère qu'il y a toujours une ligne aux adresses de borne, si la vue est bornée.
+     */
+
+    if (added)
+    {
+        if (view->unrestricted)
+            view->last += count;
+
+        else
+        {
+#if 0
+
+            /* Avant la zone représentée ? */
+            if (index < view->first)
+            {
+                view->first += count;
+                view->last += count;
+            }
+
+            /* Juste avant la zone représentée ? */
+            else if (view->first == index)
+                for (i = 0; i < count; i++)
+                {
+                    g_buffer_cache_get_line_addr(const GBufferCache *, size_t, gint, vmpa2t *);
+
+                    line = g_code_buffer_find_line_by_index(buffer, index + i);
+                    addr = get_mrange_addr(g_buffer_line_get_range(line));
+
+                    if (cmp_vmpa(&view->start, addr) == 0)
+                    {
+                        view->first++;
+                        view->last++;
+                    }
+                    else
+                        break;
+
+                }
+
+            /* Dans la zone représentée ? */
+            else if (view->first < index && index <= view->last)
+                view->last += count;
+
+            /* Juste après la vue représentée ? */
+            else if ((view->last + 1) == index)
+                for (i = 0; i < count; i++)
+                {
+                    g_buffer_cache_get_line_addr(const GBufferCache *, size_t, gint, vmpa2t *);
+
+                    line = g_code_buffer_find_line_by_index(buffer, index + i);
+                    addr = get_mrange_addr(g_buffer_line_get_range(line));
+
+                    if (cmp_vmpa(&view->end, addr) == 0)
+                        view->last++;
+                    else
+                        break;
+
+                }
+
+            //g_width_tracker_update_added(view->int_tracker, index, count);
+#endif
+
+        }
+
+    }
+
+    else
+    {
+        if (view->unrestricted)
+            view->last -= count;
+
+        else
+        {
+            /* Avant la zone représentée ? */
+            if (index <= view->first)
+            {
+                view->first -= count;
+                view->last -= count;
+            }
+
+            /* Dans la zone représentée ? */
+            else if (view->first < index && index <= view->last)
+                view->last -= count;
+
+        }
+
+        //g_width_tracker_update_deleted(view->int_tracker, index, index + count - 1);
+
+    }
+
+    //g_signal_emit_by_name(view, "need-redraw");
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : view = visualisateur à consulter.                            *
+*                                                                             *
+*  Description : Fournit le tampon de code lié à un visualisateur donné.      *
+*                                                                             *
+*  Retour      : Tampon de code associé au gestionnaire d'affichage.          *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GBufferCache *g_buffer_view_get_cache(const GBufferView *view)
+{
+    GBufferCache *result;                   /* Instance à retourner        */
+
+    result = view->cache;
+
+    g_object_ref(G_OBJECT(result));
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : view  = visualisateur à mettre à jour.                       *
+*                first = première ligne à imprimer.                           *
+*                last  = première ligne hors cadre.                           *
+*                                                                             *
+*  Description : Restreint le champ d'application de l'affichage.             *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_buffer_view_restrict(GBufferView *view, GLineCursor *start, GLineCursor *end)
+{
+    bool state;                             /* Nouvel état à proclamer     */
+    GWidthTracker *template;                /* Suivi déjà en place         */
+
+    state = (start == NULL || end == NULL);
+
+    if (view->unrestricted != state)
+    {
+        view->unrestricted = state;
+
+        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->unrestricted)
+        {
+            view->first = 0;
+            view->last = g_buffer_cache_count_lines(view->cache) - 1;
+
+            view->tracker = template;
+
+        }
+
+        else
+        {
+            g_object_ref_sink(G_OBJECT(start));
+            g_object_ref_sink(G_OBJECT(end));
+
+            view->start = start;
+            view->end = end;
+
+            view->first = g_buffer_cache_find_index_by_cursor(view->cache, start, true);
+            view->last = g_buffer_cache_find_index_by_cursor(view->cache, end, false);
+
+            view->tracker = g_width_tracker_new_restricted(template, view->first, view->last);
+
+            g_object_unref(G_OBJECT(template));
+
+        }
+
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : view  = visualisateur à consulter.                           *
+*                first = première ligne à imprimer ou NULL. [OUT]             *
+*                last  = première ligne hors cadre ou NULL. [OUT]             *
+*                                                                             *
+*  Description : Indique le champ d'application de l'affichage.               *
+*                                                                             *
+*  Retour      : true si des restrictions particulières sont en place.        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_buffer_view_get_restrictions(const GBufferView *view, GLineCursor **start, GLineCursor **end)
+{
+    if (!view->unrestricted)
+    {
+        if (start != NULL)
+        {
+            *start = view->start;
+            g_object_ref(G_OBJECT(*start));
+        }
+
+        if (end != NULL)
+        {
+            *end = view->end;
+            g_object_ref(G_OBJECT(*end));
+        }
+
+    }
+    else
+    {
+        if (start != NULL) *start = NULL;
+        if (end != NULL) *end = NULL;
+    }
+
+    return !view->unrestricted;
+
+}
+
+
+
+
+
+
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : view    = visualisation à consulter.                         *
+*                options = règles d'affichage des colonnes modulables.        *
+*                                                                             *
+*  Description : Fournit la largeur requise par une visualisation.            *
+*                                                                             *
+*  Retour      : Dimension calculée.                                          *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+gint g_buffer_view_get_width(GBufferView *view, const GDisplayOptions *options)
+{
+    gint result;                            /* Taille à retourner          */
+
+    result = g_buffer_cache_get_text_position(view->cache);
+
+    result += g_width_tracker_get_width(view->tracker, options);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : view    = visualisation à consulter.                         *
+*                options = règles d'affichage des colonnes modulables.        *
+*                                                                             *
+*  Description : Fournit la largeur requise pour dépasser les marges gauches. *
+*                                                                             *
+*  Retour      : Dimension calculée.                                          *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+gint g_buffer_view_get_margin(GBufferView *view, const GDisplayOptions *options)
+{
+    gint result;                            /* Taille à retourner          */
+
+    result = g_buffer_cache_get_text_position(view->cache);
+
+    result += g_width_tracker_get_margin(view->tracker, options);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : view = visualisation à consulter.                            *
+*                                                                             *
+*  Description : Fournit la hauteur requise par une visualisation.            *
+*                                                                             *
+*  Retour      : Dimension calculée.                                          *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+gint g_buffer_view_get_height(const GBufferView *view)
+{
+    gint result;                            /* Taille à retourner          */
+
+    result = g_buffer_cache_get_line_height(view->cache);
+
+    result *= (view->last - view->first + 1);
+
+    return result;
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : view    = vue de tampon à mettre à jour.                     *
+*                x       = abscisse proposée pour le nouvel emplacement.      *
+*                y       = ordonnée proposée pour le nouvel emplacement.      *
+*                options = règles d'affichage des colonnes modulables.        *
+*                offsets = décalages supplémentaires à appliquer.             *
+*                caret   = position du curseur à construire. [OUT]            *
+*                cursor  = emplacement correspondant à cette position. [OUT]  *
+*                                                                             *
+*  Description : Calcule la position idéale de curseur pour un point donné.   *
+*                                                                             *
+*  Retour      : true si les deux derniers arguments ont pu être constitués.  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_buffer_view_compute_caret_full(GBufferView *view, gint x, gint y, const GDisplayOptions *options, const line_width_summary *offsets, cairo_rectangle_int_t *caret, GLineCursor **cursor)
+{
+    bool result;                            /* Bilan à retourner           */
+    gint lheight;                           /* Hauteur d'une ligne         */
+    size_t index;                           /* Indice de ligne de tampon   */
+    GBufferLine *line;                      /* Ligne à la position courante*/
+
+    result = false;
+
+    /* Détermination de la ligne courante */
+
+    lheight = g_buffer_cache_get_line_height(view->cache);
+    index = y / lheight;
+
+    index += view->first;
+
+    if (index > view->last)
+        goto gbvccf_done;
+
+    line = g_buffer_cache_find_line_by_index(view->cache, index);
+
+    assert(line != NULL);
+
+    /* Calcul d'une position */
+
+    result = _g_buffer_view_compute_caret_full(view, x, line, index, options, offsets, caret, cursor);
+
+    g_object_unref(G_OBJECT(line));
+
+ gbvccf_done:
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : view    = vue de tampon à mettre à jour.                     *
+*                x       = abscisse proposée pour le nouvel emplacement.      *
+*                line    = ligne correspondant à la position.                 *
+*                index   = indice de cette même ligne dans le tampon.         *
+*                options = règles d'affichage des colonnes modulables.        *
+*                offsets = décalages supplémentaires à appliquer.             *
+*                caret   = position du curseur à construire. [OUT]            *
+*                cursor  = emplacement correspondant à cette position. [OUT]  *
+*                                                                             *
+*  Description : Calcule la position idéale de curseur pour un point donné.   *
+*                                                                             *
+*  Retour      : true si les deux derniers arguments ont pu être constitués.  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool _g_buffer_view_compute_caret_full(GBufferView *view, gint x, GBufferLine *line, size_t index, const GDisplayOptions *options, const line_width_summary *offsets, cairo_rectangle_int_t *caret, GLineCursor **cursor)
+{
+    bool result;                            /* Bilan à retourner           */
+    gint text_pos;                          /* Abscisse de départ du texte */
+    line_width_summary summary;             /* Résumé concis des largeurs  */
+    gint base;                              /* Position absolue de segment */
+    bool status;                            /* Bilan de la localisation    */
+    gint lheight;                           /* Hauteur d'une ligne         */
+
+    result = false;
+
+    /* Zone d'intervention bornée ! */
+
+    text_pos = g_buffer_cache_get_text_position(view->cache);
+
+    if (x < text_pos)
+        goto gbvccf_done;
+
+    /* Calcul d'une position */
+
+    g_width_tracker_get_local_width_summary(view->tracker, index, &summary);
+
+    x -= text_pos;
+
+    status = g_buffer_line_get_coord_at(line, &summary, options, offsets, &base, &x,
+                                        GDK_SCROLL_LEFT, true, (col_coord_t []) { { 0 } });
+
+    if (!status)
+        goto gbvccf_done;
+
+    /* Transmission des informations */
+
+    lheight = g_buffer_cache_get_line_height(view->cache);
+
+    caret->x = text_pos + base + x;
+
+    caret->y = (index - view->first) * lheight;
+
+    caret->width = 2;
+    caret->height = lheight;
+
+    g_buffer_cache_get_line_cursor(view->cache, index, caret->x, cursor);
+
+    result = true;
+
+ gbvccf_done:
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : view    = vue de tampon à manipuler.                         *
+*                line    = ligne à venir consulter.                           *
+*                index   = indice de cette même ligne dans le tampon.         *
+*                caret   = position du curseur à faire évoluer.               *
+*                ctrl    = indique la demande d'un parcours rapide.           *
+*                dir     = direction du parcours.                             *
+*                options = règles d'affichage des colonnes modulables.        *
+*                offsets = décalages supplémentaires à appliquer.             *
+*                                                                             *
+*  Description : Déplace le curseur au sein d'une vue de tampon.              *
+*                                                                             *
+*  Retour      : true si un déplacement a été effectué, false sinon.          *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool _g_buffer_view_move_caret(GBufferView *view, const GBufferLine *line, size_t index, cairo_rectangle_int_t *caret, bool ctrl, GdkScrollDirection dir, const GDisplayOptions *options, const line_width_summary *offsets)
+{
+    bool result;                            /* Bilan à retourner           */
+    gint text_pos;                          /* Abscisse de départ du texte */
+    gint offset;                            /* Point de travail modifiable */
+    line_width_summary summary;             /* Résumé concis des largeurs  */
+    gint base;                              /* Position absolue de segment */
+    col_coord_t coord;                      /* Coordonnées en interne      */
+    line_segment *segment;                  /* Bribe de texte trouvée      */
+
+
+    result = false;
+
+    /* Zone d'intervention bornée ! */
+
+    text_pos = g_buffer_cache_get_text_position(view->cache);
+
+    if (caret->x < text_pos)
+        goto gbvmc_done;
+
+    offset = caret->x - text_pos;
+
+    g_width_tracker_get_local_width_summary(view->tracker, index, &summary);
+
+    /* Déplacement au sein du segment courant ? */
+
+    result = g_buffer_line_get_coord_at(line, &summary, options, offsets, &base, &offset, dir, false, &coord);
+
+    if (result)
+    {
+        segment = g_buffer_line_get_segment_from_coord(line, &coord);
+
+        result = move_caret_on_line_segment(segment, &offset, ctrl, dir);
+
+        release_line_segment(segment);
+
+    }
+
+    /* Tentative de déplacement chez le segment voisin ? */
+
+    if (!result)
+    {
+        base = 0;
+
+        result = g_buffer_line_find_near_coord(line, &coord, &summary, options, offsets, dir, &offset);
+
+    }
+
+    /* Mise à jour éventuelle */
+
+    if (result)
+        caret->x = text_pos + base + offset;
+
+ gbvmc_done:
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : view    = vue de tampon à mettre à jour.                     *
+*                ctrl    = indique la demande d'un parcours rapide.           *
+*                dir     = direction du parcours.                             *
+*                options = règles d'affichage des colonnes modulables.        *
+*                offsets = décalages supplémentaires à appliquer.             *
+*                caret   = position du curseur à faire évoluer. [OUT]         *
+*                cursor  = emplacement correspondant à cette position. [OUT]  *
+*                                                                             *
+*  Description : Déplace le curseur au sein d'une vue de tampon.              *
+*                                                                             *
+*  Retour      : true si les deux derniers arguments ont pu être constitués.  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_buffer_view_move_caret(GBufferView *view, bool ctrl, GdkScrollDirection dir, const GDisplayOptions *options, const line_width_summary *offsets, cairo_rectangle_int_t *caret, GLineCursor **cursor)
+{
+    bool result;                            /* Bilan à retourner           */
+    size_t index;                           /* Indice de ligne de tampon   */
+    GBufferLine *line;                      /* Ligne sous le pointeur      */
+    size_t first;                           /* Première ligne intégrée     */
+    size_t last;                            /* Dernière ligne intégrée     */
+    GBufferLine *other;                     /* Ligne voisine à visiter     */
+    bool moved;                             /* Mémorisation d'une évolut°  */
+    gint text_pos;                          /* Abscisse de départ du texte */
+
+    result = false;
+
+    line = g_buffer_view_find_line_at(view, caret->y, &index);
+    if (line == NULL) goto gbvmc_done;
+
+    first = view->first;
+    last = view->last;
+
+    switch (dir)
+    {
+        case GDK_SCROLL_UP:
+
+            if (index > first)
+            {
+                index--;
+
+                other = g_buffer_cache_find_line_by_index(view->cache, index);
+                assert(other != NULL);
+
+                result = _g_buffer_view_compute_caret_full(view, caret->x, other, index,
+                                                           options, offsets, caret, cursor);
+
+                g_object_unref(G_OBJECT(other));
+
+            }
+
+            break;
+
+        case GDK_SCROLL_DOWN:
+
+            if (index < last)
+            {
+                index++;
+
+                other = g_buffer_cache_find_line_by_index(view->cache, index);
+                assert(other != NULL);
+
+                result = _g_buffer_view_compute_caret_full(view, caret->x, other, index,
+                                                           options, offsets, caret, cursor);
+
+                g_object_unref(G_OBJECT(other));
+
+            }
+
+            break;
+
+        case GDK_SCROLL_LEFT:
+
+            moved = _g_buffer_view_move_caret(view, line, index, caret, ctrl, GDK_SCROLL_LEFT, options, offsets);
+
+            if (moved)
+            {
+                g_buffer_cache_get_line_cursor(view->cache, index, caret->x, cursor);
+                result = true;
+            }
+
+            else if (index > first)
+            {
+                index--;
+
+                other = g_buffer_cache_find_line_by_index(view->cache, index);
+                assert(other != NULL);
+
+                result = _g_buffer_view_compute_caret_full(view, INT_MAX, other, index,
+                                                           options, offsets, caret, cursor);
+
+                g_object_unref(G_OBJECT(other));
+
+            }
+
+            break;
+
+        case GDK_SCROLL_RIGHT:
+
+            moved = _g_buffer_view_move_caret(view, line, index, caret, ctrl, GDK_SCROLL_RIGHT, options, offsets);
+
+            if (moved)
+            {
+                g_buffer_cache_get_line_cursor(view->cache, index, caret->x, cursor);
+                result = true;
+            }
+
+            else if (index < last)
+            {
+                index++;
+
+                text_pos = g_buffer_cache_get_text_position(view->cache);
+
+                other = g_buffer_cache_find_line_by_index(view->cache, index);
+                assert(other != NULL);
+
+                result = _g_buffer_view_compute_caret_full(view, text_pos, other, index,
+                                                           options, offsets, caret, cursor);
+
+                g_object_unref(G_OBJECT(other));
+
+            }
+
+            break;
+
+        default:    /* GDK_SCROLL_SMOOTH */
+            break;
+
+    }
+
+    g_object_unref(G_OBJECT(line));
+
+ gbvmc_done:
+
+    return result;
+
+}
+
+
+
+
+
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : view    = vue de tampon à mettre à jour.                     *
+*                x       = abscisse de la zone principale à traiter.          *
+*                y       = ordonnée de la zone principale à traiter.          *
+*                options = règles d'affichage des colonnes modulables.        *
+*                offsets = décalages supplémentaires à appliquer.             *
+*                                                                             *
+*  Description : Trouve le créateur à l'origine d'un emplacement donné.       *
+*                                                                             *
+*  Retour      : Créateur trouvé ou NULL si aucun.                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GObject *g_buffer_view_find_creator(GBufferView *view, gint x, gint y, const GDisplayOptions *options, const line_width_summary *offsets)
+{
+    GObject *result;                        /* Trouvaille à faire remonter */
+    gint text_pos;                          /* Abscisse de départ du texte */
+    gint lheight;                           /* Hauteur d'une ligne         */
+    size_t index;                           /* Indice de ligne de tampon   */
+    GBufferLine *line;                      /* Ligne à la position courante*/
+    line_width_summary summary;             /* Résumé concis des largeurs  */
+
+    result = NULL;
+
+    /* Zone d'intervention bornée ! */
+
+    text_pos = g_buffer_cache_get_text_position(view->cache);
+
+    if (x < text_pos)
+        goto gbvfc_done;
+
+    /* Détermination de la ligne concernée */
+
+    lheight = g_buffer_cache_get_line_height(view->cache);
+    index = y / lheight;
+
+    index += view->first;
+
+    if (index > view->last)
+        goto gbvfc_done;
+
+    line = g_buffer_cache_find_line_by_index(view->cache, index);
+
+    assert(line != NULL);
+
+    /* Recherche d'un segment et de son empreinte */
+
+    g_width_tracker_get_local_width_summary(view->tracker, index, &summary);
+
+    x -= text_pos;
+
+    result = g_buffer_line_get_creator_at(line, &summary, options, offsets,
+                                          (gint []) { 0 }, &x, GDK_SCROLL_LEFT, false);
+
+    g_object_unref(G_OBJECT(line));
+
+ gbvfc_done:
+
+    return result;
+
+}
+
+
+
+
+
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : view = vue de tampon à mettre à jour.                        *
+*                                                                             *
+*  Description : Supprime toute mise en évidence de segments.                 *
+*                                                                             *
+*  Retour      : true si un besoin d'actualisation d'affichage se fait sentir.*
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_buffer_view_unhighlight_segments(GBufferView *view)
+{
+    bool result;                            /* Bilan d'action à renvoyer   */
+
+    result = reset_segment_content_list(view->highlighted);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : view    = vue de tampon à mettre à jour.                     *
+*                x       = abscisse de la zone principale à traiter.          *
+*                y       = ordonnée de la zone principale à traiter.          *
+*                options = règles d'affichage des colonnes modulables.        *
+*                offsets = décalages supplémentaires à appliquer.             *
+*                                                                             *
+*  Description : Surligne tous les segments similaires à celui sous la souris.*
+*                                                                             *
+*  Retour      : true si un besoin d'actualisation d'affichage se fait sentir.*
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_buffer_view_highlight_segments(GBufferView *view, gint x, gint y, const GDisplayOptions *options, const line_width_summary *offsets)
+{
+    bool result;                            /* Besoin à faire remonter     */
+    gint text_pos;                          /* Abscisse de départ du texte */
+    gint lheight;                           /* Hauteur d'une ligne         */
+    size_t index;                           /* Indice de ligne de tampon   */
+    GBufferLine *line;                      /* Ligne à la position courante*/
+    line_width_summary summary;             /* Résumé concis des largeurs  */
+    line_segment *segment;                  /* Segment sélectionnable      */
+
+    /* Réinitialisation */
+
+    if (view->highlighted != NULL)
+        result = g_buffer_view_unhighlight_segments(view);
+    else
+        result = false;
+
+    /* Zone d'intervention bornée ! */
+
+    text_pos = g_buffer_cache_get_text_position(view->cache);
+
+    if (x < text_pos)
+        goto gbvhs_done;
+
+    /* Détermination de la ligne concernée */
+
+    lheight = g_buffer_cache_get_line_height(view->cache);
+    index = y / lheight;
+
+    index += view->first;
+
+    if (index > view->last)
+        goto gbvhs_done;
+
+    line = g_buffer_cache_find_line_by_index(view->cache, index);
+
+    assert(line != NULL);
+
+    /* Recherche d'un segment et de son empreinte */
+
+    g_width_tracker_get_local_width_summary(view->tracker, index, &summary);
+
+    x -= text_pos;
+
+    segment = g_buffer_line_get_segment_at(line, &summary, options, offsets,
+                                           (gint []) { 0 }, &x, GDK_SCROLL_LEFT, true);
+
+    g_object_unref(G_OBJECT(line));
+
+    /* Conclusion */
+
+    if (segment != NULL)
+    {
+        result |= add_segment_content_to_selection_list(view->highlighted, segment);
+        release_line_segment(segment);
+    }
+
+    if (result)
+        g_signal_emit_by_name(view, "need-redraw");
+
+ gbvhs_done:
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : view     = visualisation à représenter.                      *
+*                cr       = contexte graphique dédié à la procédure.          *
+*                virt_y   = ordonnée réelle du point 0 à l'écran.             *
+*                area     = position et surface à traiter.                    *
+*                options  = règles d'affichage des colonnes modulables.       *
+*                offsets  = décalages supplémentaires à appliquer.            *
+*                selected = ordonnée d'une ligne sélectionnée ou NULL.        *
+*                scale    = échelle appliquée à la surface de rendu.          *
+*                export   = indique si la vue est en cours d'exportation.     *
+*                                                                             *
+*  Description : Imprime la visualisation du tampon de lignes quelconques.    *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_buffer_view_draw(const GBufferView *view, cairo_t *cr, gint virt_y, const cairo_rectangle_int_t *area, const GDisplayOptions *options, const line_width_summary *offsets, gint *selected, double scale, bool export)
+{
+    gint 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        */
+    segcnt_list *highlighted;               /* Segments mis en évidence    */
+
+    line_height = g_buffer_cache_get_line_height(view->cache) * scale;
+
+    line_height = MAX(line_height, 1);
+
+    /* Indice et point de départ */
+
+    first = view->first;
+    first += (virt_y / line_height);
+
+    cr_y = area->y - (virt_y % line_height);
+
+    /* Indice de d'arrivée */
+
+    last = first + (area->height / line_height);
+    if (area->height % line_height > 0) last++;
+
+    last = MIN(last, view->last);
+
+    /* Phase de dessin ! */
+
+    /**
+     * Le contexte n'est pas sauvegardé avant modification ici car
+     * l'appelant l'a fait pour nous avant sa translation sur les abscisses.
+     */
+
+    cairo_translate(cr, 0, cr_y);
+
+    if (selected != NULL)
+        *selected -= cr_y;
+
+    if (export)
+        highlighted = init_segment_content_list();
+    else
+        highlighted = view->highlighted;
+
+    g_buffer_cache_draw(view->cache, cr, first, last, area, options, offsets, selected, highlighted);
+
+    if (export)
+        unref_segment_content_list(highlighted);
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : view = visualisation à consulter.                            *
+*                y    = ordonnée comprise dans la ligne recherchée.           *
+*                idx  = indice de la ligne trouvée ou NULL. [OUT]             *
+*                                                                             *
+*  Description : Fournit la ligne présente à une ordonnée donnée.             *
+*                                                                             *
+*  Retour      : Ligne retrouvée ou NULL si aucune.                           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static GBufferLine *g_buffer_view_find_line_at(GBufferView *view, gint y, size_t *idx)
+{
+    GBufferLine *result;                    /* Ligne trouvée à retourner   */
+    gint lheight;                           /* Hauteur d'une ligne         */
+    size_t index;                           /* Indice attendu              */
+
+    lheight = g_buffer_cache_get_line_height(view->cache);
+    index = y / lheight;
+
+    index += view->first;
+
+    if (index <= view->last)
+        result = g_buffer_cache_find_line_by_index(view->cache, index);
+    else
+        result = NULL;
+
+    if (result != NULL && idx != NULL)
+        *idx = index;
+
+    return result;
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/******************************************************************************
+*                                                                             *
+*  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_get_cursor_coordinates(GBufferView *view, const GLineCursor *cursor, bool code, gint *x, gint *y)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    result = g_buffer_cache_get_cursor_coordinates(view->cache, cursor, view->first, view->last, code, x, y);
+
+    return result;
+
+}
diff --git a/src/glibext/bufferview.h b/src/glibext/bufferview.h
new file mode 100644
index 0000000..01da713
--- /dev/null
+++ b/src/glibext/bufferview.h
@@ -0,0 +1,115 @@
+
+/* 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
+ *
+ *  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_H
+#define _GLIBEXT_BUFFERVIEW_H
+
+
+#include <glib-object.h>
+
+
+#include "buffercache.h"
+#include "gdisplayoptions.h"
+
+
+
+#define G_TYPE_BUFFER_VIEW              (g_buffer_view_get_type())
+#define G_BUFFER_VIEW(obj)              (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_BUFFER_VIEW, GBufferView))
+#define G_BUFFER_VIEW_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_BUFFER_VIEW, GBufferViewClass))
+#define G_IS_BUFFER_VIEW(obj)           (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_BUFFER_VIEW))
+#define G_IS_BUFFER_VIEW_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_BUFFER_VIEW))
+#define G_BUFFER_VIEW_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_BUFFER_VIEW, GBufferViewClass))
+
+
+/* Vue d'un tampon pour code désassemblé (instance) */
+typedef struct _GBufferView GBufferView;
+
+/* Vue d'un tampon pour code désassemblé (classe) */
+typedef struct _GBufferViewClass GBufferViewClass;
+
+
+/* Détermine le type de la vue d'un tampon pour lignes générées. */
+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 *);
+
+/* Fournit le tampon de code lié à un visualisateur donné. */
+GBufferCache *g_buffer_view_get_cache(const GBufferView *);
+
+/* Restreint le champ d'application de l'affichage. */
+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 **);
+
+
+
+/* Fournit la largeur requise par une visualisation. */
+gint g_buffer_view_get_width(GBufferView *, const GDisplayOptions *);
+
+/* Fournit la largeur requise pour dépasser les marges gauches. */
+gint g_buffer_view_get_margin(GBufferView *, const GDisplayOptions *);
+
+/* Fournit la hauteur requise par une visualisation. */
+gint g_buffer_view_get_height(const GBufferView *);
+
+
+
+
+
+/* Calcule la position idéale de curseur pour un point donné. */
+bool g_buffer_view_compute_caret_full(GBufferView *, gint, gint, const GDisplayOptions *, const line_width_summary *, cairo_rectangle_int_t *, GLineCursor **);
+
+/* Déplace le curseur au sein d'une vue de tampon. */
+bool g_buffer_view_move_caret(GBufferView *, bool, GdkScrollDirection, const GDisplayOptions *, const line_width_summary *, cairo_rectangle_int_t *, GLineCursor **);
+
+
+
+/* Trouve le créateur à l'origine d'un emplacement donné. */
+GObject *g_buffer_view_find_creator(GBufferView *, gint, gint, const GDisplayOptions *, const line_width_summary *);
+
+
+
+/* Supprime toute mise en évidence de segments. */
+bool g_buffer_view_unhighlight_segments(GBufferView *);
+
+/* Surligne tous les segments similaires à celui sous la souris. */
+bool g_buffer_view_highlight_segments(GBufferView *, gint, gint, const GDisplayOptions *, const line_width_summary *);
+
+/* Imprime la visualisation du tampon de lignes quelconques. */
+void g_buffer_view_draw(const GBufferView *, cairo_t *, gint, const cairo_rectangle_int_t *, const GDisplayOptions *, const line_width_summary *, gint *, double, bool);
+
+
+
+
+
+
+/* Indique la position d'affichage d'une adresse donnée. */
+bool g_buffer_view_get_cursor_coordinates(GBufferView *, const GLineCursor *, bool, gint *, gint *);
+
+
+
+
+
+#endif  /* _GLIBEXT_BUFFERVIEW_H */
diff --git a/src/glibext/gbuffercache-int.h b/src/glibext/gbuffercache-int.h
deleted file mode 100644
index 6886fb0..0000000
--- a/src/glibext/gbuffercache-int.h
+++ /dev/null
@@ -1,96 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * gbuffercache-int.h - définitions internes d'affichage à la demande d'un ensemble de lignes
- *
- * Copyright (C) 2020 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_GBUFFERCACHE_INT_H
-#define _GLIBEXT_GBUFFERCACHE_INT_H
-
-
-#include "gbuffercache.h"
-
-
-
-/* --------------------- FONCTIONS AUXILIAIRES DE MANIPULATIONS --------------------- */
-
-
-/* Informations rattachées à la génération d'une ligne */
-typedef struct _generator_link
-{
-    GLineGenerator *instance;               /* Fournisseur de contenu      */
-    size_t repeat;                          /* Compteur de successions     */
-
-} generator_link;
-
-/* Suivi interne de l'état d'une ligne */
-typedef struct _cache_info
-{
-    union
-    {
-        generator_link generator;           /* Générateur unique           */
-        generator_link *generators;         /* Liste de générateurs        */
-    };
-    size_t count;                           /* Taille de cette liste       */
-
-    GBufferLine *line;                      /* Ligne en place ou NULL      */
-
-    BufferLineFlags extra_flags;            /* Propriétés supplémentaires  */
-
-} cache_info;
-
-
-
-/* -------------------------- TAMPON POUR CODE DESASSEMBLE -------------------------- */
-
-
-/* Tampon pour gestion de lignes optimisée (instance) */
-struct _GBufferCache
-{
-    GObject parent;                         /* A laisser en premier        */
-
-    GBinContent *content;                   /* Contenu binaire global      */
-
-    cache_info *lines;                      /* Liste des lignes intégrées  */
-    size_t count;                           /* Quantité en cache           */
-    size_t used;                            /* Quantité utilisée           */
-
-    GWidthTracker *tracker;                 /* Suivi des largeurs          */
-
-};
-
-/* Tampon pour gestion de lignes optimisée (classe) */
-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);
-
-};
-
-
-
-#endif  /* _GLIBEXT_GBUFFERCACHE_INT_H */
diff --git a/src/glibext/gbuffercache.c b/src/glibext/gbuffercache.c
deleted file mode 100644
index b54de26..0000000
--- a/src/glibext/gbuffercache.c
+++ /dev/null
@@ -1,1725 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * gbuffercache.c - affichage à la demande d'un ensemble de lignes
- *
- * Copyright (C) 2016-2019 Cyrille Bagard
- *
- *  This file is part of Chrysalide.
- *
- *  Chrysalide is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 3 of the License, or
- *  (at your option) any later version.
- *
- *  Chrysalide is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#include "gbuffercache.h"
-
-
-#include <assert.h>
-#include <malloc.h>
-#include <stdlib.h>
-
-
-#include "gbuffercache-int.h"
-#include "chrysamarshal.h"
-
-
-
-/* --------------------- 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);
-
-/* Libère la mémoire occupée par des informations sur une ligne. */
-static void release_cache_info(cache_info *);
-
-/* Ajoute un générateur aux informations sur une ligne. */
-static void extend_cache_info(cache_info *, GLineGenerator *, BufferLineFlags);
-
-/* Retire un générateur aux informations d'une ligne. */
-static void remove_from_cache_info(cache_info *, 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);
-
-/* Fournit la ligne de tampon correspondant aux générateurs. */
-static GBufferLine *get_cache_info_line(cache_info *, size_t, const GBinContent *);
-
-/* 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 *);
-
-
-
-/* -------------------------- TAMPON POUR CODE DESASSEMBLE -------------------------- */
-
-
-/* Taille des allocations de masse */
-#define LINE_ALLOC_BULK 1000
-
-
-/* Procède à l'initialisation d'une classe de tampon de lignes. */
-static void g_buffer_cache_class_init(GBufferCacheClass *);
-
-/* Procède à l'initialisation d'un tampon de gestion de lignes. */
-static void g_buffer_cache_init(GBufferCache *);
-
-/* Supprime toutes les références externes. */
-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 *);
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/*                       FONCTIONS AUXILIAIRES DE MANIPULATIONS                       */
-/* ---------------------------------------------------------------------------------- */
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : info      = informations concernant une ligne à constituer.  *
-*                generator = générateur à associer à toutes les lignes.       *
-*                repeat    = compteur de répétition entre les lignes.         *
-*                flags     = propriétés supplémentaires à associer à la ligne.*
-*                                                                             *
-*  Description : Met en place un nouvel ensemble d'information sur une ligne. *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void init_cache_info(cache_info *info, GLineGenerator *generator, size_t repeat, BufferLineFlags flags)
-{
-    info->generator.instance = generator;
-    info->generator.repeat = repeat;
-
-    g_object_ref(G_OBJECT(generator));
-
-    info->count = 1;
-
-    info->line = NULL;
-
-    info->extra_flags = flags;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : info = informations concernant une ligne à constituer.       *
-*                                                                             *
-*  Description : Libère la mémoire occupée par des informations sur une ligne.*
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void release_cache_info(cache_info *info)
-{
-    size_t i;                               /* Boucle de parcours          */
-
-    if (info->count == 1)
-        g_object_unref(G_OBJECT(info->generator.instance));
-
-    else
-        for (i = 0; i < info->count; i++)
-            g_object_unref(G_OBJECT(info->generators[i].instance));
-
-    reset_cache_info_line(info);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  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.*
-*                                                                             *
-*  Description : Ajoute un générateur aux informations sur une ligne.         *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void extend_cache_info(cache_info *info, GLineGenerator *generator, BufferLineFlags flags)
-{
-    generator_link first;                   /* Générateur déjà en place    */
-    generator_link *new;                    /* Nouveau générateur placé    */
-
-    if (info->count == 1)
-    {
-        first = info->generator;
-
-        info->generators = (generator_link *)calloc(2, sizeof(generator_link));
-
-        info->generators[0] = first;
-        info->count = 2;
-
-        new = &info->generators[1];
-
-    }
-    else
-    {
-        info->generators = (generator_link *)realloc(info->generators,
-                                                     ++info->count * sizeof(generator_link));
-
-        new = &info->generators[info->count - 1];
-
-    }
-
-    new->instance = generator;
-    new->repeat = 0;
-
-    g_object_ref(G_OBJECT(generator));
-
-    reset_cache_info_line(info);
-
-    /**
-     * On peut rajouter des indications, mais, en cas de retrait d'un générateur,
-     * on ne saura pas forcément lesquelles retirer puisque qu'on ne trace pas
-     * leur origine.
-     *
-     * On considère donc que seul le premier générateur (le principal) a le
-     * droit de poser des fanions.
-     */
-
-    assert(flags == BLF_NONE);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : info      = informations concernant une ligne à actualiser.  *
-*                generator = générateur à dissocier de toutes les lignes.     *
-*                                                                             *
-*  Description : Retire un générateur aux informations d'une ligne.           *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void remove_from_cache_info(cache_info *info, GLineGenerator *generator)
-{
-    generator_link *link;                   /* Accès simplifié             */
-    size_t i;                               /* Boucle de parcours          */
-    generator_link *old;                    /* Mémorisation avant opérat°  */
-
-    if (info->count == 1)
-    {
-        link = &info->generator;
-
-        assert(link->instance == generator);
-
-        g_object_unref(G_OBJECT(generator));
-
-        info->count = 0;
-
-    }
-
-    else
-    {
-        for (i = 0; i < info->count; i++)
-        {
-            link = &info->generators[i];
-
-            if (link->instance == generator)
-            {
-                if ((i + 1) < info->count)
-                    memmove(&info->generators[i], &info->generators[i + 1],
-                            (info->count - i - 1) * sizeof(generator_link));
-
-                if (info->count == 2)
-                {
-                    old = info->generators;
-
-                    info->count = 1;
-                    info->generator = info->generators[0];
-
-                    free(old);
-
-                }
-                else
-                    info->generators = (generator_link *)realloc(info->generators,
-                                                                 --info->count * sizeof(generator_link));
-
-                g_object_unref(G_OBJECT(generator));
-
-                break;
-
-            }
-
-        }
-
-#ifndef NDEBUG
-
-        /**
-         * Attention : si l'élément était en dernière position,
-         * l'indice de parcours est désormais égal au nombre de générateurs présents !
-         */
-        assert(i <= info->count);
-
-        for ( ; i < info->count; i++)
-        {
-            link = &info->generators[i];
-
-            assert(link->instance != generator);
-
-        }
-
-#endif
-
-    }
-
-    reset_cache_info_line(info);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : info   = informations sur une ligne à venir consulter.       *
-*                index  = indice de la ligne visée par la consultation.       *
-*                x      = position géographique sur la ligne concernée.       *
-*                cursor = emplacement à constituer. [OUT]                     *
-*                                                                             *
-*  Description : Retrouve l'emplacement correspondant à une position de ligne.*
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void get_cache_info_cursor(const cache_info *info, size_t index, gint x, GLineCursor **cursor)
-{
-    const generator_link *generator;        /* Générateur retenu           */
-
-    if (info->count == 1)
-        generator = &info->generator;
-    else
-        generator = &info->generators[0];
-
-    *cursor = g_line_generator_compute_cursor(generator->instance, x, index, generator->repeat);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  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 *info, GBufferLine *line, gboolean last)
-{
-    if (last)
-    {
-        G_LOCK(_line_update);
-
-        assert(info->line != NULL);
-
-        _reset_cache_info_line_unlocked(info);
-
-        G_UNLOCK(_line_update);
-
-    }
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : info    = informations sur une ligne à venir manipuler.      *
-*                index   = indice de la ligne à constituer.                   *
-*                content = éventuel contenu binaire brut à imprimer.          *
-*                                                                             *
-*  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 *info, size_t index, const GBinContent *content)
-{
-    GBufferLine *result;                    /* Construction à retourner    */
-    size_t i;                               /* Boucle de parcours          */
-
-    G_LOCK(_line_update);
-
-    result = info->line;
-
-    if (result == NULL)
-    {
-        result = g_buffer_line_new(UNUSED_MRANGE_PTR, 0/* !! */);
-
-        g_object_add_toggle_ref(G_OBJECT(result), (GToggleNotify)on_line_ref_toggle, info);
-
-        if (info->count == 1)
-            g_line_generator_print(info->generator.instance, result, index,
-                                   info->generator.repeat, content);
-
-        else
-            for (i = 0; i < info->count; i++)
-                g_line_generator_print(info->generators[i].instance, result, index,
-                                       info->generators[i].repeat, content);
-
-        info->line = result;
-
-    }
-
-    else
-        g_object_ref(G_OBJECT(result));
-
-    G_UNLOCK(_line_update);
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  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_unlocked(cache_info *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.         *
-*                                                                             *
-*  Description : Force la réinitialisation d'une éventuelle ligne cachée.     *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void reset_cache_info_line(cache_info *info)
-{
-    G_LOCK(_line_update);
-
-    _reset_cache_info_line_unlocked(info);
-
-    G_UNLOCK(_line_update);
-
-}
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/*                            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  : class = classe de composant GLib à initialiser.              *
-*                                                                             *
-*  Description : Procède à l'initialisation d'une classe de tampon de lignes. *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void g_buffer_cache_class_init(GBufferCacheClass *class)
-{
-    GObjectClass *object;                   /* Autre version de la classe  */
-
-    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;
-
-    /* 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);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : cache = composant GLib à initialiser.                        *
-*                                                                             *
-*  Description : Procède à l'initialisation d'un tampon de gestion de lignes. *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void g_buffer_cache_init(GBufferCache *cache)
-{
-    cache->content = NULL;
-
-    cache->lines = NULL;
-    cache->count = 0;
-    cache->used = 0;
-
-    cache->tracker = g_width_tracker_new(cache);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  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)
-{
-    size_t i;                               /* Boucle de parcours #1       */
-    cache_info *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_clear_object(&info->generator.instance);
-
-        else
-            for (j = 0; j < info->count; j++)
-                g_clear_object(&info->generators[j].instance);
-
-        g_clear_object(&info->line);
-
-    }
-
-    g_clear_object(&cache->tracker);
-
-    G_OBJECT_CLASS(g_buffer_cache_parent_class)->dispose(G_OBJECT(cache));
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : cache = instance d'objet GLib à traiter.                     *
-*                                                                             *
-*  Description : Procède à la libération totale de la mémoire.                *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void g_buffer_cache_finalize(GBufferCache *cache)
-{
-    size_t i;                               /* Boucle de parcours          */
-    cache_info *info;                       /* Accès direct à une ligne    */
-
-    for (i = 0; i < cache->used; i++)
-    {
-        info = &cache->lines[i];
-
-        if (info->count > 1)
-            free(info->generators);
-
-    }
-
-    if (cache->lines != NULL)
-        free(cache->lines);
-
-    G_OBJECT_CLASS(g_buffer_cache_parent_class)->finalize(G_OBJECT(cache));
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : content = éventuel contenu binaire brut à référencer.        *
-*                                                                             *
-*  Description : Crée un nouveau composant de tampon pour code désassemblé.   *
-*                                                                             *
-*  Retour      : Composant GLib créé.                                         *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-GBufferCache *g_buffer_cache_new(GBinContent *content)
-{
-    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));
-    }
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : cache = tampon de lignes à consulter.                        *
-*                                                                             *
-*  Description : Fournit la hauteur d'impression d'une ligne visualisée.      *
-*                                                                             *
-*  Retour      : Hauteur de ligne en pixels.                                  *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-gint g_buffer_cache_get_line_height(const GBufferCache *cache)
-{
-    GBufferCacheClass *class;               /* Classe des tampons          */
-
-    class = G_BUFFER_CACHE_GET_CLASS(cache);
-
-    return class->line_height;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : cache = tampon de lignes à consulter.                        *
-*                                                                             *
-*  Description : Indique l'éventuel contenu binaire associé au cache.         *
-*                                                                             *
-*  Retour      : Eventuel contenu renseigné ou NULL.                          *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-GBinContent *g_buffer_cache_get_content(const GBufferCache *cache)
-{
-    GBinContent *result;                    /* Contenu à retourner         */
-
-    result = cache->content;
-
-    if (result != NULL)
-        g_object_ref(G_OBJECT(result));
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : cache = tampon de lignes à consulter.                        *
-*                                                                             *
-*  Description : Fournit la taille réservée pour la marge gauche.             *
-*                                                                             *
-*  Retour      : Largeur en pixels.                                           *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-gint g_buffer_cache_get_left_margin(const GBufferCache *cache)
-{
-    GBufferCacheClass *class;               /* Classe des tampons          */
-
-    class = G_BUFFER_CACHE_GET_CLASS(cache);
-
-    return class->left_margin;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : cache = tampon de lignes à consulter.                        *
-*                                                                             *
-*  Description : Fournit la position de départ pour l'impression de texte.    *
-*                                                                             *
-*  Retour      : Position en pixels.                                          *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-gint g_buffer_cache_get_text_position(const GBufferCache *cache)
-{
-    GBufferCacheClass *class;               /* Classe des tampons          */
-
-    class = G_BUFFER_CACHE_GET_CLASS(cache);
-
-    return class->text_pos;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  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(const GBufferCache *cache)
-{
-    return cache->used;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : cache = composant GLib à consulter.                          *
-*                                                                             *
-*  Description : Fournit un lien vers la structure de suivi de largeurs.      *
-*                                                                             *
-*  Retour      : Gestionnaire de largeurs de lignes.                          *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-GWidthTracker *g_buffer_cache_get_width_tracker(const GBufferCache *cache)
-{
-    GWidthTracker *result;                  /* Instance à retourner    *   */
-
-    result = cache->tracker;
-
-    g_object_ref(G_OBJECT(result));
-
-    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;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : cache     = instance GLib à modifier.                        *
-*                index     = point d'insertion, puis de sauvegarde.           *
-*                generator = générateur à insérer dans les lignes.            *
-*                flags     = propriétés supplémentaires à associer à la ligne.*
-*                before    = précise l'emplacement final des nouvelles lignes.*
-*                after     = précise l'emplacement final des nouvelles lignes.*
-*                                                                             *
-*  Description : Insère un générateur dans des lignes à une position donnée.  *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-void g_buffer_cache_insert_at(GBufferCache *cache, size_t index, GLineGenerator *generator, BufferLineFlags flags, bool before, bool after)
-{
-#ifndef NDEBUG
-    GLineCursor *gen_cursor;                /* Position du générateur      */
-    GLineCursor *line_cursor;               /* Position de la ligne        */
-    int ret;                                /* Bilan de comparaison        */
-#endif
-    size_t needed;                          /* Emplacements nécessaires    */
-    size_t i;                               /* Boucle de parcours          */
-
-    assert(index < cache->used);
-
-    assert(!(before && after));
-
-#ifndef NDEBUG
-
-    if (!before && !after)
-    {
-        gen_cursor = g_line_generator_compute_cursor(generator, 0, index, 0);
-
-        get_cache_info_cursor(&cache->lines[index], index, 0, &line_cursor);
-
-        ret = g_line_cursor_compare(gen_cursor, line_cursor);
-
-        g_object_unref(G_OBJECT(line_cursor));
-        g_object_unref(G_OBJECT(gen_cursor));
-
-        assert(ret == 0);
-
-    }
-
-#endif
-
-    /* Cas particulier d'ajout en fin de cache... */
-    if (after && (index + 1) == cache->used)
-    {
-        g_buffer_cache_append(cache, generator, flags);
-        goto gbcia_done;
-    }
-
-    /* Adaptation de l'espace */
-
-    needed = g_line_generator_count_lines(generator);
-
-    if (before || after)
-    {
-        if ((cache->used + needed) >= cache->count)
-        {
-            cache->count += needed + LINE_ALLOC_BULK;
-            cache->lines = (cache_info *)realloc(cache->lines, cache->count * sizeof(cache_info));
-        }
-    }
-
-    else if (needed > 1)
-    {
-        if ((cache->used + needed - 1) >= cache->count)
-        {
-            cache->count += needed - 1 + LINE_ALLOC_BULK;
-            cache->lines = (cache_info *)realloc(cache->lines, cache->count * sizeof(cache_info));
-        }
-    }
-
-    /* Insertion du générateur */
-
-    if (after)
-        index++;
-
-    if (before || after)
-    {
-        memmove(&cache->lines[index + needed], &cache->lines[index], (cache->used - index) * sizeof(cache_info));
-
-        for (i = 0; i < needed; i++)
-            init_cache_info(&cache->lines[index + i], generator, i, flags);
-
-        cache->used += needed;
-
-        g_width_tracker_update_added(cache->tracker, index, needed);
-
-        g_signal_emit_by_name(cache, "size-changed", true, index, needed);
-
-    }
-
-    else
-    {
-        extend_cache_info(&cache->lines[index], generator, flags);
-
-        g_width_tracker_update(cache->tracker, index);
-
-        if (needed > 1)
-        {
-            /* On déborde sur les lignes suivantes, donc on crée de l'espace ! */
-
-            memmove(&cache->lines[index + 1],
-                    &cache->lines[index + 1 + needed - 1], (cache->used - index - 1) * sizeof(cache_info));
-
-            for (i = 1; i < needed; i++)
-                init_cache_info(&cache->lines[index + i], generator, i, BLF_NONE);
-
-            cache->used += needed - 1;
-
-            g_width_tracker_update_added(cache->tracker, index + 1, needed - 1);
-
-        }
-
-        g_signal_emit_by_name(cache, "size-changed", true, index, needed - 1);
-
-    }
-
- gbcia_done:
-
-    ;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : cache = instance GLib à modifier.                            *
-*                index = point de suppression.                                *
-*                                                                             *
-*  Description : Retire une ligne du tampon.                                  *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-void g_buffer_cache_delete_at(GBufferCache *cache, size_t index)
-{
-    cache_info *info;                       /* Accès direct à une ligne    */
-
-    assert(index < cache->used);
-
-    info = &cache->lines[index];
-
-    release_cache_info(info);
-
-    if ((index + 1) < cache->used)
-        memmove(&cache->lines[index], &cache->lines[index + 1],
-                (cache->used - index - 1) * sizeof(cache_info));
-
-    cache->used--;
-
-    g_width_tracker_update_deleted(cache->tracker, index, index);
-
-    g_signal_emit_by_name(cache, "size-changed", false, index, 1);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : cache  = instance GLib à modifier.                           *
-*                index  = point d'insertion, puis de sauvegarde.              *
-*                type   = type de générateurs à retirer des lignes visées.    *
-*                before = précise l'emplacement final de l'élément visé.      *
-*                after  = précise l'emplacement final de l'élément visé.      *
-*                                                                             *
-*  Description : Retire un type de générateur de lignes.                      *
-*                                                                             *
-*  Retour      : Générateur éventuellement trouvé ou NULL si aucun.           *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-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    */
-    generator_link *link;                   /* Accès simplifié             */
-    size_t i;                               /* Boucle de parcours          */
-    size_t count;                           /* Emplacements occupés        */
-    size_t delete;                          /* Indice de suppression       */
-
-    assert(index < cache->used);
-
-    assert(!(before && after));
-
-    result = NULL;
-
-    /* Recherche d'un générateur correspondant */
-
-    if (before)
-        info = &cache->lines[index - 1];
-    else if (after)
-        info = &cache->lines[index + 1];
-    else
-        info = &cache->lines[index];
-
-    if (info->count == 1)
-    {
-        link = &info->generator;
-
-        if (G_OBJECT_TYPE(link->instance) == type)
-            result = link->instance;
-
-    }
-
-    else
-        for (i = 0; i < info->count && result == NULL; i++)
-        {
-            link = &info->generators[i];
-
-            if (G_OBJECT_TYPE(link->instance) == type)
-                result = link->instance;
-
-        }
-
-    /* Retrait de l'instance trouvée */
-
-    if (result != NULL)
-    {
-        count = g_line_generator_count_lines(result);
-
-#ifndef NDEBUG
-        if (!before && !after)
-            assert(count == 1);
-#endif
-
-        g_object_ref(G_OBJECT(result));
-
-        /* Suppression de l'élément */
-
-        for (i = 0; i < count; i++)
-        {
-            if (before)
-                info = &cache->lines[index - 1 - i];
-            else if (after)
-                info = &cache->lines[index + 1 + i];
-            else
-                info = &cache->lines[index];
-
-            remove_from_cache_info(info, result);
-
-        }
-
-        /* Suppression des lignes associées */
-
-        for (i = 0; i < count; i++)
-        {
-            if (before)
-                delete = index - 1;
-            else if (after)
-                delete = index + 1;
-            else
-                delete = index;
-
-            info = &cache->lines[delete];
-
-            if (info->count == 0)
-            {
-                release_cache_info(info);
-
-                if ((delete + 1) < cache->used)
-                    memmove(&cache->lines[delete], &cache->lines[delete + 1],
-                            (cache->used - delete - 1) * sizeof(cache_info));
-
-                cache->used--;
-
-                g_width_tracker_update_deleted(cache->tracker, delete, delete);
-
-                g_signal_emit_by_name(cache, "size-changed", false, delete, 1);
-
-            }
-
-        }
-
-    }
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : cache     = instance GLib à modifier.                        *
-*                generator = générateur à associer à toutes les lignes.       *
-*                flags     = propriétés supplémentaires à associer à la ligne.*
-*                                                                             *
-*  Description : Ajoute en fin de tampon un générateur de lignes.             *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-void g_buffer_cache_append(GBufferCache *cache, GLineGenerator *generator, BufferLineFlags flags)
-{
-    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    */
-
-    count = g_line_generator_count_lines(generator);
-
-    assert(count > 0);
-
-    assert((flags != BLF_NONE && count == 1) || flags == BLF_NONE);
-
-    if ((cache->used + count) > cache->count)
-    {
-        cache->count += count + LINE_ALLOC_BULK;
-        cache->lines = (cache_info *)realloc(cache->lines, cache->count * sizeof(cache_info));
-    }
-
-    index = cache->used;
-
-    for (i = 0; i < count; i++)
-    {
-        info = &cache->lines[index + i];
-
-        info->generator.instance = generator;
-        info->generator.repeat = g_buffer_cache_compute_repetition(cache, index + i, generator);
-
-        g_object_ref(G_OBJECT(generator));
-
-        info->count = 1;
-
-        info->line = NULL;
-
-        info->extra_flags = flags;
-
-    }
-
-    cache->used += count;
-
-    g_width_tracker_update_added(cache->tracker, index, count);
-
-    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 added;                           /* Nombre d'ajouts effectués   */
-
-    assert(count >= cache->used);
-
-    if (count > cache->count)
-    {
-        cache->lines = (cache_info *)realloc(cache->lines, count * sizeof(cache_info));
-        cache->count = count;
-    }
-
-    index = cache->used;
-
-    for (i = index; i < count; i++)
-    {
-        info = &cache->lines[i];
-
-        info->generator.instance = generator;
-        info->generator.repeat = g_buffer_cache_compute_repetition(cache, i, generator);
-
-        g_object_ref(G_OBJECT(generator));
-
-        info->count = 1;
-
-        info->line = NULL;
-
-    }
-
-    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 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*/
-
-    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;
-
-        g_width_tracker_update_deleted(cache->tracker, max, max + removed - 1);
-
-        g_signal_emit_by_name(cache, "size-changed", false, max, removed);
-
-    }
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : cache  = tampon de lignes à venir consulter.                 *
-*                index  = indice de la ligne visée par la consultation.       *
-*                x      = position géographique sur la ligne concernée.       *
-*                cursor = emplacement à constituer. [OUT]                     *
-*                                                                             *
-*  Description : Retrouve l'emplacement correspondant à une position de ligne.*
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-void g_buffer_cache_get_line_cursor(const GBufferCache *cache, size_t index, gint x, GLineCursor **cursor)
-{
-    assert(index < cache->used);
-
-    get_cache_info_cursor(&cache->lines[index], index, x, cursor);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : cache = tampon de lignes à venir consulter.                  *
-*                index = indice de la ligne visée par la consultation.        *
-*                                                                             *
-*  Description : Détermine l'ensemble des propriétés attachées à une ligne.   *
-*                                                                             *
-*  Retour      : Somme de toutes les propriétés enregistrées.                 *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-BufferLineFlags g_buffer_cache_get_line_flags(const GBufferCache *cache, size_t index)
-{
-    BufferLineFlags result;                 /* Somme à renvoyer            */
-    cache_info *info;                       /* Accès direct à une ligne    */
-    const generator_link *generator;        /* Générateur retenu           */
-    size_t i;                               /* Boucle de parcours          */
-
-    // TODO : check lock
-
-    assert(index < cache->used);
-
-    info = &cache->lines[index];
-
-    result = info->extra_flags;
-
-    if (info->count == 1)
-    {
-        generator = &info->generator;
-        result |= g_line_generator_get_flags(generator->instance, index, generator->repeat);
-    }
-
-    else
-        for (i = 0; i < info->count; i++)
-        {
-            generator = &info->generators[i];
-            result |= g_line_generator_get_flags(generator->instance, index, generator->repeat);
-        }
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : cache = tampon de lignes à consulter.                        *
-*                index = indice de la ligne recherchée.                       *
-*                                                                             *
-*  Description : Retrouve une ligne au sein d'un tampon avec un indice.       *
-*                                                                             *
-*  Retour      : Line retrouvée ou NULL en cas d'échec.                       *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-GBufferLine *g_buffer_cache_find_line_by_index(const GBufferCache *cache, size_t index)
-{
-    GBufferLine *result;                    /* Ligne trouvée à retourner   */
-
-    if (index < cache->used)
-        result = get_cache_info_line(&cache->lines[index], index, cache->content);
-    else
-        result = NULL;
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : cache   = tampon de lignes à venir consulter.                *
-*                index   = indice de la ligne à mesurer.                      *
-*                summary = largeurs maximales à faire évoluer.                *
-*                                                                             *
-*  Description : Fait remonter les largeurs requises par une ligne donnée.    *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-void g_buffer_cache_collect_widths(GBufferCache *cache, size_t index, line_width_summary *summary)
-{
-    GBufferLine *line;                      /* Ligne éphémère à mesurer    */
-
-    line = get_cache_info_line(&cache->lines[index], index, cache->content);
-
-    g_buffer_line_collect_widths(line, summary);
-
-    g_object_unref(G_OBJECT(line));
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : cache    = visualisation à représenter.                      *
-*                cr       = contexte graphique dédié à la procédure.          *
-*                first    = première ligne à dessiner.                        *
-*                last     = dernière ligne à dessiner.                        *
-*                area     = position et surface à traiter.                    *
-*                options  = règles d'affichage des colonnes modulables.       *
-*                offsets  = décalages supplémentaires à appliquer.            *
-*                selected = ordonnée d'une ligne sélectionnée ou NULL.        *
-*                list     = liste de contenus à mettre en évidence.           *
-*                                                                             *
-*  Description : Imprime une partie choisie du tampon contenant des lignes.   *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-void g_buffer_cache_draw(const GBufferCache *cache, cairo_t *cr, size_t first, size_t last, const cairo_rectangle_int_t *area, const GDisplayOptions *options, const line_width_summary *offsets, const gint *selected, const segcnt_list *list)
-{
-    GBufferCacheClass *class;               /* Classe des tampons          */
-    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    */
-    line_width_summary summary;             /* Résumé concis des largeurs  */
-    GBufferLine *line;                      /* Ligne à venir dessiner      */
-
-    class = G_BUFFER_CACHE_GET_CLASS(cache);
-
-    y = 0;
-
-    wait_selection = true;
-
-    if (cache->used > 0)
-        for (i = first; i <= last; i++)
-        {
-            /* Si sélection, on sousligne la ligne concernée */
-            if (wait_selection && selected != NULL && *selected == y)
-            {
-                cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.05);
-
-                cairo_rectangle(cr, area->x, y, area->width, class->line_height);
-                cairo_fill(cr);
-
-                wait_selection = false;
-
-            }
-
-            info = &cache->lines[i];
-
-            if (i == first || (g_buffer_cache_get_line_flags(cache, i) & BLF_WIDTH_MANAGER))
-                g_width_tracker_get_local_width_summary(cache->tracker, i, &summary);
-
-            line = get_cache_info_line(info, i, cache->content);
-
-            g_buffer_line_draw(line, cr, &summary, class->text_pos, y, options, offsets, list);
-
-            g_object_unref(G_OBJECT(line));
-
-            y += class->line_height;
-
-        }
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : cache  = tampon de lignes à consulter.                       *
-*                cursor = emplacement à retrouver dans le tampon.             *
-*                first  = indique si on l'arrête à la première ou la dernière.*
-*                start  = borne inférieure des recherches (incluse).          *
-*                end    = borne supérieure des recherches (incluse).          *
-*                                                                             *
-*  Description : Indique l'indice correspondant à une adresse donnée.         *
-*                                                                             *
-*  Retour      : Indice des infos à l'adresse demandée, ou nombre de lignes.  *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-size_t _g_buffer_cache_find_index_by_cursor(const 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é     */
-
-    int find_containing_generator(const GLineCursor *c, const cache_info *i)
-    {
-        const generator_link *generator;    /* Générateur retenu           */
-
-        if (i->count == 1)
-            generator = &i->generator;
-        else
-            generator = &i->generators[0];
-
-        return g_line_generator_contain_cursor(generator->instance,
-                                                i - cache->lines, generator->repeat, c);
-
-    }
-
-    found = (cache_info *)bsearch(cursor, &cache->lines[start], end - start + 1,
-                                  sizeof(cache_info), (__compar_fn_t)find_containing_generator);
-
-    if (found == NULL)
-        result = cache->used;
-
-    else
-    {
-        result = (found - cache->lines);
-        assert(start <= result && result <= end);
-
-        /* On s'assure d'un arrêt sur la bonne ligne */
-
-        if (first)
-            for (; result > start; result--)
-            {
-                found = &cache->lines[result - 1];
-
-                if (find_containing_generator(cursor, found) != 0)
-                    break;
-
-            }
-
-        else
-            for (; result < end; result++)
-            {
-                found = &cache->lines[result + 1];
-
-                if (find_containing_generator(cursor, found) != 0)
-                    break;
-
-            }
-
-    }
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : cache  = tampon de lignes à consulter.                       *
-*                cursor = emplacement à retrouver dans le tampon.             *
-*                first  = indique si on l'arrête à la première ou la dernière.*
-*                                                                             *
-*  Description : Indique l'indice correspondant à une adresse donnée.         *
-*                                                                             *
-*  Retour      : Indice des infos à l'adresse demandée, ou nombre de lignes.  *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-size_t g_buffer_cache_find_index_by_cursor(const GBufferCache *cache, const GLineCursor *cursor, bool first)
-{
-    size_t result;                          /* Indice à retourner          */
-
-    if (cache->used == 0)
-        result = 0;
-    else
-        result = _g_buffer_cache_find_index_by_cursor(cache, cursor, first, 0, cache->used - 1);
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : cache = tampon de lignes à consulter.                        *
-*                start = point de départ du parcours.                         *
-*                flag  = propriétés à retrouver si possible.                  *
-*                                                                             *
-*  Description : Avance autant que possible vers une ligne idéale.            *
-*                                                                             *
-*  Retour      : Indice de la ligne recherchée, si elle existe.               *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-size_t g_buffer_cache_look_for_flag(const GBufferCache *cache, size_t start, BufferLineFlags flag)
-{
-    size_t result;                          /* Indice de ligne à retourner */
-    GLineCursor *init;                      /* Localisation de départ      */
-    size_t i;                               /* Boucle de parcours          */
-    GLineCursor *next;                      /* Localisation suivante       */
-    int ret;                                /* Bilan de comparaison        */
-
-    // TODO : check lock
-
-    assert(start < cache->used);
-
-    result = start;
-
-    get_cache_info_cursor(&cache->lines[start], start, 0, &init);
-
-    for (i = start + 1; i < cache->used; i++)
-    {
-        get_cache_info_cursor(&cache->lines[i], i, 0, &next);
-
-        ret = g_line_cursor_compare(init, next);
-
-        g_object_unref(G_OBJECT(next));
-
-        if (ret != 0)
-            break;
-
-        if ((g_buffer_cache_get_line_flags(cache, i) & flag) != 0)
-        {
-            result = i;
-            break;
-        }
-
-    }
-
-    g_object_unref(G_OBJECT(init));
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : cache  = tampon de lignes à consulter.                       *
-*                cursor = emplacement à présenter à l'écran.                  *
-*                first  = borne inférieure des recherches (incluse).          *
-*                last   = borne supérieure des recherches (incluse).          *
-*                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_cache_get_cursor_coordinates(const GBufferCache *cache, const GLineCursor *cursor, size_t first, size_t last, bool code, gint *x, gint *y)
-{
-    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 generator_link *generator;        /* Générateur retenu           */
-
-    index = _g_buffer_cache_find_index_by_cursor(cache, cursor, true, first, last);
-
-    result = (index < cache->used);
-
-    if (result)
-    {
-        lheight = G_BUFFER_CACHE_GET_CLASS(cache)->line_height;
-
-        *x = 0;
-        *y = (index - first) * G_BUFFER_CACHE_GET_CLASS(cache)->line_height;
-
-        for (; code && index <= last; index++)
-        {
-            if (g_buffer_cache_get_line_flags(cache, index) & BLF_HAS_CODE)
-                break;
-
-            if (index == last)
-                break;
-
-            info = &cache->lines[index + 1];
-
-            if (info->count == 1)
-                generator = &info->generator;
-            else
-                generator = &info->generators[0];
-
-            if (!g_line_generator_contain_cursor(generator->instance, index + 1, generator->repeat, cursor))
-                break;
-
-            *y += lheight;
-
-        }
-
-    }
-
-    return result;
-
-}
diff --git a/src/glibext/gbuffercache.h b/src/glibext/gbuffercache.h
deleted file mode 100644
index 79158c4..0000000
--- a/src/glibext/gbuffercache.h
+++ /dev/null
@@ -1,133 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * gbuffercache.h - prototypes pour l'affichage à la demande d'un ensemble de lignes
- *
- * Copyright (C) 2016-2019 Cyrille Bagard
- *
- *  This file is part of Chrysalide.
- *
- *  Chrysalide is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 3 of the License, or
- *  (at your option) any later version.
- *
- *  Chrysalide is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#ifndef _GLIBEXT_GBUFFERCACHE_H
-#define _GLIBEXT_GBUFFERCACHE_H
-
-
-#include <glib-object.h>
-#include <stdbool.h>
-#include <gdk/gdk.h>
-
-
-#include "gdisplayoptions.h"
-#include "gwidthtracker.h"
-#include "linegen.h"
-
-
-
-/* -------------------------- TAMPON POUR CODE DESASSEMBLE -------------------------- */
-
-
-#define G_TYPE_BUFFER_CACHE            g_buffer_cache_get_type()
-#define G_BUFFER_CACHE(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_BUFFER_CACHE, GBufferCache))
-#define G_BUFFER_CACHE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_BUFFER_CACHE, GBufferCacheClass))
-#define G_IS_BUFFER_CACHE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_BUFFER_CACHE))
-#define G_IS_BUFFER_CACHE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_BUFFER_CACHE))
-#define G_BUFFER_CACHE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_BUFFER_CACHE, GBufferCacheClass))
-
-
-/* Tampon pour gestion de lignes optimisée (instance) */
-typedef struct _GBufferCache GBufferCache;
-
-/* Tampon pour gestion de lignes optimisée (classe) */
-typedef struct _GBufferCacheClass GBufferCacheClass;
-
-
-/* Détermine le type du composant de tampon pour gestion de lignes optimisée. */
-GType g_buffer_cache_get_type(void);
-
-/* Crée un nouveau composant de tampon pour code désassemblé. */
-GBufferCache *g_buffer_cache_new(GBinContent *);
-
-/* Indique l'éventuel contenu binaire associé au cache. */
-GBinContent *g_buffer_cache_get_content(const GBufferCache *);
-
-/* Fournit la hauteur d'impression d'une ligne visualisée. */
-gint g_buffer_cache_get_line_height(const GBufferCache *);
-
-/* Fournit la taille réservée pour la marge gauche. */
-gint g_buffer_cache_get_left_margin(const GBufferCache *);
-
-/* Fournit la position de départ pour l'impression de texte. */
-gint g_buffer_cache_get_text_position(const GBufferCache *);
-
-/* Compte le nombre de lignes rassemblées dans un tampon. */
-size_t g_buffer_cache_count_lines(const GBufferCache *);
-
-/* Fournit un lien vers la structure de suivi de largeurs. */
-GWidthTracker *g_buffer_cache_get_width_tracker(const 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);
-
-/* Retire une ligne du tampon. */
-void g_buffer_cache_delete_at(GBufferCache *, size_t);
-
-/* Retire un type de générateur de lignes. */
-GLineGenerator *g_buffer_cache_delete_type_at(GBufferCache *, size_t, GType, bool, bool);
-
-/* Ajoute en fin de tampon un générateur de lignes. */
-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 *);
-
-/* Réduit le tampon à une quantité de lignes précise. */
-void g_buffer_cache_truncate(GBufferCache *, size_t);
-
-/* Retrouve l'emplacement correspondant à une position de ligne. */
-void g_buffer_cache_get_line_cursor(const GBufferCache *, size_t, gint, GLineCursor **);
-
-/* Détermine l'ensemble des propriétés attachées à une ligne. */
-BufferLineFlags g_buffer_cache_get_line_flags(const GBufferCache *, size_t);
-
-#define g_buffer_cache_lock(c)
-#define g_buffer_cache_unlock(c)
-
-#define g_buffer_cache_throw_update_at_index(c, i) // check locked
-
-/* Retrouve une ligne au sein d'un tampon avec un indice. */
-GBufferLine *g_buffer_cache_find_line_by_index(const GBufferCache *, size_t);
-
-/* Fait remonter les largeurs requises par une ligne donnée. */
-void g_buffer_cache_collect_widths(GBufferCache *, size_t, line_width_summary *);
-
-/* 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 line_width_summary *, const gint *, const segcnt_list *);
-
-/* Indique l'indice correspondant à une adresse donnée. */
-size_t _g_buffer_cache_find_index_by_cursor(const GBufferCache *, const GLineCursor *, bool, size_t, size_t);
-
-/* Indique l'indice correspondant à une adresse donnée. */
-size_t g_buffer_cache_find_index_by_cursor(const GBufferCache *, const GLineCursor *, bool);
-
-/* Avance autant que possible vers une ligne idéale. */
-size_t g_buffer_cache_look_for_flag(const GBufferCache *, size_t, BufferLineFlags);
-
-/* Indique la position d'affichage d'une adresse donnée. */
-bool g_buffer_cache_get_cursor_coordinates(const GBufferCache *, const GLineCursor *, size_t, size_t, bool, gint *, gint *);
-
-
-
-#endif  /* _GLIBEXT_GBUFFERCACHE_H */
diff --git a/src/glibext/gbufferline.c b/src/glibext/gbufferline.c
deleted file mode 100644
index e3482aa..0000000
--- a/src/glibext/gbufferline.c
+++ /dev/null
@@ -1,1558 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * gbufferline.c - représentation de fragments de texte en ligne
- *
- * Copyright (C) 2010-2019 Cyrille Bagard
- *
- *  This file is part of Chrysalide.
- *
- *  Chrysalide is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 3 of the License, or
- *  (at your option) any later version.
- *
- *  Chrysalide is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#include "gbufferline.h"
-
-
-#include <assert.h>
-#include <malloc.h>
-#include <string.h>
-
-
-#include "chrysamarshal.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        */
-
-    mrange_t range;                         /* Couverture geographique     */
-    BufferLineColumn main_column;           /* Colonne principale          */
-
-    line_column columns[BLC_COUNT];         /* Répartition du texte        */
-    BufferLineColumn merge_start;           /* Début de la zone globale    */
-    BufferLineColumn last_used;             /* Dernière colonne utilisée   */
-
-    BufferLineFlags flags;                  /* Drapeaux particuliers       */
-
-    content_origin *origins;                /* Mémorisation des origines   */
-    size_t ocount;                          /* Nombre de ces mémorisations */
-
-    union
-    {
-        struct
-        {
-            gint max_widths[BLC_COUNT];     /* Taille cachée des colonnes  */
-            gint merged_width;              /* Largeur cumulée avant fusion*/
-        };
-    };
-
-};
-
-/* Représentation de fragments de texte en ligne (classe) */
-struct _GBufferLineClass
-{
-    GObjectClass parent;                    /* A laisser en premier        */
-
-    cairo_surface_t *entrypoint_img;        /* Image pour les entrées      */
-    cairo_surface_t *bookmark_img;          /* Image pour les signets      */
-
-    /* Signaux */
-
-    void (* content_changed) (GBufferLine *, line_segment *);
-
-    void (* flip_flag) (GBufferLine *, BufferLineFlags, BufferLineFlags);
-
-};
-
-
-/* Procède à l'initialisation d'une classe de représentation. */
-static void g_buffer_line_class_init(GBufferLineClass *);
-
-/* Procède à l'initialisation d'une représentation de fragments. */
-static void g_buffer_line_init(GBufferLine *);
-
-/* Supprime toutes les références externes. */
-static void g_buffer_line_dispose(GBufferLine *);
-
-/* Procède à la libération totale de la mémoire. */
-static void g_buffer_line_finalize(GBufferLine *);
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/*                              GESTION DE LINE COMPLETE                              */
-/* ---------------------------------------------------------------------------------- */
-
-
-/* Détermine le type de la représentation de fragments de texte en ligne. */
-G_DEFINE_TYPE(GBufferLine, g_buffer_line, G_TYPE_OBJECT);
-
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : class = classe de composant GTK à initialiser.               *
-*                                                                             *
-*  Description : Procède à l'initialisation d'une classe de représentation.   *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void g_buffer_line_class_init(GBufferLineClass *class)
-{
-    GObjectClass *object;                   /* Autre version de la classe  */
-    gchar *filename;                        /* Chemin d'accès à utiliser   */
-
-    object = G_OBJECT_CLASS(class);
-
-    object->dispose = (GObjectFinalizeFunc/* ! */)g_buffer_line_dispose;
-    object->finalize = (GObjectFinalizeFunc)g_buffer_line_finalize;
-
-    filename = find_pixmap_file("entrypoint.png");
-    assert(filename != NULL);
-
-    class->entrypoint_img = cairo_image_surface_create_from_png(filename);
-
-    g_free(filename);
-
-    filename = find_pixmap_file("bookmark.png");
-    assert(filename != NULL);
-
-    class->bookmark_img = cairo_image_surface_create_from_png(filename);
-
-    g_free(filename);
-
-    g_signal_new("content-changed",
-                 G_TYPE_BUFFER_LINE,
-                 G_SIGNAL_RUN_LAST,
-                 G_STRUCT_OFFSET(GBufferLineClass, content_changed),
-                 NULL, NULL,
-                 g_cclosure_marshal_VOID__OBJECT,
-                 G_TYPE_NONE, 1, G_TYPE_OBJECT);
-
-    g_signal_new("flip-flag",
-                 G_TYPE_BUFFER_LINE,
-                 G_SIGNAL_RUN_LAST,
-                 G_STRUCT_OFFSET(GBufferLineClass, flip_flag),
-                 NULL, NULL,
-                 g_cclosure_user_marshal_VOID__ENUM_ENUM,
-                 G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : line = composant GTK à initialiser.                          *
-*                                                                             *
-*  Description : Procède à l'initialisation d'une représentation de fragments.*
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void g_buffer_line_init(GBufferLine *line)
-{
-    BufferLineColumn i;                     /* Boucle de parcours          */
-
-    for (i = 0; i < BLC_COUNT; i++)
-        init_line_column(&line->columns[i]);
-
-    line->merge_start = BLC_COUNT;
-    line->last_used = BLC_COUNT;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : line = instance d'objet GLib à traiter.                      *
-*                                                                             *
-*  Description : Supprime toutes les références externes.                     *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void g_buffer_line_dispose(GBufferLine *line)
-{
-    size_t i;                               /* Boucle de parcours          */
-
-    for (i = 0; i < line->ocount; i++)
-        g_object_unref(G_OBJECT(line->origins[i].creator));
-
-    G_OBJECT_CLASS(g_buffer_line_parent_class)->dispose(G_OBJECT(line));
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : line = instance d'objet GLib à traiter.                      *
-*                                                                             *
-*  Description : Procède à la libération totale de la mémoire.                *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void g_buffer_line_finalize(GBufferLine *line)
-{
-    BufferLineColumn i;                     /* Boucle de parcours          */
-
-    for (i = 0; i < BLC_COUNT; i++)
-        reset_line_column(&line->columns[i]);
-
-    if (line->origins != NULL)
-        free(line->origins);
-
-    G_OBJECT_CLASS(g_buffer_line_parent_class)->finalize(G_OBJECT(line));
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : range = emplacement où va se situer la ligne.                *
-*                main  = colonne à référencer comme étant la principale.      *
-*                                                                             *
-*  Description : Crée une nouvelle représentation de fragments de texte.      *
-*                                                                             *
-*  Retour      : Composant GTK créé.                                          *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-GBufferLine *g_buffer_line_new(const mrange_t *range, BufferLineColumn main)
-{
-    GBufferLine *result;                    /* Composant à retourner       */
-
-    result = g_object_new(G_TYPE_BUFFER_LINE, NULL);
-
-    copy_mrange(&result->range, range);
-    result->main_column = main;
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : line = ligne à venir consulter.                              *
-*                                                                             *
-*  Description : Indique la zone mémoire où se situe la ligne.                *
-*                                                                             *
-*  Retour      : Emplacement mémoire virtuel ou physique.                     *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-const mrange_t *g_buffer_line_get_range(const GBufferLine *line)
-{
-    return &line->range;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : line = ligne à venir compléter.                              *
-*                size = taille souhaitée de l'impression des positions.       *
-*                addr = localisation physique à venir représenter.            *
-*                                                                             *
-*  Description : Construit le tronc commun d'une ligne autour de sa position. *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-void g_buffer_line_fill_phys(GBufferLine *line, MemoryDataSize size, const vmpa2t *addr)
-{
-    VMPA_BUFFER(position);                  /* Emplacement au format texte */
-    size_t len;                             /* Taille de l'élément inséré  */
-    size_t i;                               /* Boucle de parcours #1       */
-
-    vmpa2_phys_to_string(addr, size, position, &len);
-
-    for (i = 2; i < len; i++)
-        if (position[i] != '0') break;
-
-    if (i == len)
-        i = len - 1;
-
-    if (i > 0)
-        g_buffer_line_append_text(line, BLC_PHYSICAL, position, i, RTT_PHYS_ADDR_PAD, NULL);
-
-    g_buffer_line_append_text(line, BLC_PHYSICAL, &position[i], len - i, RTT_PHYS_ADDR, NULL);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : line = ligne à venir compléter.                              *
-*                size = taille souhaitée de l'impression des positions.       *
-*                addr = localisation virtuelle à venir représenter.           *
-*                                                                             *
-*  Description : Construit le tronc commun d'une ligne autour de sa position. *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-void g_buffer_line_fill_virt(GBufferLine *line, MemoryDataSize size, const vmpa2t *addr)
-{
-    VMPA_BUFFER(position);                  /* Emplacement au format texte */
-    size_t len;                             /* Taille de l'élément inséré  */
-    size_t i;                               /* Boucle de parcours #1       */
-
-    vmpa2_virt_to_string(addr, size, position, &len);
-
-    if (has_virt_addr(addr))
-    {
-        for (i = 2; i < len; i++)
-            if (position[i] != '0') break;
-
-        if (i == len)
-            i = len - 1;
-
-        if (i > 0)
-            g_buffer_line_append_text(line, BLC_VIRTUAL, position, i, RTT_VIRT_ADDR_PAD, NULL);
-
-        g_buffer_line_append_text(line, BLC_VIRTUAL, &position[i], len - i, RTT_VIRT_ADDR, NULL);
-
-    }
-
-    else
-        g_buffer_line_append_text(line, BLC_VIRTUAL, position, len, RTT_VIRT_ADDR_PAD, NULL);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : line  = ligne à venir compléter.                             *
-*                addr  = localisation à afficher.                             *
-*                psize = taille souhaitée de l'impression des positions.      *
-*                vsize = taille souhaitée de l'impression des adresses.       *
-*                                                                             *
-*  Description : Construit le tronc commun d'une ligne autour de sa position. *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-void g_buffer_line_fill_vmpa(GBufferLine *line, const vmpa2t *addr, MemoryDataSize psize, MemoryDataSize vsize)
-{
-    g_buffer_line_fill_phys(line, psize, addr);
-
-    g_buffer_line_fill_virt(line, vsize, addr);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : line    = ligne à venir compléter.                           *
-*                content = contenu binaire global à venir lire.               *
-*                range   = localisation des données à venir lire et présenter.*
-*                max     = taille maximale de la portion binaire en octets.   *
-*                                                                             *
-*  Description : Construit le tronc commun d'une ligne autour de son contenu. *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-void g_buffer_line_fill_content(GBufferLine *line, const GBinContent *content, const mrange_t *range, phys_t max)
-{
-    phys_t length;                          /* Taille de la couverture     */
-    bool truncated;                         /* Indique si le code est coupé*/
-    size_t required;                        /* Taille de traitement requise*/
-    char static_buffer[64];                 /* Petit tampon local rapide   */
-    char *bin_code;                         /* Tampon utilisé pour le code */
-    vmpa2t pos;                             /* Boucle de parcours #1       */
-    phys_t i;                               /* Boucle de parcours #2       */
-    char *iter;                             /* Boucle de parcours #3       */
-    int ret;                                /* Progression dans l'écriture */
-    uint8_t byte;                           /* Octet à représenter         */
-
-    static const char *charset = "0123456789abcdef";
-
-    /* Détermination du réceptacle */
-
-    length = get_mrange_length(range);
-
-    truncated = (max != VMPA_NO_PHYSICAL && length > max);
-
-    if (truncated)
-    {
-        length = max;
-        required = length * 3 + 4 /* "..." */ + 1;
-    }
-    else
-        required = length * 3 + 1;
-
-    if (required <= sizeof(static_buffer))
-        bin_code = static_buffer;
-    else
-        bin_code = (char *)calloc(required, sizeof(char));
-
-    /* Code brut */
-
-    copy_vmpa(&pos, get_mrange_addr(range));
-
-    for (i = 0, iter = bin_code; i < length; i++, iter += ret)
-    {
-        if (i == 0)
-            ret = 0;
-        else
-        {
-            iter[0] = ' ';
-            ret = 1;
-        }
-
-        if (!g_binary_content_read_u8(content, &pos, &byte))
-        {
-            iter[ret + 0] = '?';
-            iter[ret + 1] = '?';
-        }
-        else
-        {
-            iter[ret + 0] = charset[byte >> 4];
-            iter[ret + 1] = charset[byte & 0x0f];
-        }
-
-        ret += 2;
-
-    }
-
-    if (truncated)
-    {
-        strcpy(iter, "...");
-        iter += 3;
-    }
-    else
-        *iter = '\0';
-
-    /* Conclusion */
-
-    g_buffer_line_append_text(line, BLC_BINARY, bin_code, iter - bin_code, RTT_RAW_CODE, NULL);
-
-    if (bin_code != static_buffer)
-        free(bin_code);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : line   = ligne à venir consulter.                            *
-*                column = indice de la colonne visée par les recherches.      *
-*                                                                             *
-*  Description : Recherche le premier créateur enregistré dans des segments.  *
-*                                                                             *
-*  Retour      : Créateur trouvé à déréférencer par la suite ou NULL si échec.*
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-GObject *g_buffer_line_find_first_segment_creator(const GBufferLine *line, BufferLineColumn column)
-{
-    GObject *result;                        /* Trouvaille à retourner      */
-    size_t i;                               /* Boucle de parcours          */
-
-    assert(column < BLC_COUNT);
-
-    result = NULL;
-
-    for (i = 0; i < line->ocount && result == NULL; i++)
-    {
-        if (line->origins[i].coord.column == column)
-            result = line->origins[i].creator;
-    }
-
-    if (result != NULL)
-        g_object_ref(G_OBJECT(result));
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : line    = ligne à venir compléter.                           *
-*                column  = colonne de la ligne visée par l'insertion.         *
-*                text    = texte à insérer dans l'existant.                   *
-*                length  = taille du texte à traiter.                         *
-*                type    = type de décorateur à utiliser.                     *
-*                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, const char *text, size_t length, RenderingTagType type, GObject *creator)
-{
-    size_t index;                           /* Indice d'insertion          */
-    content_origin *origin;                 /* Définition d'une origine    */
-
-    assert(length > 0);
-
-    if (column == -1)
-        column = BLC_LAST_USED;
-
-    if (column == BLC_MAIN)
-        column = BLC_ASSEMBLY;//line->main_column;
-
-    if (column == BLC_LAST_USED)
-        column = line->last_used;
-    else
-        line->last_used = column;
-
-    index = append_text_to_line_column(&line->columns[column], text, length, type);
-
-    if (creator != NULL)
-    {
-        line->origins = (content_origin *)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 à venir compléter.                           *
-*                creator = instance GLib quelconque identifiant un segment.   *
-*                text    = texte à insérer dans l'existant.                   *
-*                length  = taille du texte à traiter.                         *
-*                                                                             *
-*  Description : Remplace du texte dans une ligne donnée.                     *
-*                                                                             *
-*  Retour      : Bilan de l'opération.                                        *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-bool g_buffer_line_replace_text(GBufferLine *line, const GObject *creator, const char *text, size_t length)
-{
-    bool result;                            /* Bilan à retourner            */
-    size_t i;                               /* Boucle de parcours          */
-    const col_coord_t *coord;               /* Emplacement du contenu visé */
-
-    result = false;
-
-    for (i = 0; i < line->ocount && !result; i++)
-    {
-        if (line->origins[i].creator == creator)
-        {
-            coord = &line->origins[i].coord;
-
-            replace_text_in_line_column(&line->columns[coord->column], coord->index, text, length);
-
-            g_signal_emit_by_name(line, "content-changed", NULL);
-
-            result = true;
-
-        }
-
-    }
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : line   = ligne à venir consulter.                            *
-*                first  = première colonne à parcourir.                       *
-*                end    = colonne de fin de parcours.                         *
-*                                                                             *
-*  Description : Indique si du texte est présent dans une ligne de tampon.    *
-*                                                                             *
-*  Retour      : true pour indiquer la présence de texte, false pour du vide. *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-bool g_buffer_line_has_text(const GBufferLine *line, BufferLineColumn first, BufferLineColumn end)
-{
-    bool result;                            /* Bilan à retourner           */
-    BufferLineColumn i;                     /* Boucle de parcours          */
-
-    result = false;
-
-    assert(first < end);
-
-    for (i = first; i < end && !result; i++)
-        result = (line->columns[i].count > 0);
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : line   = ligne à venir consulter.                            *
-*                first  = première colonne à parcourir.                       *
-*                end    = colonne de fin de parcours.                         *
-*                markup = indique si le texte doit être décoré ou non.        *
-*                                                                             *
-*  Description : Donne le texte représenté par une ligne de tampon.           *
-*                                                                             *
-*  Retour      : Texte à libérer de la mémoire après usage.                   *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-char *g_buffer_line_get_text(const GBufferLine *line, BufferLineColumn first, BufferLineColumn end, bool markup)
-{
-    char *result;                           /* Construction à retourner    */
-    BufferLineColumn i;                     /* Boucle de parcours          */
-    char *extra;                            /* Contenu à intégrer au texte */
-
-    result = NULL;
-
-    assert(first < end);
-
-    for (i = first; i < end; i++)
-    {
-        if (i > first && result != NULL)
-            result = stradd(result, " ");
-
-        extra = get_line_column_text(&line->columns[i], markup);
-
-        /* Si la colonne était vide, suivante ! */
-        if (extra == NULL) continue;
-
-        if (result == NULL)
-            result = extra;
-
-        else
-        {
-            result = stradd(result, extra);
-            free(extra);
-        }
-
-    }
-
-    return result;
-
-}
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : line  = ligne à venir modifier.                              *
-*                first = première colonne à parcourir.                        *
-*                end   = colonne de fin de parcours.                          *
-*                                                                             *
-*  Description : Supprime du texte représenté par une ligne de tampon.        *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-void g_buffer_line_delete_text(GBufferLine *line, BufferLineColumn first, BufferLineColumn end)
-{
-    BufferLineColumn i;                     /* Boucle de parcours #1       */
-
-    assert(first < end);
-
-    for (i = first; i < end; i++)
-        reset_line_column(&line->columns[i]);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : line = ligne à venir consulter.                              *
-*                                                                             *
-*  Description : Fournit la colonne à partir de laquelle une fusion opère.    *
-*                                                                             *
-*  Retour      : Début de la première (et unique) zone globale.               *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-BufferLineColumn g_buffer_line_get_merge_start(const GBufferLine *line)
-{
-    return line->merge_start;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : line  = ligne à venir compléter.                             *
-*                start = début de la première (et unique) zone globale.       *
-*                                                                             *
-*  Description : Définit la colonne à partir de laquelle la fusion opère.     *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-void g_buffer_line_start_merge_at(GBufferLine *line, BufferLineColumn start)
-{
-    if (start == BLC_LAST_USED)
-        line->merge_start = line->last_used;
-    else
-        line->merge_start = start;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : line = ligne à venir compléter.                              *
-*                flag = propriété à intégrer.                                 *
-*                                                                             *
-*  Description : Ajoute une propriété particulière à une ligne donnée.        *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-void g_buffer_line_add_flag(GBufferLine *line, BufferLineFlags flag)
-{
-    if ((line->flags & flag) == 0)
-    {
-        g_signal_emit_by_name(line, "flip-flag", line->flags, flag);
-
-        line->flags |= flag;
-
-    }
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : line = ligne à venir consulter.                              *
-*                                                                             *
-*  Description : Renseigne sur les propriétés particulières liées à une ligne.*
-*                                                                             *
-*  Retour      : Propriétés intégrées.                                        *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-BufferLineFlags g_buffer_line_get_flags(const GBufferLine *line)
-{
-    return line->flags;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : line = ligne à venir compléter.                              *
-*                flag = propriété à supprimer.                                *
-*                                                                             *
-*  Description : Retire une propriété particulière à une ligne donnée.        *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-void g_buffer_line_remove_flag(GBufferLine *line, BufferLineFlags flag)
-{
-    if ((line->flags & flag) != 0)
-    {
-        g_signal_emit_by_name(line, "flip-flag", line->flags, flag);
-
-        line->flags &= ~flag;
-
-    }
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : line    = ligne de texte à manipuler.                        *
-*                ctx     = éléments à disposition pour l'exportation.         *
-*                type    = type d'exportation attendue.                       *
-*                display = règles d'affichage des colonnes modulables.        *
-*                                                                             *
-*  Description : Exporte la ligne de texte représentée.                       *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-void g_buffer_line_export(GBufferLine *line, buffer_export_context *ctx, BufferExportType type, const bool *display)
-{
-    BufferLineColumn i;                     /* Boucle de parcours          */
-    int col_span;                           /* Fusion de colonnes ?        */
-
-    switch (type)
-    {
-        case BET_HTML:
-            dprintf(ctx->fd, "\t<TR>\n");
-            break;
-        default:
-            break;
-    }
-
-    for (i = 0; i < BLC_COUNT; i++)
-    {
-        if (i < BLC_DISPLAY && !display[i]) continue;
-
-        switch (type)
-        {
-            case BET_TEXT:
-                if (i > 0) dprintf(ctx->fd, "%s", ctx->sep);
-                break;
-            default:
-                break;
-        }
-
-        /**
-         * Pour la signification des différentes valeurs assignées,
-         * se référer au code de export_line_column_segments().
-         *
-         * En gros :
-         *   - 1  = rien de spécial.
-         *   - >1 = il s'agit de la première cellule fusionnée de la ligne.
-         *   - 0  = fusion déjà faite, on ne peut que rajouter du contenu dedans.
-         *   - <1 = il s'agit de la dernière cellule fusionnée de la ligne.
-         *
-         * On considère qu'une fusion ne peut pas se réaliser sur la dernière
-         * cellule uniquement (ce qui a du sens : c'est inutile).
-         */
-
-        if (i < line->merge_start)
-            col_span = 1;
-
-        else if (i == line->merge_start)
-            col_span = BLC_COUNT - i;
-
-        else
-            col_span = ((i + 1) == BLC_COUNT ? -1 : 0);
-
-        export_line_column_segments(&line->columns[i], ctx, type, col_span);
-
-    }
-
-    switch (type)
-    {
-        case BET_TEXT:
-            dprintf(ctx->fd, "\n");
-            break;
-        case BET_HTML:
-            dprintf(ctx->fd, "</TR>\n");
-            break;
-        default:
-            break;
-    }
-
-}
-
-
-
-/*----------------------------------------------------------------------------------- */
-/*                         MANIPULATION DES LARGEURS REQUISES                         */
-/* ---------------------------------------------------------------------------------- */
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : line    = ligne à venir consulter.                           *
-*                summary = largeurs maximales à faire évoluer.                *
-*                                                                             *
-*  Description : Fait remonter les largeurs requises par une ligne donnée.    *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-void g_buffer_line_collect_widths(GBufferLine *line, line_width_summary *summary)
-{
-    gint merged_width;                      /* Largeur cumulée avant fusion*/
-    BufferLineColumn i;                     /* Boucle de parcours          */
-    gint width;                             /* Largeur d'une colonne       */
-
-    merged_width = 0;
-
-    for (i = 0; i < BLC_COUNT; i++)
-    {
-        width = get_column_width(&line->columns[i]);
-
-        if (i < line->merge_start)
-            summary->max_widths[i] = MAX(summary->max_widths[i], width);
-
-        if (i >= BLC_DISPLAY)
-        {
-            merged_width += width;
-
-            if (i < line->merge_start && (i + 1) < BLC_COUNT)
-                merged_width += COL_MARGIN;
-
-        }
-
-    }
-
-    if (line->merge_start != BLC_COUNT)
-        summary->merged_width = MAX(summary->merged_width, merged_width);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : line    = ligne à venir consulter.                           *
-*                index   = indice de la colonne visée.                        *
-*                summary = résumé des largeurs maximales.                     *
-*                offsets = décalages supplémentaires à appliquer.             *
-*                                                                             *
-*  Description : Fournit la largeur d'une colonne finalement appliquée.       *
-*                                                                             *
-*  Retour      : Largeur globale ou spécifique, selon l'indice communiqué.    *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-gint g_buffer_line_compute_max_width(const GBufferLine *line, BufferLineColumn index, const line_width_summary *summary, const line_width_summary *offsets)
-{
-    gint result;                            /* Largeur à retourner         */
-
-    assert(index < BLC_COUNT);
-
-    if (index >= line->merge_start)
-        result = get_column_width(&line->columns[index]);
-
-    else
-        result = summary->max_widths[index];
-
-    if (result < offsets->max_widths[index])
-        result = offsets->max_widths[index];
-
-    return result;
-
-}
-
-
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : line  = ligne à venir consulter.                             *
-*                coord = coordonnées interne du segment à retrouver.          *
-*                                                                             *
-*  Description : Fournit le segment présent à une position donnée.            *
-*                                                                             *
-*  Retour      : Segment trouvé ou NULL si hors borne.                        *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-line_segment *g_buffer_line_get_segment_from_coord(const GBufferLine *line, const col_coord_t *coord)
-{
-    line_segment *result;                   /* Trouvaille à retourner      */
-
-    if (coord->column < BLC_COUNT)
-        result = get_line_column_content_from_index(&line->columns[coord->column], coord->index);
-    else
-        result = NULL;
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : line    = ligne à venir consulter.                           *
-*                summary = résumé des largeurs maximales.                     *
-*                options = règles d'affichage des colonnes modulables.        *
-*                offsets = décalages supplémentaires à appliquer.             *
-*                base    = position jusqu'au segment trouvé. [OUT]            *
-*                offset  = position à la colonne visée. [OUT]                 *
-*                dir     = direction d'un éventuel déplacement en cours.      *
-*                force   = accepte les segments en bordure au pire.           *
-*                coord   = cordonnées à usage interne à renseigner. [OUT]     *
-*                                                                             *
-*  Description : Fournit les coordonnées correspondant à une abscisse donnée. *
-*                                                                             *
-*  Retour      : true si des coordonnées valides ont été renseignées.         *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-bool g_buffer_line_get_coord_at(const GBufferLine *line, const line_width_summary *summary, const GDisplayOptions *options, const line_width_summary *offsets, gint *base, gint *offset, GdkScrollDirection dir, bool force, col_coord_t *coord)
-{
-    bool result;                            /* Bilan à retourner           */
-    BufferLineColumn last;                  /* Dernière colonne remplie    */
-    gint last_base;                         /* Dernière abscisse associée  */
-    size_t count;                           /* Qté de colonnes en option   */
-    size_t i;                               /* Boucle de parcours          */
-    gint width;                             /* Largeur d'une colonne donnée*/
-    gint limit;                             /* Limite d'appartenance       */
-    gint consumed;                          /* Distance vers le segment    */
-    gint old_base;                          /* Somme de toutes les largeurs*/
-
-    result = false;
-
-    *base = 0;
-
-    last = BLC_COUNT;
-    last_base = 0;
-
-    /* On cible déjà la colonne idéale */
-
-    count = g_display_options_count(options);
-
-    for (i = 0; i < BLC_COUNT; i++)
-    {
-        if (i < count)
-        {
-            if (!g_display_options_get(options, i))
-                continue;
-        }
-
-        /* Mémorisation de la dernière colonne contenant quelque chose... */
-        if (get_column_width(&line->columns[i]) > 0)
-        {
-            last = i;
-            last_base = *base;
-        }
-
-        if (i < line->merge_start)
-        {
-            width = g_buffer_line_compute_max_width(line, i, summary, offsets);
-
-            /* Si la colonne n'est absolument pas visible, on ne s'arrête pas dessus ! */
-            if (width == 0) continue;
-
-            if ((i + 1) < BLC_COUNT) limit = width + COL_MARGIN / 2;
-            else limit = width;
-
-            if (*offset <= limit) break;
-            else
-            {
-                *offset -= width + COL_MARGIN;
-                *base += width + COL_MARGIN;
-            }
-
-        }
-        else
-        {
-            width = get_column_width(&line->columns[i]);
-
-            if (*offset <= width) break;
-            else
-            {
-                *offset -= width;
-                *base += width;
-            }
-
-        }
-
-
-    }
-
-    /* Si l'abscisse fournie tombe encore dans une colonne... */
-
-    if (i < BLC_COUNT)
-    {
-        /* Il y a bien du contenu dans cette colonne */
-
-        if (get_column_width(&line->columns[i]) > 0)
-        {
-            /**
-             * Si la position était au milieu d'une marge, la sélection a pu pousser
-             * jusqu'à la colonne suivante, plus proche.
-             * Relativment à la base de cette dernière, la position est donc devenue négative.
-             */
-            if (*offset < 0) *offset = 0;
-
-            result = get_line_column_content_index_at(&line->columns[i], offset, dir, &consumed, &coord->index);
-
-            if (result)
-            {
-                coord->column = i;
-
-                *base += consumed;
-
-            }
-
-        }
-
-        /* La position fournie tombe dans une colonne vide ! */
-
-        else
-        {
-            if (force || get_column_width(&line->columns[i]) == 0)
-            {
-                result = false;
-                *offset = 0;
-
-                old_base = *base;
-
-                for (i++; i < BLC_COUNT && !result; i++)
-                {
-                    if ((i - 1) < line->merge_start)
-                    {
-                        width = g_buffer_line_compute_max_width(line, i - 1, summary, offsets);
-
-                        if (width > 0)
-                            *base += (width + COL_MARGIN);
-
-                    }
-                    else
-                        *base += get_column_width(&line->columns[i - 1]);
-
-                    result = get_line_column_first_content_index(&line->columns[i], &coord->index);
-
-                    if (result)
-                        coord->column = i;
-
-                }
-
-                if (!result)
-                {
-                    *base = old_base;
-                    goto use_right_border;
-                }
-
-            }
-
-        }
-
-    }
-
-    else /* if (i == BLC_COUNT) */
-    {
-        if (force)
-        {
- use_right_border:
-
-            if (last != BLC_COUNT)
-            {
-                result = get_line_column_last_content_index(&line->columns[last], &coord->index);
-
-                if (result)
-                {
-                    coord->column = last;
-
-                    *base = last_base;
-                    *offset = get_column_width(&line->columns[last]);
-
-                }
-
-            }
-
-            /* Il n'y a rien sur la ligne ! */
-            else
-            {
-                result = true;
-
-                *base = 0;
-                *offset = 0;
-
-                coord->column = BLC_COUNT;
-                coord->index = -1;
-
-            }
-
-        }
-        else
-            result = false;
-
-    }
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : line    = ligne à venir consulter.                           *
-*                summary = résumé des largeurs maximales.                     *
-*                options = règles d'affichage des colonnes modulables.        *
-*                offsets = décalages supplémentaires à appliquer.             *
-*                base    = position jusqu'au segment trouvé. [OUT]            *
-*                offset  = position à la colonne visée. [OUT]                 *
-*                dir     = direction d'un éventuel déplacement en cours.      *
-*                force   = accepte les segments en bordure au pire.           *
-*                                                                             *
-*  Description : Donne le segment présent à une abscisse donnée.              *
-*                                                                             *
-*  Retour      : Segment trouvé ou NULL si hors borne.                        *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-line_segment *g_buffer_line_get_segment_at(const GBufferLine *line, const line_width_summary *summary, const GDisplayOptions *options, const line_width_summary *offsets, gint *base, gint *offset, GdkScrollDirection dir, bool force)
-{
-    line_segment *result;                   /* Trouvaille à retourner      */
-    col_coord_t coord;                      /* Emplacement du contenu visé */
-    bool status;                            /* Bilan de la localisation    */
-
-    status = g_buffer_line_get_coord_at(line, summary, options, offsets, base, offset, dir, force, &coord);
-
-    if (status)
-        result = g_buffer_line_get_segment_from_coord(line, &coord);
-    else
-        result = NULL;
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : line    = ligne à venir consulter.                           *
-*                summary = résumé des largeurs maximales.                     *
-*                options = règles d'affichage des colonnes modulables.        *
-*                offsets = décalages supplémentaires à appliquer.             *
-*                base    = position jusqu'au segment trouvé. [OUT]            *
-*                offset  = position à la colonne visée. [OUT]                 *
-*                dir     = direction d'un éventuel déplacement en cours.      *
-*                force   = accepte les segments en bordure au pire.           *
-*                                                                             *
-*  Description : Donne le créateur présent à une abscisse donnée.             *
-*                                                                             *
-*  Retour      : Créateur trouvé ou NULL si hors borne.                       *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-GObject *g_buffer_line_get_creator_at(const GBufferLine *line, const line_width_summary *summary, const GDisplayOptions *options, const line_width_summary *offsets, gint *base, gint *offset, GdkScrollDirection dir, bool force)
-{
-    GObject *result;                        /* Trouvaille à retourner      */
-    col_coord_t target;                     /* Emplacement du contenu visé */
-    bool status;                            /* Bilan de la localisation    */
-    size_t i;                               /* Boucle de parcours          */
-    const col_coord_t *coord;               /* Emplacement du contenu visé */
-
-    result = NULL;
-
-    status = g_buffer_line_get_coord_at(line, summary, options, offsets, base, offset, dir, force, &target);
-
-    if (status)
-    {
-        for (i = 0; i < line->ocount && result == NULL; i++)
-        {
-            coord = &line->origins[i].coord;
-
-            if (coord->column == target.column && coord->index == target.index)
-                result = line->origins[i].creator;
-
-        }
-
-        if (result != NULL)
-            g_object_ref(G_OBJECT(result));
-
-    }
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : line    = ligne à venir consulter.                           *
-*                coord   = cordonnées à consulter puis renseigner. [OUT]      *
-*                summary = résumé des largeurs maximales.                     *
-*                options = règles d'affichage des colonnes modulables.        *
-*                offsets = décalages supplémentaires à appliquer.             *
-*                dir     = orientation des recherches.                        *
-*                offset  = décalage pour amener à l'extrémité nouvelle. [OUT] *
-*                                                                             *
-*  Description : Fournit des coordonnées voisines selon une direction donnée. *
-*                                                                             *
-*  Retour      : true si des coordonnées valides ont été renseignées.         *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-bool g_buffer_line_find_near_coord(const GBufferLine *line, col_coord_t *coord, const line_width_summary *summary, const GDisplayOptions *options, const line_width_summary *offsets, GdkScrollDirection dir, gint *offset)
-{
-    bool result;                            /* Bilan à retourner           */
-    size_t count;                           /* Qté de colonnes en option   */
-    size_t i;                               /* Boucle de parcours #1       */
-    bool displayed;                         /* Confort de lecture          */
-    size_t k;                               /* Boucle de parcours #2       */
-    gint width;                             /* Largeur d'une colonne donnée*/
-
-    result = false;
-
-    /* Recherche dans la colonne de départ */
-
-    i = coord->column;
-
-    if (i == BLC_COUNT) return false;
-
-    result = find_near_segment(&line->columns[i], &coord->index, dir);
-
-    /* Recherche dans la direction des colonnes voisines */
-
-    count = g_display_options_count(options);
-
-    if (!result)
-        switch (dir)
-        {
-            case GDK_SCROLL_LEFT:
-
-                /* Si on a atteint la première colonne sans trouver... */
-                if (i == 0) break;
-
-                /* On s'assure que la colonne précédente est visible et peuplée */
-                for (; i > BLC_FIRST && !result; i--)
-                {
-                    displayed = (i <= count ? g_display_options_get(options, i - 1) : true);
-
-                    if (displayed)
-                    {
-                        result = get_line_column_first_content_index(&line->columns[i - 1], &coord->index);
-
-                        if (result)
-                            coord->column = i - 1;
-
-                    }
-
-                }
-
-                break;
-
-            case GDK_SCROLL_RIGHT:
-
-                /* On s'assure que la colonne suivante est visible et peuplée */
-                for (; (i + 1) < BLC_COUNT && !result; i++)
-                {
-                    displayed = ((i + 1) < count ? g_display_options_get(options, i + 1) : true);
-
-                    if (displayed)
-                    {
-                        result = get_line_column_first_content_index(&line->columns[i + 1], &coord->index);
-
-                        if (result)
-                            coord->column = i + 1;
-
-                    }
-
-                }
-
-                break;
-
-        default:
-            break;
-
-    }
-
-    /* Calcul de la position finale */
-
-    if (result)
-    {
-        *offset = 0;
-
-        for (k = 0; k < i; k++)
-        {
-            displayed = (k < count ? g_display_options_get(options, k) : true);
-
-            if (displayed)
-            {
-                width = g_buffer_line_compute_max_width(line, k, summary, offsets);
-
-                if (width > 0)
-                {
-                    *offset += width;
-                    if (k < line->merge_start) *offset += COL_MARGIN;
-                }
-
-            }
-
-        }
-
-        switch (dir)
-        {
-            case GDK_SCROLL_LEFT:
-                *offset += get_column_width(&line->columns[i]);
-                break;
-
-            case GDK_SCROLL_RIGHT:
-                /**offset += 0;*/
-                break;
-
-            default:
-                break;
-
-        }
-
-    }
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : line    = ligne de texte à manipuler.                        *
-*                cairo   = contexte graphique à utiliser pour les pinceaux.   *
-*                summary = résumé des largeurs maximales.                     *
-*                x_init  = abscisse du point d'impression de départ.          *
-*                y       = ordonnée du point d'impression.                    *
-*                options = règles d'affichage des colonnes modulables.        *
-*                offsets = décalages supplémentaires à appliquer.             *
-*                list    = liste de contenus à mettre en évidence.            *
-*                                                                             *
-*  Description : Imprime la ligne de texte représentée.                       *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-void g_buffer_line_draw(GBufferLine *line, cairo_t *cairo, const line_width_summary *summary, gint x_init, gint y, const GDisplayOptions *options, const line_width_summary *offsets, const segcnt_list *list)
-{
-    GBufferLineClass *class;                /* Stockage de briques de base */
-    bool has_src_surface;                   /* Note une présence définie   */
-    gint x;                                 /* Point de départ d'impression*/
-    size_t count;                           /* Qté de colonnes en option   */
-    size_t i;                               /* Boucle de parcours          */
-    gint max_width;                         /* Largeur maximale de colonne */
-
-    if (line->flags != BLF_NONE && line->flags != BLF_HAS_CODE)
-    {
-        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);
-
-    }
-
-    x = x_init;
-
-    count = g_display_options_count(options);
-
-    for (i = 0; i < BLC_COUNT; i++)
-    {
-        if (i < count)
-        {
-            if (!g_display_options_get(options, i))
-                continue;
-        }
-
-        draw_line_column_segments(&line->columns[i], cairo, x, y, list);
-
-        if (i < line->merge_start)
-        {
-            max_width = g_buffer_line_compute_max_width(line, i, summary, offsets);
-
-            if (max_width > 0)
-                x += max_width + COL_MARGIN;
-
-        }
-
-    }
-
-}
diff --git a/src/glibext/gbufferline.h b/src/glibext/gbufferline.h
deleted file mode 100644
index 11790fe..0000000
--- a/src/glibext/gbufferline.h
+++ /dev/null
@@ -1,218 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * gbufferline.h - prototypes pour la représentation de fragments de texte en ligne
- *
- * Copyright (C) 2010-2018 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_GBUFFERLINE_H
-#define _GLIBEXT_GBUFFERLINE_H
-
-
-#include <glib-object.h>
-#include <stdbool.h>
-
-
-#include "gdisplayoptions.h"
-#include "linesegment.h"
-#include "../analysis/content.h"
-#include "../arch/vmpa.h"
-
-
-
-#define G_TYPE_BUFFER_LINE            g_buffer_line_get_type()
-#define G_BUFFER_LINE(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_BUFFER_LINE, GBufferLine))
-#define G_BUFFER_LINE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_BUFFER_LINE, GBufferLineClass))
-#define G_IS_BUFFER_LINE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_BUFFER_LINE))
-#define G_IS_BUFFER_LINE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_BUFFER_LINE))
-#define G_BUFFER_LINE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_BUFFER_LINE, GBufferLineClass))
-
-
-/* Représentation de fragments de texte en ligne (instance) */
-typedef struct _GBufferLine GBufferLine;
-
-/* Représentation de fragments de texte en ligne (classe) */
-typedef struct _GBufferLineClass GBufferLineClass;
-
-
-/* Désignation des colonnes d'une ligne */
-typedef enum _BufferLineColumn
-{
-    BLC_PHYSICAL,                           /* Position physique           */
-    BLC_VIRTUAL,                            /* Adresse virtuelle           */
-    BLC_BINARY,                             /* Contenu sous forme binaire  */
-    BLC_ASSEMBLY_LABEL,                     /* Etiquette dans les données  */
-    BLC_ASSEMBLY_HEAD,                      /* Instruction pour assembleur */
-    BLC_ASSEMBLY,                           /* Code pour assembleur        */
-    BLC_COMMENTS,                           /* Commentaires éventuels      */
-
-    BLC_COUNT,
-
-    BLC_LAST_USED,                          /* Dernière colonne utilisée   */
-    BLC_INVALID,                            /* Valeur de non-initialisation*/
-    BLC_MAIN                                /* Colonne principale (cf. imm)*/
-
-} BufferLineColumn;
-
-/* Première colonne de l'ensemble */
-#define BLC_FIRST BLC_PHYSICAL
-
-/* Première colonne toujours affichée */
-#define BLC_DISPLAY BLC_ASSEMBLY_LABEL
-
-
-/* Confort pour l'insertion de texte */
-#define SL(str) str, strlen(str)
-
-/* Espace entre les colonnes */
-#define COL_MARGIN 23
-
-
-/* Propriétés particulières supplémentaires */
-typedef enum _BufferLineFlags
-{
-    BLF_NONE            = 0 << 0,           /* Aucune                      */
-    BLF_HAS_CODE        = 1 << 0,           /* La ligne contient du code   */
-    BLF_IS_LABEL        = 1 << 1,           /* Etiquette pour symbole      */
-    BLF_ENTRYPOINT      = 1 << 2,           /* Représentation d'une entrée */
-    BLF_BOOKMARK        = 1 << 3,           /* Signet associé              */
-    BLF_WIDTH_MANAGER   = 1 << 4,           /* Début de groupe des largeurs*/
-
-    BLF_ALL             = ((1 << 5) - 1)
-
-} 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(const mrange_t *, BufferLineColumn);
-
-/* Indique la zone mémoire où se situe la ligne. */
-const mrange_t *g_buffer_line_get_range(const GBufferLine *);
-
-/* Construit le tronc commun d'une ligne autour de sa position. */
-void g_buffer_line_fill_phys(GBufferLine *, MemoryDataSize, const vmpa2t *);
-
-/* Construit le tronc commun d'une ligne autour de sa position. */
-void g_buffer_line_fill_virt(GBufferLine *, MemoryDataSize, const vmpa2t *);
-
-/* Construit le tronc commun d'une ligne autour de sa position. */
-void g_buffer_line_fill_vmpa(GBufferLine *, const vmpa2t *, MemoryDataSize, MemoryDataSize);
-
-/* Construit le tronc commun d'une ligne autour de son contenu. */
-void g_buffer_line_fill_content(GBufferLine *, const GBinContent *, const mrange_t *, phys_t);
-
-/* Recherche le premier créateur enregistré dans des segments. */
-GObject *g_buffer_line_find_first_segment_creator(const GBufferLine *, BufferLineColumn);
-
-/* Ajoute du texte à formater dans une ligne donnée. */
-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);
-
-/* Indique si du texte est présent dans une ligne de tampon. */
-bool g_buffer_line_has_text(const GBufferLine *, BufferLineColumn, BufferLineColumn);
-
-/* Donne le texte représenté par une ligne de tampon. */
-char *g_buffer_line_get_text(const GBufferLine *, BufferLineColumn, BufferLineColumn, bool);
-
-/* Supprime du texte représenté par une ligne de tampon. */
-void g_buffer_line_delete_text(GBufferLine *, BufferLineColumn, BufferLineColumn);
-
-/* Fournit la colonne à partir de laquelle une fusion opère. */
-BufferLineColumn g_buffer_line_get_merge_start(const GBufferLine *);
-
-/* Définit la colonne à partir de laquelle la fusion opère. */
-void g_buffer_line_start_merge_at(GBufferLine *, BufferLineColumn);
-
-/* Ajoute une propriété particulière à une ligne donnée. */
-void g_buffer_line_add_flag(GBufferLine *, BufferLineFlags);
-
-/* Renseigne sur les propriétés particulières liées à une ligne. */
-BufferLineFlags g_buffer_line_get_flags(const GBufferLine *);
-
-/* Retire une propriété particulière à une ligne donnée. */
-void g_buffer_line_remove_flag(GBufferLine *, BufferLineFlags);
-
-/* Exporte la ligne de texte représentée. */
-void g_buffer_line_export(GBufferLine *, buffer_export_context *, BufferExportType, const bool *);
-
-
-/* Petite aide pour la détection de commentaire */
-#define g_buffer_line_has_comment(ln)                                       \
-    ({                                                                      \
-        bool __result;                                                      \
-        __result = g_buffer_line_has_text(ln, BLC_COMMENTS, BLC_COUNT);     \
-        __result |= (g_buffer_line_get_merge_start(ln) == BLC_DISPLAY       \
-                     && !(g_buffer_line_get_flags(ln) & BLF_IS_LABEL));     \
-        __result;                                                           \
-    })
-
-
-
-/* ----------------------- MANIPULATION DES LARGEURS REQUISES ----------------------- */
-
-
-/* Mémorisation des largeurs pour un groupe de lignes */
-typedef struct _line_width_summary
-{
-    gint max_widths[BLC_COUNT];             /* Taille cachée des colonnes  */
-    gint merged_width;                      /* Largeur cumulée avant fusion*/
-
-} line_width_summary;
-
-/* Identification d'un contenu de colonne */
-typedef struct _col_coord_t
-{
-    BufferLineColumn column;                /* Colonne concernée           */
-    size_t index;                           /* Indice d'insertion          */
-
-} col_coord_t;
-
-
-/* Fait remonter les largeurs requises par une ligne donnée. */
-void g_buffer_line_collect_widths(GBufferLine *, line_width_summary *);
-
-/* Fournit la largeur d'une colonne finalement appliquée. */
-gint g_buffer_line_compute_max_width(const GBufferLine *, BufferLineColumn, const line_width_summary *, const line_width_summary *);
-
-/* Fournit le segment présent à une position donnée. */
-line_segment *g_buffer_line_get_segment_from_coord(const GBufferLine *, const col_coord_t *);
-
-/* Fournit les coordonnées correspondant à une abscisse donnée. */
-bool g_buffer_line_get_coord_at(const GBufferLine *, const line_width_summary *, const GDisplayOptions *, const line_width_summary *, gint *, gint *, GdkScrollDirection, bool, col_coord_t *);
-
-/* Donne le segment présent à une abscisse donnée. */
-line_segment *g_buffer_line_get_segment_at(const GBufferLine *, const line_width_summary *, const GDisplayOptions *, const line_width_summary *, gint *, gint *, GdkScrollDirection, bool);
-
-/* Donne le créateur présent à une abscisse donnée. */
-GObject *g_buffer_line_get_creator_at(const GBufferLine *, const line_width_summary *, const GDisplayOptions *, const line_width_summary *, gint *, gint *, GdkScrollDirection, bool);
-
-/* Fournit des coordonnées voisines selon une direction donnée. */
-bool g_buffer_line_find_near_coord(const GBufferLine *, col_coord_t *, const line_width_summary *, const GDisplayOptions *, const line_width_summary *, GdkScrollDirection, gint *);
-
-/* Imprime la ligne de texte représentée. */
-void g_buffer_line_draw(GBufferLine *, cairo_t *, const line_width_summary *, gint, gint, const GDisplayOptions *, const line_width_summary *, const segcnt_list *);
-
-
-
-#endif  /* _GLIBEXT_GBUFFERLINE_H */
diff --git a/src/glibext/gbufferview.c b/src/glibext/gbufferview.c
deleted file mode 100644
index 0df96cc..0000000
--- a/src/glibext/gbufferview.c
+++ /dev/null
@@ -1,1285 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * gbufferview.c - affichage d'une vue particulière d'un tampon de lignes
- *
- * Copyright (C) 2016-2019 Cyrille Bagard
- *
- *  This file is part of Chrysalide.
- *
- *  Chrysalide is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 3 of the License, or
- *  (at your option) any later version.
- *
- *  Chrysalide is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#include "gbufferview.h"
-
-
-#include <assert.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 *);
-
-};
-
-
-/* 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. */
-static void g_buffer_view_init(GBufferView *);
-
-/* Supprime toutes les références externes. */
-static void g_buffer_view_dispose(GBufferView *);
-
-/* Procède à la libération totale de la mémoire. */
-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 *);
-
-/* Calcule la position idéale de curseur pour un point donné. */
-bool _g_buffer_view_compute_caret_full(GBufferView *, gint, GBufferLine *, size_t, const GDisplayOptions *, const line_width_summary *, cairo_rectangle_int_t *, GLineCursor **);
-
-/* 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 *, const line_width_summary *);
-
-
-/* Fournit la ligne présente à une ordonnée donnée. */
-static GBufferLine *g_buffer_view_find_line_at(GBufferView *, gint, size_t *);
-
-
-
-
-
-
-
-/* Détermine le type de la vue d'un tampon pour code désassemblé. */
-G_DEFINE_TYPE(GBufferView, g_buffer_view, G_TYPE_OBJECT);
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : class = classe de composant GTK à initialiser.               *
-*                                                                             *
-*  Description : Procède à l'initialisation d'une classe de vue de tampon.    *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void g_buffer_view_class_init(GBufferViewClass *class)
-{
-    GObjectClass *object;                   /* Autre version de la classe  */
-
-    object = G_OBJECT_CLASS(class);
-
-    object->dispose = (GObjectFinalizeFunc/* ! */)g_buffer_view_dispose;
-    object->finalize = (GObjectFinalizeFunc)g_buffer_view_finalize;
-
-    /* Sigaux */
-
-    g_signal_new("need-redraw",
-                 G_TYPE_BUFFER_VIEW,
-                 G_SIGNAL_RUN_LAST,
-                 G_STRUCT_OFFSET(GBufferViewClass, need_redraw),
-                 NULL, NULL,
-                 g_cclosure_marshal_VOID__VOID,
-                 G_TYPE_NONE, 0);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : view = composant GLib à initialiser.                         *
-*                                                                             *
-*  Description : Procède à l'initialisation d'une vue d'un tampon pour code.  *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void g_buffer_view_init(GBufferView *view)
-{
-    view->cache = NULL;
-
-    view->highlighted = NULL;
-
-    /**
-     * Inversion du statut pour forcer l'actualisation lors de la création.
-     */
-    view->unrestricted = false;
-
-    view->start = NULL;
-    view->end = NULL;
-
-    view->first = 0;
-    view->last = 0;
-
-    view->tracker = NULL;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : view = instance d'objet GLib à traiter.                      *
-*                                                                             *
-*  Description : Supprime toutes les références externes.                     *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void g_buffer_view_dispose(GBufferView *view)
-{
-    g_clear_object(&view->cache);
-
-    g_clear_object(&view->start);
-    g_clear_object(&view->end);
-
-    g_clear_object(&view->tracker);
-
-    G_OBJECT_CLASS(g_buffer_view_parent_class)->dispose(G_OBJECT(view));
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : view = instance d'objet GLib à traiter.                      *
-*                                                                             *
-*  Description : Procède à la libération totale de la mémoire.                *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-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));
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : buffer      = tampon à représenter à l'écran.                *
-*                highlighted = gestionnaire de surbrillance pour segments.    *
-*                                                                             *
-*  Description : Crée une nouvelle vue d'un tampon pour code désassemblé.     *
-*                                                                             *
-*  Retour      : Composant GTK créé.                                          *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-GBufferView *g_buffer_view_new(GBufferCache *cache, segcnt_list *highlighted)
-{
-    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);
-
-    if (highlighted != NULL)
-    {
-        ref_segment_content_list(highlighted);
-        result->highlighted = highlighted;
-    }
-    else
-        result->highlighted = init_segment_content_list();
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : cache = tampon de lignes cohérentes à manipuler.             *
-*                added = indication sur la variation de la taille du tampon.  *
-*                index = indice de la première ligne à traiter.               *
-*                count = nombre de lignes à traiter.                          *
-*                view  = vue active du tampon de lignes concerné.             *
-*                                                                             *
-*  Description : Accompagne une variation de la quantité de lignes du tampon. *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void on_buffer_cache_size_changed(const GBufferCache *cache, bool added, size_t index, size_t count, GBufferView *view)
-{
-    //size_t i;                               /* Boucle de parcours          */
-    //GBufferLine *line;                      /* Ligne à manipuler           */
-    //const vmpa2t *addr;                     /* Localisation de ligne       */
-
-    /**
-     * Il n'y a pas besoin de verrou ici car la fonction est appelée directement par le tampon.
-     * D'autre part, on considère qu'il y a toujours une ligne aux adresses de borne, si la vue est bornée.
-     */
-
-    if (added)
-    {
-        if (view->unrestricted)
-            view->last += count;
-
-        else
-        {
-#if 0
-
-            /* Avant la zone représentée ? */
-            if (index < view->first)
-            {
-                view->first += count;
-                view->last += count;
-            }
-
-            /* Juste avant la zone représentée ? */
-            else if (view->first == index)
-                for (i = 0; i < count; i++)
-                {
-                    g_buffer_cache_get_line_addr(const GBufferCache *, size_t, gint, vmpa2t *);
-
-                    line = g_code_buffer_find_line_by_index(buffer, index + i);
-                    addr = get_mrange_addr(g_buffer_line_get_range(line));
-
-                    if (cmp_vmpa(&view->start, addr) == 0)
-                    {
-                        view->first++;
-                        view->last++;
-                    }
-                    else
-                        break;
-
-                }
-
-            /* Dans la zone représentée ? */
-            else if (view->first < index && index <= view->last)
-                view->last += count;
-
-            /* Juste après la vue représentée ? */
-            else if ((view->last + 1) == index)
-                for (i = 0; i < count; i++)
-                {
-                    g_buffer_cache_get_line_addr(const GBufferCache *, size_t, gint, vmpa2t *);
-
-                    line = g_code_buffer_find_line_by_index(buffer, index + i);
-                    addr = get_mrange_addr(g_buffer_line_get_range(line));
-
-                    if (cmp_vmpa(&view->end, addr) == 0)
-                        view->last++;
-                    else
-                        break;
-
-                }
-
-            //g_width_tracker_update_added(view->int_tracker, index, count);
-#endif
-
-        }
-
-    }
-
-    else
-    {
-        if (view->unrestricted)
-            view->last -= count;
-
-        else
-        {
-            /* Avant la zone représentée ? */
-            if (index <= view->first)
-            {
-                view->first -= count;
-                view->last -= count;
-            }
-
-            /* Dans la zone représentée ? */
-            else if (view->first < index && index <= view->last)
-                view->last -= count;
-
-        }
-
-        //g_width_tracker_update_deleted(view->int_tracker, index, index + count - 1);
-
-    }
-
-    //g_signal_emit_by_name(view, "need-redraw");
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : view = visualisateur à consulter.                            *
-*                                                                             *
-*  Description : Fournit le tampon de code lié à un visualisateur donné.      *
-*                                                                             *
-*  Retour      : Tampon de code associé au gestionnaire d'affichage.          *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-GBufferCache *g_buffer_view_get_cache(const GBufferView *view)
-{
-    GBufferCache *result;                   /* Instance à retourner        */
-
-    result = view->cache;
-
-    g_object_ref(G_OBJECT(result));
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : view  = visualisateur à mettre à jour.                       *
-*                first = première ligne à imprimer.                           *
-*                last  = première ligne hors cadre.                           *
-*                                                                             *
-*  Description : Restreint le champ d'application de l'affichage.             *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-void g_buffer_view_restrict(GBufferView *view, GLineCursor *start, GLineCursor *end)
-{
-    bool state;                             /* Nouvel état à proclamer     */
-    GWidthTracker *template;                /* Suivi déjà en place         */
-
-    state = (start == NULL || end == NULL);
-
-    if (view->unrestricted != state)
-    {
-        view->unrestricted = state;
-
-        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->unrestricted)
-        {
-            view->first = 0;
-            view->last = g_buffer_cache_count_lines(view->cache) - 1;
-
-            view->tracker = template;
-
-        }
-
-        else
-        {
-            g_object_ref_sink(G_OBJECT(start));
-            g_object_ref_sink(G_OBJECT(end));
-
-            view->start = start;
-            view->end = end;
-
-            view->first = g_buffer_cache_find_index_by_cursor(view->cache, start, true);
-            view->last = g_buffer_cache_find_index_by_cursor(view->cache, end, false);
-
-            view->tracker = g_width_tracker_new_restricted(template, view->first, view->last);
-
-            g_object_unref(G_OBJECT(template));
-
-        }
-
-    }
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : view  = visualisateur à consulter.                           *
-*                first = première ligne à imprimer ou NULL. [OUT]             *
-*                last  = première ligne hors cadre ou NULL. [OUT]             *
-*                                                                             *
-*  Description : Indique le champ d'application de l'affichage.               *
-*                                                                             *
-*  Retour      : true si des restrictions particulières sont en place.        *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-bool g_buffer_view_get_restrictions(const GBufferView *view, GLineCursor **start, GLineCursor **end)
-{
-    if (!view->unrestricted)
-    {
-        if (start != NULL)
-        {
-            *start = view->start;
-            g_object_ref(G_OBJECT(*start));
-        }
-
-        if (end != NULL)
-        {
-            *end = view->end;
-            g_object_ref(G_OBJECT(*end));
-        }
-
-    }
-    else
-    {
-        if (start != NULL) *start = NULL;
-        if (end != NULL) *end = NULL;
-    }
-
-    return !view->unrestricted;
-
-}
-
-
-
-
-
-
-
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : view    = visualisation à consulter.                         *
-*                options = règles d'affichage des colonnes modulables.        *
-*                                                                             *
-*  Description : Fournit la largeur requise par une visualisation.            *
-*                                                                             *
-*  Retour      : Dimension calculée.                                          *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-gint g_buffer_view_get_width(GBufferView *view, const GDisplayOptions *options)
-{
-    gint result;                            /* Taille à retourner          */
-
-    result = g_buffer_cache_get_text_position(view->cache);
-
-    result += g_width_tracker_get_width(view->tracker, options);
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : view    = visualisation à consulter.                         *
-*                options = règles d'affichage des colonnes modulables.        *
-*                                                                             *
-*  Description : Fournit la largeur requise pour dépasser les marges gauches. *
-*                                                                             *
-*  Retour      : Dimension calculée.                                          *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-gint g_buffer_view_get_margin(GBufferView *view, const GDisplayOptions *options)
-{
-    gint result;                            /* Taille à retourner          */
-
-    result = g_buffer_cache_get_text_position(view->cache);
-
-    result += g_width_tracker_get_margin(view->tracker, options);
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : view = visualisation à consulter.                            *
-*                                                                             *
-*  Description : Fournit la hauteur requise par une visualisation.            *
-*                                                                             *
-*  Retour      : Dimension calculée.                                          *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-gint g_buffer_view_get_height(const GBufferView *view)
-{
-    gint result;                            /* Taille à retourner          */
-
-    result = g_buffer_cache_get_line_height(view->cache);
-
-    result *= (view->last - view->first + 1);
-
-    return result;
-
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : view    = vue de tampon à mettre à jour.                     *
-*                x       = abscisse proposée pour le nouvel emplacement.      *
-*                y       = ordonnée proposée pour le nouvel emplacement.      *
-*                options = règles d'affichage des colonnes modulables.        *
-*                offsets = décalages supplémentaires à appliquer.             *
-*                caret   = position du curseur à construire. [OUT]            *
-*                cursor  = emplacement correspondant à cette position. [OUT]  *
-*                                                                             *
-*  Description : Calcule la position idéale de curseur pour un point donné.   *
-*                                                                             *
-*  Retour      : true si les deux derniers arguments ont pu être constitués.  *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-bool g_buffer_view_compute_caret_full(GBufferView *view, gint x, gint y, const GDisplayOptions *options, const line_width_summary *offsets, cairo_rectangle_int_t *caret, GLineCursor **cursor)
-{
-    bool result;                            /* Bilan à retourner           */
-    gint lheight;                           /* Hauteur d'une ligne         */
-    size_t index;                           /* Indice de ligne de tampon   */
-    GBufferLine *line;                      /* Ligne à la position courante*/
-
-    result = false;
-
-    /* Détermination de la ligne courante */
-
-    lheight = g_buffer_cache_get_line_height(view->cache);
-    index = y / lheight;
-
-    index += view->first;
-
-    if (index > view->last)
-        goto gbvccf_done;
-
-    line = g_buffer_cache_find_line_by_index(view->cache, index);
-
-    assert(line != NULL);
-
-    /* Calcul d'une position */
-
-    result = _g_buffer_view_compute_caret_full(view, x, line, index, options, offsets, caret, cursor);
-
-    g_object_unref(G_OBJECT(line));
-
- gbvccf_done:
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : view    = vue de tampon à mettre à jour.                     *
-*                x       = abscisse proposée pour le nouvel emplacement.      *
-*                line    = ligne correspondant à la position.                 *
-*                index   = indice de cette même ligne dans le tampon.         *
-*                options = règles d'affichage des colonnes modulables.        *
-*                offsets = décalages supplémentaires à appliquer.             *
-*                caret   = position du curseur à construire. [OUT]            *
-*                cursor  = emplacement correspondant à cette position. [OUT]  *
-*                                                                             *
-*  Description : Calcule la position idéale de curseur pour un point donné.   *
-*                                                                             *
-*  Retour      : true si les deux derniers arguments ont pu être constitués.  *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-bool _g_buffer_view_compute_caret_full(GBufferView *view, gint x, GBufferLine *line, size_t index, const GDisplayOptions *options, const line_width_summary *offsets, cairo_rectangle_int_t *caret, GLineCursor **cursor)
-{
-    bool result;                            /* Bilan à retourner           */
-    gint text_pos;                          /* Abscisse de départ du texte */
-    line_width_summary summary;             /* Résumé concis des largeurs  */
-    gint base;                              /* Position absolue de segment */
-    bool status;                            /* Bilan de la localisation    */
-    gint lheight;                           /* Hauteur d'une ligne         */
-
-    result = false;
-
-    /* Zone d'intervention bornée ! */
-
-    text_pos = g_buffer_cache_get_text_position(view->cache);
-
-    if (x < text_pos)
-        goto gbvccf_done;
-
-    /* Calcul d'une position */
-
-    g_width_tracker_get_local_width_summary(view->tracker, index, &summary);
-
-    x -= text_pos;
-
-    status = g_buffer_line_get_coord_at(line, &summary, options, offsets, &base, &x,
-                                        GDK_SCROLL_LEFT, true, (col_coord_t []) { { 0 } });
-
-    if (!status)
-        goto gbvccf_done;
-
-    /* Transmission des informations */
-
-    lheight = g_buffer_cache_get_line_height(view->cache);
-
-    caret->x = text_pos + base + x;
-
-    caret->y = (index - view->first) * lheight;
-
-    caret->width = 2;
-    caret->height = lheight;
-
-    g_buffer_cache_get_line_cursor(view->cache, index, caret->x, cursor);
-
-    result = true;
-
- gbvccf_done:
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : view    = vue de tampon à manipuler.                         *
-*                line    = ligne à venir consulter.                           *
-*                index   = indice de cette même ligne dans le tampon.         *
-*                caret   = position du curseur à faire évoluer.               *
-*                ctrl    = indique la demande d'un parcours rapide.           *
-*                dir     = direction du parcours.                             *
-*                options = règles d'affichage des colonnes modulables.        *
-*                offsets = décalages supplémentaires à appliquer.             *
-*                                                                             *
-*  Description : Déplace le curseur au sein d'une vue de tampon.              *
-*                                                                             *
-*  Retour      : true si un déplacement a été effectué, false sinon.          *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static bool _g_buffer_view_move_caret(GBufferView *view, const GBufferLine *line, size_t index, cairo_rectangle_int_t *caret, bool ctrl, GdkScrollDirection dir, const GDisplayOptions *options, const line_width_summary *offsets)
-{
-    bool result;                            /* Bilan à retourner           */
-    gint text_pos;                          /* Abscisse de départ du texte */
-    gint offset;                            /* Point de travail modifiable */
-    line_width_summary summary;             /* Résumé concis des largeurs  */
-    gint base;                              /* Position absolue de segment */
-    col_coord_t coord;                      /* Coordonnées en interne      */
-    line_segment *segment;                  /* Bribe de texte trouvée      */
-
-
-    result = false;
-
-    /* Zone d'intervention bornée ! */
-
-    text_pos = g_buffer_cache_get_text_position(view->cache);
-
-    if (caret->x < text_pos)
-        goto gbvmc_done;
-
-    offset = caret->x - text_pos;
-
-    g_width_tracker_get_local_width_summary(view->tracker, index, &summary);
-
-    /* Déplacement au sein du segment courant ? */
-
-    result = g_buffer_line_get_coord_at(line, &summary, options, offsets, &base, &offset, dir, false, &coord);
-
-    if (result)
-    {
-        segment = g_buffer_line_get_segment_from_coord(line, &coord);
-
-        result = move_caret_on_line_segment(segment, &offset, ctrl, dir);
-
-        release_line_segment(segment);
-
-    }
-
-    /* Tentative de déplacement chez le segment voisin ? */
-
-    if (!result)
-    {
-        base = 0;
-
-        result = g_buffer_line_find_near_coord(line, &coord, &summary, options, offsets, dir, &offset);
-
-    }
-
-    /* Mise à jour éventuelle */
-
-    if (result)
-        caret->x = text_pos + base + offset;
-
- gbvmc_done:
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : view    = vue de tampon à mettre à jour.                     *
-*                ctrl    = indique la demande d'un parcours rapide.           *
-*                dir     = direction du parcours.                             *
-*                options = règles d'affichage des colonnes modulables.        *
-*                offsets = décalages supplémentaires à appliquer.             *
-*                caret   = position du curseur à faire évoluer. [OUT]         *
-*                cursor  = emplacement correspondant à cette position. [OUT]  *
-*                                                                             *
-*  Description : Déplace le curseur au sein d'une vue de tampon.              *
-*                                                                             *
-*  Retour      : true si les deux derniers arguments ont pu être constitués.  *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-bool g_buffer_view_move_caret(GBufferView *view, bool ctrl, GdkScrollDirection dir, const GDisplayOptions *options, const line_width_summary *offsets, cairo_rectangle_int_t *caret, GLineCursor **cursor)
-{
-    bool result;                            /* Bilan à retourner           */
-    size_t index;                           /* Indice de ligne de tampon   */
-    GBufferLine *line;                      /* Ligne sous le pointeur      */
-    size_t first;                           /* Première ligne intégrée     */
-    size_t last;                            /* Dernière ligne intégrée     */
-    GBufferLine *other;                     /* Ligne voisine à visiter     */
-    bool moved;                             /* Mémorisation d'une évolut°  */
-    gint text_pos;                          /* Abscisse de départ du texte */
-
-    result = false;
-
-    line = g_buffer_view_find_line_at(view, caret->y, &index);
-    if (line == NULL) goto gbvmc_done;
-
-    first = view->first;
-    last = view->last;
-
-    switch (dir)
-    {
-        case GDK_SCROLL_UP:
-
-            if (index > first)
-            {
-                index--;
-
-                other = g_buffer_cache_find_line_by_index(view->cache, index);
-                assert(other != NULL);
-
-                result = _g_buffer_view_compute_caret_full(view, caret->x, other, index,
-                                                           options, offsets, caret, cursor);
-
-                g_object_unref(G_OBJECT(other));
-
-            }
-
-            break;
-
-        case GDK_SCROLL_DOWN:
-
-            if (index < last)
-            {
-                index++;
-
-                other = g_buffer_cache_find_line_by_index(view->cache, index);
-                assert(other != NULL);
-
-                result = _g_buffer_view_compute_caret_full(view, caret->x, other, index,
-                                                           options, offsets, caret, cursor);
-
-                g_object_unref(G_OBJECT(other));
-
-            }
-
-            break;
-
-        case GDK_SCROLL_LEFT:
-
-            moved = _g_buffer_view_move_caret(view, line, index, caret, ctrl, GDK_SCROLL_LEFT, options, offsets);
-
-            if (moved)
-            {
-                g_buffer_cache_get_line_cursor(view->cache, index, caret->x, cursor);
-                result = true;
-            }
-
-            else if (index > first)
-            {
-                index--;
-
-                other = g_buffer_cache_find_line_by_index(view->cache, index);
-                assert(other != NULL);
-
-                result = _g_buffer_view_compute_caret_full(view, INT_MAX, other, index,
-                                                           options, offsets, caret, cursor);
-
-                g_object_unref(G_OBJECT(other));
-
-            }
-
-            break;
-
-        case GDK_SCROLL_RIGHT:
-
-            moved = _g_buffer_view_move_caret(view, line, index, caret, ctrl, GDK_SCROLL_RIGHT, options, offsets);
-
-            if (moved)
-            {
-                g_buffer_cache_get_line_cursor(view->cache, index, caret->x, cursor);
-                result = true;
-            }
-
-            else if (index < last)
-            {
-                index++;
-
-                text_pos = g_buffer_cache_get_text_position(view->cache);
-
-                other = g_buffer_cache_find_line_by_index(view->cache, index);
-                assert(other != NULL);
-
-                result = _g_buffer_view_compute_caret_full(view, text_pos, other, index,
-                                                           options, offsets, caret, cursor);
-
-                g_object_unref(G_OBJECT(other));
-
-            }
-
-            break;
-
-        default:    /* GDK_SCROLL_SMOOTH */
-            break;
-
-    }
-
-    g_object_unref(G_OBJECT(line));
-
- gbvmc_done:
-
-    return result;
-
-}
-
-
-
-
-
-
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : view    = vue de tampon à mettre à jour.                     *
-*                x       = abscisse de la zone principale à traiter.          *
-*                y       = ordonnée de la zone principale à traiter.          *
-*                options = règles d'affichage des colonnes modulables.        *
-*                offsets = décalages supplémentaires à appliquer.             *
-*                                                                             *
-*  Description : Trouve le créateur à l'origine d'un emplacement donné.       *
-*                                                                             *
-*  Retour      : Créateur trouvé ou NULL si aucun.                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-GObject *g_buffer_view_find_creator(GBufferView *view, gint x, gint y, const GDisplayOptions *options, const line_width_summary *offsets)
-{
-    GObject *result;                        /* Trouvaille à faire remonter */
-    gint text_pos;                          /* Abscisse de départ du texte */
-    gint lheight;                           /* Hauteur d'une ligne         */
-    size_t index;                           /* Indice de ligne de tampon   */
-    GBufferLine *line;                      /* Ligne à la position courante*/
-    line_width_summary summary;             /* Résumé concis des largeurs  */
-
-    result = NULL;
-
-    /* Zone d'intervention bornée ! */
-
-    text_pos = g_buffer_cache_get_text_position(view->cache);
-
-    if (x < text_pos)
-        goto gbvfc_done;
-
-    /* Détermination de la ligne concernée */
-
-    lheight = g_buffer_cache_get_line_height(view->cache);
-    index = y / lheight;
-
-    index += view->first;
-
-    if (index > view->last)
-        goto gbvfc_done;
-
-    line = g_buffer_cache_find_line_by_index(view->cache, index);
-
-    assert(line != NULL);
-
-    /* Recherche d'un segment et de son empreinte */
-
-    g_width_tracker_get_local_width_summary(view->tracker, index, &summary);
-
-    x -= text_pos;
-
-    result = g_buffer_line_get_creator_at(line, &summary, options, offsets,
-                                          (gint []) { 0 }, &x, GDK_SCROLL_LEFT, false);
-
-    g_object_unref(G_OBJECT(line));
-
- gbvfc_done:
-
-    return result;
-
-}
-
-
-
-
-
-
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : view = vue de tampon à mettre à jour.                        *
-*                                                                             *
-*  Description : Supprime toute mise en évidence de segments.                 *
-*                                                                             *
-*  Retour      : true si un besoin d'actualisation d'affichage se fait sentir.*
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-bool g_buffer_view_unhighlight_segments(GBufferView *view)
-{
-    bool result;                            /* Bilan d'action à renvoyer   */
-
-    result = reset_segment_content_list(view->highlighted);
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : view    = vue de tampon à mettre à jour.                     *
-*                x       = abscisse de la zone principale à traiter.          *
-*                y       = ordonnée de la zone principale à traiter.          *
-*                options = règles d'affichage des colonnes modulables.        *
-*                offsets = décalages supplémentaires à appliquer.             *
-*                                                                             *
-*  Description : Surligne tous les segments similaires à celui sous la souris.*
-*                                                                             *
-*  Retour      : true si un besoin d'actualisation d'affichage se fait sentir.*
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-bool g_buffer_view_highlight_segments(GBufferView *view, gint x, gint y, const GDisplayOptions *options, const line_width_summary *offsets)
-{
-    bool result;                            /* Besoin à faire remonter     */
-    gint text_pos;                          /* Abscisse de départ du texte */
-    gint lheight;                           /* Hauteur d'une ligne         */
-    size_t index;                           /* Indice de ligne de tampon   */
-    GBufferLine *line;                      /* Ligne à la position courante*/
-    line_width_summary summary;             /* Résumé concis des largeurs  */
-    line_segment *segment;                  /* Segment sélectionnable      */
-
-    /* Réinitialisation */
-
-    if (view->highlighted != NULL)
-        result = g_buffer_view_unhighlight_segments(view);
-    else
-        result = false;
-
-    /* Zone d'intervention bornée ! */
-
-    text_pos = g_buffer_cache_get_text_position(view->cache);
-
-    if (x < text_pos)
-        goto gbvhs_done;
-
-    /* Détermination de la ligne concernée */
-
-    lheight = g_buffer_cache_get_line_height(view->cache);
-    index = y / lheight;
-
-    index += view->first;
-
-    if (index > view->last)
-        goto gbvhs_done;
-
-    line = g_buffer_cache_find_line_by_index(view->cache, index);
-
-    assert(line != NULL);
-
-    /* Recherche d'un segment et de son empreinte */
-
-    g_width_tracker_get_local_width_summary(view->tracker, index, &summary);
-
-    x -= text_pos;
-
-    segment = g_buffer_line_get_segment_at(line, &summary, options, offsets,
-                                           (gint []) { 0 }, &x, GDK_SCROLL_LEFT, true);
-
-    g_object_unref(G_OBJECT(line));
-
-    /* Conclusion */
-
-    if (segment != NULL)
-    {
-        result |= add_segment_content_to_selection_list(view->highlighted, segment);
-        release_line_segment(segment);
-    }
-
-    if (result)
-        g_signal_emit_by_name(view, "need-redraw");
-
- gbvhs_done:
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : view     = visualisation à représenter.                      *
-*                cr       = contexte graphique dédié à la procédure.          *
-*                virt_y   = ordonnée réelle du point 0 à l'écran.             *
-*                area     = position et surface à traiter.                    *
-*                options  = règles d'affichage des colonnes modulables.       *
-*                offsets  = décalages supplémentaires à appliquer.            *
-*                selected = ordonnée d'une ligne sélectionnée ou NULL.        *
-*                scale    = échelle appliquée à la surface de rendu.          *
-*                export   = indique si la vue est en cours d'exportation.     *
-*                                                                             *
-*  Description : Imprime la visualisation du tampon de lignes quelconques.    *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-void g_buffer_view_draw(const GBufferView *view, cairo_t *cr, gint virt_y, const cairo_rectangle_int_t *area, const GDisplayOptions *options, const line_width_summary *offsets, gint *selected, double scale, bool export)
-{
-    gint 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        */
-    segcnt_list *highlighted;               /* Segments mis en évidence    */
-
-    line_height = g_buffer_cache_get_line_height(view->cache) * scale;
-
-    line_height = MAX(line_height, 1);
-
-    /* Indice et point de départ */
-
-    first = view->first;
-    first += (virt_y / line_height);
-
-    cr_y = area->y - (virt_y % line_height);
-
-    /* Indice de d'arrivée */
-
-    last = first + (area->height / line_height);
-    if (area->height % line_height > 0) last++;
-
-    last = MIN(last, view->last);
-
-    /* Phase de dessin ! */
-
-    /**
-     * Le contexte n'est pas sauvegardé avant modification ici car
-     * l'appelant l'a fait pour nous avant sa translation sur les abscisses.
-     */
-
-    cairo_translate(cr, 0, cr_y);
-
-    if (selected != NULL)
-        *selected -= cr_y;
-
-    if (export)
-        highlighted = init_segment_content_list();
-    else
-        highlighted = view->highlighted;
-
-    g_buffer_cache_draw(view->cache, cr, first, last, area, options, offsets, selected, highlighted);
-
-    if (export)
-        unref_segment_content_list(highlighted);
-
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : view = visualisation à consulter.                            *
-*                y    = ordonnée comprise dans la ligne recherchée.           *
-*                idx  = indice de la ligne trouvée ou NULL. [OUT]             *
-*                                                                             *
-*  Description : Fournit la ligne présente à une ordonnée donnée.             *
-*                                                                             *
-*  Retour      : Ligne retrouvée ou NULL si aucune.                           *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static GBufferLine *g_buffer_view_find_line_at(GBufferView *view, gint y, size_t *idx)
-{
-    GBufferLine *result;                    /* Ligne trouvée à retourner   */
-    gint lheight;                           /* Hauteur d'une ligne         */
-    size_t index;                           /* Indice attendu              */
-
-    lheight = g_buffer_cache_get_line_height(view->cache);
-    index = y / lheight;
-
-    index += view->first;
-
-    if (index <= view->last)
-        result = g_buffer_cache_find_line_by_index(view->cache, index);
-    else
-        result = NULL;
-
-    if (result != NULL && idx != NULL)
-        *idx = index;
-
-    return result;
-
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-/******************************************************************************
-*                                                                             *
-*  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_get_cursor_coordinates(GBufferView *view, const GLineCursor *cursor, bool code, gint *x, gint *y)
-{
-    bool result;                            /* Bilan à retourner           */
-
-    result = g_buffer_cache_get_cursor_coordinates(view->cache, cursor, view->first, view->last, code, x, y);
-
-    return result;
-
-}
diff --git a/src/glibext/gbufferview.h b/src/glibext/gbufferview.h
deleted file mode 100644
index 2930cf9..0000000
--- a/src/glibext/gbufferview.h
+++ /dev/null
@@ -1,115 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * gbufferview.h - prototypes pour l'affichage d'une vue particulière d'un tampon de lignes
- *
- * Copyright (C) 2016-2019 Cyrille Bagard
- *
- *  This file is part of Chrysalide.
- *
- *  Chrysalide is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 3 of the License, or
- *  (at your option) any later version.
- *
- *  Chrysalide is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#ifndef _GLIBEXT_GBUFFERVIEW_H
-#define _GLIBEXT_GBUFFERVIEW_H
-
-
-#include <glib-object.h>
-
-
-#include "gbuffercache.h"
-#include "gdisplayoptions.h"
-
-
-
-#define G_TYPE_BUFFER_VIEW              (g_buffer_view_get_type())
-#define G_BUFFER_VIEW(obj)              (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_BUFFER_VIEW, GBufferView))
-#define G_BUFFER_VIEW_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_BUFFER_VIEW, GBufferViewClass))
-#define G_IS_BUFFER_VIEW(obj)           (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_BUFFER_VIEW))
-#define G_IS_BUFFER_VIEW_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_BUFFER_VIEW))
-#define G_BUFFER_VIEW_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_BUFFER_VIEW, GBufferViewClass))
-
-
-/* Vue d'un tampon pour code désassemblé (instance) */
-typedef struct _GBufferView GBufferView;
-
-/* Vue d'un tampon pour code désassemblé (classe) */
-typedef struct _GBufferViewClass GBufferViewClass;
-
-
-/* Détermine le type de la vue d'un tampon pour lignes générées. */
-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 *);
-
-/* Fournit le tampon de code lié à un visualisateur donné. */
-GBufferCache *g_buffer_view_get_cache(const GBufferView *);
-
-/* Restreint le champ d'application de l'affichage. */
-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 **);
-
-
-
-/* Fournit la largeur requise par une visualisation. */
-gint g_buffer_view_get_width(GBufferView *, const GDisplayOptions *);
-
-/* Fournit la largeur requise pour dépasser les marges gauches. */
-gint g_buffer_view_get_margin(GBufferView *, const GDisplayOptions *);
-
-/* Fournit la hauteur requise par une visualisation. */
-gint g_buffer_view_get_height(const GBufferView *);
-
-
-
-
-
-/* Calcule la position idéale de curseur pour un point donné. */
-bool g_buffer_view_compute_caret_full(GBufferView *, gint, gint, const GDisplayOptions *, const line_width_summary *, cairo_rectangle_int_t *, GLineCursor **);
-
-/* Déplace le curseur au sein d'une vue de tampon. */
-bool g_buffer_view_move_caret(GBufferView *, bool, GdkScrollDirection, const GDisplayOptions *, const line_width_summary *, cairo_rectangle_int_t *, GLineCursor **);
-
-
-
-/* Trouve le créateur à l'origine d'un emplacement donné. */
-GObject *g_buffer_view_find_creator(GBufferView *, gint, gint, const GDisplayOptions *, const line_width_summary *);
-
-
-
-/* Supprime toute mise en évidence de segments. */
-bool g_buffer_view_unhighlight_segments(GBufferView *);
-
-/* Surligne tous les segments similaires à celui sous la souris. */
-bool g_buffer_view_highlight_segments(GBufferView *, gint, gint, const GDisplayOptions *, const line_width_summary *);
-
-/* Imprime la visualisation du tampon de lignes quelconques. */
-void g_buffer_view_draw(const GBufferView *, cairo_t *, gint, const cairo_rectangle_int_t *, const GDisplayOptions *, const line_width_summary *, gint *, double, bool);
-
-
-
-
-
-
-/* Indique la position d'affichage d'une adresse donnée. */
-bool g_buffer_view_get_cursor_coordinates(GBufferView *, const GLineCursor *, bool, gint *, gint *);
-
-
-
-
-
-#endif  /* _GLIBEXT_GBUFFERVIEW_H */
diff --git a/src/glibext/generators/hex.c b/src/glibext/generators/hex.c
index 13a76e3..b261f36 100644
--- a/src/glibext/generators/hex.c
+++ b/src/glibext/generators/hex.c
@@ -28,8 +28,8 @@
 #include <ctype.h>
 
 
+#include "../bufferline.h"
 #include "../gbinarycursor.h"
-#include "../gbufferline.h"
 #include "../linegen-int.h"
 #include "../linesegment.h"
 #include "../../core/params.h"
diff --git a/src/glibext/generators/prologue.c b/src/glibext/generators/prologue.c
index 3295e73..5829fde 100644
--- a/src/glibext/generators/prologue.c
+++ b/src/glibext/generators/prologue.c
@@ -28,8 +28,8 @@
 #include <malloc.h>
 
 
+#include "../bufferline.h"
 #include "../gbinarycursor.h"
-#include "../gbufferline.h"
 #include "../linegen-int.h"
 #include "../linesegment.h"
 #include "../../format/executable.h"
diff --git a/src/glibext/generators/rborder.c b/src/glibext/generators/rborder.c
index 8509376..8ff1271 100644
--- a/src/glibext/generators/rborder.c
+++ b/src/glibext/generators/rborder.c
@@ -29,8 +29,8 @@
 #include <string.h>
 
 
+#include "../bufferline.h"
 #include "../gbinarycursor.h"
-#include "../gbufferline.h"
 #include "../linegen-int.h"
 #include "../linesegment.h"
 
diff --git a/src/glibext/gwidthtracker.c b/src/glibext/gwidthtracker.c
deleted file mode 100644
index c9aff7b..0000000
--- a/src/glibext/gwidthtracker.c
+++ /dev/null
@@ -1,1271 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * gwidthtracker.c - suivi des largeurs associées à un ensemble de lignes
- *
- * Copyright (C) 2016-2019 Cyrille Bagard
- *
- *  This file is part of Chrysalide.
- *
- *  Chrysalide is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 3 of the License, or
- *  (at your option) any later version.
- *
- *  Chrysalide is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#include "gwidthtracker.h"
-
-
-#include <assert.h>
-#include <malloc.h>
-#include <stdlib.h>
-#include <string.h>
-
-
-#include <i18n.h>
-
-
-#include "delayed-int.h"
-#include "gbuffercache.h"
-#include "../core/global.h"
-#include "../core/nproc.h"
-
-
-
-/* --------------------------- PRISE DE MESURES INITIALES --------------------------- */
-
-
-/* Procédure de mise à jour des mesures de largeurs (instance) */
-typedef struct _GWidthUpdate
-{
-    GDelayedWork parent;                    /* A laisser en premier        */
-
-    activity_id_t id;                       /* Groupe de progression       */
-
-    GWidthTracker *tracker;                 /* Gestionnaire à manipuler    */
-
-    size_t start;                           /* Premier indice à traiter    */
-    size_t end;                             /* Premier indice à écarter    */
-
-    line_width_summary summary;             /* Largeurs requises suivies   */
-
-} GWidthUpdate;
-
-/* Procédure de mise à jour des mesures de largeurs (classe) */
-typedef struct _GWidthUpdateClass
-{
-    GDelayedWorkClass parent;               /* A laisser en premier        */
-
-} GWidthUpdateClass;
-
-
-#define G_TYPE_WIDTH_UPDATE            g_width_update_get_type()
-#define G_WIDTH_UPDATE(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_WIDTH_UPDATE, GWidthUpdate))
-#define G_IS_WIDTH_UPDATE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_WIDTH_UPDATE))
-#define G_WIDTH_UPDATE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_WIDTH_UPDATE, GWidthUpdateClass))
-#define G_IS_WIDTH_UPDATE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_WIDTH_UPDATE))
-#define G_WIDTH_UPDATE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_WIDTH_UPDATE, GWidthUpdateClass))
-
-
-/* Initialise la classe des tâches de mesures de largeurs. */
-static void g_width_update_class_init(GWidthUpdateClass *);
-
-/* Initialise une tâche de mesures de largeurs. */
-static void g_width_update_init(GWidthUpdate *);
-
-/* Supprime toutes les références externes. */
-static void g_width_update_dispose(GWidthUpdate *);
-
-/* Procède à la libération totale de la mémoire. */
-static void g_width_update_finalize(GWidthUpdate *);
-
-/* Indique le type défini pour les tâches de mesures de largeurs. */
-GType g_width_update_get_type(void);
-
-/* Crée une tâche de mesures de largeurs. */
-static GWidthUpdate *g_width_update_new(activity_id_t, GWidthTracker *, size_t, size_t);
-
-/* Assure les mesures initiales d'un ensemble de lignes. */
-static void g_width_update_process(GWidthUpdate *, GtkStatusStack *);
-
-/* Récupère les données obtenues lors d'une mesure globale. */
-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  */
-
-    common_metrics *portions;               /* Portions représentées       */
-    size_t count;                           /* Quantité de ces portions    */
-
-    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);
-
-/* Prend en compte une évolution du volume de lignes. */
-static void g_width_tracker_update_ranges(GWidthTracker *, size_t, size_t);
-
-/* Réinitialise les largeurs requises par une portion de lignes.* */
-static void g_width_tracker_reset_widths(GWidthTracker *, size_t);
-
-/* Recalcule les largeurs requises par une portion de lignes. */
-static const line_width_summary *g_width_tracker_get_up_to_date_widths(GWidthTracker *, size_t);
-
-/* Calcule les largeurs requises par un ensemble de lignes. */
-static void g_width_tracker_ensure_valid_required_widths(GWidthTracker *);
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/*                             PRISE DE MESURES INITIALES                             */
-/* ---------------------------------------------------------------------------------- */
-
-
-/* Indique le type défini pour les tâches de mesures de largeurs. */
-G_DEFINE_TYPE(GWidthUpdate, g_width_update, G_TYPE_DELAYED_WORK);
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : klass = classe à initialiser.                                *
-*                                                                             *
-*  Description : Initialise la classe des tâches de mesures de largeurs.      *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void g_width_update_class_init(GWidthUpdateClass *klass)
-{
-    GObjectClass *object;                   /* Autre version de la classe  */
-    GDelayedWorkClass *work;                /* Version en classe parente   */
-
-    object = G_OBJECT_CLASS(klass);
-
-    object->dispose = (GObjectFinalizeFunc/* ! */)g_width_update_dispose;
-    object->finalize = (GObjectFinalizeFunc)g_width_update_finalize;
-
-    work = G_DELAYED_WORK_CLASS(klass);
-
-    work->run = (run_task_fc)g_width_update_process;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : update = instance à initialiser.                             *
-*                                                                             *
-*  Description : Initialise une tâche de mesures de largeurs.                 *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void g_width_update_init(GWidthUpdate *update)
-{
-    memset(&update->summary, 0, sizeof(line_width_summary));
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : update = instance d'objet GLib à traiter.                    *
-*                                                                             *
-*  Description : Supprime toutes les références externes.                     *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void g_width_update_dispose(GWidthUpdate *update)
-{
-    g_clear_object(&update->tracker);
-
-    G_OBJECT_CLASS(g_width_update_parent_class)->dispose(G_OBJECT(update));
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : update = instance d'objet GLib à traiter.                    *
-*                                                                             *
-*  Description : Procède à la libération totale de la mémoire.                *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void g_width_update_finalize(GWidthUpdate *update)
-{
-    G_OBJECT_CLASS(g_width_update_parent_class)->finalize(G_OBJECT(update));
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : id      = identifiant pour signaler la progression courante. *
-*                tracker = gestionnaire de largeurs à consulter.              *
-*                start   = indice de la première ligne à traiter.             *
-*                end     = indice de la première ligne à éviter.              *
-*                                                                             *
-*  Description : Crée une tâche de mesures de largeurs.                       *
-*                                                                             *
-*  Retour      : Tâche créée.                                                 *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static GWidthUpdate *g_width_update_new(activity_id_t id, GWidthTracker *tracker, size_t start, size_t end)
-{
-    GWidthUpdate *result;                   /* Tâche à retourner           */
-
-    result = g_object_new(G_TYPE_WIDTH_UPDATE, NULL);
-
-    result->id = id;
-
-    g_object_ref(G_OBJECT(tracker));
-    result->tracker = tracker;
-
-    result->start = start;
-    result->end = end;
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : update = opération de mesures à mener.                       *
-*                status = barre de statut à tenir informée.                   *
-*                                                                             *
-*  Description : Assure les mesures initiales d'un ensemble de lignes.        *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void g_width_update_process(GWidthUpdate *update, GtkStatusStack *status)
-{
-    line_width_summary *local;              /* Valeurs collectées          */
-    size_t i;                               /* Boucle de parcours #1       */
-    const line_width_summary *summary;      /* Valeurs à intégrer          */
-    BufferLineColumn k;                     /* Boucle de parcours #2       */
-
-    local = &update->summary;
-
-    for (i = update->start; i < update->end; i++)
-    {
-        summary = g_width_tracker_get_up_to_date_widths(update->tracker, i);
-
-        for (k = 0; k < BLC_COUNT; k++)
-            local->max_widths[k] = MAX(local->max_widths[k], summary->max_widths[k]);
-
-        local->merged_width = MAX(local->merged_width, summary->merged_width);
-
-        gtk_status_stack_update_activity_value(status, update->id, 1);
-
-    }
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : update = opération de mesures menée à bien.                  *
-*                global = lieu de centralisation des données globales.        *
-*                                                                             *
-*  Description : Récupère les données obtenues lors d'une mesure globale.     *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void g_width_update_collect(GWidthUpdate *update, line_width_summary *global)
-{
-    line_width_summary *local;              /* Valeurs collectées          */
-    BufferLineColumn i;                     /* Boucle de parcours          */
-
-    local = &update->summary;
-
-    for (i = 0; i < BLC_COUNT; i++)
-        global->max_widths[i] = MAX(global->max_widths[i], local->max_widths[i]);
-
-    global->merged_width = MAX(global->merged_width, local->merged_width);
-
-}
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/*                              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 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)
-{
-    G_OBJECT_CLASS(g_width_tracker_parent_class)->finalize(G_OBJECT(tracker));
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : buffer = tampon contenant les lignes à surveiller.           *
-*                first  = adresse contenant l'indice de la première ligne.    *
-*                last   = adresse contenant l'indice de la dernière ligne.    *
-*                                                                             *
-*  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);
-
-    g_object_ref(G_OBJECT(cache));
-    result->cache = cache;
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : buffer = tampon contenant les lignes à surveiller.           *
-*                first  = indice de la première ligne d'une zone réduite.     *
-*                last   = indice de la dernière ligne d'une zone réduite.     *
-*                                                                             *
-*  Description : Crée un nouveau suivi de largeurs au sein de lignes.         *
-*                                                                             *
-*  Retour      : Composant GLib créé.                                         *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-GWidthTracker *g_width_tracker_new_restricted(const GWidthTracker *template, size_t first, size_t last)
-{
-    GWidthTracker *result;                  /* Composant à retourner       */
-    size_t start;                           /* Début de la zone à copier   */
-    size_t end;                             /* Fin de cette même zone      */
-    size_t i;                               /* Boucle de parcours          */
-
-    result = g_object_new(G_TYPE_WIDTH_TRACKER, NULL);
-
-    g_object_ref(G_OBJECT(template->cache));
-    result->cache = template->cache;
-
-    start = g_width_tracker_find_metrics(template, first);
-    assert(start < template->count);
-
-    end = g_width_tracker_find_metrics(template, last);
-    assert(end < template->count);
-
-    result->count = end - start + 1;
-    result->portions = (common_metrics *)calloc(result->count, sizeof(common_metrics));
-
-    for (i = 0; i < result->count; i++)
-        memcpy(&result->portions[i], &template->portions[start + i], sizeof(common_metrics));
-
-    if (result->portions[0].first != first)
-    {
-        result->portions[0].first = first;
-        g_width_tracker_reset_widths(result, 0);
-    }
-
-    if (result->portions[result->count - 1].last != last)
-    {
-        result->portions[result->count - 1].last = last;
-        g_width_tracker_reset_widths(result, result->count - 1);
-    }
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : tracker = gestionnaire de suivi à consulter.                 *
-*                index   = indice d'une ligne dont la portion est inconnue.   *
-*                                                                             *
-*  Description : Recherche la portion contenant un indice de ligne donné.     *
-*                                                                             *
-*  Retour      : Indice de portion trouvée ou le nombre de portions sinon.    *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static size_t g_width_tracker_find_metrics(const GWidthTracker *tracker, size_t index)
-{
-    size_t result;                          /* Indice trouvé à retourner   */
-    common_metrics *found;                  /* Portion trouvée ou NULL     */
-
-    int look_for_metrics(const size_t *idx, const common_metrics *m)
-    {
-        int status;
-
-        if (*idx < m->first)
-            status = -1;
-
-        else if (*idx > m->last)
-            status = 1;
-
-        else
-            status = 0;
-
-        return status;
-
-    }
-
-    found = bsearch(&index, tracker->portions, tracker->count,
-                    sizeof(common_metrics), (__compar_fn_t)look_for_metrics);
-
-    if (found == NULL)
-        result = tracker->count;
-    else
-        result = found - tracker->portions;
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : tracker = gestionnaire de largeurs de lignes à mettre jour.  *
-*                start   = première ligne à traiter.                          *
-*                diff    = nombre de lignes ajoutées ou supprimées.           *
-*                                                                             *
-*  Description : Prend en compte une évolution du volume de lignes.           *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void g_width_tracker_update_ranges(GWidthTracker *tracker, size_t start, size_t diff)
-{
-    size_t i;                               /* Boucle de parcours          */
-
-    for (i = start; i < tracker->count; i++)
-    {
-#ifndef NDEBUG
-        if ((i + 1) < tracker->count)
-            assert((tracker->portions[i].last + 1) == tracker->portions[i + 1].first);
-#endif
-
-        tracker->portions[i].first += diff;
-        tracker->portions[i].last += diff;
-
-    }
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : tracker = gestionnaire de largeurs de lignes à mettre jour.  *
-*                index   = indice de portion à marquer pour réinitialisation. *
-*                                                                             *
-*  Description : Réinitialise les largeurs requises par une portion de lignes.*
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void g_width_tracker_reset_widths(GWidthTracker *tracker, size_t index)
-{
-    common_metrics *portion;                /* Portion à actualiser        */
-    BufferLineColumn k;                     /* Boucle de parcours          */
-
-    assert(index < tracker->count);
-
-    portion = &tracker->portions[index];
-
-    /* Réinitialisation globale ? */
-
-    if (portion->cached)
-    {
-        for (k = 0; k < BLC_COUNT && tracker->cached; k++)
-            tracker->cached &= (tracker->summary.max_widths[k] != portion->summary.max_widths[k]);
-
-        tracker->cached &= (tracker->summary.merged_width != portion->summary.merged_width);
-
-    }
-
-    /* Réinitialisation locale */
-
-    portion->cached = false;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : tracker = gestionnaire de largeurs de lignes à mettre jour.  *
-*                index   = indice de la portion à rafraîchir.                 *
-*                                                                             *
-*  Description : Recalcule les largeurs requises par une portion de lignes.   *
-*                                                                             *
-*  Retour      : Accès en lecture seule au résumé à jour.                     *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static const line_width_summary *g_width_tracker_get_up_to_date_widths(GWidthTracker *tracker, size_t index)
-{
-    common_metrics *portion;                /* Portion à actualiser        */
-    size_t i;                               /* Boucle de parcours          */
-
-    assert(index < tracker->count);
-
-    portion = &tracker->portions[index];
-
-    if (!portion->cached)
-    {
-        /* Réinitialisation locale */
-
-        memset(&portion->summary, 0, sizeof(line_width_summary));
-
-        /* Collecte */
-
-        for (i = portion->first; i <= portion->last; i++)
-            g_buffer_cache_collect_widths(tracker->cache, i, &portion->summary);
-
-        /* Marquage pour mémoire */
-
-        portion->cached = true;
-
-    }
-
-    return &portion->summary;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : tracker = gestionnaire de largeurs de lignes à mettre jour.  *
-*                index   = position de la première des lignes à ajouter.      *
-*                                                                             *
-*  Description : Prend acte d'un changement sur une ligne pour les largeurs.  *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-void g_width_tracker_update(GWidthTracker *tracker, size_t index)
-{
-    size_t current;                         /* Indice de portion visée     */
-
-    current = g_width_tracker_find_metrics(tracker, index);
-
-    g_width_tracker_reset_widths(tracker, current);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : tracker = gestionnaire de largeurs de lignes à mettre jour.  *
-*                index   = position de la première des lignes à ajouter.      *
-*                count   = quantité de lignes devant être ajoutées.           *
-*                                                                             *
-*  Description : Prend acte de l'ajout de lignes pour les largeurs.           *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-void g_width_tracker_update_added(GWidthTracker *tracker, size_t index, size_t count)
-{
-    size_t current;                         /* Indice de portion visée     */
-    common_metrics *portion;                /* Portion sélectionnée        */
-    size_t i;                               /* Boucle de parcours          */
-    size_t dest;                            /* Destination d'une recopie   */
-    size_t src;                             /* Source d'une recopie        */
-
-    /* Cas particulier du premier ajout */
-    if (tracker->count == 0)
-    {
-        assert(index == 0);
-
-        tracker->portions = (common_metrics *)calloc(1, sizeof(common_metrics));
-        tracker->count = 1;
-
-        tracker->portions[0].first = 0;
-        tracker->portions[0].last = count - 1;
-
-        g_width_tracker_reset_widths(tracker, 0);
-
-        return;
-
-    }
-
-    current = g_width_tracker_find_metrics(tracker, index);
-
-    /* Si la ligne est rajoutée en fin d'ensemble */
-    if (current == tracker->count)
-    {
-        current = tracker->count - 1;
-        portion = &tracker->portions[current];
-
-        assert(index == (portion->last + 1));
-
-    }
-    else
-        portion = &tracker->portions[current];
-
-    portion->last += count;
-
-    g_width_tracker_reset_widths(tracker, current);
-
-    /* Suite impérative : accroître les indices ! */
-
-    g_width_tracker_update_ranges(tracker, current + 1, count);
-
-    /* Un découpage s'impose-t-il quelque part ? */
-
-    for (i = index + count - 1; i >= index; i--)
-    {
-        if (g_buffer_cache_get_line_flags(tracker->cache, i) & BLF_WIDTH_MANAGER)
-        {
-            /* Insertion d'une nouvelle place */
-
-            tracker->count++;
-
-            tracker->portions = (common_metrics *)realloc(tracker->portions,
-                                                          tracker->count * sizeof(common_metrics));
-
-            portion = &tracker->portions[current];
-
-            dest = current + 2;
-            src = current + 1;
-
-            if ((tracker->count - src) > 0)
-                memmove(&tracker->portions[dest], &tracker->portions[src],
-                        (tracker->count - src - 1) * sizeof(common_metrics));
-
-            /* Insertion au début */
-            if (i == portion->first)
-            {
-                assert(i == index);
-
-                tracker->portions[current + 1].first = i + 1;
-                tracker->portions[current + 1].last = portion->last;
-
-                tracker->portions[current + 1].cached = false;
-
-                portion->first = i;
-                portion->last = i;
-
-            }
-
-            /* Insertion au sein de la portion ou à la fin */
-            else
-            {
-                tracker->portions[current + 1].first = i;
-                tracker->portions[current + 1].last = portion->last;
-
-                tracker->portions[current + 1].cached = false;
-
-                portion->last = i - 1;
-
-            }
-
-            assert((tracker->portions[current].last + 1) == tracker->portions[current + 1].first);
-
-            /* Mise à jour des largeurs */
-
-            g_width_tracker_reset_widths(tracker, current);
-
-            g_width_tracker_reset_widths(tracker, current + 1);
-
-        }
-
-    }
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : tracker = gestionnaire de largeurs de lignes à mettre jour.  *
-*                start   = première ligne devant être supprimée.              *
-*                end     = dernière ligne devant être supprimée.              *
-*                                                                             *
-*  Description : Prend acte de la suppression de lignes pour les largeurs.    *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-void g_width_tracker_update_deleted(GWidthTracker *tracker, size_t start, size_t end)
-{
-    size_t first;                           /* Première portion concernée  */
-    size_t last;                            /* Dernière portion concernée  */
-    size_t diff;                            /* Nombre de lignes supprimées */
-    bool keep_first;                        /* Conservation de portion #1  */
-    size_t dest;                            /* Destination du transfert    */
-    bool keep_last;                         /* Conservation de portion #2  */
-    size_t src;                             /* Source du transfert         */
-    size_t update;                          /* Début de la série en rafale */
-
-    first = g_width_tracker_find_metrics(tracker, start);
-    assert(first < tracker->count);
-
-    last = g_width_tracker_find_metrics(tracker, end);
-    assert(last < tracker->count);
-
-    diff = end - start + 1;
-
-    /* Suppression de portions inutiles ? */
-
-    keep_first = (tracker->portions[first].first < start);
-
-    dest = (keep_first ? first + 1 : first);
-
-    keep_last = (end < tracker->portions[last].last);
-
-    src = (keep_last ? last : last + 1);
-
-    if (src > dest)
-    {
-        if (src < tracker->count)
-            memmove(&tracker->portions[dest], &tracker->portions[src],
-                    (tracker->count - src) * sizeof(common_metrics));
-
-        tracker->count -= (src - dest);
-
-        tracker->portions = (common_metrics *)realloc(tracker->portions,
-                                                      tracker->count * sizeof(common_metrics));
-
-    }
-
-    /* Si une fusion s'impose */
-
-    if (keep_first && keep_last && last != first)
-    {
-        tracker->portions[first].last = tracker->portions[first + 1].last;
-
-        if ((first - 2) < tracker->count)
-            memmove(&tracker->portions[first + 1], &tracker->portions[first + 2],
-                    (tracker->count - first - 2) * sizeof(common_metrics));
-
-        tracker->count--;
-
-        tracker->portions = (common_metrics *)realloc(tracker->portions,
-                                                      tracker->count * sizeof(common_metrics));
-
-        keep_last = false;
-
-    }
-
-    /* Avant toute chose : faire décroître les indices ! */
-
-    if (keep_first && keep_last)
-    {
-        tracker->portions[first].last -= diff;
-        update = first + 1;
-    }
-
-    else
-    {
-        if (keep_first)
-        {
-            tracker->portions[first].last = start - 1;
-            update = first + 1;
-        }
-        else
-            update = first;
-
-        if (keep_last)
-            tracker->portions[update].first = end + 1;
-
-    }
-
-    g_width_tracker_update_ranges(tracker, update, -diff);
-
-    /* Mise à jour des largeurs aux extrémités */
-
-    if (keep_first)
-        g_width_tracker_reset_widths(tracker, first);
-
-    if (keep_last && !keep_first)
-        g_width_tracker_reset_widths(tracker, update);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : tracker = suivi de largeurs dont le cache est à construire.  *
-*                gid     = groupe de travail impliqué.                        *
-*                status  = barre de statut à tenir informée.                  *
-*                                                                             *
-*  Description : Calcule les largeurs requises par un ensemble de lignes.     *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-void g_width_tracker_build_initial_cache(GWidthTracker *tracker, wgroup_id_t gid, GtkStatusStack *status)
-{
-    guint runs_count;                       /* Qté d'exécutions parallèles */
-    GWidthUpdate **updates;                 /* Mesures à suivre            */
-    size_t run_size;                        /* Volume réparti par exécution*/
-    GWorkQueue *queue;                      /* Gestionnaire de différés    */
-    activity_id_t id;                       /* Identifiant de progression  */
-    guint i;                                /* Boucle de parcours          */
-    size_t start;                           /* Début de zone de traitement */
-    bool closing;                           /* Détection de fin en amont   */
-    size_t end;                             /* Fin de zone de traitement   */
-
-    assert(!tracker->cached);
-
-    /* Lancement des traitements */
-
-    run_size = compute_run_size(tracker->count, &runs_count);
-
-    updates = (GWidthUpdate **)calloc(runs_count, sizeof(GWidthUpdate *));
-
-    queue = get_work_queue();
-
-    id = gtk_status_stack_add_activity(status, _("Computing width of all lines for rendering"), tracker->count);
-
-    for (i = 0; i < runs_count; i++)
-    {
-        start = i * run_size;
-
-        closing = ((i + 1) == runs_count);
-
-        if (closing)
-            end = tracker->count;
-        else
-            end = start + run_size;
-
-        updates[i] = g_width_update_new(id, tracker, start, end);
-
-        g_object_ref(G_OBJECT(updates[i]));
-        g_work_queue_schedule_work(queue, G_DELAYED_WORK(updates[i]), gid);
-
-    }
-
-    g_work_queue_wait_for_completion(queue, gid);
-
-    /* Récupération des aires */
-
-    memset(&tracker->summary, 0, sizeof(line_width_summary));
-
-    for (i = 0; i < runs_count; i++)
-    {
-        g_width_update_collect(updates[i], &tracker->summary);
-
-        g_object_unref(G_OBJECT(updates[i]));
-
-    }
-
-    /* Fin */
-
-    free(updates);
-
-    gtk_status_stack_remove_activity(status, id);
-
-    tracker->cached = true;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : tracker = suivi de largeurs à mettre à jour si besoin est.   *
-*                                                                             *
-*  Description : Calcule les largeurs requises par un ensemble de lignes.     *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void g_width_tracker_ensure_valid_required_widths(GWidthTracker *tracker)
-{
-    line_width_summary *global;             /* Valeurs collectées          */
-    size_t i;                               /* Boucle de parcours #1       */
-    const line_width_summary *summary;      /* Valeurs à intégrer          */
-    BufferLineColumn k;                     /* Boucle de parcours #2       */
-
-    if (!tracker->cached)
-    {
-        global = &tracker->summary;
-
-        /* Réinitialisation */
-
-        memset(global, 0, sizeof(line_width_summary));
-
-        /* Collecte */
-
-        for (i = 0; i < tracker->count; i++)
-        {
-            summary = g_width_tracker_get_up_to_date_widths(tracker, i);
-
-            for (k = 0; k < BLC_COUNT; k++)
-                global->max_widths[k] = MAX(global->max_widths[k], summary->max_widths[k]);
-
-            global->merged_width = MAX(global->merged_width, summary->merged_width);
-
-        }
-
-        tracker->cached = true;
-
-    }
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : tracker = suivi de largeurs à consulter.                     *
-*                                                                             *
-*  Description : Fournit un bon résumé des largeurs en vigueur.               *
-*                                                                             *
-*  Retour      : Ensemble des largeurs collectées.                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-const line_width_summary *g_width_tracker_get_width_summary(GWidthTracker *tracker)
-{
-    g_width_tracker_ensure_valid_required_widths(tracker);
-
-    return &tracker->summary;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : tracker = suivi de largeurs à consulter.                     *
-*                index   = indice de la ligne dont la portion est recherchée. *
-*                summary = ensemble ciblé de largeurs collectées. [OUT]       *
-*                                                                             *
-*  Description : Fournit un résumé local des largeurs en vigueur.             *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-void g_width_tracker_get_local_width_summary(GWidthTracker *tracker, size_t index, line_width_summary *summary)
-{
-    size_t current;                         /* Indice de portion visée     */
-    const line_width_summary *local;        /* Valeurs à intégrer          */
-    BufferLineColumn i;                     /* Boucle de parcours          */
-
-    g_width_tracker_ensure_valid_required_widths(tracker);
-
-    current = g_width_tracker_find_metrics(tracker, index);
-    assert(current < tracker->count);
-
-    local = g_width_tracker_get_up_to_date_widths(tracker, current);
-
-    for (i = BLC_FIRST; i < BLC_DISPLAY; i++)
-        summary->max_widths[i] = tracker->summary.max_widths[i];
-
-    for (i = BLC_DISPLAY; i < BLC_COUNT; i++)
-        summary->max_widths[i] = local->max_widths[i];
-
-    summary->merged_width = local->merged_width;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : tracker = suivi de largeurs à consulter.                     *
-*                options = règles d'affichage des colonnes modulables.        *
-*                                                                             *
-*  Description : Fournit la largeur requise par une visualisation.            *
-*                                                                             *
-*  Retour      : Dimension calculée.                                          *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-gint g_width_tracker_get_width(GWidthTracker *tracker, const GDisplayOptions *options)
-{
-    gint result;                            /* Taille à retourner          */
-    const line_width_summary *summary;      /* Accès rapide aux mesures    */
-    gint col_width;                         /* Calcul selon les colonnes   */
-    gint full_width;                        /* Calcul selon les fusions    */
-    size_t count;                           /* Qté de colonnes en option   */
-    size_t i;                               /* Boucle de parcours          */
-
-    g_width_tracker_ensure_valid_required_widths(tracker);
-
-    result = 0;
-
-    summary = &tracker->summary;
-
-    col_width = 0;
-    full_width = 0;
-
-    count = g_display_options_count(options);
-
-    /* Première méthode */
-
-    for (i = 0; i < BLC_COUNT; i++)
-    {
-        if (i < count)
-        {
-            if (!g_display_options_get(options, i))
-                continue;
-        }
-
-        col_width += summary->max_widths[i];
-
-        if ((i + 1) < BLC_COUNT)
-            col_width += COL_MARGIN;
-
-    }
-
-    /* Seconde méthode */
-
-    for (i = 0; i < count; i++)
-    {
-        if (!g_display_options_get(options, i))
-            continue;
-
-        full_width += summary->max_widths[i] + COL_MARGIN;
-
-    }
-
-    full_width += summary->merged_width;
-
-    /* Mise en concurrence et poursuite... */
-
-    result += + MAX(col_width, full_width);
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : tracker = suivi de largeurs à consulter.                     *
-*                display = règles d'affichage des colonnes modulables.        *
-*                                                                             *
-*  Description : Fournit la largeur requise pour dépasser les marges gauches. *
-*                                                                             *
-*  Retour      : Dimension calculée.                                          *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-gint g_width_tracker_get_margin(GWidthTracker *tracker, const GDisplayOptions *options)
-{
-    gint result;                            /* Taille à retourner          */
-    const line_width_summary *summary;      /* Accès rapide aux mesures    */
-    size_t count;                           /* Qté de colonnes en option   */
-    size_t i;                               /* Boucle de parcours          */
-
-    g_width_tracker_ensure_valid_required_widths(tracker);
-
-    result = 0;
-
-    summary = &tracker->summary;
-
-    count = g_display_options_count(options);
-
-    for (i = 0; i < count; i++)
-    {
-        if (!g_display_options_get(options, i))
-            continue;
-
-        result += summary->max_widths[i] + COL_MARGIN;
-
-    }
-
-    return result;
-
-}
diff --git a/src/glibext/gwidthtracker.h b/src/glibext/gwidthtracker.h
deleted file mode 100644
index 610c736..0000000
--- a/src/glibext/gwidthtracker.h
+++ /dev/null
@@ -1,95 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * gwidthtracker.h - prototypes pour le suivi des largeurs associées à un ensemble de lignes
- *
- * Copyright (C) 2016-2018 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_GWIDTHTRACKER_H
-#define _GLIBEXT_GWIDTHTRACKER_H
-
-
-#include <glib-object.h>
-#include <stdbool.h>
-
-
-#include "delayed.h"
-#include "gbufferline.h"
-#include "gdisplayoptions.h"
-
-
-
-/* ---------------------------- RASSEMBLEMENT DE MESURES ---------------------------- */
-
-
-/* gbuffercache.h : Tampon pour gestion de lignes optimisée (instance) */
-typedef struct _GBufferCache GBufferCache;
-
-
-#define G_TYPE_WIDTH_TRACKER            (g_width_tracker_get_type())
-#define G_WIDTH_TRACKER(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_WIDTH_TRACKER, GWidthTracker))
-#define G_WIDTH_TRACKER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_WIDTH_TRACKER, GWidthTrackerClass))
-#define G_IS_WIDTH_TRACKER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_WIDTH_TRACKER))
-#define G_IS_WIDTH_TRACKER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_WIDTH_TRACKER))
-#define G_WIDTH_TRACKER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_WIDTH_TRACKER, GWidthTrackerClass))
-
-
-/* Gestionnaire de largeurs associées aux lignes (instance) */
-typedef struct _GWidthTracker GWidthTracker;
-
-/* Gestionnaire de largeurs associées aux lignes (classe) */
-typedef struct _GWidthTrackerClass GWidthTrackerClass;
-
-
-/* Détermine le type du gestionnaire de largeurs associées aux lignes. */
-GType g_width_tracker_get_type(void);
-
-/* Crée un nouveau suivi de largeurs au sein de lignes. */
-GWidthTracker *g_width_tracker_new(GBufferCache *);
-
-/* Crée un nouveau suivi de largeurs au sein de lignes. */
-GWidthTracker *g_width_tracker_new_restricted(const GWidthTracker *, size_t, size_t);
-
-/* Prend acte d'un changement sur une ligne pour les largeurs. */
-void g_width_tracker_update(GWidthTracker *, size_t);
-
-/* Prend acte de l'ajout de lignes pour les largeurs. */
-void g_width_tracker_update_added(GWidthTracker *, size_t, size_t);
-
-/* Prend acte de la suppression de lignes pour les largeurs. */
-void g_width_tracker_update_deleted(GWidthTracker *, size_t, size_t);
-
-/* Calcule les largeurs requises par un ensemble de lignes. */
-void g_width_tracker_build_initial_cache(GWidthTracker *, wgroup_id_t, GtkStatusStack *);
-
-/* Fournit un bon résumé des largeurs en vigueur. */
-const line_width_summary *g_width_tracker_get_width_summary(GWidthTracker *);
-
-/* Fournit un résumé local des largeurs en vigueur. */
-void g_width_tracker_get_local_width_summary(GWidthTracker *, size_t, line_width_summary *);
-
-/* Fournit la largeur requise par une visualisation. */
-gint g_width_tracker_get_width(GWidthTracker *, const GDisplayOptions *);
-
-/* Fournit la largeur requise pour dépasser les marges gauches. */
-gint g_width_tracker_get_margin(GWidthTracker *, const GDisplayOptions *);
-
-
-
-#endif  /* _GLIBEXT_GWIDTHTRACKER_H */
diff --git a/src/glibext/linegen.h b/src/glibext/linegen.h
index 74a889a..d40a598 100644
--- a/src/glibext/linegen.h
+++ b/src/glibext/linegen.h
@@ -28,7 +28,7 @@
 #include <glib-object.h>
 
 
-#include "gbufferline.h"
+#include "bufferline.h"
 #include "glinecursor.h"
 #include "../analysis/content.h"
 
diff --git a/src/glibext/widthtracker.c b/src/glibext/widthtracker.c
new file mode 100644
index 0000000..274b53c
--- /dev/null
+++ b/src/glibext/widthtracker.c
@@ -0,0 +1,1271 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * widthtracker.c - suivi des largeurs associées à un ensemble de lignes
+ *
+ * Copyright (C) 2016-2019 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Chrysalide is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "widthtracker.h"
+
+
+#include <assert.h>
+#include <malloc.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+#include <i18n.h>
+
+
+#include "buffercache.h"
+#include "delayed-int.h"
+#include "../core/global.h"
+#include "../core/nproc.h"
+
+
+
+/* --------------------------- PRISE DE MESURES INITIALES --------------------------- */
+
+
+/* Procédure de mise à jour des mesures de largeurs (instance) */
+typedef struct _GWidthUpdate
+{
+    GDelayedWork parent;                    /* A laisser en premier        */
+
+    activity_id_t id;                       /* Groupe de progression       */
+
+    GWidthTracker *tracker;                 /* Gestionnaire à manipuler    */
+
+    size_t start;                           /* Premier indice à traiter    */
+    size_t end;                             /* Premier indice à écarter    */
+
+    line_width_summary summary;             /* Largeurs requises suivies   */
+
+} GWidthUpdate;
+
+/* Procédure de mise à jour des mesures de largeurs (classe) */
+typedef struct _GWidthUpdateClass
+{
+    GDelayedWorkClass parent;               /* A laisser en premier        */
+
+} GWidthUpdateClass;
+
+
+#define G_TYPE_WIDTH_UPDATE            g_width_update_get_type()
+#define G_WIDTH_UPDATE(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_WIDTH_UPDATE, GWidthUpdate))
+#define G_IS_WIDTH_UPDATE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_WIDTH_UPDATE))
+#define G_WIDTH_UPDATE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_WIDTH_UPDATE, GWidthUpdateClass))
+#define G_IS_WIDTH_UPDATE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_WIDTH_UPDATE))
+#define G_WIDTH_UPDATE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_WIDTH_UPDATE, GWidthUpdateClass))
+
+
+/* Initialise la classe des tâches de mesures de largeurs. */
+static void g_width_update_class_init(GWidthUpdateClass *);
+
+/* Initialise une tâche de mesures de largeurs. */
+static void g_width_update_init(GWidthUpdate *);
+
+/* Supprime toutes les références externes. */
+static void g_width_update_dispose(GWidthUpdate *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_width_update_finalize(GWidthUpdate *);
+
+/* Indique le type défini pour les tâches de mesures de largeurs. */
+GType g_width_update_get_type(void);
+
+/* Crée une tâche de mesures de largeurs. */
+static GWidthUpdate *g_width_update_new(activity_id_t, GWidthTracker *, size_t, size_t);
+
+/* Assure les mesures initiales d'un ensemble de lignes. */
+static void g_width_update_process(GWidthUpdate *, GtkStatusStack *);
+
+/* Récupère les données obtenues lors d'une mesure globale. */
+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  */
+
+    common_metrics *portions;               /* Portions représentées       */
+    size_t count;                           /* Quantité de ces portions    */
+
+    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);
+
+/* Prend en compte une évolution du volume de lignes. */
+static void g_width_tracker_update_ranges(GWidthTracker *, size_t, size_t);
+
+/* Réinitialise les largeurs requises par une portion de lignes.* */
+static void g_width_tracker_reset_widths(GWidthTracker *, size_t);
+
+/* Recalcule les largeurs requises par une portion de lignes. */
+static const line_width_summary *g_width_tracker_get_up_to_date_widths(GWidthTracker *, size_t);
+
+/* Calcule les largeurs requises par un ensemble de lignes. */
+static void g_width_tracker_ensure_valid_required_widths(GWidthTracker *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                             PRISE DE MESURES INITIALES                             */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour les tâches de mesures de largeurs. */
+G_DEFINE_TYPE(GWidthUpdate, g_width_update, G_TYPE_DELAYED_WORK);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des tâches de mesures de largeurs.      *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_width_update_class_init(GWidthUpdateClass *klass)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+    GDelayedWorkClass *work;                /* Version en classe parente   */
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_width_update_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_width_update_finalize;
+
+    work = G_DELAYED_WORK_CLASS(klass);
+
+    work->run = (run_task_fc)g_width_update_process;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : update = instance à initialiser.                             *
+*                                                                             *
+*  Description : Initialise une tâche de mesures de largeurs.                 *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_width_update_init(GWidthUpdate *update)
+{
+    memset(&update->summary, 0, sizeof(line_width_summary));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : update = instance d'objet GLib à traiter.                    *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_width_update_dispose(GWidthUpdate *update)
+{
+    g_clear_object(&update->tracker);
+
+    G_OBJECT_CLASS(g_width_update_parent_class)->dispose(G_OBJECT(update));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : update = instance d'objet GLib à traiter.                    *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_width_update_finalize(GWidthUpdate *update)
+{
+    G_OBJECT_CLASS(g_width_update_parent_class)->finalize(G_OBJECT(update));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : id      = identifiant pour signaler la progression courante. *
+*                tracker = gestionnaire de largeurs à consulter.              *
+*                start   = indice de la première ligne à traiter.             *
+*                end     = indice de la première ligne à éviter.              *
+*                                                                             *
+*  Description : Crée une tâche de mesures de largeurs.                       *
+*                                                                             *
+*  Retour      : Tâche créée.                                                 *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static GWidthUpdate *g_width_update_new(activity_id_t id, GWidthTracker *tracker, size_t start, size_t end)
+{
+    GWidthUpdate *result;                   /* Tâche à retourner           */
+
+    result = g_object_new(G_TYPE_WIDTH_UPDATE, NULL);
+
+    result->id = id;
+
+    g_object_ref(G_OBJECT(tracker));
+    result->tracker = tracker;
+
+    result->start = start;
+    result->end = end;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : update = opération de mesures à mener.                       *
+*                status = barre de statut à tenir informée.                   *
+*                                                                             *
+*  Description : Assure les mesures initiales d'un ensemble de lignes.        *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_width_update_process(GWidthUpdate *update, GtkStatusStack *status)
+{
+    line_width_summary *local;              /* Valeurs collectées          */
+    size_t i;                               /* Boucle de parcours #1       */
+    const line_width_summary *summary;      /* Valeurs à intégrer          */
+    BufferLineColumn k;                     /* Boucle de parcours #2       */
+
+    local = &update->summary;
+
+    for (i = update->start; i < update->end; i++)
+    {
+        summary = g_width_tracker_get_up_to_date_widths(update->tracker, i);
+
+        for (k = 0; k < BLC_COUNT; k++)
+            local->max_widths[k] = MAX(local->max_widths[k], summary->max_widths[k]);
+
+        local->merged_width = MAX(local->merged_width, summary->merged_width);
+
+        gtk_status_stack_update_activity_value(status, update->id, 1);
+
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : update = opération de mesures menée à bien.                  *
+*                global = lieu de centralisation des données globales.        *
+*                                                                             *
+*  Description : Récupère les données obtenues lors d'une mesure globale.     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_width_update_collect(GWidthUpdate *update, line_width_summary *global)
+{
+    line_width_summary *local;              /* Valeurs collectées          */
+    BufferLineColumn i;                     /* Boucle de parcours          */
+
+    local = &update->summary;
+
+    for (i = 0; i < BLC_COUNT; i++)
+        global->max_widths[i] = MAX(global->max_widths[i], local->max_widths[i]);
+
+    global->merged_width = MAX(global->merged_width, local->merged_width);
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                              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 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)
+{
+    G_OBJECT_CLASS(g_width_tracker_parent_class)->finalize(G_OBJECT(tracker));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : buffer = tampon contenant les lignes à surveiller.           *
+*                first  = adresse contenant l'indice de la première ligne.    *
+*                last   = adresse contenant l'indice de la dernière ligne.    *
+*                                                                             *
+*  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);
+
+    g_object_ref(G_OBJECT(cache));
+    result->cache = cache;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : buffer = tampon contenant les lignes à surveiller.           *
+*                first  = indice de la première ligne d'une zone réduite.     *
+*                last   = indice de la dernière ligne d'une zone réduite.     *
+*                                                                             *
+*  Description : Crée un nouveau suivi de largeurs au sein de lignes.         *
+*                                                                             *
+*  Retour      : Composant GLib créé.                                         *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GWidthTracker *g_width_tracker_new_restricted(const GWidthTracker *template, size_t first, size_t last)
+{
+    GWidthTracker *result;                  /* Composant à retourner       */
+    size_t start;                           /* Début de la zone à copier   */
+    size_t end;                             /* Fin de cette même zone      */
+    size_t i;                               /* Boucle de parcours          */
+
+    result = g_object_new(G_TYPE_WIDTH_TRACKER, NULL);
+
+    g_object_ref(G_OBJECT(template->cache));
+    result->cache = template->cache;
+
+    start = g_width_tracker_find_metrics(template, first);
+    assert(start < template->count);
+
+    end = g_width_tracker_find_metrics(template, last);
+    assert(end < template->count);
+
+    result->count = end - start + 1;
+    result->portions = (common_metrics *)calloc(result->count, sizeof(common_metrics));
+
+    for (i = 0; i < result->count; i++)
+        memcpy(&result->portions[i], &template->portions[start + i], sizeof(common_metrics));
+
+    if (result->portions[0].first != first)
+    {
+        result->portions[0].first = first;
+        g_width_tracker_reset_widths(result, 0);
+    }
+
+    if (result->portions[result->count - 1].last != last)
+    {
+        result->portions[result->count - 1].last = last;
+        g_width_tracker_reset_widths(result, result->count - 1);
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : tracker = gestionnaire de suivi à consulter.                 *
+*                index   = indice d'une ligne dont la portion est inconnue.   *
+*                                                                             *
+*  Description : Recherche la portion contenant un indice de ligne donné.     *
+*                                                                             *
+*  Retour      : Indice de portion trouvée ou le nombre de portions sinon.    *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static size_t g_width_tracker_find_metrics(const GWidthTracker *tracker, size_t index)
+{
+    size_t result;                          /* Indice trouvé à retourner   */
+    common_metrics *found;                  /* Portion trouvée ou NULL     */
+
+    int look_for_metrics(const size_t *idx, const common_metrics *m)
+    {
+        int status;
+
+        if (*idx < m->first)
+            status = -1;
+
+        else if (*idx > m->last)
+            status = 1;
+
+        else
+            status = 0;
+
+        return status;
+
+    }
+
+    found = bsearch(&index, tracker->portions, tracker->count,
+                    sizeof(common_metrics), (__compar_fn_t)look_for_metrics);
+
+    if (found == NULL)
+        result = tracker->count;
+    else
+        result = found - tracker->portions;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : tracker = gestionnaire de largeurs de lignes à mettre jour.  *
+*                start   = première ligne à traiter.                          *
+*                diff    = nombre de lignes ajoutées ou supprimées.           *
+*                                                                             *
+*  Description : Prend en compte une évolution du volume de lignes.           *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_width_tracker_update_ranges(GWidthTracker *tracker, size_t start, size_t diff)
+{
+    size_t i;                               /* Boucle de parcours          */
+
+    for (i = start; i < tracker->count; i++)
+    {
+#ifndef NDEBUG
+        if ((i + 1) < tracker->count)
+            assert((tracker->portions[i].last + 1) == tracker->portions[i + 1].first);
+#endif
+
+        tracker->portions[i].first += diff;
+        tracker->portions[i].last += diff;
+
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : tracker = gestionnaire de largeurs de lignes à mettre jour.  *
+*                index   = indice de portion à marquer pour réinitialisation. *
+*                                                                             *
+*  Description : Réinitialise les largeurs requises par une portion de lignes.*
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_width_tracker_reset_widths(GWidthTracker *tracker, size_t index)
+{
+    common_metrics *portion;                /* Portion à actualiser        */
+    BufferLineColumn k;                     /* Boucle de parcours          */
+
+    assert(index < tracker->count);
+
+    portion = &tracker->portions[index];
+
+    /* Réinitialisation globale ? */
+
+    if (portion->cached)
+    {
+        for (k = 0; k < BLC_COUNT && tracker->cached; k++)
+            tracker->cached &= (tracker->summary.max_widths[k] != portion->summary.max_widths[k]);
+
+        tracker->cached &= (tracker->summary.merged_width != portion->summary.merged_width);
+
+    }
+
+    /* Réinitialisation locale */
+
+    portion->cached = false;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : tracker = gestionnaire de largeurs de lignes à mettre jour.  *
+*                index   = indice de la portion à rafraîchir.                 *
+*                                                                             *
+*  Description : Recalcule les largeurs requises par une portion de lignes.   *
+*                                                                             *
+*  Retour      : Accès en lecture seule au résumé à jour.                     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static const line_width_summary *g_width_tracker_get_up_to_date_widths(GWidthTracker *tracker, size_t index)
+{
+    common_metrics *portion;                /* Portion à actualiser        */
+    size_t i;                               /* Boucle de parcours          */
+
+    assert(index < tracker->count);
+
+    portion = &tracker->portions[index];
+
+    if (!portion->cached)
+    {
+        /* Réinitialisation locale */
+
+        memset(&portion->summary, 0, sizeof(line_width_summary));
+
+        /* Collecte */
+
+        for (i = portion->first; i <= portion->last; i++)
+            g_buffer_cache_collect_widths(tracker->cache, i, &portion->summary);
+
+        /* Marquage pour mémoire */
+
+        portion->cached = true;
+
+    }
+
+    return &portion->summary;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : tracker = gestionnaire de largeurs de lignes à mettre jour.  *
+*                index   = position de la première des lignes à ajouter.      *
+*                                                                             *
+*  Description : Prend acte d'un changement sur une ligne pour les largeurs.  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_width_tracker_update(GWidthTracker *tracker, size_t index)
+{
+    size_t current;                         /* Indice de portion visée     */
+
+    current = g_width_tracker_find_metrics(tracker, index);
+
+    g_width_tracker_reset_widths(tracker, current);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : tracker = gestionnaire de largeurs de lignes à mettre jour.  *
+*                index   = position de la première des lignes à ajouter.      *
+*                count   = quantité de lignes devant être ajoutées.           *
+*                                                                             *
+*  Description : Prend acte de l'ajout de lignes pour les largeurs.           *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_width_tracker_update_added(GWidthTracker *tracker, size_t index, size_t count)
+{
+    size_t current;                         /* Indice de portion visée     */
+    common_metrics *portion;                /* Portion sélectionnée        */
+    size_t i;                               /* Boucle de parcours          */
+    size_t dest;                            /* Destination d'une recopie   */
+    size_t src;                             /* Source d'une recopie        */
+
+    /* Cas particulier du premier ajout */
+    if (tracker->count == 0)
+    {
+        assert(index == 0);
+
+        tracker->portions = (common_metrics *)calloc(1, sizeof(common_metrics));
+        tracker->count = 1;
+
+        tracker->portions[0].first = 0;
+        tracker->portions[0].last = count - 1;
+
+        g_width_tracker_reset_widths(tracker, 0);
+
+        return;
+
+    }
+
+    current = g_width_tracker_find_metrics(tracker, index);
+
+    /* Si la ligne est rajoutée en fin d'ensemble */
+    if (current == tracker->count)
+    {
+        current = tracker->count - 1;
+        portion = &tracker->portions[current];
+
+        assert(index == (portion->last + 1));
+
+    }
+    else
+        portion = &tracker->portions[current];
+
+    portion->last += count;
+
+    g_width_tracker_reset_widths(tracker, current);
+
+    /* Suite impérative : accroître les indices ! */
+
+    g_width_tracker_update_ranges(tracker, current + 1, count);
+
+    /* Un découpage s'impose-t-il quelque part ? */
+
+    for (i = index + count - 1; i >= index; i--)
+    {
+        if (g_buffer_cache_get_line_flags(tracker->cache, i) & BLF_WIDTH_MANAGER)
+        {
+            /* Insertion d'une nouvelle place */
+
+            tracker->count++;
+
+            tracker->portions = (common_metrics *)realloc(tracker->portions,
+                                                          tracker->count * sizeof(common_metrics));
+
+            portion = &tracker->portions[current];
+
+            dest = current + 2;
+            src = current + 1;
+
+            if ((tracker->count - src) > 0)
+                memmove(&tracker->portions[dest], &tracker->portions[src],
+                        (tracker->count - src - 1) * sizeof(common_metrics));
+
+            /* Insertion au début */
+            if (i == portion->first)
+            {
+                assert(i == index);
+
+                tracker->portions[current + 1].first = i + 1;
+                tracker->portions[current + 1].last = portion->last;
+
+                tracker->portions[current + 1].cached = false;
+
+                portion->first = i;
+                portion->last = i;
+
+            }
+
+            /* Insertion au sein de la portion ou à la fin */
+            else
+            {
+                tracker->portions[current + 1].first = i;
+                tracker->portions[current + 1].last = portion->last;
+
+                tracker->portions[current + 1].cached = false;
+
+                portion->last = i - 1;
+
+            }
+
+            assert((tracker->portions[current].last + 1) == tracker->portions[current + 1].first);
+
+            /* Mise à jour des largeurs */
+
+            g_width_tracker_reset_widths(tracker, current);
+
+            g_width_tracker_reset_widths(tracker, current + 1);
+
+        }
+
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : tracker = gestionnaire de largeurs de lignes à mettre jour.  *
+*                start   = première ligne devant être supprimée.              *
+*                end     = dernière ligne devant être supprimée.              *
+*                                                                             *
+*  Description : Prend acte de la suppression de lignes pour les largeurs.    *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_width_tracker_update_deleted(GWidthTracker *tracker, size_t start, size_t end)
+{
+    size_t first;                           /* Première portion concernée  */
+    size_t last;                            /* Dernière portion concernée  */
+    size_t diff;                            /* Nombre de lignes supprimées */
+    bool keep_first;                        /* Conservation de portion #1  */
+    size_t dest;                            /* Destination du transfert    */
+    bool keep_last;                         /* Conservation de portion #2  */
+    size_t src;                             /* Source du transfert         */
+    size_t update;                          /* Début de la série en rafale */
+
+    first = g_width_tracker_find_metrics(tracker, start);
+    assert(first < tracker->count);
+
+    last = g_width_tracker_find_metrics(tracker, end);
+    assert(last < tracker->count);
+
+    diff = end - start + 1;
+
+    /* Suppression de portions inutiles ? */
+
+    keep_first = (tracker->portions[first].first < start);
+
+    dest = (keep_first ? first + 1 : first);
+
+    keep_last = (end < tracker->portions[last].last);
+
+    src = (keep_last ? last : last + 1);
+
+    if (src > dest)
+    {
+        if (src < tracker->count)
+            memmove(&tracker->portions[dest], &tracker->portions[src],
+                    (tracker->count - src) * sizeof(common_metrics));
+
+        tracker->count -= (src - dest);
+
+        tracker->portions = (common_metrics *)realloc(tracker->portions,
+                                                      tracker->count * sizeof(common_metrics));
+
+    }
+
+    /* Si une fusion s'impose */
+
+    if (keep_first && keep_last && last != first)
+    {
+        tracker->portions[first].last = tracker->portions[first + 1].last;
+
+        if ((first - 2) < tracker->count)
+            memmove(&tracker->portions[first + 1], &tracker->portions[first + 2],
+                    (tracker->count - first - 2) * sizeof(common_metrics));
+
+        tracker->count--;
+
+        tracker->portions = (common_metrics *)realloc(tracker->portions,
+                                                      tracker->count * sizeof(common_metrics));
+
+        keep_last = false;
+
+    }
+
+    /* Avant toute chose : faire décroître les indices ! */
+
+    if (keep_first && keep_last)
+    {
+        tracker->portions[first].last -= diff;
+        update = first + 1;
+    }
+
+    else
+    {
+        if (keep_first)
+        {
+            tracker->portions[first].last = start - 1;
+            update = first + 1;
+        }
+        else
+            update = first;
+
+        if (keep_last)
+            tracker->portions[update].first = end + 1;
+
+    }
+
+    g_width_tracker_update_ranges(tracker, update, -diff);
+
+    /* Mise à jour des largeurs aux extrémités */
+
+    if (keep_first)
+        g_width_tracker_reset_widths(tracker, first);
+
+    if (keep_last && !keep_first)
+        g_width_tracker_reset_widths(tracker, update);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : tracker = suivi de largeurs dont le cache est à construire.  *
+*                gid     = groupe de travail impliqué.                        *
+*                status  = barre de statut à tenir informée.                  *
+*                                                                             *
+*  Description : Calcule les largeurs requises par un ensemble de lignes.     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_width_tracker_build_initial_cache(GWidthTracker *tracker, wgroup_id_t gid, GtkStatusStack *status)
+{
+    guint runs_count;                       /* Qté d'exécutions parallèles */
+    GWidthUpdate **updates;                 /* Mesures à suivre            */
+    size_t run_size;                        /* Volume réparti par exécution*/
+    GWorkQueue *queue;                      /* Gestionnaire de différés    */
+    activity_id_t id;                       /* Identifiant de progression  */
+    guint i;                                /* Boucle de parcours          */
+    size_t start;                           /* Début de zone de traitement */
+    bool closing;                           /* Détection de fin en amont   */
+    size_t end;                             /* Fin de zone de traitement   */
+
+    assert(!tracker->cached);
+
+    /* Lancement des traitements */
+
+    run_size = compute_run_size(tracker->count, &runs_count);
+
+    updates = (GWidthUpdate **)calloc(runs_count, sizeof(GWidthUpdate *));
+
+    queue = get_work_queue();
+
+    id = gtk_status_stack_add_activity(status, _("Computing width of all lines for rendering"), tracker->count);
+
+    for (i = 0; i < runs_count; i++)
+    {
+        start = i * run_size;
+
+        closing = ((i + 1) == runs_count);
+
+        if (closing)
+            end = tracker->count;
+        else
+            end = start + run_size;
+
+        updates[i] = g_width_update_new(id, tracker, start, end);
+
+        g_object_ref(G_OBJECT(updates[i]));
+        g_work_queue_schedule_work(queue, G_DELAYED_WORK(updates[i]), gid);
+
+    }
+
+    g_work_queue_wait_for_completion(queue, gid);
+
+    /* Récupération des aires */
+
+    memset(&tracker->summary, 0, sizeof(line_width_summary));
+
+    for (i = 0; i < runs_count; i++)
+    {
+        g_width_update_collect(updates[i], &tracker->summary);
+
+        g_object_unref(G_OBJECT(updates[i]));
+
+    }
+
+    /* Fin */
+
+    free(updates);
+
+    gtk_status_stack_remove_activity(status, id);
+
+    tracker->cached = true;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : tracker = suivi de largeurs à mettre à jour si besoin est.   *
+*                                                                             *
+*  Description : Calcule les largeurs requises par un ensemble de lignes.     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_width_tracker_ensure_valid_required_widths(GWidthTracker *tracker)
+{
+    line_width_summary *global;             /* Valeurs collectées          */
+    size_t i;                               /* Boucle de parcours #1       */
+    const line_width_summary *summary;      /* Valeurs à intégrer          */
+    BufferLineColumn k;                     /* Boucle de parcours #2       */
+
+    if (!tracker->cached)
+    {
+        global = &tracker->summary;
+
+        /* Réinitialisation */
+
+        memset(global, 0, sizeof(line_width_summary));
+
+        /* Collecte */
+
+        for (i = 0; i < tracker->count; i++)
+        {
+            summary = g_width_tracker_get_up_to_date_widths(tracker, i);
+
+            for (k = 0; k < BLC_COUNT; k++)
+                global->max_widths[k] = MAX(global->max_widths[k], summary->max_widths[k]);
+
+            global->merged_width = MAX(global->merged_width, summary->merged_width);
+
+        }
+
+        tracker->cached = true;
+
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : tracker = suivi de largeurs à consulter.                     *
+*                                                                             *
+*  Description : Fournit un bon résumé des largeurs en vigueur.               *
+*                                                                             *
+*  Retour      : Ensemble des largeurs collectées.                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+const line_width_summary *g_width_tracker_get_width_summary(GWidthTracker *tracker)
+{
+    g_width_tracker_ensure_valid_required_widths(tracker);
+
+    return &tracker->summary;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : tracker = suivi de largeurs à consulter.                     *
+*                index   = indice de la ligne dont la portion est recherchée. *
+*                summary = ensemble ciblé de largeurs collectées. [OUT]       *
+*                                                                             *
+*  Description : Fournit un résumé local des largeurs en vigueur.             *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_width_tracker_get_local_width_summary(GWidthTracker *tracker, size_t index, line_width_summary *summary)
+{
+    size_t current;                         /* Indice de portion visée     */
+    const line_width_summary *local;        /* Valeurs à intégrer          */
+    BufferLineColumn i;                     /* Boucle de parcours          */
+
+    g_width_tracker_ensure_valid_required_widths(tracker);
+
+    current = g_width_tracker_find_metrics(tracker, index);
+    assert(current < tracker->count);
+
+    local = g_width_tracker_get_up_to_date_widths(tracker, current);
+
+    for (i = BLC_FIRST; i < BLC_DISPLAY; i++)
+        summary->max_widths[i] = tracker->summary.max_widths[i];
+
+    for (i = BLC_DISPLAY; i < BLC_COUNT; i++)
+        summary->max_widths[i] = local->max_widths[i];
+
+    summary->merged_width = local->merged_width;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : tracker = suivi de largeurs à consulter.                     *
+*                options = règles d'affichage des colonnes modulables.        *
+*                                                                             *
+*  Description : Fournit la largeur requise par une visualisation.            *
+*                                                                             *
+*  Retour      : Dimension calculée.                                          *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+gint g_width_tracker_get_width(GWidthTracker *tracker, const GDisplayOptions *options)
+{
+    gint result;                            /* Taille à retourner          */
+    const line_width_summary *summary;      /* Accès rapide aux mesures    */
+    gint col_width;                         /* Calcul selon les colonnes   */
+    gint full_width;                        /* Calcul selon les fusions    */
+    size_t count;                           /* Qté de colonnes en option   */
+    size_t i;                               /* Boucle de parcours          */
+
+    g_width_tracker_ensure_valid_required_widths(tracker);
+
+    result = 0;
+
+    summary = &tracker->summary;
+
+    col_width = 0;
+    full_width = 0;
+
+    count = g_display_options_count(options);
+
+    /* Première méthode */
+
+    for (i = 0; i < BLC_COUNT; i++)
+    {
+        if (i < count)
+        {
+            if (!g_display_options_get(options, i))
+                continue;
+        }
+
+        col_width += summary->max_widths[i];
+
+        if ((i + 1) < BLC_COUNT)
+            col_width += COL_MARGIN;
+
+    }
+
+    /* Seconde méthode */
+
+    for (i = 0; i < count; i++)
+    {
+        if (!g_display_options_get(options, i))
+            continue;
+
+        full_width += summary->max_widths[i] + COL_MARGIN;
+
+    }
+
+    full_width += summary->merged_width;
+
+    /* Mise en concurrence et poursuite... */
+
+    result += + MAX(col_width, full_width);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : tracker = suivi de largeurs à consulter.                     *
+*                display = règles d'affichage des colonnes modulables.        *
+*                                                                             *
+*  Description : Fournit la largeur requise pour dépasser les marges gauches. *
+*                                                                             *
+*  Retour      : Dimension calculée.                                          *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+gint g_width_tracker_get_margin(GWidthTracker *tracker, const GDisplayOptions *options)
+{
+    gint result;                            /* Taille à retourner          */
+    const line_width_summary *summary;      /* Accès rapide aux mesures    */
+    size_t count;                           /* Qté de colonnes en option   */
+    size_t i;                               /* Boucle de parcours          */
+
+    g_width_tracker_ensure_valid_required_widths(tracker);
+
+    result = 0;
+
+    summary = &tracker->summary;
+
+    count = g_display_options_count(options);
+
+    for (i = 0; i < count; i++)
+    {
+        if (!g_display_options_get(options, i))
+            continue;
+
+        result += summary->max_widths[i] + COL_MARGIN;
+
+    }
+
+    return result;
+
+}
diff --git a/src/glibext/widthtracker.h b/src/glibext/widthtracker.h
new file mode 100644
index 0000000..b7bb8a4
--- /dev/null
+++ b/src/glibext/widthtracker.h
@@ -0,0 +1,95 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * widthtracker.h - prototypes pour le suivi des largeurs associées à un ensemble de lignes
+ *
+ * Copyright (C) 2016-2018 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_H
+#define _GLIBEXT_WIDTHTRACKER_H
+
+
+#include <glib-object.h>
+#include <stdbool.h>
+
+
+#include "bufferline.h"
+#include "delayed.h"
+#include "gdisplayoptions.h"
+
+
+
+/* ---------------------------- RASSEMBLEMENT DE MESURES ---------------------------- */
+
+
+/* gbuffercache.h : Tampon pour gestion de lignes optimisée (instance) */
+typedef struct _GBufferCache GBufferCache;
+
+
+#define G_TYPE_WIDTH_TRACKER            (g_width_tracker_get_type())
+#define G_WIDTH_TRACKER(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_WIDTH_TRACKER, GWidthTracker))
+#define G_WIDTH_TRACKER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_WIDTH_TRACKER, GWidthTrackerClass))
+#define G_IS_WIDTH_TRACKER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_WIDTH_TRACKER))
+#define G_IS_WIDTH_TRACKER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_WIDTH_TRACKER))
+#define G_WIDTH_TRACKER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_WIDTH_TRACKER, GWidthTrackerClass))
+
+
+/* Gestionnaire de largeurs associées aux lignes (instance) */
+typedef struct _GWidthTracker GWidthTracker;
+
+/* Gestionnaire de largeurs associées aux lignes (classe) */
+typedef struct _GWidthTrackerClass GWidthTrackerClass;
+
+
+/* Détermine le type du gestionnaire de largeurs associées aux lignes. */
+GType g_width_tracker_get_type(void);
+
+/* Crée un nouveau suivi de largeurs au sein de lignes. */
+GWidthTracker *g_width_tracker_new(GBufferCache *);
+
+/* Crée un nouveau suivi de largeurs au sein de lignes. */
+GWidthTracker *g_width_tracker_new_restricted(const GWidthTracker *, size_t, size_t);
+
+/* Prend acte d'un changement sur une ligne pour les largeurs. */
+void g_width_tracker_update(GWidthTracker *, size_t);
+
+/* Prend acte de l'ajout de lignes pour les largeurs. */
+void g_width_tracker_update_added(GWidthTracker *, size_t, size_t);
+
+/* Prend acte de la suppression de lignes pour les largeurs. */
+void g_width_tracker_update_deleted(GWidthTracker *, size_t, size_t);
+
+/* Calcule les largeurs requises par un ensemble de lignes. */
+void g_width_tracker_build_initial_cache(GWidthTracker *, wgroup_id_t, GtkStatusStack *);
+
+/* Fournit un bon résumé des largeurs en vigueur. */
+const line_width_summary *g_width_tracker_get_width_summary(GWidthTracker *);
+
+/* Fournit un résumé local des largeurs en vigueur. */
+void g_width_tracker_get_local_width_summary(GWidthTracker *, size_t, line_width_summary *);
+
+/* Fournit la largeur requise par une visualisation. */
+gint g_width_tracker_get_width(GWidthTracker *, const GDisplayOptions *);
+
+/* Fournit la largeur requise pour dépasser les marges gauches. */
+gint g_width_tracker_get_margin(GWidthTracker *, const GDisplayOptions *);
+
+
+
+#endif  /* _GLIBEXT_WIDTHTRACKER_H */
diff --git a/src/gtkext/gtkblockdisplay.h b/src/gtkext/gtkblockdisplay.h
index 2b523c4..2effb9b 100644
--- a/src/gtkext/gtkblockdisplay.h
+++ b/src/gtkext/gtkblockdisplay.h
@@ -29,7 +29,7 @@
 #include <gtk/gtk.h>
 
 
-#include "../glibext/gbufferview.h"
+#include "../glibext/bufferview.h"
 
 
 
diff --git a/src/gtkext/gtkbufferdisplay.h b/src/gtkext/gtkbufferdisplay.h
index 2aec5a8..8f2d63c 100644
--- a/src/gtkext/gtkbufferdisplay.h
+++ b/src/gtkext/gtkbufferdisplay.h
@@ -29,7 +29,7 @@
 #include <gtk/gtk.h>
 
 
-#include "../glibext/gbufferview.h"
+#include "../glibext/bufferview.h"
 
 
 
-- 
cgit v0.11.2-87-g4458