From c644db0ad3b1a276f2c3bf9be72026c3581dd35f Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Wed, 9 Dec 2015 23:06:59 +0100
Subject: Avoided to throw comments too far by defining local columns managers.

---
 ChangeLog                          |  15 +++
 src/analysis/disass/disassembler.c |  12 +-
 src/analysis/disass/output.c       |  20 +++-
 src/glibext/gbinportion.c          |   2 +
 src/glibext/gbufferline.c          | 239 +++++++++++++++++++++++++++++++++----
 src/glibext/gbufferline.h          |  25 ++--
 src/glibext/gcodebuffer.c          | 113 ++++++++++++------
 7 files changed, 353 insertions(+), 73 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 5ccb406..856036d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+15-12-09  Cyrille Bagard <nocbos@gmail.com>
+
+	* src/analysis/disass/disassembler.c:
+	Mark the first line of a disassembly as a line starting a group.
+
+	* src/analysis/disass/output.c:
+	* src/glibext/gbinportion.c:
+	Mark some lines as lines managing a local group of columns widths.
+
+	* src/glibext/gbufferline.c:
+	* src/glibext/gbufferline.h:
+	* src/glibext/gcodebuffer.c:
+	Avoid to throw comments too far by defining local columns managers.
+	Clean and update code.
+
 15-12-04  Cyrille Bagard <nocbos@gmail.com>
 
 	* configure.ac:
diff --git a/src/analysis/disass/disassembler.c b/src/analysis/disass/disassembler.c
index ce2e6ff..c563b2e 100644
--- a/src/analysis/disass/disassembler.c
+++ b/src/analysis/disass/disassembler.c
@@ -625,13 +625,20 @@ static void build_disass_prologue(GCodeBuffer *buffer, const char *filename, con
 {
     GLangOutput *output;                    /* Modèle de sortie adéquat    */
     GBufferLine *line;                      /* Ligne de destination        */
+    bool managed;                           /* Groupe déjà défini ?        */
     size_t len;                             /* Taille du texte             */
     char *content;                          /* Contenu textuel d'une ligne */
 
     output = g_asm_output_new();
 
     line = g_lang_output_start_comments(output, buffer);
-    if (line != NULL) g_buffer_line_start_merge_at(line, BLC_PHYSICAL);
+    if (line != NULL)
+    {
+        g_buffer_line_start_merge_at(line, BLC_PHYSICAL);
+        g_buffer_line_add_flag(line, BLF_WIDTH_MANAGER);
+    }
+
+    managed = (line != NULL);
 
     /* Introduction */
 
@@ -639,6 +646,9 @@ static void build_disass_prologue(GCodeBuffer *buffer, const char *filename, con
                                            SL(_("Disassembly generated by Chrysalide")));
     g_buffer_line_start_merge_at(line, BLC_PHYSICAL);
 
+    if (!managed)
+        g_buffer_line_add_flag(line, BLF_WIDTH_MANAGER);
+
     line = g_lang_output_continue_comments(output, buffer,
                                            SL(_("Chrysalide is free software - © 2008-2015 Cyrille Bagard")));
     g_buffer_line_start_merge_at(line, BLC_PHYSICAL);
diff --git a/src/analysis/disass/output.c b/src/analysis/disass/output.c
index d698c71..727c34f 100644
--- a/src/analysis/disass/output.c
+++ b/src/analysis/disass/output.c
@@ -236,12 +236,29 @@ void print_disassembled_instructions(GCodeBuffer *buffer, const GExeFormat *form
 
             if (cmp_vmpa(iaddr, saddr) == 0)
             {
-
                 /* Point d'entrée ? */
 
                 if (g_binary_symbol_get_target_type(symbols[sym_index]) == STP_ENTRY_POINT)
                     g_buffer_line_add_flag(line, BLF_ENTRYPOINT);
 
+                /* Début d'un groupe bien cohérent avec les alignements ? */
+
+                switch (g_binary_symbol_get_target_type(symbols[sym_index]))
+                {
+                    case STP_ROUTINE:
+                    case STP_OBJECT:
+                    case STP_FUNCTION:
+                    case STP_ENTRY_POINT:
+                    case STP_STRING:
+                    case STP_RO_STRING:
+                        g_buffer_line_add_flag(line, BLF_WIDTH_MANAGER);
+                        break;
+
+                    default:
+                        break;
+
+                }
+
                 /* Commentaire ? */
 
                 comment = g_binary_symbol_get_comment(symbols[sym_index]);
@@ -266,7 +283,6 @@ void print_disassembled_instructions(GCodeBuffer *buffer, const GExeFormat *form
 
                 sym_index++;
 
-
             }
 
         }
diff --git a/src/glibext/gbinportion.c b/src/glibext/gbinportion.c
index 16f4814..bd4702b 100644
--- a/src/glibext/gbinportion.c
+++ b/src/glibext/gbinportion.c
@@ -711,6 +711,8 @@ void g_binary_portion_print(const GBinPortion *portion, GCodeBuffer *buffer, Mem
     line = g_code_buffer_append_new_line(buffer, &range);
     g_buffer_line_fill_mrange(line, msize, msize);
 
+    g_buffer_line_add_flag(line, BLF_WIDTH_MANAGER);
+
     /* Séparation */
 
     line = g_code_buffer_append_new_line(buffer, &range);
diff --git a/src/glibext/gbufferline.c b/src/glibext/gbufferline.c
index 7768a0e..c998fce 100644
--- a/src/glibext/gbufferline.c
+++ b/src/glibext/gbufferline.c
@@ -99,6 +99,16 @@ struct _GBufferLine
 
     BufferLineFlags flags;                  /* Drapeaux particuliers       */
 
+    union
+    {
+        struct
+        {
+            gint max_widths[BLC_COUNT];     /* Taille cachée des colonnes  */
+            gint merged_width;              /* Largeur cumulée avant fusion*/
+        };
+        GBufferLine *manager;               /* Représentante d'un groupe   */
+    };
+
 };
 
 /* Représentation de fragments de texte en ligne (classe) */
@@ -122,6 +132,12 @@ 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 *);
+
 
 
 /* ---------------------------------------------------------------------------------- */
@@ -453,8 +469,14 @@ G_DEFINE_TYPE(GBufferLine, g_buffer_line, G_TYPE_OBJECT);
 
 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);
 
@@ -507,6 +529,49 @@ static void g_buffer_line_init(GBufferLine *line)
 
 /******************************************************************************
 *                                                                             *
+*  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)
+{
+    if (line->flags & BLF_WIDTH_MANAGER)
+        g_object_unref(G_OBJECT(line->manager));
+
+    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)
+{
+    /* TODO : segments des colonnes... */
+
+    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.      *
 *                                                                             *
@@ -792,7 +857,7 @@ GBufferSegment *g_buffer_line_get_segment_at(const GBufferLine *line, const gint
 
         if (i < line->merge_start)
         {
-            width = max_widths[i];
+            width = g_buffer_line_compute_max_width(line, i, max_widths);
 
             if ((i + 1) < BLC_COUNT) limit = width + COL_MARGIN / 2;
             else limit = width;
@@ -863,7 +928,10 @@ GBufferSegment *g_buffer_line_get_segment_at(const GBufferLine *line, const gint
                     printf(" -- update to col %u  -- x = %d\n", i, *offset);
 
                     if ((i - 1) < line->merge_start)
-                        *base += (max_widths[i - 1] + COL_MARGIN);
+                    {
+                        width = g_buffer_line_compute_max_width(line, i - 1, max_widths);
+                        *base += (width + COL_MARGIN);
+                    }
                     else
                         *base += get_column_width(&line->columns[i - 1]);
 
@@ -998,7 +1066,10 @@ GBufferSegment *g_buffer_line_find_near_segment(const GBufferLine *line, GBuffer
             displayed = (k < BLC_DISPLAY ? display[k] : true);
 
             if (displayed)
-                *offset += max_widths[k] + COL_MARGIN;
+            {
+                *offset += g_buffer_line_compute_max_width(line, k, max_widths);
+                if (k < line->merge_start) *offset += COL_MARGIN;
+            }
 
         }
 
@@ -1118,55 +1189,147 @@ char *g_buffer_line_get_text(const GBufferLine *line, BufferLineColumn first, Bu
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : line  = ligne à venir compléter.                             *
-*                index = index de la colonne visée par la procédure.          *
+*  Paramètres  : line    = ligne à venir consulter/compléter.                 *
+*                manager = ligne de départ d'un groupe de ligne.              *
 *                                                                             *
-*  Description : Fournit la largeur requise pour une colonne de ligne donnée. *
+*  Description : Retient les largeurs d'une ligne si maximales.               *
 *                                                                             *
-*  Retour      : Largeur en pixel requise.                                    *
+*  Retour      : -                                                            *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-gint g_buffer_line_get_column_width(GBufferLine *line, BufferLineColumn index)
+void g_buffer_line_update_max_widths(GBufferLine *line, GBufferLine *manager)
 {
-    gint result;                            /* Largeur à retourner         */
+    BufferLineColumn i;                     /* Boucle de parcours          */
+    GBufferLine *old;                       /* Ancienne ligne associée     */
+    gint merged_width;                      /* Largeur cumulée avant fusion*/
+    gint width;                             /* Largeur d'une colonne       */
 
-    if (index >= line->merge_start) result = 0;
-    else result = get_column_width(&line->columns[index]);
+    /* Réinitialisation ? */
 
-    return result;
+    if (line == manager)
+    {
+        assert(line->flags & BLF_WIDTH_MANAGER);
+
+        for (i = 0; i < BLC_COUNT; i++)
+            line->max_widths[i] = 0;
+
+        line->merged_width = 0;
+
+    }
+    else
+    {
+        assert((line->flags & BLF_WIDTH_MANAGER) == 0);
+
+        old = line->manager;
+
+        g_object_ref(G_OBJECT(manager));
+        line->manager = manager;
+
+        g_object_unref(G_OBJECT(old));
+
+    }
+
+    /* Mises à jour */
+
+    merged_width = 0;
+
+    for (i = 0; i < BLC_COUNT; i++)
+    {
+        width = get_column_width(&line->columns[i]);
+
+        if (i < line->merge_start)
+            manager->max_widths[i] = MAX(manager->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)
+        manager->merged_width = MAX(manager->merged_width, merged_width);
 
 }
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : line    = ligne à venir compléter.                           *
-*                merge   = précise la première colonne marquant la fusion. [OUT]*
-*                display = règles d'affichage des colonnes modulables.        *
+*  Paramètres  : line         = ligne à venir consulter.                      *
+*                max_widths   = tableau résumant les largeurs maximales. [OUT]*
+*                merged_width = largeur maximale en cas de fusion. |OUT]      *
 *                                                                             *
-*  Description : Fournit la dernière largeur d'une ligne avec fusion.         *
+*  Description : Filtre des largeurs de lignes et ne garde que les maximales. *
 *                                                                             *
-*  Retour      : Largeur en pixel requise.                                    *
+*  Retour      : -                                                            *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-gint g_buffer_line_get_merge_width(GBufferLine *line, BufferLineColumn *merge, const bool *display)
+void g_buffer_line_apply_max_widths(GBufferLine *line, gint *max_widths, gint *merged_width)
+{
+    GBufferLine *manager;                   /* Gestionnaire de groupe      */
+    BufferLineColumn i;                     /* Boucle de parcours          */
+
+    if (line->flags & BLF_WIDTH_MANAGER)
+        manager = line;
+    else
+        manager = line->manager;
+
+    for (i = 0; i < BLC_COUNT; i++)
+        max_widths[i] = MAX(manager->max_widths[i], max_widths[i]);
+
+    *merged_width = MAX(manager->merged_width, *merged_width);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : line       = ligne à venir consulter.                        *
+*                index      = indice de la colonne visée.                     *
+*                max_widths = tableau résumant les largeurs maximales.        *
+*                                                                             *
+*  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 gint *max_widths)
 {
     gint result;                            /* Largeur à retourner         */
 
-    result = 0;
+    assert(index < BLC_COUNT);
+
+    if (index >= line->merge_start)
+        result = get_column_width(&line->columns[index]);
+
+    else
+    {
+        if (index < BLC_ASSEMBLY)
+            result = max_widths[index];
 
-    /* TODO : wtf ?! quelle est l'utilité des arguments booléens ? */
+        else
+        {
+            if (line->flags & BLF_WIDTH_MANAGER)
+                result = line->max_widths[index];
+            else
+                result = line->manager->max_widths[index];
 
-    *merge = line->merge_start;
+        }
 
-    if (line->merge_start < BLC_COUNT)
-        result = get_column_width(&line->columns[line->merge_start]);
+    }
 
     return result;
 
@@ -1175,6 +1338,25 @@ gint g_buffer_line_get_merge_width(GBufferLine *line, BufferLineColumn *merge, c
 
 /******************************************************************************
 *                                                                             *
+*  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.       *
 *                                                                             *
@@ -1290,6 +1472,7 @@ void g_buffer_line_draw(GBufferLine *line, cairo_t *cairo, const gint max_widths
     GBufferLineClass *class;                /* Stockage de briques de base */
     gint x;                                 /* Point de départ d'impression*/
     BufferLineColumn i;                     /* Boucle de parcours          */
+    gint max_width;                         /* Largeur maximale de colonne */
 
     if (line->flags != BLF_NONE && line->flags != BLF_HAS_CODE)
     {
@@ -1300,6 +1483,9 @@ void g_buffer_line_draw(GBufferLine *line, cairo_t *cairo, const gint max_widths
         else if (line->flags & BLF_BOOKMARK)
             cairo_set_source_surface(cairo, class->bookmark_img, 5, y);
 
+        //////////////////
+        cairo_set_source_surface(cairo, class->entrypoint_img, 5, y);
+
         cairo_paint(cairo);
 
     }
@@ -1313,7 +1499,12 @@ void g_buffer_line_draw(GBufferLine *line, cairo_t *cairo, const gint max_widths
         draw_segments_of_column(&line->columns[i], cairo, x, y, list);
 
         if (i < line->merge_start)
-            x += max_widths[i] + COL_MARGIN;
+        {
+            max_width = g_buffer_line_compute_max_width(line, i, max_widths);
+
+            x += max_width + COL_MARGIN;
+
+        }
 
     }
 
diff --git a/src/glibext/gbufferline.h b/src/glibext/gbufferline.h
index 0da5ffd..7ba5467 100644
--- a/src/glibext/gbufferline.h
+++ b/src/glibext/gbufferline.h
@@ -87,12 +87,13 @@ typedef enum _BufferLineColumn
 /* 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_ENTRYPOINT  = 1 << 1,               /* Représentation d'une entrée */
-    BLF_BOOKMARK    = 1 << 2,               /* Signet associé              */
+    BLF_NONE            = 0 << 0,           /* Aucune                      */
+    BLF_HAS_CODE        = 1 << 0,           /* La ligne contient du code   */
+    BLF_ENTRYPOINT      = 1 << 1,           /* Représentation d'une entrée */
+    BLF_BOOKMARK        = 1 << 2,           /* Signet associé              */
+    BLF_WIDTH_MANAGER   = 1 << 3,           /* Début de groupe des largeurs*/
 
-    BLF_ALL         = ((1 << 3) - 1)
+    BLF_ALL             = ((1 << 4) - 1)
 
 } BufferLineFlags;
 
@@ -127,11 +128,17 @@ GBufferSegment *g_buffer_line_insert_text(GBufferLine *, BufferLineColumn, const
 /* Donne le texte représenté par une ligne de tampon. */
 char *g_buffer_line_get_text(const GBufferLine *, BufferLineColumn, BufferLineColumn, bool);
 
-/* Fournit la largeur requise pour une colonne de ligne donnée. */
-gint g_buffer_line_get_column_width(GBufferLine *, BufferLineColumn);
+/* Retient les largeurs d'une ligne si maximales. */
+void g_buffer_line_update_max_widths(GBufferLine *, GBufferLine *);
 
-/* Fournit la dernière largeur d'une ligne avec fusion. */
-gint g_buffer_line_get_merge_width(GBufferLine *, BufferLineColumn *, const bool *);
+/* Filtre des largeurs de lignes et ne garde que les maximales. */
+void g_buffer_line_apply_max_widths(GBufferLine *, gint *, gint *);
+
+/* Fournit la largeur d'une colonne finalement appliquée. */
+gint g_buffer_line_compute_max_width(const GBufferLine *, BufferLineColumn, const gint *);
+
+/* 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);
diff --git a/src/glibext/gcodebuffer.c b/src/glibext/gcodebuffer.c
index c676b7c..b211c4a 100644
--- a/src/glibext/gcodebuffer.c
+++ b/src/glibext/gcodebuffer.c
@@ -24,6 +24,7 @@
 #include "gcodebuffer.h"
 
 
+#include <assert.h>
 #include <malloc.h>
 #include <stdlib.h>
 #include <string.h>
@@ -132,6 +133,9 @@ static size_t _g_code_buffer_get_index_from_address_new(const GCodeBuffer *, con
 /* Convertit une adresse en indice de ligne. */
 static size_t g_code_buffer_get_index_from_address(GCodeBuffer *, const vmpa2t *, bool);
 
+/* Actualise les largeurs maximales par groupes de lignes. */
+static void g_code_buffer_update_line_max_widths(const GCodeBuffer *, size_t, size_t);
+
 
 
 /* ---------------------- VUE PARTICULIERE D'UN TAMPON DE CODE ---------------------- */
@@ -149,11 +153,10 @@ struct _GBufferView
     size_t last_index;                      /* Indice de la dernière ligne */   /* FIXME : idem */
 
     gint line_height;                       /* Hauteur maximale des lignes */
-    gint max_widths[BLC_COUNT];             /* Taille cachée des colonnes  */
     gint left_margin;                       /* Marge gauche + espace       */
     gint left_text;                         /* Début d'impression du code  */
-    gint last_width;                        /* Plus grande col. de fusion  */
-    BufferLineColumn last_merge;            /* Colonne de fusion extrême   */
+    gint max_widths[BLC_COUNT];             /* Taille cachée des colonnes  */
+    gint merged_width;                      /* Plus grande taille de fusion*/
 
     segcnt_list *highlighted;               /* Segments mis en évidence    */
     bool external;                          /* Note l'origine de la liste  */
@@ -634,6 +637,60 @@ static size_t g_code_buffer_get_index_from_address(GCodeBuffer *buffer, const vm
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : buffer = tampon contentenant un ensemble de lignes.          *
+*                first  = première ligne modifiée à considérer.               *
+*                last   = dernière ligne modifiée à considérer.               *
+*                                                                             *
+*  Description : Actualise les largeurs maximales par groupes de lignes.      *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_code_buffer_update_line_max_widths(const GCodeBuffer *buffer, size_t first, size_t last)
+{
+    GBufferLine **lines;                    /* Liste des lignes à traiter  */
+    size_t start;                           /* Début de groupe de largeurs */
+    size_t end;                             /* Fin de groupe de largeurs   */
+    GBufferLine *manager;                   /* Ligne de gestion de largeurs*/
+    size_t i;                               /* Boucle de parcours          */
+
+    assert(buffer->used > 0);
+
+    lines = buffer->lines;
+
+    /* Recherche des bornes du groupe de largeurs courant */
+
+    for (start = first; start > 0; start--)
+        if (g_buffer_line_get_flags(lines[start]) & BLF_WIDTH_MANAGER)
+            break;
+
+    for (end = last; end < (buffer->used - 1); end++)
+        if (g_buffer_line_get_flags(lines[end + 1]) & BLF_WIDTH_MANAGER)
+            break;
+
+    /* Réinitialisation ciblée des largeurs */
+
+    assert(g_buffer_line_get_flags(lines[start]) & BLF_WIDTH_MANAGER);
+
+    manager = NULL;
+
+    for (i = start; i <= end; i++)
+    {
+        if (g_buffer_line_get_flags(lines[i]) & BLF_WIDTH_MANAGER)
+            manager = lines[i];
+
+        g_buffer_line_update_max_widths(lines[i], manager);
+
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : buffer = composant GTK à mettre à jour.                      *
 *                range  = emplacement où va se situer la ligne.               *
 *                                                                             *
@@ -1144,6 +1201,8 @@ static void g_buffer_view_reset_required_widths(GBufferView *view)
     for (i = 0; i < BLC_COUNT; i++)
         view->max_widths[i] = -1;
 
+    view->merged_width = 0;
+
 }
 
 
@@ -1184,10 +1243,7 @@ static void g_buffer_view_compute_required_widths(GBufferView *view, const bool
     GBufferLine **lines;                    /* Liste des lignes à traiter  */
     size_t first;                           /* Première ligne intégrée     */
     size_t last;                            /* Dernière ligne intégrée     */
-    size_t i;                               /* Boucle de parcours #1       */
-    unsigned int j;                         /* Boucle de parcours #2       */
-    gint width;                             /* Largeur d'une colonne       */
-    BufferLineColumn merge;                 /* Début de fusion de colonnes */
+    size_t i;                               /* Boucle de parcours          */
 
     if (!HEIGHT_CACHED(view))
         g_buffer_view_compute_required_height(view);
@@ -1200,32 +1256,14 @@ static void g_buffer_view_compute_required_widths(GBufferView *view, const bool
     view->left_margin = 2 * view->line_height;
     view->left_text = 2.5 * view->line_height;
 
-    view->last_width = 0;
-    view->last_merge = BLC_INVALID;
-
     if (view->buffer->used > 0)
-        for (i = first; i <= last; i++)
-        {
-            for (j = 0; j < BLC_COUNT; j++)
-            {
-                width = g_buffer_line_get_column_width(lines[i], j);
-                view->max_widths[j] = MAX(view->max_widths[j], width);
-            }
-
-            width = g_buffer_line_get_merge_width(lines[i], &merge, display);
-            view->last_width = MAX(view->last_width, width);
-            if (merge != BLC_COUNT)
-            {
-                if (view->last_merge == BLC_INVALID)
-                    view->last_merge = merge;
-                else
-                    view->last_merge = MAX(view->last_merge, merge);
-            }
+    {
+        g_code_buffer_update_line_max_widths(view->buffer, first, last);
 
-        }
+        for (i = first; i <= last; i++)
+            g_buffer_line_apply_max_widths(lines[i], view->max_widths, &view->merged_width);
 
-    if (view->last_merge == BLC_INVALID)
-        view->last_merge = BLC_COUNT;
+    }
 
 }
 
@@ -1295,18 +1333,15 @@ gint g_buffer_view_get_width(GBufferView *view, const bool *display)
 
     /* Seconde méthode */
 
-    for (i = 0; i < view->last_merge; i++)
+    for (i = 0; i < BLC_DISPLAY; i++)
     {
-        if (i < BLC_DISPLAY && !display[i]) continue;
-
-        full_width += view->max_widths[i];
+        if (!display[i]) continue;
 
-        if ((i + 1) < view->last_merge)
-            full_width += COL_MARGIN;
+        full_width += view->max_widths[i] + COL_MARGIN;
 
     }
 
-    full_width += view->last_width + COL_MARGIN;
+    full_width += view->merged_width;
 
     /* Mise en concurrence et poursuite... */
 
@@ -1712,7 +1747,11 @@ const vmpa2t *g_buffer_view_move_caret(GBufferView *view, GdkRectangle *caret, b
             for (i = BLC_ASSEMBLY_HEAD; i < BLC_COUNT; i++)
                 right_pos += view->max_widths[i] + COL_MARGIN;
 
+            /*
+gint g_buffer_line_compute_max_width(const GBufferLine *line, BufferLineColumn index, const gint *max_widths)
 
+BufferLineColumn g_buffer_line_get_merge_start(const GBufferLine *line)
+            */
 
             left_pos = view->left_text;
 
-- 
cgit v0.11.2-87-g4458