From a6c46fc296db67321db3d4bb586346998de90422 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Sun, 26 Jul 2020 20:52:15 +0200
Subject: Reduced the quantity of arguments used to deal with lines.

---
 src/analysis/disass/block.c        |   3 +-
 src/analysis/disass/disassembler.c |  12 ++-
 src/core/params.c                  |   3 +
 src/core/params.h                  |   1 +
 src/glibext/buffercache.c          |  21 ++---
 src/glibext/buffercache.h          |   4 +-
 src/glibext/bufferline.c           | 144 +++++++++++++---------------------
 src/glibext/bufferline.h           |  22 ++----
 src/glibext/bufferview.c           |  67 ++++++----------
 src/glibext/bufferview.h           |  10 +--
 src/glibext/generators/hex.c       |  15 ++--
 src/glibext/widthtracker.c         | 155 +++++++++++++++++++++++++++++--------
 src/glibext/widthtracker.h         |  27 +++++--
 src/gtkext/gtkblockdisplay.c       |  21 ++---
 src/gtkext/gtkblockdisplay.h       |  28 +++++--
 src/gtkext/gtkbufferdisplay-int.h  |   1 -
 src/gtkext/gtkbufferdisplay.c      |  20 +----
 src/gtkext/hexdisplay.c            |  11 ++-
 src/gtkext/hexdisplay.h            |  13 ++++
 19 files changed, 327 insertions(+), 251 deletions(-)

diff --git a/src/analysis/disass/block.c b/src/analysis/disass/block.c
index d314b5a..74aaf66 100644
--- a/src/analysis/disass/block.c
+++ b/src/analysis/disass/block.c
@@ -36,6 +36,7 @@
 #include "../../common/extstr.h"
 #include "../../core/params.h"
 #include "../../glibext/gbinarycursor.h"
+#include "../../gtkext/gtkblockdisplay.h"
 
 
 
@@ -572,7 +573,7 @@ static char *g_basic_block_build_tooltip(const GBasicBlock *block)
 
         if (label != NULL)
         {
-            cache = g_buffer_cache_new(NULL);
+            cache = g_buffer_cache_new(NULL, DLC_COUNT);
             g_buffer_cache_append(cache, G_LINE_GENERATOR(symbol), BLF_NONE);
 
             line = g_buffer_cache_find_line_by_index(cache, 0);
diff --git a/src/analysis/disass/disassembler.c b/src/analysis/disass/disassembler.c
index af67fdf..9e4cd3e 100644
--- a/src/analysis/disass/disassembler.c
+++ b/src/analysis/disass/disassembler.c
@@ -39,8 +39,10 @@
 #include "../human/asm/lang.h"
 #include "../../arch/storage.h"
 #include "../../core/global.h"
+#include "../../core/params.h"
 #include "../../core/nproc.h"
 #include "../../glibext/generators/prologue.h"
+#include "../../gtkext/gtkblockdisplay.h"
 #include "../../plugins/pglist.h"
 
 
@@ -388,6 +390,8 @@ void output_disassembly(GLoadedBinary *binary, GProcContext *context, GtkStatusS
     GBinFormat *format;                     /* Format associé au binaire   */
     GBinContent *content;                   /* Contenu bianire manipulé    */
     GCodingLanguage *lang;                  /* Langage de sortie préféré   */
+    int offset;                             /* Décalage des étiquettes     */
+    GWidthTracker *tracker;                 /* Gestionnaire de largeurs    */
     char **text;                            /* Contenu brute à imprimer    */
     char *desc;                             /* Désignation du binaire      */
     const gchar *checksum;                  /* Identifiant de binaire      */
@@ -401,7 +405,13 @@ void output_disassembly(GLoadedBinary *binary, GProcContext *context, GtkStatusS
     content = g_known_format_get_content(G_KNOWN_FORMAT(format));
     lang = g_asm_language_new();
 
-    *cache = g_buffer_cache_new(content);
+    *cache = g_buffer_cache_new(content, DLC_COUNT);
+
+    g_generic_config_get_value(get_main_configuration(), MPK_LABEL_OFFSET, &offset);
+
+    tracker = g_buffer_cache_get_width_tracker(*cache);
+    g_width_tracker_set_column_min_width(tracker, DLC_ASSEMBLY_LABEL, offset);
+    g_object_unref(G_OBJECT(tracker));
 
     /**
      * Impression du prologue.
diff --git a/src/core/params.c b/src/core/params.c
index 109593d..7e6e1ed 100644
--- a/src/core/params.c
+++ b/src/core/params.c
@@ -77,6 +77,9 @@ bool load_main_config_parameters(void)
     param = g_generic_config_create_param(config, MPK_LABEL_OFFSET, CPT_INTEGER, 10);
     if (param == NULL) return false;
 
+    param = g_generic_config_create_param(config, MPK_HEX_PADDING, CPT_INTEGER, 10);
+    if (param == NULL) return false;
+
     param = g_generic_config_create_param(config, MPK_SELECTION_LINE, CPT_BOOLEAN, true);
     if (param == NULL) return false;
 
diff --git a/src/core/params.h b/src/core/params.h
index 6c4c062..dc6b180 100644
--- a/src/core/params.h
+++ b/src/core/params.h
@@ -44,6 +44,7 @@
 #define MPK_WELCOME_STARTUP     "gui.editor.panels.welcome.show_at_startup"
 #define MPK_WELCOME_CHECK       "gui.editor.panels.welcome.check_version"
 #define MPK_LABEL_OFFSET        "gui.editor.views.label_offset"
+#define MPK_HEX_PADDING         "gui.editor.views.hex_padding"
 #define MPK_SELECTION_LINE      "gui.editor.views.selection_line"
 #define MPK_TOOLTIP_MAX_CALLS   "gui.editor.views.tooltip_max_calls"
 #define MPK_TOOLTIP_MAX_STRINGS "gui.editor.views.tooltip_max_strings"
diff --git a/src/glibext/buffercache.c b/src/glibext/buffercache.c
index 16d96dc..bfc2360 100644
--- a/src/glibext/buffercache.c
+++ b/src/glibext/buffercache.c
@@ -537,7 +537,7 @@ static void g_buffer_cache_init(GBufferCache *cache)
     cache->count = 0;
     cache->used = 0;
 
-    cache->tracker = g_width_tracker_new(cache);
+    cache->tracker = NULL;
 
 }
 
@@ -620,7 +620,8 @@ static void g_buffer_cache_finalize(GBufferCache *cache)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : content = éventuel contenu binaire brut à référencer.        *
+*  Paramètres  : content   = éventuel contenu binaire brut à référencer.      *
+*                col_count = quantité maximale de colonnes à considérer.      *
 *                                                                             *
 *  Description : Crée un nouveau composant de tampon pour code désassemblé.   *
 *                                                                             *
@@ -630,7 +631,7 @@ static void g_buffer_cache_finalize(GBufferCache *cache)
 *                                                                             *
 ******************************************************************************/
 
-GBufferCache *g_buffer_cache_new(GBinContent *content)
+GBufferCache *g_buffer_cache_new(GBinContent *content, size_t col_count)
 {
     GBufferCache *result;                   /* Composant à retourner       */
 
@@ -642,6 +643,8 @@ GBufferCache *g_buffer_cache_new(GBinContent *content)
         g_object_ref(G_OBJECT(content));
     }
 
+    result->tracker = g_width_tracker_new(result, col_count);
+
     return result;
 
 }
@@ -786,9 +789,6 @@ GWidthTracker *g_buffer_cache_get_width_tracker(const GBufferCache *cache)
 }
 
 
-
-
-
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : cache     = instance GLib à consulter.                       *
@@ -1439,7 +1439,6 @@ void g_buffer_cache_collect_widths(GBufferCache *cache, size_t index, line_width
 *                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.           *
 *                                                                             *
@@ -1451,14 +1450,13 @@ void g_buffer_cache_collect_widths(GBufferCache *cache, size_t index, line_width
 *                                                                             *
 ******************************************************************************/
 
-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)
+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 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);
@@ -1484,12 +1482,9 @@ void g_buffer_cache_draw(const GBufferCache *cache, cairo_t *cr, size_t first, s
 
             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_buffer_line_draw(line, i, cr, class->text_pos, y, cache->tracker, options, list);
 
             g_object_unref(G_OBJECT(line));
 
diff --git a/src/glibext/buffercache.h b/src/glibext/buffercache.h
index 5094b53..70154a0 100644
--- a/src/glibext/buffercache.h
+++ b/src/glibext/buffercache.h
@@ -58,7 +58,7 @@ typedef struct _GBufferCacheClass GBufferCacheClass;
 GType g_buffer_cache_get_type(void);
 
 /* Crée un nouveau composant de tampon pour code désassemblé. */
-GBufferCache *g_buffer_cache_new(GBinContent *);
+GBufferCache *g_buffer_cache_new(GBinContent *, size_t);
 
 /* Indique l'éventuel contenu binaire associé au cache. */
 GBinContent *g_buffer_cache_get_content(const GBufferCache *);
@@ -114,7 +114,7 @@ GBufferLine *g_buffer_cache_find_line_by_index(const GBufferCache *, size_t);
 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 *);
+void g_buffer_cache_draw(const GBufferCache *, cairo_t *, size_t, size_t, const cairo_rectangle_int_t *, const GDisplayOptions *, const gint *, const segcnt_list *);
 
 /* 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);
diff --git a/src/glibext/bufferline.c b/src/glibext/bufferline.c
index b9413e2..2f694dd 100644
--- a/src/glibext/bufferline.c
+++ b/src/glibext/bufferline.c
@@ -65,15 +65,6 @@ struct _GBufferLine
     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) */
@@ -568,7 +559,7 @@ void g_buffer_line_append_text(GBufferLine *line, size_t column, const char *tex
 
     if (creator != NULL)
     {
-        line->origins = (content_origin *)realloc(line->origins, ++line->ocount * sizeof(content_origin));
+        line->origins = realloc(line->origins, ++line->ocount * sizeof(content_origin));
 
         origin = &line->origins[line->ocount - 1];
 
@@ -984,43 +975,6 @@ void g_buffer_line_collect_widths(GBufferLine *line, line_width_summary *summary
 
 /******************************************************************************
 *                                                                             *
-*  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.          *
 *                                                                             *
@@ -1049,7 +1003,8 @@ line_segment *g_buffer_line_get_segment_from_coord(const GBufferLine *line, cons
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : line    = ligne à venir consulter.                           *
-*                summary = résumé des largeurs maximales.                     *
+*                index   = indice de ligne associé.                           *
+*                tracker = gestionnaire de largeur à consulter au besoin.     *
 *                options = règles d'affichage des colonnes modulables.        *
 *                offsets = décalages supplémentaires à appliquer.             *
 *                base    = position jusqu'au segment trouvé. [OUT]            *
@@ -1066,12 +1021,13 @@ line_segment *g_buffer_line_get_segment_from_coord(const GBufferLine *line, cons
 *                                                                             *
 ******************************************************************************/
 
-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 g_buffer_line_get_coord_at(const GBufferLine *line, size_t index, GWidthTracker *tracker, const GDisplayOptions *options, 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 col_count;                       /* Qté de colonnes présentes   */
+    size_t opt_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       */
@@ -1087,11 +1043,12 @@ bool g_buffer_line_get_coord_at(const GBufferLine *line, const line_width_summar
 
     /* On cible déjà la colonne idéale */
 
-    count = g_display_options_count(options);
+    col_count = g_width_tracker_count_columns(tracker);
+    opt_count = g_display_options_count(options);
 
-    for (i = 0; i < BLC_COUNT; i++)
+    for (i = 0; i < col_count; i++)
     {
-        if (i < count)
+        if (i < opt_count)
         {
             if (!g_display_options_get(options, i))
                 continue;
@@ -1106,12 +1063,12 @@ bool g_buffer_line_get_coord_at(const GBufferLine *line, const line_width_summar
 
         if (i < line->merge_start)
         {
-            width = g_buffer_line_compute_max_width(line, i, summary, offsets);
+            width = g_width_tracker_get_local_column_width(tracker, index, i, opt_count);
 
             /* 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;
+            if ((i + 1) < col_count) limit = width + COL_MARGIN / 2;
             else limit = width;
 
             if (*offset <= limit) break;
@@ -1140,7 +1097,7 @@ bool g_buffer_line_get_coord_at(const GBufferLine *line, const line_width_summar
 
     /* Si l'abscisse fournie tombe encore dans une colonne... */
 
-    if (i < BLC_COUNT)
+    if (i < col_count)
     {
         /* Il y a bien du contenu dans cette colonne */
 
@@ -1176,11 +1133,11 @@ bool g_buffer_line_get_coord_at(const GBufferLine *line, const line_width_summar
 
                 old_base = *base;
 
-                for (i++; i < BLC_COUNT && !result; i++)
+                for (i++; i < col_count && !result; i++)
                 {
                     if ((i - 1) < line->merge_start)
                     {
-                        width = g_buffer_line_compute_max_width(line, i - 1, summary, offsets);
+                        width = g_width_tracker_get_local_column_width(tracker, index, i - 1, opt_count);
 
                         if (width > 0)
                             *base += (width + COL_MARGIN);
@@ -1208,13 +1165,13 @@ bool g_buffer_line_get_coord_at(const GBufferLine *line, const line_width_summar
 
     }
 
-    else /* if (i == BLC_COUNT) */
+    else /* if (i == col_count) */
     {
         if (force)
         {
  use_right_border:
 
-            if (last != BLC_COUNT)
+            if (last != col_count)
             {
                 result = get_line_column_last_content_index(&line->columns[last], &coord->index);
 
@@ -1237,7 +1194,7 @@ bool g_buffer_line_get_coord_at(const GBufferLine *line, const line_width_summar
                 *base = 0;
                 *offset = 0;
 
-                coord->column = BLC_COUNT;
+                coord->column = col_count;
                 coord->index = -1;
 
             }
@@ -1256,9 +1213,9 @@ bool g_buffer_line_get_coord_at(const GBufferLine *line, const line_width_summar
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : line    = ligne à venir consulter.                           *
-*                summary = résumé des largeurs maximales.                     *
+*                index   = indice de ligne associé.                           *
+*                tracker = gestionnaire de largeur à consulter au besoin.     *
 *                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.      *
@@ -1272,13 +1229,13 @@ bool g_buffer_line_get_coord_at(const GBufferLine *line, const line_width_summar
 *                                                                             *
 ******************************************************************************/
 
-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 *g_buffer_line_get_segment_at(const GBufferLine *line, size_t index, GWidthTracker *tracker, const GDisplayOptions *options, 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);
+    status = g_buffer_line_get_coord_at(line, index, tracker, options, base, offset, dir, force, &coord);
 
     if (status)
         result = g_buffer_line_get_segment_from_coord(line, &coord);
@@ -1293,9 +1250,9 @@ line_segment *g_buffer_line_get_segment_at(const GBufferLine *line, const line_w
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : line    = ligne à venir consulter.                           *
-*                summary = résumé des largeurs maximales.                     *
+*                index   = indice de ligne associé.                           *
+*                tracker = gestionnaire de largeur à consulter au besoin.     *
 *                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.      *
@@ -1309,7 +1266,7 @@ line_segment *g_buffer_line_get_segment_at(const GBufferLine *line, const line_w
 *                                                                             *
 ******************************************************************************/
 
-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 *g_buffer_line_get_creator_at(const GBufferLine *line, size_t index, GWidthTracker *tracker, const GDisplayOptions *options, gint *base, gint *offset, GdkScrollDirection dir, bool force)
 {
     GObject *result;                        /* Trouvaille à retourner      */
     col_coord_t target;                     /* Emplacement du contenu visé */
@@ -1319,7 +1276,7 @@ GObject *g_buffer_line_get_creator_at(const GBufferLine *line, const line_width_
 
     result = NULL;
 
-    status = g_buffer_line_get_coord_at(line, summary, options, offsets, base, offset, dir, force, &target);
+    status = g_buffer_line_get_coord_at(line, index, tracker, options, base, offset, dir, force, &target);
 
     if (status)
     {
@@ -1345,10 +1302,10 @@ GObject *g_buffer_line_get_creator_at(const GBufferLine *line, const line_width_
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : line    = ligne à venir consulter.                           *
+*                index   = indice de ligne associé.                           *
 *                coord   = cordonnées à consulter puis renseigner. [OUT]      *
-*                summary = résumé des largeurs maximales.                     *
+*                tracker = gestionnaire de largeur à consulter au besoin.     *
 *                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] *
 *                                                                             *
@@ -1360,28 +1317,31 @@ GObject *g_buffer_line_get_creator_at(const GBufferLine *line, const line_width_
 *                                                                             *
 ******************************************************************************/
 
-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 g_buffer_line_find_near_coord(const GBufferLine *line, size_t index, col_coord_t *coord, GWidthTracker *tracker, const GDisplayOptions *options, GdkScrollDirection dir, gint *offset)
 {
     bool result;                            /* Bilan à retourner           */
-    size_t count;                           /* Qté de colonnes en option   */
+    size_t col_count;                       /* Qté de colonnes présentes   */
     size_t i;                               /* Boucle de parcours #1       */
+    size_t opt_count;                       /* Qté de colonnes en option   */
     bool displayed;                         /* Confort de lecture          */
     size_t k;                               /* Boucle de parcours #2       */
     gint width;                             /* Largeur d'une colonne donnée*/
 
     result = false;
 
+    col_count = g_width_tracker_count_columns(tracker);
+
     /* Recherche dans la colonne de départ */
 
     i = coord->column;
 
-    if (i == BLC_COUNT) return false;
+    if (i == col_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);
+    opt_count = g_display_options_count(options);
 
     if (!result)
         switch (dir)
@@ -1392,9 +1352,9 @@ bool g_buffer_line_find_near_coord(const GBufferLine *line, col_coord_t *coord,
                 if (i == 0) break;
 
                 /* On s'assure que la colonne précédente est visible et peuplée */
-                for (; i > BLC_FIRST && !result; i--)
+                for (; i > 0 && !result; i--)
                 {
-                    displayed = (i <= count ? g_display_options_get(options, i - 1) : true);
+                    displayed = (i <= opt_count ? g_display_options_get(options, i - 1) : true);
 
                     if (displayed)
                     {
@@ -1412,9 +1372,9 @@ bool g_buffer_line_find_near_coord(const GBufferLine *line, col_coord_t *coord,
             case GDK_SCROLL_RIGHT:
 
                 /* On s'assure que la colonne suivante est visible et peuplée */
-                for (; (i + 1) < BLC_COUNT && !result; i++)
+                for (; (i + 1) < col_count && !result; i++)
                 {
-                    displayed = ((i + 1) < count ? g_display_options_get(options, i + 1) : true);
+                    displayed = ((i + 1) < opt_count ? g_display_options_get(options, i + 1) : true);
 
                     if (displayed)
                     {
@@ -1442,11 +1402,15 @@ bool g_buffer_line_find_near_coord(const GBufferLine *line, col_coord_t *coord,
 
         for (k = 0; k < i; k++)
         {
-            displayed = (k < count ? g_display_options_get(options, k) : true);
+            displayed = (k < opt_count ? g_display_options_get(options, k) : true);
 
             if (displayed)
             {
-                width = g_buffer_line_compute_max_width(line, k, summary, offsets);
+
+                if (k >= line->merge_start)
+                    width = get_column_width(&line->columns[index]);
+                else
+                    width = g_width_tracker_get_local_column_width(tracker, index, k, opt_count);
 
                 if (width > 0)
                 {
@@ -1483,12 +1447,12 @@ bool g_buffer_line_find_near_coord(const GBufferLine *line, col_coord_t *coord,
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : line    = ligne de texte à manipuler.                        *
+*                index   = indice de ligne associé.                           *
 *                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.                    *
+*                tracker = gestionnaire de largeur à consulter au besoin.     *
 *                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.                       *
@@ -1499,12 +1463,13 @@ bool g_buffer_line_find_near_coord(const GBufferLine *line, col_coord_t *coord,
 *                                                                             *
 ******************************************************************************/
 
-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)
+void g_buffer_line_draw(GBufferLine *line, size_t index, cairo_t *cairo, gint x_init, gint y, GWidthTracker *tracker, const GDisplayOptions *options, 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 col_count;                       /* Qté de colonnes présentes   */
+    size_t opt_count;                       /* Qté de colonnes en option   */
     size_t i;                               /* Boucle de parcours          */
     gint max_width;                         /* Largeur maximale de colonne */
 
@@ -1532,11 +1497,12 @@ void g_buffer_line_draw(GBufferLine *line, cairo_t *cairo, const line_width_summ
 
     x = x_init;
 
-    count = g_display_options_count(options);
+    col_count = g_width_tracker_count_columns(tracker);
+    opt_count = g_display_options_count(options);
 
-    for (i = 0; i < BLC_COUNT; i++)
+    for (i = 0; i < col_count; i++)
     {
-        if (i < count)
+        if (i < opt_count)
         {
             if (!g_display_options_get(options, i))
                 continue;
@@ -1546,7 +1512,7 @@ void g_buffer_line_draw(GBufferLine *line, cairo_t *cairo, const line_width_summ
 
         if (i < line->merge_start)
         {
-            max_width = g_buffer_line_compute_max_width(line, i, summary, offsets);
+            max_width = g_width_tracker_get_local_column_width(tracker, index, i, opt_count);
 
             if (max_width > 0)
                 x += max_width + COL_MARGIN;
diff --git a/src/glibext/bufferline.h b/src/glibext/bufferline.h
index 95db203..a7982d0 100644
--- a/src/glibext/bufferline.h
+++ b/src/glibext/bufferline.h
@@ -31,6 +31,7 @@
 
 #include "gdisplayoptions.h"
 #include "linesegment.h"
+#include "widthtracker.h"
 #include "../analysis/content.h"
 #include "../arch/vmpa.h"
 
@@ -172,14 +173,6 @@ void g_buffer_line_export(GBufferLine *, buffer_export_context *, BufferExportTy
 /* ----------------------- 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
 {
@@ -192,26 +185,23 @@ typedef struct _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 *);
+bool g_buffer_line_get_coord_at(const GBufferLine *, size_t, GWidthTracker *, const GDisplayOptions *, 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);
+line_segment *g_buffer_line_get_segment_at(const GBufferLine *, size_t, GWidthTracker *, const GDisplayOptions *, 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);
+GObject *g_buffer_line_get_creator_at(const GBufferLine *, size_t, GWidthTracker *, const GDisplayOptions *, 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 *);
+bool g_buffer_line_find_near_coord(const GBufferLine *, size_t, col_coord_t *, GWidthTracker *, const GDisplayOptions *, GdkScrollDirection, gint *);
 
 /* Imprime la ligne de texte représentée. */
-void g_buffer_line_draw(GBufferLine *, cairo_t *, const line_width_summary *, gint, gint, const GDisplayOptions *, const line_width_summary *, const segcnt_list *);
+void g_buffer_line_draw(GBufferLine *, size_t, cairo_t *, gint, gint, GWidthTracker *, const GDisplayOptions *, const segcnt_list *);
 
 
 
diff --git a/src/glibext/bufferview.c b/src/glibext/bufferview.c
index e40715e..769cd8b 100644
--- a/src/glibext/bufferview.c
+++ b/src/glibext/bufferview.c
@@ -76,10 +76,10 @@ static void g_buffer_view_finalize(GBufferView *);
 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 **);
+static bool _g_buffer_view_compute_caret_full(GBufferView *, gint, GBufferLine *, size_t, const GDisplayOptions *, 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 *);
+static bool _g_buffer_view_move_caret(GBufferView *, const GBufferLine *, size_t, cairo_rectangle_int_t *, bool, GdkScrollDirection, const GDisplayOptions *);
 
 
 /* Fournit la ligne présente à une ordonnée donnée. */
@@ -598,7 +598,6 @@ gint g_buffer_view_get_height(const GBufferView *view)
 *                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]  *
 *                                                                             *
@@ -610,7 +609,7 @@ gint g_buffer_view_get_height(const GBufferView *view)
 *                                                                             *
 ******************************************************************************/
 
-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 g_buffer_view_compute_caret_full(GBufferView *view, gint x, gint y, const GDisplayOptions *options, cairo_rectangle_int_t *caret, GLineCursor **cursor)
 {
     bool result;                            /* Bilan à retourner           */
     gint lheight;                           /* Hauteur d'une ligne         */
@@ -635,7 +634,7 @@ bool g_buffer_view_compute_caret_full(GBufferView *view, gint x, gint y, const G
 
     /* Calcul d'une position */
 
-    result = _g_buffer_view_compute_caret_full(view, x, line, index, options, offsets, caret, cursor);
+    result = _g_buffer_view_compute_caret_full(view, x, line, index, options, caret, cursor);
 
     g_object_unref(G_OBJECT(line));
 
@@ -653,7 +652,6 @@ bool g_buffer_view_compute_caret_full(GBufferView *view, gint x, gint y, const G
 *                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]  *
 *                                                                             *
@@ -665,11 +663,10 @@ bool g_buffer_view_compute_caret_full(GBufferView *view, gint x, gint y, const G
 *                                                                             *
 ******************************************************************************/
 
-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)
+static bool _g_buffer_view_compute_caret_full(GBufferView *view, gint x, GBufferLine *line, size_t index, const GDisplayOptions *options, 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         */
@@ -685,11 +682,9 @@ bool _g_buffer_view_compute_caret_full(GBufferView *view, gint x, GBufferLine *l
 
     /* 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,
+    status = g_buffer_line_get_coord_at(line, index, view->tracker, options, &base, &x,
                                         GDK_SCROLL_LEFT, true, (col_coord_t []) { { 0 } });
 
     if (!status)
@@ -726,7 +721,6 @@ bool _g_buffer_view_compute_caret_full(GBufferView *view, gint x, GBufferLine *l
 *                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.              *
 *                                                                             *
@@ -736,12 +730,11 @@ bool _g_buffer_view_compute_caret_full(GBufferView *view, gint x, GBufferLine *l
 *                                                                             *
 ******************************************************************************/
 
-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)
+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)
 {
     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      */
@@ -758,11 +751,9 @@ static bool _g_buffer_view_move_caret(GBufferView *view, const GBufferLine *line
 
     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);
+    result = g_buffer_line_get_coord_at(line, index, view->tracker, options, &base, &offset, dir, false, &coord);
 
     if (result)
     {
@@ -780,7 +771,7 @@ static bool _g_buffer_view_move_caret(GBufferView *view, const GBufferLine *line
     {
         base = 0;
 
-        result = g_buffer_line_find_near_coord(line, &coord, &summary, options, offsets, dir, &offset);
+        result = g_buffer_line_find_near_coord(line, index, &coord, view->tracker, options, dir, &offset);
 
     }
 
@@ -802,7 +793,6 @@ static bool _g_buffer_view_move_caret(GBufferView *view, const GBufferLine *line
 *                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]  *
 *                                                                             *
@@ -814,7 +804,7 @@ static bool _g_buffer_view_move_caret(GBufferView *view, const GBufferLine *line
 *                                                                             *
 ******************************************************************************/
 
-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 g_buffer_view_move_caret(GBufferView *view, bool ctrl, GdkScrollDirection dir, const GDisplayOptions *options, cairo_rectangle_int_t *caret, GLineCursor **cursor)
 {
     bool result;                            /* Bilan à retourner           */
     size_t index;                           /* Indice de ligne de tampon   */
@@ -844,8 +834,7 @@ bool g_buffer_view_move_caret(GBufferView *view, bool ctrl, GdkScrollDirection d
                 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);
+                result = _g_buffer_view_compute_caret_full(view, caret->x, other, index, options, caret, cursor);
 
                 g_object_unref(G_OBJECT(other));
 
@@ -862,8 +851,7 @@ bool g_buffer_view_move_caret(GBufferView *view, bool ctrl, GdkScrollDirection d
                 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);
+                result = _g_buffer_view_compute_caret_full(view, caret->x, other, index, options, caret, cursor);
 
                 g_object_unref(G_OBJECT(other));
 
@@ -873,7 +861,7 @@ bool g_buffer_view_move_caret(GBufferView *view, bool ctrl, GdkScrollDirection d
 
         case GDK_SCROLL_LEFT:
 
-            moved = _g_buffer_view_move_caret(view, line, index, caret, ctrl, GDK_SCROLL_LEFT, options, offsets);
+            moved = _g_buffer_view_move_caret(view, line, index, caret, ctrl, GDK_SCROLL_LEFT, options);
 
             if (moved)
             {
@@ -888,8 +876,7 @@ bool g_buffer_view_move_caret(GBufferView *view, bool ctrl, GdkScrollDirection d
                 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);
+                result = _g_buffer_view_compute_caret_full(view, INT_MAX, other, index, options, caret, cursor);
 
                 g_object_unref(G_OBJECT(other));
 
@@ -899,7 +886,7 @@ bool g_buffer_view_move_caret(GBufferView *view, bool ctrl, GdkScrollDirection d
 
         case GDK_SCROLL_RIGHT:
 
-            moved = _g_buffer_view_move_caret(view, line, index, caret, ctrl, GDK_SCROLL_RIGHT, options, offsets);
+            moved = _g_buffer_view_move_caret(view, line, index, caret, ctrl, GDK_SCROLL_RIGHT, options);
 
             if (moved)
             {
@@ -916,8 +903,7 @@ bool g_buffer_view_move_caret(GBufferView *view, bool ctrl, GdkScrollDirection d
                 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);
+                result = _g_buffer_view_compute_caret_full(view, text_pos, other, index, options, caret, cursor);
 
                 g_object_unref(G_OBJECT(other));
 
@@ -951,7 +937,6 @@ bool g_buffer_view_move_caret(GBufferView *view, bool ctrl, GdkScrollDirection d
 *                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é.       *
 *                                                                             *
@@ -961,14 +946,13 @@ bool g_buffer_view_move_caret(GBufferView *view, bool ctrl, GdkScrollDirection d
 *                                                                             *
 ******************************************************************************/
 
-GObject *g_buffer_view_find_creator(GBufferView *view, gint x, gint y, const GDisplayOptions *options, const line_width_summary *offsets)
+GObject *g_buffer_view_find_creator(GBufferView *view, gint x, gint y, const GDisplayOptions *options)
 {
     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;
 
@@ -995,11 +979,9 @@ GObject *g_buffer_view_find_creator(GBufferView *view, gint x, gint y, const GDi
 
     /* 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,
+    result = g_buffer_line_get_creator_at(line, index, view->tracker, options,
                                           (gint []) { 0 }, &x, GDK_SCROLL_LEFT, false);
 
     g_object_unref(G_OBJECT(line));
@@ -1046,7 +1028,6 @@ bool g_buffer_view_unhighlight_segments(GBufferView *view)
 *                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.*
 *                                                                             *
@@ -1056,14 +1037,13 @@ bool g_buffer_view_unhighlight_segments(GBufferView *view)
 *                                                                             *
 ******************************************************************************/
 
-bool g_buffer_view_highlight_segments(GBufferView *view, gint x, gint y, const GDisplayOptions *options, const line_width_summary *offsets)
+bool g_buffer_view_highlight_segments(GBufferView *view, gint x, gint y, const GDisplayOptions *options)
 {
     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 */
@@ -1096,11 +1076,9 @@ bool g_buffer_view_highlight_segments(GBufferView *view, gint x, gint y, const G
 
     /* 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,
+    segment = g_buffer_line_get_segment_at(line, index, view->tracker, options,
                                            (gint []) { 0 }, &x, GDK_SCROLL_LEFT, true);
 
     g_object_unref(G_OBJECT(line));
@@ -1130,7 +1108,6 @@ bool g_buffer_view_highlight_segments(GBufferView *view, gint x, gint y, const G
 *                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.     *
@@ -1143,7 +1120,7 @@ bool g_buffer_view_highlight_segments(GBufferView *view, gint x, gint y, const G
 *                                                                             *
 ******************************************************************************/
 
-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)
+void g_buffer_view_draw(const GBufferView *view, cairo_t *cr, gint virt_y, const cairo_rectangle_int_t *area, const GDisplayOptions *options, gint *selected, double scale, bool export)
 {
     gint line_height;                       /* Hauteur d'une ligne         */
     gint cr_y;                              /* Ordonnée pour le dessin     */
@@ -1186,7 +1163,7 @@ void g_buffer_view_draw(const GBufferView *view, cairo_t *cr, gint virt_y, const
     else
         highlighted = view->highlighted;
 
-    g_buffer_cache_draw(view->cache, cr, first, last, area, options, offsets, selected, highlighted);
+    g_buffer_cache_draw(view->cache, cr, first, last, area, options, selected, highlighted);
 
     if (export)
         unref_segment_content_list(highlighted);
diff --git a/src/glibext/bufferview.h b/src/glibext/bufferview.h
index 01da713..43e6293 100644
--- a/src/glibext/bufferview.h
+++ b/src/glibext/bufferview.h
@@ -79,15 +79,15 @@ 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 **);
+bool g_buffer_view_compute_caret_full(GBufferView *, gint, gint, const GDisplayOptions *, 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 **);
+bool g_buffer_view_move_caret(GBufferView *, bool, GdkScrollDirection, const GDisplayOptions *, 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 *);
+GObject *g_buffer_view_find_creator(GBufferView *, gint, gint, const GDisplayOptions *);
 
 
 
@@ -95,10 +95,10 @@ GObject *g_buffer_view_find_creator(GBufferView *, gint, gint, const GDisplayOpt
 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 *);
+bool g_buffer_view_highlight_segments(GBufferView *, gint, gint, const GDisplayOptions *);
 
 /* 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);
+void g_buffer_view_draw(const GBufferView *, cairo_t *, gint, const cairo_rectangle_int_t *, const GDisplayOptions *, gint *, double, bool);
 
 
 
diff --git a/src/glibext/generators/hex.c b/src/glibext/generators/hex.c
index b261f36..f08d3fb 100644
--- a/src/glibext/generators/hex.c
+++ b/src/glibext/generators/hex.c
@@ -33,6 +33,7 @@
 #include "../linegen-int.h"
 #include "../linesegment.h"
 #include "../../core/params.h"
+#include "../../gtkext/hexdisplay.h"
 
 
 
@@ -504,9 +505,9 @@ static void g_hex_generator_print(GHexGenerator *generator, GBufferLine *line, s
         if (i > 0)
         {
             if (i % 4 == 0)
-                g_buffer_line_append_text(line, BLC_BINARY, "\t", 1, RTT_RAW, NULL);
+                g_buffer_line_append_text(line, HLC_BINARY, "\t", 1, RTT_RAW, NULL);
             else
-                g_buffer_line_append_text(line, BLC_BINARY, " ", 1, RTT_RAW, NULL);
+                g_buffer_line_append_text(line, HLC_BINARY, " ", 1, RTT_RAW, NULL);
         }
 
         /* Binaire brut */
@@ -514,26 +515,26 @@ static void g_hex_generator_print(GHexGenerator *generator, GBufferLine *line, s
         byte = raw[i];
 
         if (byte == 0x00)
-            g_buffer_line_append_text(line, BLC_BINARY, "00", 2, RTT_RAW_NULL, NULL);
+            g_buffer_line_append_text(line, HLC_BINARY, "00", 2, RTT_RAW_NULL, NULL);
 
         else if (byte == 0xff)
-            g_buffer_line_append_text(line, BLC_BINARY, ff, 2, RTT_RAW_FULL, NULL);
+            g_buffer_line_append_text(line, HLC_BINARY, ff, 2, RTT_RAW_FULL, NULL);
 
         else
         {
             tmp[1] = hexa[byte & 0xf];
             tmp[0] = hexa[(byte >> 4) & 0xf];
 
-            g_buffer_line_append_text(line, BLC_BINARY, tmp, 2, RTT_RAW, NULL);
+            g_buffer_line_append_text(line, HLC_BINARY, tmp, 2, RTT_RAW, NULL);
 
         }
 
         /* Représentation humaine ? */
 
         if (isgraph(byte) || byte == ' ')
-            g_buffer_line_append_text(line, BLC_ASSEMBLY, (char *)raw + i, 1, RTT_PRINTABLE, NULL);
+            g_buffer_line_append_text(line, HLC_TRANSLATION, (char *)raw + i, 1, RTT_PRINTABLE, NULL);
         else
-            g_buffer_line_append_text(line, BLC_ASSEMBLY, ".", 1, RTT_NOT_PRINTABLE, NULL);
+            g_buffer_line_append_text(line, HLC_TRANSLATION, ".", 1, RTT_NOT_PRINTABLE, NULL);
 
     }
 
diff --git a/src/glibext/widthtracker.c b/src/glibext/widthtracker.c
index 274b53c..8ecaad0 100644
--- a/src/glibext/widthtracker.c
+++ b/src/glibext/widthtracker.c
@@ -122,10 +122,13 @@ struct _GWidthTracker
     GObject parent;                         /* A laisser en premier        */
 
     GBufferCache *cache;                    /* Ensemble complet de lignes  */
+    size_t col_count;                       /* Nombre maximum de colonnes  */
 
     common_metrics *portions;               /* Portions représentées       */
     size_t count;                           /* Quantité de ces portions    */
 
+    gint *min_widths;                       /* Largeurs min. à respecter   */
+
     line_width_summary summary;             /* Largeurs requises suivies   */
     bool cached;                            /* Mise en cache des calculs   */
 
@@ -457,6 +460,9 @@ static void g_width_tracker_dispose(GWidthTracker *tracker)
 
 static void g_width_tracker_finalize(GWidthTracker *tracker)
 {
+    if (tracker->min_widths != NULL)
+        free(tracker->min_widths);
+
     G_OBJECT_CLASS(g_width_tracker_parent_class)->finalize(G_OBJECT(tracker));
 
 }
@@ -464,9 +470,8 @@ static void g_width_tracker_finalize(GWidthTracker *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.    *
+*  Paramètres  : cache     = tampon de lignes à lier au futur élément.        *
+*                col_count = quantité maximale de colonnes à considérer.      *
 *                                                                             *
 *  Description : Crée un nouveau suivi de largeurs au sein de lignes.         *
 *                                                                             *
@@ -476,7 +481,7 @@ static void g_width_tracker_finalize(GWidthTracker *tracker)
 *                                                                             *
 ******************************************************************************/
 
-GWidthTracker *g_width_tracker_new(GBufferCache *cache)
+GWidthTracker *g_width_tracker_new(GBufferCache *cache, size_t col_count)
 {
     GWidthTracker *result;                  /* Composant à retourner       */
 
@@ -485,6 +490,10 @@ GWidthTracker *g_width_tracker_new(GBufferCache *cache)
     g_object_ref(G_OBJECT(cache));
     result->cache = cache;
 
+    result->col_count = col_count;
+
+    result->min_widths = calloc(col_count, sizeof(gint));
+
     return result;
 
 }
@@ -516,6 +525,8 @@ GWidthTracker *g_width_tracker_new_restricted(const GWidthTracker *template, siz
     g_object_ref(G_OBJECT(template->cache));
     result->cache = template->cache;
 
+    result->col_count = template->col_count;
+
     start = g_width_tracker_find_metrics(template, first);
     assert(start < template->count);
 
@@ -523,7 +534,7 @@ GWidthTracker *g_width_tracker_new_restricted(const GWidthTracker *template, siz
     assert(end < template->count);
 
     result->count = end - start + 1;
-    result->portions = (common_metrics *)calloc(result->count, sizeof(common_metrics));
+    result->portions = calloc(result->count, sizeof(common_metrics));
 
     for (i = 0; i < result->count; i++)
         memcpy(&result->portions[i], &template->portions[start + i], sizeof(common_metrics));
@@ -540,6 +551,34 @@ GWidthTracker *g_width_tracker_new_restricted(const GWidthTracker *template, siz
         g_width_tracker_reset_widths(result, result->count - 1);
     }
 
+    result->min_widths = calloc(template->col_count, sizeof(gint));
+
+    for (i = 0; i < template->col_count; i++)
+        result->min_widths[i] = template->min_widths[i];
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : tracker = gestionnaire de largeurs de lignes à consulter.    *
+*                                                                             *
+*  Description : Indique le nombre de colonnes prises en compte.              *
+*                                                                             *
+*  Retour      : Quantité normalement strictement positive.                   *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+size_t g_width_tracker_count_columns(const GWidthTracker *tracker)
+{
+    size_t result;                          /* Quantité à retourner        */
+
+    result = tracker->col_count;
+
     return result;
 
 }
@@ -547,6 +586,29 @@ GWidthTracker *g_width_tracker_new_restricted(const GWidthTracker *template, siz
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : tracker = gestionnaire de largeurs de lignes à mettre jour.  *
+*                col     = indice de colonne visée.                           *
+*                width   = largeur minimale à imposer.                        *
+*                                                                             *
+*  Description : Impose une largeur minimale pour une colonne donnée.         *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_width_tracker_set_column_min_width(GWidthTracker *tracker, size_t col, gint width)
+{
+    assert(col < tracker->col_count);
+
+    tracker->min_widths[col] = width;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : tracker = gestionnaire de suivi à consulter.                 *
 *                index   = indice d'une ligne dont la portion est inconnue.   *
 *                                                                             *
@@ -761,7 +823,7 @@ void g_width_tracker_update_added(GWidthTracker *tracker, size_t index, size_t c
     {
         assert(index == 0);
 
-        tracker->portions = (common_metrics *)calloc(1, sizeof(common_metrics));
+        tracker->portions = calloc(1, sizeof(common_metrics));
         tracker->count = 1;
 
         tracker->portions[0].first = 0;
@@ -805,8 +867,7 @@ void g_width_tracker_update_added(GWidthTracker *tracker, size_t index, size_t c
 
             tracker->count++;
 
-            tracker->portions = (common_metrics *)realloc(tracker->portions,
-                                                          tracker->count * sizeof(common_metrics));
+            tracker->portions = realloc(tracker->portions, tracker->count * sizeof(common_metrics));
 
             portion = &tracker->portions[current];
 
@@ -910,8 +971,7 @@ void g_width_tracker_update_deleted(GWidthTracker *tracker, size_t start, size_t
 
         tracker->count -= (src - dest);
 
-        tracker->portions = (common_metrics *)realloc(tracker->portions,
-                                                      tracker->count * sizeof(common_metrics));
+        tracker->portions = realloc(tracker->portions, tracker->count * sizeof(common_metrics));
 
     }
 
@@ -927,8 +987,7 @@ void g_width_tracker_update_deleted(GWidthTracker *tracker, size_t start, size_t
 
         tracker->count--;
 
-        tracker->portions = (common_metrics *)realloc(tracker->portions,
-                                                      tracker->count * sizeof(common_metrics));
+        tracker->portions = realloc(tracker->portions, tracker->count * sizeof(common_metrics));
 
         keep_last = false;
 
@@ -1002,7 +1061,7 @@ void g_width_tracker_build_initial_cache(GWidthTracker *tracker, wgroup_id_t gid
 
     run_size = compute_run_size(tracker->count, &runs_count);
 
-    updates = (GWidthUpdate **)calloc(runs_count, sizeof(GWidthUpdate *));
+    updates = calloc(runs_count, sizeof(GWidthUpdate *));
 
     queue = get_work_queue();
 
@@ -1101,27 +1160,6 @@ static void g_width_tracker_ensure_valid_required_widths(GWidthTracker *tracker)
 /******************************************************************************
 *                                                                             *
 *  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]       *
 *                                                                             *
@@ -1269,3 +1307,52 @@ gint g_width_tracker_get_margin(GWidthTracker *tracker, const GDisplayOptions *o
     return result;
 
 }
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : tracker   = suivi de largeurs à consulter.                   *
+*                index     = indice de la ligne dont la portion est visée.    *
+*                col       = indice de la colonne visée par l'opération.      *
+*                opt_count = quantité de colonnes initiales en options.       *
+*                                                                             *
+*  Description : Indique la largeur locale d'une colonne donnée.              *
+*                                                                             *
+*  Retour      : Taille positive ou nulle.                                    *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+gint g_width_tracker_get_local_column_width(GWidthTracker *tracker, size_t index, size_t col, size_t opt_count)
+{
+    gint result;                            /* Largeur à retourner         */
+    size_t current;                         /* Indice de portion visée     */
+    const line_width_summary *local;        /* Valeurs à intégrer          */
+
+    g_width_tracker_ensure_valid_required_widths(tracker);
+
+    assert(col < tracker->col_count);
+
+    if (col < opt_count)
+    {
+        assert(opt_count < tracker->col_count);
+        result = tracker->summary.max_widths[col];
+    }
+
+    else
+    {
+        current = g_width_tracker_find_metrics(tracker, index);
+        assert(current < tracker->count);
+
+        local = g_width_tracker_get_up_to_date_widths(tracker, current);
+
+        result = local->max_widths[col];
+
+    }
+
+    result = MAX(result, tracker->min_widths[col]);
+
+    return result;
+
+}
diff --git a/src/glibext/widthtracker.h b/src/glibext/widthtracker.h
index b7bb8a4..82442ae 100644
--- a/src/glibext/widthtracker.h
+++ b/src/glibext/widthtracker.h
@@ -29,12 +29,23 @@
 #include <stdbool.h>
 
 
-#include "bufferline.h"
+//#include "bufferline.h"
 #include "delayed.h"
 #include "gdisplayoptions.h"
 
 
 
+
+/* Mémorisation des largeurs pour un groupe de lignes */
+typedef struct _line_width_summary
+{
+    gint max_widths[10/*BLC_COUNT*/];             /* Taille cachée des colonnes  */
+    gint merged_width;                      /* Largeur cumulée avant fusion*/
+
+} line_width_summary;
+
+
+
 /* ---------------------------- RASSEMBLEMENT DE MESURES ---------------------------- */
 
 
@@ -61,11 +72,17 @@ typedef struct _GWidthTrackerClass GWidthTrackerClass;
 GType g_width_tracker_get_type(void);
 
 /* Crée un nouveau suivi de largeurs au sein de lignes. */
-GWidthTracker *g_width_tracker_new(GBufferCache *);
+GWidthTracker *g_width_tracker_new(GBufferCache *, size_t);
 
 /* Crée un nouveau suivi de largeurs au sein de lignes. */
 GWidthTracker *g_width_tracker_new_restricted(const GWidthTracker *, size_t, size_t);
 
+/* Indique le nombre de colonnes prises en compte. */
+size_t g_width_tracker_count_columns(const GWidthTracker *);
+
+/* Impose une largeur minimale pour une colonne donnée. */
+void g_width_tracker_set_column_min_width(GWidthTracker *, size_t, gint);
+
 /* Prend acte d'un changement sur une ligne pour les largeurs. */
 void g_width_tracker_update(GWidthTracker *, size_t);
 
@@ -78,9 +95,6 @@ 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 *);
 
@@ -90,6 +104,9 @@ 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 *);
 
+/* Indique la largeur locale d'une colonne donnée. */
+gint g_width_tracker_get_local_column_width(GWidthTracker *, size_t, size_t, size_t);
+
 
 
 #endif  /* _GLIBEXT_WIDTHTRACKER_H */
diff --git a/src/gtkext/gtkblockdisplay.c b/src/gtkext/gtkblockdisplay.c
index b53f59d..f34df3c 100644
--- a/src/gtkext/gtkblockdisplay.c
+++ b/src/gtkext/gtkblockdisplay.c
@@ -264,9 +264,7 @@ static gboolean gtk_block_display_button_press(GtkWidget *widget, GdkEventButton
 
         view = gtk_buffer_display_get_view(GTK_BUFFER_DISPLAY(display));
 
-        changed = g_buffer_view_highlight_segments(view, real_x, real_y,
-                                                   GTK_DISPLAY_PANEL(display)->options,
-                                                   &GTK_BUFFER_DISPLAY(display)->offsets);
+        changed = g_buffer_view_highlight_segments(view, real_x, real_y, GTK_DISPLAY_PANEL(display)->options);
 
         g_object_unref(G_OBJECT(view));
 
@@ -317,8 +315,7 @@ static gboolean gtk_block_display_query_tooltip(GtkWidget *widget, gint x, gint
     real_y = y;
     gtk_display_panel_compute_real_coord(panel, &real_x, &real_y);
 
-    creator = g_buffer_view_find_creator(GTK_BUFFER_DISPLAY(display)->view, real_x, real_y,
-                                         panel->options, &GTK_BUFFER_DISPLAY(display)->offsets);
+    creator = g_buffer_view_find_creator(GTK_BUFFER_DISPLAY(display)->view, real_x, real_y, panel->options);
 
     if (creator != NULL)
     {
@@ -391,9 +388,7 @@ static bool gtk_block_display_notify_caret_relocation(GtkBlockDisplay *display,
 
     view = gtk_buffer_display_get_view(GTK_BUFFER_DISPLAY(display));
 
-    result = g_buffer_view_highlight_segments(view, area->x, area->y,
-                                              GTK_DISPLAY_PANEL(display)->options,
-                                              &GTK_BUFFER_DISPLAY(display)->offsets);
+    result = g_buffer_view_highlight_segments(view, area->x, area->y, GTK_DISPLAY_PANEL(display)->options);
 
     g_object_unref(G_OBJECT(view));
 
@@ -421,13 +416,21 @@ static bool gtk_block_display_notify_caret_relocation(GtkBlockDisplay *display,
 void gtk_block_display_override_view_index(GtkBlockDisplay *display, unsigned int index)
 {
     GtkDisplayPanel *panel;                 /* Version de plus haut niveau */
+    GBufferCache *cache;                    /* Tampon de données affiché   */
+    GWidthTracker *tracker;                 /* Gestionnaire de largeurs    */
 
     panel = GTK_DISPLAY_PANEL(display);
 
     panel->view_index = index;
     panel->options = g_loaded_content_get_display_options(G_LOADED_CONTENT(panel->binary), index);
 
-    GTK_BUFFER_DISPLAY(display)->offsets.max_widths[BLC_ASSEMBLY_LABEL] = 0;
+    cache = g_buffer_view_get_cache(GTK_BUFFER_DISPLAY(display)->view);
+
+    tracker = g_buffer_cache_get_width_tracker(cache);
+    g_width_tracker_set_column_min_width(tracker, BLC_ASSEMBLY_LABEL, 0);
+    g_object_unref(G_OBJECT(tracker));
+
+    g_object_unref(G_OBJECT(cache));
 
     gtk_buffer_display_add_block_bar(GTK_BUFFER_DISPLAY(display));
 
diff --git a/src/gtkext/gtkblockdisplay.h b/src/gtkext/gtkblockdisplay.h
index 2effb9b..196fe2e 100644
--- a/src/gtkext/gtkblockdisplay.h
+++ b/src/gtkext/gtkblockdisplay.h
@@ -33,12 +33,12 @@
 
 
 
-#define GTK_TYPE_BLOCK_DISPLAY              (gtk_block_display_get_type())
-#define GTK_BLOCK_DISPLAY(obj)              (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_BLOCK_DISPLAY, GtkBlockDisplay))
-#define GTK_BLOCK_DISPLAY_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST((klass), GTK_TYPE_BLOCK_DISPLAY, GtkBlockDisplayClass))
-#define GTK_IS_BLOCK_DISPLAY(obj)           (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_BLOCK_DISPLAY))
-#define GTK_IS_BLOCK_DISPLAY_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE((klass), GTK_TYPE_BLOCK_DISPLAY))
-#define GTK_BLOCK_DISPLAY_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_BLOCK_DISPLAY, GtkBlockDisplayClass))
+#define GTK_TYPE_BLOCK_DISPLAY            (gtk_block_display_get_type())
+#define GTK_BLOCK_DISPLAY(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_BLOCK_DISPLAY, GtkBlockDisplay))
+#define GTK_BLOCK_DISPLAY_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), GTK_TYPE_BLOCK_DISPLAY, GtkBlockDisplayClass))
+#define GTK_IS_BLOCK_DISPLAY(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_BLOCK_DISPLAY))
+#define GTK_IS_BLOCK_DISPLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GTK_TYPE_BLOCK_DISPLAY))
+#define GTK_BLOCK_DISPLAY_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_BLOCK_DISPLAY, GtkBlockDisplayClass))
 
 
 /* Composant d'affichage de code d'assembleur (instance) */
@@ -48,6 +48,22 @@ typedef struct _GtkBlockDisplay GtkBlockDisplay;
 typedef struct _GtkBlockDisplayClass GtkBlockDisplayClass;
 
 
+/* Désignation des colonnes d'une ligne */
+typedef enum _DisassLineColumn
+{
+    DLC_PHYSICAL,                           /* Position physique           */
+    DLC_VIRTUAL,                            /* Adresse virtuelle           */
+    DLC_BINARY,                             /* Contenu sous forme binaire  */
+    DLC_ASSEMBLY_LABEL,                     /* Etiquette dans les données  */
+    DLC_ASSEMBLY_HEAD,                      /* Instruction pour assembleur */
+    DLC_ASSEMBLY,                           /* Code pour assembleur        */
+    DLC_COMMENTS,                           /* Commentaires éventuels      */
+
+    DLC_COUNT,
+
+} DisassLineColumn;
+
+
 /* Détermine le type du composant d'affichage de bloc en langage d'assemblage. */
 GType gtk_block_display_get_type(void);
 
diff --git a/src/gtkext/gtkbufferdisplay-int.h b/src/gtkext/gtkbufferdisplay-int.h
index 9fc8331..d02aa37 100644
--- a/src/gtkext/gtkbufferdisplay-int.h
+++ b/src/gtkext/gtkbufferdisplay-int.h
@@ -42,7 +42,6 @@ struct _GtkBufferDisplay
     GtkDisplayPanel parent;                 /* A laisser en premier        */
 
     GBufferView *view;                      /* Vue sur le contenu affiché  */
-    line_width_summary offsets;             /* Décalages supplémentaires   */
 
     cairo_rectangle_int_t caret;            /* Emplacement du curseur #1   */
     GLineCursor *cursor;                    /* Emplacement du curseur #2   */
diff --git a/src/gtkext/gtkbufferdisplay.c b/src/gtkext/gtkbufferdisplay.c
index eec0e5b..e419125 100644
--- a/src/gtkext/gtkbufferdisplay.c
+++ b/src/gtkext/gtkbufferdisplay.c
@@ -28,8 +28,6 @@
 
 
 #include "gtkbufferdisplay-int.h"
-
-
 #include "../core/params.h"
 #include "../glibext/gbinarycursor.h" // REMME
 
@@ -215,13 +213,6 @@ static void gtk_buffer_display_class_init(GtkBufferDisplayClass *class)
 
 static void gtk_buffer_display_init(GtkBufferDisplay *display)
 {
-    int offset;                             /* Décalage des étiquettes     */
-
-    memset(&display->offsets, 0, sizeof(line_width_summary));
-
-    g_generic_config_get_value(get_main_configuration(), MPK_LABEL_OFFSET, &offset);
-    display->offsets.max_widths[BLC_ASSEMBLY_LABEL] = offset;
-
     display->cursor = NULL;
 
 }
@@ -522,7 +513,7 @@ static gboolean gtk_buffer_display_draw(GtkWidget *widget, cairo_t *cr)
         area.x -= virt_x;
         virt_y += area.y;
 
-        g_buffer_view_draw(display->view, cr, virt_y, &area, parent->options, &display->offsets,
+        g_buffer_view_draw(display->view, cr, virt_y, &area, parent->options,
                            selected, parent->scale, parent->export);
 
     }
@@ -613,8 +604,7 @@ static gboolean gtk_buffer_display_key_press(GtkWidget *widget, GdkEventKey *eve
         ctrl = (event->state & GDK_CONTROL_MASK);
         area = display->caret;
 
-        status = g_buffer_view_move_caret(display->view, ctrl, dir, panel->options, &display->offsets,
-                                          &area, &cursor);
+        status = g_buffer_view_move_caret(display->view, ctrl, dir, panel->options, &area, &cursor);
 
         if (status)
         {
@@ -828,8 +818,7 @@ GObject *gtk_buffer_display_get_active_object(const GtkBufferDisplay *display)
     else
         result = g_buffer_view_find_creator(display->view,
                                             display->caret.x, display->caret.y,
-                                            GTK_DISPLAY_PANEL(display)->options,
-                                            &display->offsets);
+                                            GTK_DISPLAY_PANEL(display)->options);
 
     return result;
 
@@ -996,8 +985,7 @@ static bool _gtk_buffer_display_move_caret_to(GtkBufferDisplay *display, gint x,
 
     panel = GTK_DISPLAY_PANEL(display);
 
-    result = g_buffer_view_compute_caret_full(display->view, x, y, panel->options, &display->offsets,
-                                              &new, &cursor);
+    result = g_buffer_view_compute_caret_full(display->view, x, y, panel->options, &new, &cursor);
 
     if (result)
         gtk_buffer_display_relocate_caret(display, &new, cursor);
diff --git a/src/gtkext/hexdisplay.c b/src/gtkext/hexdisplay.c
index 0f0bd30..cf1f600 100644
--- a/src/gtkext/hexdisplay.c
+++ b/src/gtkext/hexdisplay.c
@@ -25,6 +25,7 @@
 
 
 #include "gtkbufferdisplay-int.h"
+#include "../core/params.h"
 #include "../format/format.h"
 #include "../glibext/generators/hex.h"
 
@@ -185,12 +186,20 @@ GtkWidget *gtk_hex_display_new(GBinContent *content)
 {
     GtkHexDisplay *result;                  /* Composant à retourner       */
     GBufferView *view;                      /* Vue pointée sur un tampon   */
+    int padding;                            /* Bourrage entre colonnes     */
+    GWidthTracker *tracker;                 /* Gestionnaire de largeurs    */
 
     result = g_object_new(GTK_TYPE_HEX_DISPLAY, NULL);
 
-    result->cache = g_buffer_cache_new(content);
+    result->cache = g_buffer_cache_new(content, HLC_COUNT);
     g_object_ref_sink(G_OBJECT(result->cache));
 
+    g_generic_config_get_value(get_main_configuration(), MPK_HEX_PADDING, &padding);
+
+    tracker = g_buffer_cache_get_width_tracker(result->cache);
+    g_width_tracker_set_column_min_width(tracker, HLC_PADDING, padding);
+    g_object_unref(G_OBJECT(tracker));
+
     result->generator = g_hex_generator_new(content);
 
     gtk_hex_display_populate_cache(result);
diff --git a/src/gtkext/hexdisplay.h b/src/gtkext/hexdisplay.h
index 9190548..45a1da9 100644
--- a/src/gtkext/hexdisplay.h
+++ b/src/gtkext/hexdisplay.h
@@ -48,6 +48,19 @@ typedef struct _GtkHexDisplay GtkHexDisplay;
 typedef struct _GtkHexDisplayClass GtkHexDisplayClass;
 
 
+/* Désignation des colonnes d'une ligne */
+typedef enum _HexLineColumn
+{
+    HLC_PHYSICAL,                           /* Position physique           */
+    HLC_BINARY,                             /* Données binaires brutes     */
+    HLC_PADDING,                            /* Espacement forcé            */
+    HLC_TRANSLATION,                        /* Traduction de contenu       */
+
+    HLC_COUNT,
+
+} HexLineColumn;
+
+
 /* Détermine le type du composant d'affichage sous forme hexadécimale. */
 GType gtk_hex_display_get_type(void);
 
-- 
cgit v0.11.2-87-g4458