From dd33acbff36c0a3ae4618ac5021e74448cad5ce5 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Thu, 21 Jan 2016 21:51:27 +0100
Subject: Defined some raw primitives to write or delete comments.

---
 ChangeLog                          |  15 +
 src/analysis/disass/disassembler.c |  20 +-
 src/analysis/disass/output.c       |   6 +-
 src/arch/instruction.c             |   2 +-
 src/arch/raw.c                     |   2 +-
 src/glibext/gbinportion.c          |  24 +-
 src/glibext/gbufferline.c          | 106 ++++-
 src/glibext/gbufferline.h          |  29 +-
 src/glibext/gcodebuffer.c          | 806 +++++++++++++++++++++++++++++++++++--
 src/glibext/gcodebuffer.h          |  43 +-
 10 files changed, 1003 insertions(+), 50 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 2901b77..204c090 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,20 @@
 16-01-21  Cyrille Bagard <nocbos@gmail.com>
 
+	* src/analysis/disass/disassembler.c:
+	* src/analysis/disass/output.c:
+	* src/arch/instruction.c:
+	* src/arch/raw.c:
+	* src/glibext/gbinportion.c:
+	Update calls registering new lines.
+
+	* src/glibext/gbufferline.c:
+	* src/glibext/gbufferline.h:
+	* src/glibext/gcodebuffer.c:
+	* src/glibext/gcodebuffer.h:
+	Define some raw primitives to write or delete comments.
+
+16-01-21  Cyrille Bagard <nocbos@gmail.com>
+
 	* src/glibext/gcodebuffer.c:
 	* src/glibext/gcodebuffer.h:
 	Remove useless functions dealing with buffers and optimize some old code.
diff --git a/src/analysis/disass/disassembler.c b/src/analysis/disass/disassembler.c
index 272529c..0fcc7f3 100644
--- a/src/analysis/disass/disassembler.c
+++ b/src/analysis/disass/disassembler.c
@@ -636,6 +636,9 @@ static void build_disass_prologue(GCodeBuffer *buffer, const char *filename, con
     {
         g_buffer_line_start_merge_at(line, BLC_PHYSICAL);
         g_buffer_line_add_flag(line, BLF_WIDTH_MANAGER);
+
+        g_code_buffer_append_new_line(buffer, line);
+
     }
 
     managed = (line != NULL);
@@ -649,13 +652,19 @@ static void build_disass_prologue(GCodeBuffer *buffer, const char *filename, con
     if (!managed)
         g_buffer_line_add_flag(line, BLF_WIDTH_MANAGER);
 
+    g_code_buffer_append_new_line(buffer, line);
+
     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);
 
+    g_code_buffer_append_new_line(buffer, line);
+
     line = g_lang_output_continue_comments(output, buffer, NULL, 0);
     g_buffer_line_start_merge_at(line, BLC_PHYSICAL);
 
+    g_code_buffer_append_new_line(buffer, line);
+
     /* Fichier */
 
     len = strlen(_("File: ")) + strlen(filename) + 1;
@@ -666,6 +675,8 @@ static void build_disass_prologue(GCodeBuffer *buffer, const char *filename, con
     line = g_lang_output_continue_comments(output, buffer, content, len - 1);
     g_buffer_line_start_merge_at(line, BLC_PHYSICAL);
 
+    g_code_buffer_append_new_line(buffer, line);
+
     free(content);
 
     /* Checksum SHA256 */
@@ -678,17 +689,24 @@ static void build_disass_prologue(GCodeBuffer *buffer, const char *filename, con
     line = g_lang_output_continue_comments(output, buffer, content, len - 1);
     g_buffer_line_start_merge_at(line, BLC_PHYSICAL);
 
+    g_code_buffer_append_new_line(buffer, line);
+
     free(content);
 
     /* Ligne de séparation */
 
     line = g_lang_output_continue_comments(output, buffer, NULL, 0);
     g_buffer_line_start_merge_at(line, BLC_PHYSICAL);
+    g_code_buffer_append_new_line(buffer, line);
 
     /* Conclusion */
 
     line = g_lang_output_end_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_code_buffer_append_new_line(buffer, line);
+    }
 
     g_object_unref(G_OBJECT(output));
 
diff --git a/src/analysis/disass/output.c b/src/analysis/disass/output.c
index 67a3ce8..75444a5 100644
--- a/src/analysis/disass/output.c
+++ b/src/analysis/disass/output.c
@@ -210,13 +210,15 @@ void print_disassembled_instructions(GCodeBuffer *buffer, const GExeFormat *form
                 {
                     init_mrange(&range, get_mrange_addr(g_binary_symbol_get_range(symbols[sym_index])), 0);
 
-                    line = g_code_buffer_append_new_line(buffer, &range);
+                    line = g_code_buffer_prepare_new_line(buffer, &range);
+                    g_buffer_line_add_flag(line, BLF_IS_LABEL);
                     g_buffer_line_fill_mrange(line, msize, msize);
 
                     g_buffer_line_start_merge_at(line, BLC_ASSEMBLY_HEAD);
                     g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, label, strlen(label), RTT_LABEL);
                     g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, ":", 1, RTT_PUNCT);
 
+                    g_code_buffer_append_new_line(buffer, line);
 
                 }
 
@@ -288,6 +290,8 @@ void print_disassembled_instructions(GCodeBuffer *buffer, const GExeFormat *form
 
         }
 
+        g_code_buffer_append_new_line(buffer, line);
+
 
         //gtk_extended_status_bar_update_activity(statusbar, id, (iaddr - start) * 1.0 / (end - start));
 
diff --git a/src/arch/instruction.c b/src/arch/instruction.c
index 184d98c..021bdd4 100644
--- a/src/arch/instruction.c
+++ b/src/arch/instruction.c
@@ -895,7 +895,7 @@ static GBufferLine *_g_arch_instruction_print(const GArchInstruction *instr, GCo
     size_t klen;                            /* Taille de ce mot clef       */
     size_t i;                               /* Boucle de parcours          */
 
-    result = g_code_buffer_append_new_line(buffer, &instr->range);
+    result = g_code_buffer_prepare_new_line(buffer, &instr->range);
 
     g_buffer_line_add_flag(result, BLF_HAS_CODE);
 
diff --git a/src/arch/raw.c b/src/arch/raw.c
index 57860c0..d04f141 100644
--- a/src/arch/raw.c
+++ b/src/arch/raw.c
@@ -366,7 +366,7 @@ static GBufferLine *g_raw_instruction_print(const GRawInstruction *instr, GCodeB
 
     else
     {
-        result = g_code_buffer_append_new_line(buffer, &base->range);
+        result = g_code_buffer_prepare_new_line(buffer, &base->range);
 
         g_buffer_line_add_flag(result, BLF_HAS_CODE);
 
diff --git a/src/glibext/gbinportion.c b/src/glibext/gbinportion.c
index abdec60..0744a79 100644
--- a/src/glibext/gbinportion.c
+++ b/src/glibext/gbinportion.c
@@ -536,31 +536,37 @@ void g_binary_portion_print(const GBinPortion *portion, GCodeBuffer *buffer, Mem
 
     init_mrange(&range, get_mrange_addr(&portion->range), 0);
 
-    line = g_code_buffer_append_new_line(buffer, &range);
+    line = g_code_buffer_prepare_new_line(buffer, &range);
     g_buffer_line_fill_mrange(line, msize, msize);
 
     g_buffer_line_add_flag(line, BLF_WIDTH_MANAGER);
 
+    g_code_buffer_append_new_line(buffer, line);
+
     /* Séparation */
 
-    line = g_code_buffer_append_new_line(buffer, &range);
+    line = g_code_buffer_prepare_new_line(buffer, &range);
     g_buffer_line_fill_mrange(line, msize, msize);
 
     g_buffer_line_start_merge_at(line, BLC_ASSEMBLY_HEAD);
     g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD,
                               "; ======================================================", 56, RTT_COMMENT);
 
+    g_code_buffer_append_new_line(buffer, line);
+
     /* Retour à la ligne */
 
-    line = g_code_buffer_append_new_line(buffer, &range);
+    line = g_code_buffer_prepare_new_line(buffer, &range);
     g_buffer_line_fill_mrange(line, msize, msize);
 
     g_buffer_line_start_merge_at(line, BLC_ASSEMBLY_HEAD);
     g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "; ", 2, RTT_COMMENT);
 
+    g_code_buffer_append_new_line(buffer, line);
+
     /* Description */
 
-    line = g_code_buffer_append_new_line(buffer, &range);
+    line = g_code_buffer_prepare_new_line(buffer, &range);
     g_buffer_line_fill_mrange(line, msize, msize);
 
     g_buffer_line_start_merge_at(line, BLC_ASSEMBLY_HEAD);
@@ -577,16 +583,22 @@ void g_binary_portion_print(const GBinPortion *portion, GCodeBuffer *buffer, Mem
 
     g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, rights, strlen(rights), RTT_COMMENT);
 
+    g_code_buffer_append_new_line(buffer, line);
+
     /* Retour à la ligne */
 
-    line = g_code_buffer_append_new_line(buffer, &range);
+    line = g_code_buffer_prepare_new_line(buffer, &range);
     g_buffer_line_fill_mrange(line, msize, msize);
 
     g_buffer_line_start_merge_at(line, BLC_ASSEMBLY_HEAD);
     g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "; ", 2, RTT_COMMENT);
 
-    line = g_code_buffer_append_new_line(buffer, &range);
+    g_code_buffer_append_new_line(buffer, line);
+
+    line = g_code_buffer_prepare_new_line(buffer, &range);
     g_buffer_line_fill_mrange(line, msize, msize);
+    g_code_buffer_append_new_line(buffer, line);
+
 
 }
 
diff --git a/src/glibext/gbufferline.c b/src/glibext/gbufferline.c
index d09758f..2f29ee4 100644
--- a/src/glibext/gbufferline.c
+++ b/src/glibext/gbufferline.c
@@ -170,6 +170,19 @@ static void on_line_segment_changed(GBufferSegment *, GBufferLine *);
 
 static void reset_column(buffer_line_column *column)
 {
+    size_t i;                               /* Boucle de parcours          */
+
+    for (i = 0; i < column->count; i++)
+        g_object_unref(G_OBJECT(column->segments[i]));
+
+    if (column->segments != NULL)
+    {
+        free(column->segments);
+        column->segments = NULL;
+    }
+
+    column->count = 0;
+
     column->max_width = 0;
 
 }
@@ -1264,6 +1277,37 @@ GBufferSegment *g_buffer_line_insert_text(GBufferLine *line, BufferLineColumn co
 *  Paramètres  : line   = ligne à venir consulter.                            *
 *                first  = première colonne à parcourir.                       *
 *                end    = colonne de fin de parcours.                         *
+*                                                                             *
+*  Description : Indique si du texte est présent dans une ligne de tampon.    *
+*                                                                             *
+*  Retour      : true pour indiquer la présence de texte, false pour du vide. *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_buffer_line_has_text(const GBufferLine *line, BufferLineColumn first, BufferLineColumn end)
+{
+    bool result;                            /* Bilan à retourner           */
+    BufferLineColumn i;                     /* Boucle de parcours          */
+
+    result = false;
+
+    assert(first < end);
+
+    for (i = first; i < end && !result; i++)
+        result = (line->columns[i].count > 0);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : line   = ligne à venir consulter.                            *
+*                first  = première colonne à parcourir.                       *
+*                end    = colonne de fin de parcours.                         *
 *                markup = indique si le texte doit être décoré ou non.        *
 *                                                                             *
 *  Description : Donne le texte représenté par une ligne de tampon.           *
@@ -1311,6 +1355,31 @@ char *g_buffer_line_get_text(const GBufferLine *line, BufferLineColumn first, Bu
 
 }
 
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : line  = ligne à venir modifier.                              *
+*                first = première colonne à parcourir.                        *
+*                end   = colonne de fin de parcours.                          *
+*                                                                             *
+*  Description : Supprime du texte représenté par une ligne de tampon.        *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_buffer_line_delete_text(GBufferLine *line, BufferLineColumn first, BufferLineColumn end)
+{
+    BufferLineColumn i;                     /* Boucle de parcours #1       */
+
+    assert(first < end);
+
+    for (i = first; i < end; i++)
+        reset_column(&line->columns[i]);
+
+}
+
 
 /******************************************************************************
 *                                                                             *
@@ -1353,7 +1422,8 @@ void g_buffer_line_update_max_widths(GBufferLine *line, GBufferLine *manager)
         g_object_ref(G_OBJECT(manager));
         line->manager = manager;
 
-        g_object_unref(G_OBJECT(old));
+        if (old != NULL)
+            g_object_unref(G_OBJECT(old));
 
     }
 
@@ -1388,6 +1458,32 @@ void g_buffer_line_update_max_widths(GBufferLine *line, GBufferLine *manager)
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : line         = ligne à venir consulter.                      *
+*                                                                             *
+*  Description : Renvoie la ligne comptabilisant les largeurs pour un groupe. *
+*                                                                             *
+*  Retour      : Ligne considérée comme la gestionnaire d'un ensemble.        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GBufferLine *g_buffer_line_get_width_manager(GBufferLine *line)
+{
+    GBufferLine *result;                    /* Gestionnaire à retourner    */
+
+    if (line->flags & BLF_WIDTH_MANAGER)
+        result = line;
+    else
+        result = line->manager;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : line         = ligne à venir consulter.                      *
 *                max_widths   = tableau résumant les largeurs maximales. [OUT]*
 *                merged_width = largeur maximale en cas de fusion. |OUT]      *
 *                                                                             *
@@ -1404,10 +1500,7 @@ void g_buffer_line_apply_max_widths(GBufferLine *line, gint *max_widths, gint *m
     GBufferLine *manager;                   /* Gestionnaire de groupe      */
     BufferLineColumn i;                     /* Boucle de parcours          */
 
-    if (line->flags & BLF_WIDTH_MANAGER)
-        manager = line;
-    else
-        manager = line->manager;
+    manager = g_buffer_line_get_width_manager(line);
 
     for (i = 0; i < BLC_COUNT; i++)
         max_widths[i] = MAX(manager->max_widths[i], max_widths[i]);
@@ -1434,6 +1527,7 @@ void g_buffer_line_apply_max_widths(GBufferLine *line, gint *max_widths, gint *m
 gint g_buffer_line_compute_max_width(const GBufferLine *line, BufferLineColumn index, const gint *max_widths)
 {
     gint result;                            /* Largeur à retourner         */
+    //GBufferLine *manager;                   /* Gestionnaire de groupe      */
 
     assert(index < BLC_COUNT);
 
@@ -1447,6 +1541,8 @@ gint g_buffer_line_compute_max_width(const GBufferLine *line, BufferLineColumn i
 
         else
         {
+            //manager = g_buffer_line_get_width_manager(line);
+
             if (line->flags & BLF_WIDTH_MANAGER)
                 result = line->max_widths[index];
             else
diff --git a/src/glibext/gbufferline.h b/src/glibext/gbufferline.h
index 643e899..19652ab 100644
--- a/src/glibext/gbufferline.h
+++ b/src/glibext/gbufferline.h
@@ -89,11 +89,12 @@ 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_WIDTH_MANAGER   = 1 << 3,           /* Début de groupe des largeurs*/
+    BLF_IS_LABEL        = 1 << 1,           /* Etiquette pour symbole      */
+    BLF_ENTRYPOINT      = 1 << 2,           /* Représentation d'une entrée */
+    BLF_BOOKMARK        = 1 << 3,           /* Signet associé              */
+    BLF_WIDTH_MANAGER   = 1 << 4,           /* Début de groupe des largeurs*/
 
-    BLF_ALL             = ((1 << 4) - 1)
+    BLF_ALL             = ((1 << 5) - 1)
 
 } BufferLineFlags;
 
@@ -125,12 +126,21 @@ GBufferSegment *g_buffer_line_find_segment_from_creator(const GBufferLine *, GOb
 /* Ajoute du texte à formater dans une ligne donnée. */
 GBufferSegment *g_buffer_line_insert_text(GBufferLine *, BufferLineColumn, const char *, size_t, RenderingTagType);
 
+/* Indique si du texte est présent dans une ligne de tampon. */
+bool g_buffer_line_has_text(const GBufferLine *, BufferLineColumn, BufferLineColumn);
+
 /* Donne le texte représenté par une ligne de tampon. */
 char *g_buffer_line_get_text(const GBufferLine *, BufferLineColumn, BufferLineColumn, bool);
 
+/* Supprime du texte représenté par une ligne de tampon. */
+void g_buffer_line_delete_text(GBufferLine *, BufferLineColumn, BufferLineColumn);
+
 /* Retient les largeurs d'une ligne si maximales. */
 void g_buffer_line_update_max_widths(GBufferLine *, GBufferLine *);
 
+/* Renvoie la ligne comptabilisant les largeurs pour un groupe. */
+GBufferLine *g_buffer_line_get_width_manager(GBufferLine *);
+
 /* Filtre des largeurs de lignes et ne garde que les maximales. */
 void g_buffer_line_apply_max_widths(GBufferLine *, gint *, gint *);
 
@@ -159,5 +169,16 @@ void g_buffer_line_draw(GBufferLine *, cairo_t *, const gint [BLC_COUNT], gint,
 void g_buffer_line_export(GBufferLine *, buffer_export_context *, BufferExportType, const bool *);
 
 
+/* Petite aide pour la détection de commentaire */
+#define g_buffer_line_has_comment(ln)                                       \
+    ({                                                                      \
+        bool __result;                                                      \
+        __result = g_buffer_line_has_text(ln, BLC_COMMENTS, BLC_COUNT);     \
+        __result |= (g_buffer_line_get_merge_start(ln) == BLC_DISPLAY       \
+                     && !(g_buffer_line_get_flags(ln) & BLF_IS_LABEL));     \
+        __result;                                                           \
+    })
+
+
 
 #endif  /* _GLIBEXT_GBUFFERLINE_H */
diff --git a/src/glibext/gcodebuffer.c b/src/glibext/gcodebuffer.c
index 1d4e6cd..f3634f0 100644
--- a/src/glibext/gcodebuffer.c
+++ b/src/glibext/gcodebuffer.c
@@ -32,6 +32,7 @@
 
 #include "chrysamarshal.h"
 #include "delayed-int.h"
+#include "../common/extstr.h"
 
 
 
@@ -148,11 +149,28 @@ static void on_line_content_change(GBufferLine *, GBufferSegment *, GCodeBuffer
 /* Réagit à un changement de propriété rattachée à une ligne. */
 static void on_line_flag_flip(GBufferLine *, BufferLineFlags, BufferLineFlags, GCodeBuffer *);
 
-/* Ajoute une nouvelle ligne à une position donnée. */
-static GBufferLine *g_code_buffer_create_new_line(GCodeBuffer *, size_t, const mrange_t *);
+/* Ajoute de nouvelles lignes à une position donnée. */
+static void g_code_buffer_insert_lines_at(GCodeBuffer *, GBufferLine **, size_t, size_t);
 
-/* Retrouve l'indice associé à une ligne au sein d'un tampon. */
-static size_t g_code_buffer_find_index_by_line(const GCodeBuffer *, const GBufferLine *);
+
+
+/* ------------------------- CONFORTS POUR LES COMMENTAIRES ------------------------- */
+
+
+/* Affiche un commentaire sur une ligne de tampon donnée. */
+static bool _g_code_buffer_write_inlined_comment(GCodeBuffer *, GBufferLine *, const char *);
+
+/* Affiche un commentaire sur une ligne de tampon dédiée. */
+static bool _g_code_buffer_write_comment_area(GCodeBuffer *, GBufferLine *, const char *, bool);
+
+/* Retrouve la première ligne d'une zone de commentaire. */
+static size_t g_code_buffer_find_first_line_comment(const GCodeBuffer *, size_t);
+
+/* Retrouve la dernière ligne d'une zone de commentaire. */
+static size_t g_code_buffer_find_last_line_comment(const GCodeBuffer *, size_t);
+
+/* Supprime un commentaire existant. */
+static bool _g_code_buffer_delete_lines_comment(GCodeBuffer *, GBufferLine *);
 
 
 
@@ -426,6 +444,591 @@ static void g_buffer_scan_process(GBufferScan *scan, GtkExtStatusBar *statusbar)
 
 
 /* ---------------------------------------------------------------------------------- */
+/*                           CONFORTS POUR LES COMMENTAIRES                           */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : buffer  = tampon de lignes à consulter.                      *
+*                line    = ligne à l'intérieur d'un commentaire.              *
+*                comment = nouveau commentaire à inscrire à la ligne donnée.  *
+*                                                                             *
+*  Description : Affiche un commentaire sur une ligne de tampon donnée.       *
+*                                                                             *
+*  Retour      : Bilan de l'opération : ajout ou non ?                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool _g_code_buffer_write_inlined_comment(GCodeBuffer *buffer, GBufferLine *line, const char *comment)
+{
+    bool result;                            /* Bilan à retourner           */
+    const mrange_t *range;                  /* Emplace de ligne à utiliser */
+    char *wcopy;                            /* Copie de travail            */
+    GBufferLine **extra;                    /* Lignes supplémentaires      */
+    size_t extra_count;                     /* Quantité de ces lignes      */
+    char *saveptr;                          /* Sauvegarde pour la sécurité */
+    char *token;                            /* Fragment à insérer          */
+    size_t len;                             /* Taille dudit fragment       */
+    GBufferLine *new;                       /* Nouvelle ligne créée        */
+    size_t i;                               /* Boucle de parcours          */
+
+    assert(!g_buffer_line_has_comment(line));
+
+    result = false;
+
+    range = g_buffer_line_get_range(line);
+
+    wcopy = strdup(comment);
+
+    extra = NULL;
+    extra_count = 0;
+
+    for (token = strtok_r(wcopy, COMMENT_LINE_SEP, &saveptr);
+         token != NULL;
+         token = strtok_r(NULL, COMMENT_LINE_SEP, &saveptr))
+    {
+        len = strlen(token);
+
+        if (!result)
+            g_buffer_line_insert_text(line, BLC_COMMENTS, token, len, RTT_COMMENT);
+
+        else
+        {
+            new = g_code_buffer_prepare_new_line(buffer, range);
+            g_buffer_line_insert_text(new, BLC_COMMENTS, token, len, RTT_COMMENT);
+
+            extra = (GBufferLine **)realloc(extra, ++extra_count * sizeof(GBufferLine *));
+
+            extra[extra_count - 1] = new;
+
+        }
+
+        result = true;
+
+    }
+
+    free(wcopy);
+
+    if (extra_count > 0)
+    {
+        result &= g_code_buffer_insert_lines(buffer, extra, extra_count, line, false);
+
+        if (!result)
+            for (i = 0; i < extra_count; i++)
+                g_object_unref(G_OBJECT(extra[i]));
+
+        free(extra);
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : buffer  = tampon de lignes à consulter.                      *
+*                line    = ligne à l'intérieur d'un commentaire.              *
+*                comment = nouveau commentaire à inscrire à la ligne donnée.  *
+*                                                                             *
+*  Description : Affiche un commentaire sur une ligne de tampon donnée.       *
+*                                                                             *
+*  Retour      : Bilan de l'opération : ajout ou non ?                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_code_buffer_update_inlined_comment(GCodeBuffer *buffer, GBufferLine *line, const char *comment)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    if (g_buffer_line_has_comment(line))
+        result = _g_code_buffer_delete_lines_comment(buffer, line);
+    else
+        result = true;
+
+    if (result)
+        result = _g_code_buffer_write_inlined_comment(buffer, line, comment);
+
+    /* TODO : emit() */
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : buffer  = tampon de lignes à consulter.                      *
+*                line    = ligne à l'intérieur d'un commentaire.              *
+*                comment = nouveau commentaire à inscrire à la ligne donnée.  *
+*                before  = précise la position du commentaire.                *
+*                                                                             *
+*  Description : Affiche un commentaire sur une ligne de tampon dédiée.       *
+*                                                                             *
+*  Retour      : Bilan de l'opération : ajout ou non ?                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool _g_code_buffer_write_comment_area(GCodeBuffer *buffer, GBufferLine *line, const char *comment, bool before)
+{
+    bool result;                            /* Bilan à retourner           */
+    const mrange_t *range;                  /* Emplace de ligne à utiliser */
+    char *wcopy;                            /* Copie de travail            */
+    GBufferLine **extra;                    /* Lignes supplémentaires      */
+    size_t extra_count;                     /* Quantité de ces lignes      */
+    char *saveptr;                          /* Sauvegarde pour la sécurité */
+    char *token;                            /* Fragment à insérer          */
+    size_t len;                             /* Taille dudit fragment       */
+    GBufferLine *new;                       /* Nouvelle ligne créée        */
+    size_t i;                               /* Boucle de parcours          */
+
+    assert(!g_buffer_line_has_comment(line));
+
+    result = false;
+
+    range = g_buffer_line_get_range(line);
+
+    wcopy = strdup(comment);
+
+    extra = NULL;
+    extra_count = 0;
+
+    for (token = strtok_r(wcopy, COMMENT_LINE_SEP, &saveptr);
+         token != NULL;
+         token = strtok_r(NULL, COMMENT_LINE_SEP, &saveptr))
+    {
+        len = strlen(token);
+
+        new = g_code_buffer_prepare_new_line(buffer, range);
+        g_buffer_line_start_merge_at(new, BLC_DISPLAY);
+        g_buffer_line_insert_text(new, BLC_DISPLAY, token, len, RTT_COMMENT);
+
+        extra = (GBufferLine **)realloc(extra, ++extra_count * sizeof(GBufferLine *));
+
+        extra[extra_count - 1] = new;
+
+        result = true;
+
+    }
+
+    free(wcopy);
+
+    if (extra_count > 0)
+    {
+        result &= g_code_buffer_insert_lines(buffer, extra, extra_count, line, before);
+
+        if (!result)
+            for (i = 0; i < extra_count; i++)
+                g_object_unref(G_OBJECT(extra[i]));
+
+        free(extra);
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : buffer  = tampon de lignes à consulter.                      *
+*                line    = ligne à l'intérieur d'un commentaire.              *
+*                comment = nouveau commentaire à inscrire à la ligne donnée.  *
+*                before  = précise la position du commentaire.                *
+*                                                                             *
+*  Description : Affiche un commentaire sur une ligne de tampon dédiée.       *
+*                                                                             *
+*  Retour      : Bilan de l'opération : ajout ou non ?                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_code_buffer_update_comment_area(GCodeBuffer *buffer, GBufferLine *line, const char *comment, bool before)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    if (g_buffer_line_has_comment(line))
+        result = _g_code_buffer_delete_lines_comment(buffer, line);
+    else
+        result = true;
+
+    if (result)
+        result = _g_code_buffer_write_comment_area(buffer, line, comment, before);
+
+    /* TODO : emit() */
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : buffer = tampon de lignes à consulter.                       *
+*                index  = indice de ligne à l'intérieur d'un commentaire.     *
+*                                                                             *
+*  Description : Retrouve la première ligne d'une zone de commentaire.        *
+*                                                                             *
+*  Retour      : Indice de l'adresse trouvée, ou le nombre de lignes sinon.   *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static size_t g_code_buffer_find_first_line_comment(const GCodeBuffer *buffer, size_t index)
+{
+    size_t result;                          /* Indice trouvé à retourner   */
+    GBufferLine *prev;                      /* Ligne précédente            */
+
+    assert(index < buffer->used);
+
+    bool is_first_line_of_comment(const GBufferLine *ln, const GBufferLine *pv)
+    {
+        bool first;                         /* Statut à renvoyer           */
+        BufferLineColumn merge_col;         /* Colonne de fusion #1        */
+        BufferLineColumn prev_merge_col;    /* Colonne de fusion #2        */
+
+        merge_col = g_buffer_line_get_merge_start(ln);
+
+        /**
+         * La ligne consultée contient toujours un commentaire.
+         *
+         * Deux cas de figures sont possibles ici :
+         *
+         *  - soit du texte est présent dans la colonne "commentaires".
+         *    Si du texte est présent avant, alors il s'agit forcément de
+         *    la première (et unique ?) ligne de commentaire.
+         *
+         *  - soit la ligne effectue une fusion des colonnes depuis BLC_DISPLAY.
+         *    Si la ligne qui précède fait de même, il s'agit alors d'une étiquette
+         *    ou de l'amont du commentaire.
+         *
+         */
+
+        if (g_buffer_line_has_text(ln, BLC_COMMENTS, BLC_COUNT))
+        {
+            first = g_buffer_line_has_text(ln, BLC_DISPLAY, BLC_COMMENTS);
+
+            if (!first)
+            {
+                /* La ligne d'avant doit avoir un commentaire ! */
+                first = !g_buffer_line_has_text(pv, BLC_COMMENTS, BLC_COUNT);
+            }
+
+        }
+
+        else
+        {
+            /**
+             * Le prologue "merge_col == BLC_FIRST" n'étant pas éditable,
+             * la seule fusion possible ici est la suivante.
+             */
+            assert(merge_col == BLC_DISPLAY);
+
+            /**
+             * La première ligne d'un tampon est toujours un prologue.
+             */
+            assert(pv != NULL);
+
+            prev_merge_col = g_buffer_line_get_merge_start(pv);
+
+            first = (prev_merge_col != BLC_DISPLAY);
+
+            if (!first)
+                first = (g_buffer_line_get_flags(pv) & BLF_IS_LABEL);
+
+        }
+
+        return first;
+
+    }
+
+    for (result = index; result > 0; result--)
+    {
+        prev = (result > 0 ? buffer->lines[result - 1] : NULL);
+
+        if (is_first_line_of_comment(buffer->lines[result], prev))
+            break;
+
+    }
+
+    if (result == 0)
+    {
+        if (!is_first_line_of_comment(buffer->lines[0], NULL))
+            result = buffer->used;
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : buffer = tampon de lignes à consulter.                       *
+*                index  = indice de ligne à l'intérieur d'un commentaire.     *
+*                                                                             *
+*  Description : Retrouve la dernière ligne d'une zone de commentaire.        *
+*                                                                             *
+*  Retour      : Indice de l'adresse trouvée, ou le nombre de lignes sinon.   *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static size_t g_code_buffer_find_last_line_comment(const GCodeBuffer *buffer, size_t index)
+{
+    size_t result;                          /* Indice trouvé à retourner   */
+    GBufferLine *next;                      /* Ligne suivante              */
+
+    assert(index < buffer->used);
+
+    bool is_last_line_of_comment(const GBufferLine *ln, const GBufferLine *nx)
+    {
+        bool last;                          /* Statut à renvoyer           */
+        BufferLineColumn merge_col;         /* Colonne de fusion #1        */
+        BufferLineColumn next_merge_col;    /* Colonne de fusion #2        */
+
+        merge_col = g_buffer_line_get_merge_start(ln);
+
+        /**
+         * La ligne consultée contient toujours un commentaire.
+         *
+         * Deux cas de figures sont possibles ici :
+         *
+         *  - soit du texte est présent dans la colonne "commentaires".
+         *    Si la ligne suivante est similaire et si du texte est présent avant,
+         *    alors il s'agit forcément de d'un nouveau commentaire. S'il n'y a
+         *    aucun texte, il s'agit de la suite du commentaire.
+         *
+         *  - soit la ligne effectue une fusion des colonnes depuis BLC_DISPLAY.
+         *    Si la ligne qui suit fait de même, il s'agit alors d'une étiquette
+         *    ou de l'aval du commentaire.
+         *
+         */
+
+        if (g_buffer_line_has_text(ln, BLC_COMMENTS, BLC_COUNT))
+        {
+            last = !g_buffer_line_has_text(nx, BLC_COMMENTS, BLC_COUNT);
+
+            if (!last)
+                last = g_buffer_line_has_text(nx, BLC_DISPLAY, BLC_COMMENTS);
+
+        }
+
+        else
+        {
+            /**
+             * Le prologue "merge_col == BLC_FIRST" n'étant pas éditable,
+             * la seule fusion possible ici est la suivante.
+             */
+            assert(merge_col == BLC_DISPLAY);
+
+            if (nx == NULL)
+                last = true;
+
+            else
+            {
+                next_merge_col = g_buffer_line_get_merge_start(nx);
+
+                last = (next_merge_col != BLC_DISPLAY);
+
+                if (!last)
+                    last = (g_buffer_line_get_flags(nx) & BLF_IS_LABEL);
+
+            }
+
+        }
+
+        return last;
+
+    }
+
+    for (result = index; result < buffer->used; result++)
+    {
+        next = ((result + 1) < buffer->used ? buffer->lines[result + 1] : NULL);
+
+        if (is_last_line_of_comment(buffer->lines[result], next))
+            break;
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : buffer = tampon de lignes à consulter.                       *
+*                line   = ligne à l'intérieur d'un commentaire.               *
+*                                                                             *
+*  Description : Récupère le contenu d'un commentaire existant.               *
+*                                                                             *
+*  Retour      : Commentaire retrouver à libérer ou NULL en cas d'échec.      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+char *g_code_buffer_get_lines_comment(const GCodeBuffer *buffer, const GBufferLine *line)
+{
+    char *result;                           /* Contenu à retourner         */
+    size_t index;                           /* Indice de la ligne fournie  */
+    size_t start;                           /* Ligne de départ             */
+    size_t end;                             /* Ligne d'arrivée             */
+    BufferLineColumn merge_col;             /* Colonne de fusion           */
+    size_t i;                               /* Boucle de parcours          */
+    char *extra;                            /* Commentaire supplémentaire  */
+
+    /* Pas de prologue ici ! */
+    assert(g_buffer_line_has_comment(line));
+
+    result = NULL;
+
+    index = g_code_buffer_find_index_by_line(buffer, line);
+
+    if (index == buffer->used)
+        goto gcbglc_exit;
+
+    start = g_code_buffer_find_first_line_comment(buffer, index);
+
+    if (start == buffer->used)
+        goto gcbglc_exit;
+
+    end = g_code_buffer_find_last_line_comment(buffer, index);
+
+    if (end == buffer->used)
+        goto gcbglc_exit;
+
+    merge_col = g_buffer_line_get_merge_start(line);
+
+    for (i = start; i <= end; i++)
+    {
+        if (merge_col == BLC_DISPLAY)
+            extra = g_buffer_line_get_text(buffer->lines[i], BLC_DISPLAY, BLC_COUNT, false);
+
+        else
+            extra = g_buffer_line_get_text(buffer->lines[i], BLC_COMMENTS, BLC_COUNT, false);
+
+        assert(extra != NULL);
+
+        if (result == NULL)
+            result = extra;
+
+        else
+        {
+            result = stradd(result, extra);
+            free(extra);
+        }
+
+    }
+
+ gcbglc_exit:
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : buffer = tampon de lignes à modifier.                        *
+*                line   = ligne à l'intérieur d'un commentaire.               *
+*                                                                             *
+*  Description : Supprime un commentaire existant.                            *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool _g_code_buffer_delete_lines_comment(GCodeBuffer *buffer, GBufferLine *line)
+{
+    bool result;                            /* Bilan à retourner           */
+    size_t index;                           /* Indice de la ligne fournie  */
+    size_t start;                           /* Ligne de départ             */
+    size_t end;                             /* Ligne d'arrivée             */
+    BufferLineColumn merge_col;             /* Colonne de fusion           */
+
+    /* Pas de prologue ici ! */
+    assert(g_buffer_line_has_comment(line));
+
+    result = false;
+
+    index = g_code_buffer_find_index_by_line(buffer, line);
+
+    if (index == buffer->used)
+        goto gcbdlc_exit;
+
+    start = g_code_buffer_find_first_line_comment(buffer, index);
+
+    if (start == buffer->used)
+        goto gcbdlc_exit;
+
+    end = g_code_buffer_find_last_line_comment(buffer, index);
+
+    if (end == buffer->used)
+        goto gcbdlc_exit;
+
+    result = true;
+
+    merge_col = g_buffer_line_get_merge_start(line);
+
+    if (merge_col == BLC_DISPLAY)
+        g_code_buffer_delete_lines(buffer, start, end);
+
+    else
+    {
+        g_buffer_line_delete_text(buffer->lines[start], BLC_COMMENTS, BLC_COUNT);
+
+        if (end > start)
+            g_code_buffer_delete_lines(buffer, start + 1, end);
+
+    }
+
+ gcbdlc_exit:
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : buffer = tampon de lignes à modifier.                        *
+*                line   = ligne à l'intérieur d'un commentaire.               *
+*                                                                             *
+*  Description : Supprime un commentaire existant.                            *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_code_buffer_delete_lines_comment(GCodeBuffer *buffer, GBufferLine *line)
+{
+    _g_code_buffer_delete_lines_comment(buffer, line);
+
+    /* TODO : emit() */
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
 /*                            TAMPON POUR CODE DESASSEMBLE                            */
 /* ---------------------------------------------------------------------------------- */
 
@@ -642,6 +1245,34 @@ static void g_code_buffer_update_line_max_widths(const GCodeBuffer *buffer, size
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : buffer = composant GLib à consulter.                         *
+*                range  = emplacement où va se situer la ligne.               *
+*                                                                             *
+*  Description : Initie une nouvelle ligne devant être insérée dans le tampon.*
+*                                                                             *
+*  Retour      : Nouvelle ligne vierge à écrire.                              *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GBufferLine *g_code_buffer_prepare_new_line(GCodeBuffer *buffer, const mrange_t *range)
+{
+    GBufferLine *result;                    /* Instance à retourner        */
+    size_t i;                               /* Boucle de parcours          */
+
+    result = g_buffer_line_new(range, buffer->main_column);
+
+    for (i = 0; i < buffer->indent; i++)
+        g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, "    ", 4, RTT_RAW);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : line    = ligne dont la définition vient d'évoluer.          *
 *                segment = éventuel segment qui vient d'évoluer ou NULL.      *
 *                buffer  = tampon de lignes cohérentes à manipuler.           *
@@ -686,41 +1317,64 @@ static void on_line_flag_flip(GBufferLine *line, BufferLineFlags old, BufferLine
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : buffer = composant GLib à mettre à jour.                     *
-*                range  = emplacement où va se situer la ligne.               *
+*                lines  = liste de lignes à insérer.                          *
+*                count  = taille de cette liste.                              *
+*                index  = point d'insertion de la première ligne.             *
 *                                                                             *
-*  Description : Ajoute une nouvelle ligne à une position donnée.             *
+*  Description : Ajoute de nouvelles lignes à une position donnée.            *
 *                                                                             *
-*  Retour      : Nouvelle ligne vierge à écrire.                              *
+*  Retour      : -                                                            *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static GBufferLine *g_code_buffer_create_new_line(GCodeBuffer *buffer, size_t index, const mrange_t *range)
+static void g_code_buffer_insert_lines_at(GCodeBuffer *buffer, GBufferLine **lines, size_t count, size_t index)
 {
-    GBufferLine *result;                    /* Instance à retourner        */
     size_t i;                               /* Boucle de parcours          */
 
-    if (buffer->used == buffer->count)
+    /* Elaboration d'un espace suffisant */
+
+    if ((buffer->used + count) > buffer->count)
     {
-        buffer->count += LINE_ALLOC_BULK;
+        if (count > LINE_ALLOC_BULK)
+            buffer->count += count;
+        else
+            buffer->count += LINE_ALLOC_BULK;
+
         buffer->lines = (GBufferLine **)realloc(buffer->lines,
                                                 buffer->count * sizeof(GBufferLine *));
+
     }
 
-    buffer->used++;
-    assert(index < buffer->used);
+    /* Insertion des lignes */
 
-    result = g_buffer_line_new(range, buffer->main_column);
-    buffer->lines[index] = result;
+    if (index < buffer->used)
+    {
+        memmove(&buffer->lines[index + count], &buffer->lines[index],
+                (buffer->used - index) * sizeof(GBufferLine *));
+    }
 
-    for (i = 0; i < buffer->indent; i++)
-        g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, "    ", 4, RTT_RAW);
+    buffer->used += count;
 
-    g_signal_connect(result, "content-changed", G_CALLBACK(on_line_content_change), buffer);
-    g_signal_connect(result, "flip-flag", G_CALLBACK(on_line_flag_flip), buffer);
+    for (i = 0; i < count; i++)
+    {
+        assert((index + i) < buffer->used);
 
-    return result;
+        buffer->lines[index + i] = lines[i];
+
+        g_signal_connect(lines[i], "content-changed", G_CALLBACK(on_line_content_change), buffer);
+        g_signal_connect(lines[i], "flip-flag", G_CALLBACK(on_line_flag_flip), buffer);
+
+    }
+
+    /* Recueil initial des largeurs */
+
+    /**
+     * Comme des optimisations reposant sur des cas particuliers peuvent être
+     * réalisées ici, c'est à l'appelant de prendre cette charge de calculs à
+     * son compte !
+     */
 
 }
 
@@ -728,21 +1382,78 @@ static GBufferLine *g_code_buffer_create_new_line(GCodeBuffer *buffer, size_t in
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : buffer = composant GLib à mettre à jour.                     *
-*                range  = emplacement où va se situer la ligne.               *
+*                line   = lign à insérer à la fin du tampon.                  *
 *                                                                             *
-*  Description : Ajoute une nouvelle ligne à un tampon pour code désassemblé. *
+*  Description : Ajoute une nouvelle ligne en fin de tampon.                  *
 *                                                                             *
-*  Retour      : Nouvelle ligne vierge à écrire.                              *
+*  Retour      : -                                                            *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-GBufferLine *g_code_buffer_append_new_line(GCodeBuffer *buffer, const mrange_t *range)
+void g_code_buffer_append_new_line(GCodeBuffer *buffer, GBufferLine *line)
 {
-    GBufferLine *result;                    /* Instance à retourner        */
+    GBufferLine *manager;                   /* Ligne de gestion de largeurs*/
 
-    result = g_code_buffer_create_new_line(buffer, buffer->used, range);
+    g_code_buffer_insert_lines_at(buffer, (GBufferLine *[]) { line }, 1, buffer->used);
+
+    /* Recueil initial des largeurs */
+
+    if (g_buffer_line_get_flags(line) & BLF_WIDTH_MANAGER)
+        manager = line;
+
+    else
+    {
+        assert(buffer->used > 1);
+        manager = g_buffer_line_get_width_manager(buffer->lines[buffer->used - 2]);
+    }
+
+    g_buffer_line_update_max_widths(line, manager);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : buffer = composant GLib à mettre à jour.                     *
+*                lines  = liste de lignes à insérer.                          *
+*                count  = taille de cette liste.                              *
+*                point  = point d'insertion du bloc de ligne.                 *
+*                before = emplacement de l'insertion par rapport au point.    *
+*                                                                             *
+*  Description : Ajoute de nouvelles lignes par rapport à une ligne donnée.   *
+*                                                                             *
+*  Retour      : Bilan : insertion réussie ou non ?                           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_code_buffer_insert_lines(GCodeBuffer *buffer, GBufferLine **lines, size_t count, const GBufferLine *point, bool before)
+{
+    bool result;                            /* Bilan à retourner           */
+    size_t index;                           /* Indice d'insertion final    */
+
+    result = false;
+
+    index = g_code_buffer_find_index_by_line(buffer, point);
+
+    if (index == buffer->used)
+        goto gcbil_exit;
+
+    if (!before)
+        index++;
+
+    g_code_buffer_insert_lines_at(buffer, lines, count, index);
+
+
+    g_code_buffer_update_line_max_widths(buffer, index, index + count);
+
+
+    result = true;
+
+ gcbil_exit:
 
     return result;
 
@@ -751,6 +1462,45 @@ GBufferLine *g_code_buffer_append_new_line(GCodeBuffer *buffer, const mrange_t *
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : buffer = composant GLib à mettre à jour.                     *
+*                start  = première ligne devant être supprimée.               *
+*                end    = dernière ligne devant être supprimée.               *
+*                                                                             *
+*  Description : Supprime une ou plusieurs lignes du tampon indiqué.          *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_code_buffer_delete_lines(GCodeBuffer *buffer, size_t start, size_t end)
+{
+    size_t i;                               /* Boucle de parcours          */
+    GBufferLine *line;                      /* Ligne en cours de traitement*/
+
+    assert(start < buffer->used);
+    assert(end < buffer->used);
+
+    for (i = start; i <= end; i++)
+    {
+        line = buffer->lines[i];
+
+        g_signal_handlers_disconnect_by_func(line, G_CALLBACK(on_line_content_change), buffer);
+        g_signal_handlers_disconnect_by_func(line, G_CALLBACK(on_line_flag_flip), buffer);
+
+        g_object_unref(G_OBJECT(line));
+
+    }
+
+    memmove(&buffer->lines[start], &buffer->lines[end + 1],
+            (buffer->used - end - 1) * sizeof(GBufferLine *));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : buffer = composant GTK à mettre à jour.                      *
 *                addr   = adresse où retrouver la ligne recherchée.           *
 *                flags  = propriétés à vérifier en tout ou partie.            *
@@ -844,7 +1594,7 @@ GBufferLine *g_code_buffer_find_line_by_index(const GCodeBuffer *buffer, size_t
 *                                                                             *
 ******************************************************************************/
 
-static size_t g_code_buffer_find_index_by_line(const GCodeBuffer *buffer, const GBufferLine *line)
+size_t g_code_buffer_find_index_by_line(const GCodeBuffer *buffer, const GBufferLine *line)
 {
     size_t result;                          /* Indice trouvé à retourner   */
     const mrange_t *range;                  /* Emplacement de la ligne     */
@@ -1289,7 +2039,7 @@ static void g_buffer_view_compute_required_widths(GBufferView *view, const bool
 
     if (view->buffer->used > 0)
     {
-        g_code_buffer_update_line_max_widths(view->buffer, first, last);
+        //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);
diff --git a/src/glibext/gcodebuffer.h b/src/glibext/gcodebuffer.h
index 86e94d2..0f2d601 100644
--- a/src/glibext/gcodebuffer.h
+++ b/src/glibext/gcodebuffer.h
@@ -57,22 +57,38 @@ GType g_code_buffer_get_type(void);
 /* Crée un nouveau composant de tampon pour code désassemblé. */
 GCodeBuffer *g_code_buffer_new(BufferLineColumn);
 
+/* Initie une nouvelle ligne devant être insérée dans le tampon. */
+GBufferLine *g_code_buffer_prepare_new_line(GCodeBuffer *, const mrange_t *);
+
+/* Ajoute une nouvelle ligne en fin de tampon. */
+void g_code_buffer_append_new_line(GCodeBuffer *, GBufferLine *);
+
+/* Ajoute de nouvelles lignes par rapport à une ligne donnée. */
+bool g_code_buffer_insert_lines(GCodeBuffer *, GBufferLine **, size_t, const GBufferLine *, bool);
+
+/* Supprime une ou plusieurs lignes du tampon indiqué. */
+void g_code_buffer_delete_lines(GCodeBuffer *, size_t, size_t);
+
+
+
 /* FIXME */
 #define g_code_buffer_append_new_line_fixme(b) \
     g_code_buffer_append_new_line(b, (mrange_t []){ { 0, 0 }, 0 })
 
-/* Ajoute une nouvelle ligne à un tampon pour code désassemblé. */
-GBufferLine *g_code_buffer_append_new_line(GCodeBuffer *, const mrange_t *);
-
 /* FIXME */
 #define g_code_buffer_insert_at(buf, a, b) NULL
 
+
+
 /* Retrouve une ligne au sein d'un tampon avec une adresse. */
 GBufferLine *g_code_buffer_find_line_by_addr(const GCodeBuffer *, const vmpa2t *, BufferLineFlags, size_t *);
 
 /* Retrouve une ligne au sein d'un tampon avec un indice. */
 GBufferLine *g_code_buffer_find_line_by_index(const GCodeBuffer *, size_t);
 
+/* Retrouve l'indice associé à une ligne au sein d'un tampon. */
+size_t g_code_buffer_find_index_by_line(const GCodeBuffer *, const GBufferLine *);
+
 /* Augmente l'indentation des prochaines lignes. */
 void g_code_buffer_inc_indentation(GCodeBuffer *);
 
@@ -87,6 +103,27 @@ GDelayedWork *g_buffer_code_scan(GCodeBuffer *, const vmpa2t *, const vmpa2t *,
 
 
 
+/* ------------------------- CONFORTS POUR LES COMMENTAIRES ------------------------- */
+
+
+/* Séparateur commun à tous les plateformes */
+#define COMMENT_LINE_SEP "\n"
+
+
+/* Affiche un commentaire sur une ligne de tampon donnée. */
+bool g_code_buffer_update_inlined_comment(GCodeBuffer *, GBufferLine *, const char *);
+
+/* Affiche un commentaire sur une ligne de tampon dédiée. */
+bool g_code_buffer_update_comment_area(GCodeBuffer *, GBufferLine *, const char *, bool);
+
+/* Récupère le contenu d'un commentaire existant. */
+char *g_code_buffer_get_lines_comment(const GCodeBuffer *, const GBufferLine *);
+
+/* Supprime un commentaire existant. */
+bool g_code_buffer_delete_lines_comment(GCodeBuffer *, GBufferLine *);
+
+
+
 /* ---------------------- VUE PARTICULIERE D'UN TAMPON DE CODE ---------------------- */
 
 
-- 
cgit v0.11.2-87-g4458