From 56f7524c4fd0fc14a509be7689f4820b31564dbc Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Sun, 23 Oct 2016 18:22:50 +0200
Subject: Deleted a level of data to reduce the memory fingerprint.

---
 ChangeLog                             |   74 ++
 plugins/androhelpers/switch.c         |    6 +-
 plugins/androhelpers/try_n_catch.c    |    4 +-
 src/analysis/db/items/switcher.c      |   26 +-
 src/analysis/disass/output.c          |   14 +-
 src/analysis/routine.c                |   14 +-
 src/analysis/types/basic.c            |    2 +-
 src/analysis/types/cse.c              |    4 +-
 src/analysis/types/encaps.c           |    2 +-
 src/analysis/types/literal.c          |    2 +-
 src/analysis/types/template.c         |    6 +-
 src/analysis/variable.c               |    4 +-
 src/arch/arm/v7/cregister.c           |    2 +-
 src/arch/arm/v7/operands/coproc.c     |    2 +-
 src/arch/arm/v7/operands/estate.c     |    4 +-
 src/arch/arm/v7/operands/limitation.c |   18 +-
 src/arch/arm/v7/operands/maccess.c    |   16 +-
 src/arch/arm/v7/operands/offset.c     |    2 +-
 src/arch/arm/v7/operands/reglist.c    |    8 +-
 src/arch/arm/v7/operands/rotation.c   |    4 +-
 src/arch/arm/v7/operands/shift.c      |   12 +-
 src/arch/arm/v7/register.c            |    2 +-
 src/arch/dalvik/operands/args.c       |    8 +-
 src/arch/dalvik/operands/pool.c       |   36 +-
 src/arch/dalvik/register.c            |    2 +-
 src/arch/instruction.c                |    6 +-
 src/arch/operand.c                    |    5 +-
 src/arch/raw.c                        |   20 +-
 src/arch/target.c                     |    4 +-
 src/arch/undefined.c                  |    2 +-
 src/arch/x86/register.c               |    2 +-
 src/decomp/expr/access.c              |    2 +-
 src/decomp/expr/arithm.c              |    2 +-
 src/decomp/expr/array.c               |    4 +-
 src/decomp/expr/assign.c              |    2 +-
 src/decomp/expr/call.c                |   10 +-
 src/decomp/expr/dalvik/array.c        |    4 +-
 src/decomp/expr/pseudo.c              |    4 +-
 src/decomp/expr/return.c              |    4 +-
 src/decomp/expr/text.c                |    6 +-
 src/decomp/expression.c               |    2 +-
 src/decomp/instr/ite.c                |    4 +-
 src/decomp/instr/keyword.c            |    4 +-
 src/decomp/instr/switch.c             |   24 +-
 src/decomp/lang/asm.c                 |   28 +-
 src/decomp/lang/java.c                |   74 +-
 src/format/dex/class.c                |    2 +-
 src/glibext/Makefile.am               |    3 +-
 src/glibext/gbinportion.c             |   14 +-
 src/glibext/gbufferline.c             |  806 +++-----------------
 src/glibext/gbufferline.h             |   31 +-
 src/glibext/gbuffersegment.c          | 1333 ---------------------------------
 src/glibext/gbuffersegment.h          |  203 -----
 src/glibext/gbufferview.c             |  112 +--
 src/glibext/gbufferview.h             |    2 +-
 src/glibext/gcodebuffer.c             |    8 +-
 src/glibext/linecolumn.c              |  480 ++++++++++++
 src/glibext/linecolumn.h              |   93 +++
 src/glibext/linesegment.c             | 1155 ++++++++++++++++++++++++++++
 src/glibext/linesegment.h             |  196 +++++
 src/gtkext/gtkbufferview.c            |    3 +
 src/gui/core/core.c                   |    6 +-
 src/gui/dialogs/export.c              |    2 +-
 63 files changed, 2387 insertions(+), 2549 deletions(-)
 delete mode 100644 src/glibext/gbuffersegment.c
 delete mode 100644 src/glibext/gbuffersegment.h
 create mode 100644 src/glibext/linecolumn.c
 create mode 100644 src/glibext/linecolumn.h
 create mode 100644 src/glibext/linesegment.c
 create mode 100644 src/glibext/linesegment.h

diff --git a/ChangeLog b/ChangeLog
index 11da097..3a5e6e8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,79 @@
 16-10-23  Cyrille Bagard <nocbos@gmail.com>
 
+	* plugins/androhelpers/switch.c:
+	* plugins/androhelpers/try_n_catch.c:
+	* src/analysis/db/items/switcher.c:
+	* src/analysis/disass/output.c:
+	* src/analysis/routine.c:
+	* src/analysis/types/basic.c:
+	* src/analysis/types/cse.c:
+	* src/analysis/types/encaps.c:
+	* src/analysis/types/literal.c:
+	* src/analysis/types/template.c:
+	* src/analysis/variable.c:
+	* src/arch/arm/v7/cregister.c:
+	* src/arch/arm/v7/operands/coproc.c:
+	* src/arch/arm/v7/operands/estate.c:
+	* src/arch/arm/v7/operands/limitation.c:
+	* src/arch/arm/v7/operands/maccess.c:
+	* src/arch/arm/v7/operands/offset.c:
+	* src/arch/arm/v7/operands/reglist.c:
+	* src/arch/arm/v7/operands/rotation.c:
+	* src/arch/arm/v7/operands/shift.c:
+	* src/arch/arm/v7/register.c:
+	* src/arch/dalvik/operands/args.c:
+	* src/arch/dalvik/operands/pool.c:
+	* src/arch/dalvik/register.c:
+	* src/arch/instruction.c:
+	* src/arch/operand.c:
+	* src/arch/raw.c:
+	* src/arch/target.c:
+	* src/arch/undefined.c:
+	* src/arch/x86/register.c:
+	* src/decomp/expr/access.c:
+	* src/decomp/expr/arithm.c:
+	* src/decomp/expr/array.c:
+	* src/decomp/expr/assign.c:
+	* src/decomp/expr/call.c:
+	* src/decomp/expr/dalvik/array.c:
+	* src/decomp/expression.c:
+	* src/decomp/expr/pseudo.c:
+	* src/decomp/expr/return.c:
+	* src/decomp/expr/text.c:
+	* src/decomp/instr/ite.c:
+	* src/decomp/instr/keyword.c:
+	* src/decomp/instr/switch.c:
+	* src/decomp/lang/asm.c:
+	* src/decomp/lang/java.c:
+	* src/format/dex/class.c:
+	* src/glibext/gbinportion.c:
+	Update code.
+
+	* src/glibext/gbufferline.c:
+	* src/glibext/gbufferline.h:
+	* src/glibext/gbuffersegment.c:
+	* src/glibext/gbuffersegment.h:
+	* src/glibext/gbufferview.c:
+	* src/glibext/gbufferview.h:
+	* src/glibext/gcodebuffer.c:
+	Delete a level of data to reduce the memory fingerprint.
+
+	* src/glibext/linecolumn.c:
+	* src/glibext/linecolumn.h:
+	New entries: delete a level of data to reduce the memory fingerprint.
+
+	* src/glibext/linesegment.c:
+	* src/glibext/linesegment.h:
+	Renamed entries: delete a level of data to reduce the memory fingerprint.
+
+	* src/glibext/Makefile.am:
+	* src/gtkext/gtkbufferview.c:
+	* src/gui/core/core.c:
+	* src/gui/dialogs/export.c:
+	Update code.
+
+16-10-23  Cyrille Bagard <nocbos@gmail.com>
+
 	* src/arch/immediate.c:
 	* src/arch/target.c:
 	Update code.
diff --git a/plugins/androhelpers/switch.c b/plugins/androhelpers/switch.c
index 20b2119..2434897 100644
--- a/plugins/androhelpers/switch.c
+++ b/plugins/androhelpers/switch.c
@@ -286,7 +286,7 @@ static void mark_all_switch_cases(const GArchInstruction *instr, const dex_switc
         fulldesc = (char *)calloc(len + 1, sizeof(char));
         len = snprintf(fulldesc, len + 1, _("; Case for value 0x%08x (%d)"), value, value);
 
-        g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, fulldesc, len, RTT_INDICATION);
+        g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, fulldesc, len, RTT_INDICATION, NULL);
 
         free(fulldesc);
 
@@ -304,8 +304,8 @@ static void mark_all_switch_cases(const GArchInstruction *instr, const dex_switc
         g_buffer_line_start_merge_at(line, BLC_ASSEMBLY_HEAD);
 
         fulldesc = _("; Default case");
-        g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD,
-                                  fulldesc, strlen(fulldesc), RTT_INDICATION);
+        g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD,
+                                  fulldesc, strlen(fulldesc), RTT_INDICATION, NULL);
 
     }
 
diff --git a/plugins/androhelpers/try_n_catch.c b/plugins/androhelpers/try_n_catch.c
index 0e2ae43..7e39327 100644
--- a/plugins/androhelpers/try_n_catch.c
+++ b/plugins/androhelpers/try_n_catch.c
@@ -204,13 +204,13 @@ static void mark_exception_handlers(const GLoadedBinary *binary, uleb128_t size,
             line = g_code_buffer_insert_at(buffer, handlers[i][j].addr, true);
             g_buffer_line_start_merge_at(line, BLC_ASSEMBLY_HEAD);
 
-            g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "; ", 2, RTT_INDICATION);
+            g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, "; ", 2, RTT_INDICATION, NULL);
 
             len = strlen(_("Handler for caught '%s'")) + strlen(handlers[i][j].desc);
             fulldesc = (char *)calloc(len + 1, sizeof(char));
             snprintf(fulldesc, len + 1, _("Handler for caught '%s'"), handlers[i][j].desc);
 
-            g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, fulldesc, len, RTT_INDICATION);
+            g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, fulldesc, len, RTT_INDICATION, NULL);
 
             free(fulldesc);
 
diff --git a/src/analysis/db/items/switcher.c b/src/analysis/db/items/switcher.c
index a67040f..08a5a5f 100644
--- a/src/analysis/db/items/switcher.c
+++ b/src/analysis/db/items/switcher.c
@@ -502,7 +502,6 @@ static bool g_db_switcher_run(GDbSwitcher *switcher, GLoadedBinary *binary, ImmO
     GArchOperand *op;                       /* Opérande à modifier         */
     GCodeBuffer *buffer;                    /* Tampon de lignes à traiter  */
     GBufferLine *line;                      /* Ligne de tampon à marquer   */
-    GBufferSegment *segment;                /* Segment de texte  à modifier*/
     GImmOperand *operand;                   /* Opérande de valeur immédiate*/
     char value[IMM_MAX_SIZE];               /* Chaîne à imprimer           */
     size_t len;                             /* Taille de l'élément inséré  */
@@ -541,29 +540,18 @@ static bool g_db_switcher_run(GDbSwitcher *switcher, GLoadedBinary *binary, ImmO
         goto exit_gui;
     }
 
-    segment = g_buffer_line_find_segment_from_creator(line, G_OBJECT(op));
-    result = (segment != NULL);
+    operand = G_IMM_OPERAND(op);
 
-    /* Applications globales finales */
+    *old = g_imm_operand_get_display(operand);
 
-    if (result)
-    {
-        operand = G_IMM_OPERAND(op);
-
-        *old = g_imm_operand_get_display(operand);
-
-        if (new == IOD_COUNT)
-            new = g_imm_operand_get_default_display(operand);
+    if (new == IOD_COUNT)
+        new = g_imm_operand_get_default_display(operand);
 
-        g_imm_operand_set_display(operand, new);
+    g_imm_operand_set_display(operand, new);
 
-        len = g_imm_operand_to_string(operand, ASX_INTEL, value);
+    len = g_imm_operand_to_string(operand, ASX_INTEL, value);
 
-        g_buffer_segment_update_text(segment, value, len);
-
-        g_object_unref(G_OBJECT(segment));
-
-    }
+    result = g_buffer_line_replace_text(line, G_OBJECT(op), value, len);
 
     g_object_unref(G_OBJECT(line));
 
diff --git a/src/analysis/disass/output.c b/src/analysis/disass/output.c
index fb3f5ed..4fdc3c0 100644
--- a/src/analysis/disass/output.c
+++ b/src/analysis/disass/output.c
@@ -147,8 +147,8 @@ void print_disassembled_instructions(GCodeBuffer *buffer, GExeFormat *format, GA
             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,
-                                      ROUTINE_OUTRO_MSG, strlen(ROUTINE_OUTRO_MSG), RTT_COMMENT);
+            g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD,
+                                      ROUTINE_OUTRO_MSG, strlen(ROUTINE_OUTRO_MSG), RTT_COMMENT, NULL);
 
             g_code_buffer_append_new_line(buffer, line);
 
@@ -223,8 +223,8 @@ void print_disassembled_instructions(GCodeBuffer *buffer, GExeFormat *format, GA
                     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,
-                                              ROUTINE_INTRO_MSG, strlen(ROUTINE_INTRO_MSG), RTT_COMMENT);
+                    g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD,
+                                              ROUTINE_INTRO_MSG, strlen(ROUTINE_INTRO_MSG), RTT_COMMENT, NULL);
 
                     g_code_buffer_append_new_line(buffer, line);
 
@@ -255,8 +255,8 @@ void print_disassembled_instructions(GCodeBuffer *buffer, GExeFormat *format, GA
                     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_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, label, strlen(label), RTT_LABEL, NULL);
+                    g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, ":", 1, RTT_PUNCT, NULL);
 
                     g_code_buffer_append_new_line(buffer, line);
 
@@ -311,7 +311,7 @@ void print_disassembled_instructions(GCodeBuffer *buffer, GExeFormat *format, GA
 
 
 
-                    g_buffer_line_insert_text(line, BLC_COMMENTS, prefixed, strlen(prefixed), RTT_COMMENT);
+                    g_buffer_line_append_text(line, BLC_COMMENTS, prefixed, strlen(prefixed), RTT_COMMENT, NULL);
 
 
                     free(prefixed);
diff --git a/src/analysis/routine.c b/src/analysis/routine.c
index 7483bf0..ed91726 100644
--- a/src/analysis/routine.c
+++ b/src/analysis/routine.c
@@ -1033,7 +1033,7 @@ void g_binary_routine_output_info(const GBinRoutine *routine, GLangOutput *lang,
 
     g_data_type_output(routine->ret_type, lang, line, true, false);
 
-    g_buffer_line_insert_text(line, BLC_LAST_USED, " ", 1, RTT_COMMENT);
+    g_buffer_line_append_text(line, BLC_LAST_USED, " ", 1, RTT_COMMENT, NULL);
 
     /* Nom de la routine */
 
@@ -1045,22 +1045,22 @@ void g_binary_routine_output_info(const GBinRoutine *routine, GLangOutput *lang,
         len = 3;
     }
 
-    g_buffer_line_insert_text(line, BLC_LAST_USED, name, len, RTT_COMMENT);
+    g_buffer_line_append_text(line, BLC_LAST_USED, name, len, RTT_COMMENT, NULL);
 
     /* Arguments éventuels... */
 
-    g_buffer_line_insert_text(line, BLC_LAST_USED, "(", 1, RTT_COMMENT);
+    g_buffer_line_append_text(line, BLC_LAST_USED, "(", 1, RTT_COMMENT, NULL);
 
     for (i = 0; i < routine->args_count; i++)
     {
         if (i > 0)
-            g_buffer_line_insert_text(line, BLC_LAST_USED, ", ", 2, RTT_COMMENT);
+            g_buffer_line_append_text(line, BLC_LAST_USED, ", ", 2, RTT_COMMENT, NULL);
 
         g_binary_variable_output(routine->args[i], lang, line, true, false);
 
     }
 
-    g_buffer_line_insert_text(line, BLC_LAST_USED, ")", 1, RTT_COMMENT);
+    g_buffer_line_append_text(line, BLC_LAST_USED, ")", 1, RTT_COMMENT, NULL);
 
     //g_lang_output_end_routine_prototype(lang, buffer, line);
 
@@ -1092,7 +1092,7 @@ void g_binary_routine_print_code(const GBinRoutine *routine, GLangOutput *lang,
 
     line = g_lang_output_start_routine_prototype(lang, buffer, routine->ret_type);
 
-    g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, " ", 1, RTT_RAW);
+    g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, " ", 1, RTT_RAW, NULL);
 
     /* Nom de la routine */
 
@@ -1104,7 +1104,7 @@ void g_binary_routine_print_code(const GBinRoutine *routine, GLangOutput *lang,
         len = 3;
     }
 
-    g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, name, len, RTT_COMMENT);
+    g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, name, len, RTT_COMMENT, NULL);
 
 
 
diff --git a/src/analysis/types/basic.c b/src/analysis/types/basic.c
index 0bf3ad4..dcd8634 100644
--- a/src/analysis/types/basic.c
+++ b/src/analysis/types/basic.c
@@ -319,7 +319,7 @@ static void g_basic_type_output(const GBasicType *type, GLangOutput *lang, GBuff
     text = g_basic_type_to_string(type);
     len = strlen(text);
 
-    g_buffer_line_insert_text(line, BLC_LAST_USED, text, len, info ? RTT_COMMENT : RTT_RAW);
+    g_buffer_line_append_text(line, BLC_LAST_USED, text, len, info ? RTT_COMMENT : RTT_RAW, NULL);
 
     free(text);
 
diff --git a/src/analysis/types/cse.c b/src/analysis/types/cse.c
index 4a0e4e5..2411cd1 100644
--- a/src/analysis/types/cse.c
+++ b/src/analysis/types/cse.c
@@ -172,7 +172,7 @@ char *g_class_enum_type_to_string(const GClassEnumType *type)
 
 void g_class_enum_type_output(const GClassEnumType *type, GLangOutput *lang, GBufferLine *line, bool info, bool full)
 {
-    g_buffer_line_insert_text(line, BLC_LAST_USED, type->name, strlen(type->name),
-                              info ? RTT_COMMENT : RTT_RAW);
+    g_buffer_line_append_text(line, BLC_LAST_USED, type->name, strlen(type->name),
+                              info ? RTT_COMMENT : RTT_RAW, NULL);
 
 }
diff --git a/src/analysis/types/encaps.c b/src/analysis/types/encaps.c
index dffc69d..7ca8885 100644
--- a/src/analysis/types/encaps.c
+++ b/src/analysis/types/encaps.c
@@ -276,7 +276,7 @@ static char *g_encapsulated_type_to_string(const GEncapsulatedType *type)
 
 static void g_encapsulated_type_output(const GEncapsulatedType *type, GLangOutput *lang, GBufferLine *line, bool info, bool full)
 {
-    g_buffer_line_insert_text(line, BLC_LAST_USED, "!TODO!", 6, info ? RTT_COMMENT : RTT_RAW);
+    g_buffer_line_append_text(line, BLC_LAST_USED, "!TODO!", 6, info ? RTT_COMMENT : RTT_RAW, NULL);
 
 }
 
diff --git a/src/analysis/types/literal.c b/src/analysis/types/literal.c
index 7dbd5f0..5c3a3e8 100644
--- a/src/analysis/types/literal.c
+++ b/src/analysis/types/literal.c
@@ -234,7 +234,7 @@ static void g_literal_type_output(const GLiteralType *type, GLangOutput *lang, G
     text = g_literal_type_to_string(type);
     len = strlen(text);
 
-    g_buffer_line_insert_text(line, BLC_LAST_USED, text, len, info ? RTT_COMMENT : RTT_RAW);
+    g_buffer_line_append_text(line, BLC_LAST_USED, text, len, info ? RTT_COMMENT : RTT_RAW, NULL);
 
     free(text);
 
diff --git a/src/analysis/types/template.c b/src/analysis/types/template.c
index daeb454..974991a 100644
--- a/src/analysis/types/template.c
+++ b/src/analysis/types/template.c
@@ -240,18 +240,18 @@ static void g_template_type_output(const GTemplateType *type, GLangOutput *lang,
 
     g_class_enum_type_output(G_CLASS_ENUM_TYPE(type), lang, line, info, full);
 
-    g_buffer_line_insert_text(line, BLC_LAST_USED, "<", 1, info ? RTT_COMMENT : RTT_LTGT);
+    g_buffer_line_append_text(line, BLC_LAST_USED, "<", 1, info ? RTT_COMMENT : RTT_LTGT, NULL);
 
     for (i = 0; i < type->models_count; i++)
     {
         if (i > 0)
-            g_buffer_line_insert_text(line, BLC_LAST_USED, ", ", 2, info ? RTT_COMMENT : RTT_SIGNS);
+            g_buffer_line_append_text(line, BLC_LAST_USED, ", ", 2, info ? RTT_COMMENT : RTT_SIGNS, NULL);
 
         g_data_type_output(type->models[i], lang, line, info, full);
 
     }
 
-    g_buffer_line_insert_text(line, BLC_LAST_USED, ">", 1, info ? RTT_COMMENT : RTT_LTGT);
+    g_buffer_line_append_text(line, BLC_LAST_USED, ">", 1, info ? RTT_COMMENT : RTT_LTGT, NULL);
 
 }
 
diff --git a/src/analysis/variable.c b/src/analysis/variable.c
index d547281..e78c793 100644
--- a/src/analysis/variable.c
+++ b/src/analysis/variable.c
@@ -295,9 +295,9 @@ void g_binary_variable_output(const GBinVariable *var, GLangOutput *lang, GBuffe
     if (var->name != NULL)
     {
         if (!g_data_type_is_pointer(var->type, true))
-            g_buffer_line_insert_text(line, BLC_LAST_USED, " ", 1, RTT_COMMENT);
+            g_buffer_line_append_text(line, BLC_LAST_USED, " ", 1, RTT_COMMENT, NULL);
 
-        g_buffer_line_insert_text(line, BLC_LAST_USED, var->name, strlen(var->name), RTT_COMMENT);
+        g_buffer_line_append_text(line, BLC_LAST_USED, var->name, strlen(var->name), RTT_COMMENT, NULL);
 
     }
 
diff --git a/src/arch/arm/v7/cregister.c b/src/arch/arm/v7/cregister.c
index 62f3833..f247df4 100644
--- a/src/arch/arm/v7/cregister.c
+++ b/src/arch/arm/v7/cregister.c
@@ -207,6 +207,6 @@ static void g_armv7_cregister_print(const GArmV7CRegister *reg, GBufferLine *lin
             break;
     }
 
-    g_buffer_line_insert_text(line, BLC_ASSEMBLY, key, klen, RTT_REGISTER);
+    g_buffer_line_append_text(line, BLC_ASSEMBLY, key, klen, RTT_REGISTER, NULL);
 
 }
diff --git a/src/arch/arm/v7/operands/coproc.c b/src/arch/arm/v7/operands/coproc.c
index c816b37..90f8874 100644
--- a/src/arch/arm/v7/operands/coproc.c
+++ b/src/arch/arm/v7/operands/coproc.c
@@ -197,7 +197,7 @@ static void g_armv7_coproc_operand_print(const GArmV7CoprocOperand *operand, GBu
 
     nlen = snprintf(name, sizeof(name), "p%hhu", operand->index);
 
-    g_buffer_line_insert_text(line, BLC_ASSEMBLY, name, nlen, RTT_REGISTER);
+    g_buffer_line_append_text(line, BLC_ASSEMBLY, name, nlen, RTT_REGISTER, NULL);
 
 }
 
diff --git a/src/arch/arm/v7/operands/estate.c b/src/arch/arm/v7/operands/estate.c
index 214508a..6f66832 100644
--- a/src/arch/arm/v7/operands/estate.c
+++ b/src/arch/arm/v7/operands/estate.c
@@ -193,9 +193,9 @@ GArchOperand *g_armv7_endian_operand_new(bool big)
 static void g_armv7_endian_operand_print(const GArmV7EndianOperand *operand, GBufferLine *line, AsmSyntax syntax)
 {
     if (operand->big)
-        g_buffer_line_insert_text(line, BLC_ASSEMBLY, "BE", 2, RTT_KEY_WORD);
+        g_buffer_line_append_text(line, BLC_ASSEMBLY, "BE", 2, RTT_KEY_WORD, NULL);
     else
-        g_buffer_line_insert_text(line, BLC_ASSEMBLY, "LE", 2, RTT_KEY_WORD);
+        g_buffer_line_append_text(line, BLC_ASSEMBLY, "LE", 2, RTT_KEY_WORD, NULL);
 
 }
 
diff --git a/src/arch/arm/v7/operands/limitation.c b/src/arch/arm/v7/operands/limitation.c
index 4d1d661..5a5b567 100644
--- a/src/arch/arm/v7/operands/limitation.c
+++ b/src/arch/arm/v7/operands/limitation.c
@@ -199,39 +199,39 @@ static void g_armv7_limitation_operand_print(const GArmV7LimitationOperand *oper
     switch (operand->type)
     {
         case BLT_SY:
-            g_buffer_line_insert_text(line, BLC_ASSEMBLY, "SY", 2, RTT_KEY_WORD);
+            g_buffer_line_append_text(line, BLC_ASSEMBLY, "SY", 2, RTT_KEY_WORD, NULL);
             break;
 
         case BLT_ST:
-            g_buffer_line_insert_text(line, BLC_ASSEMBLY, "ST", 2, RTT_KEY_WORD);
+            g_buffer_line_append_text(line, BLC_ASSEMBLY, "ST", 2, RTT_KEY_WORD, NULL);
             break;
 
         case BLT_ISH:
-            g_buffer_line_insert_text(line, BLC_ASSEMBLY, "ISH", 3, RTT_KEY_WORD);
+            g_buffer_line_append_text(line, BLC_ASSEMBLY, "ISH", 3, RTT_KEY_WORD, NULL);
             break;
 
         case BLT_ISHST:
-            g_buffer_line_insert_text(line, BLC_ASSEMBLY, "ISHST", 5, RTT_KEY_WORD);
+            g_buffer_line_append_text(line, BLC_ASSEMBLY, "ISHST", 5, RTT_KEY_WORD, NULL);
             break;
 
         case BLT_NSH:
-            g_buffer_line_insert_text(line, BLC_ASSEMBLY, "NSH", 3, RTT_KEY_WORD);
+            g_buffer_line_append_text(line, BLC_ASSEMBLY, "NSH", 3, RTT_KEY_WORD, NULL);
             break;
 
         case BLT_NSHST:
-            g_buffer_line_insert_text(line, BLC_ASSEMBLY, "NSHST", 5, RTT_KEY_WORD);
+            g_buffer_line_append_text(line, BLC_ASSEMBLY, "NSHST", 5, RTT_KEY_WORD, NULL);
             break;
 
         case BLT_OSH:
-            g_buffer_line_insert_text(line, BLC_ASSEMBLY, "OSH", 3, RTT_KEY_WORD);
+            g_buffer_line_append_text(line, BLC_ASSEMBLY, "OSH", 3, RTT_KEY_WORD, NULL);
             break;
 
         case BLT_OSHST:
-            g_buffer_line_insert_text(line, BLC_ASSEMBLY, "OSHST", 5, RTT_KEY_WORD);
+            g_buffer_line_append_text(line, BLC_ASSEMBLY, "OSHST", 5, RTT_KEY_WORD, NULL);
             break;
 
         default:
-            g_buffer_line_insert_text(line, BLC_ASSEMBLY, "(reserved)", 10, RTT_KEY_WORD);
+            g_buffer_line_append_text(line, BLC_ASSEMBLY, "(reserved)", 10, RTT_KEY_WORD, NULL);
             break;
 
     }
diff --git a/src/arch/arm/v7/operands/maccess.c b/src/arch/arm/v7/operands/maccess.c
index 8eb5b57..10c8328 100644
--- a/src/arch/arm/v7/operands/maccess.c
+++ b/src/arch/arm/v7/operands/maccess.c
@@ -213,17 +213,17 @@ GArchOperand *g_armv7_maccess_operand_new(GArchOperand *base, GArchOperand *offs
 
 static void g_armv7_maccess_operand_print(const GArmV7MAccessOperand *operand, GBufferLine *line, AsmSyntax syntax)
 {
-    g_buffer_line_insert_text(line, BLC_ASSEMBLY, "[", 1, RTT_HOOK);
+    g_buffer_line_append_text(line, BLC_ASSEMBLY, "[", 1, RTT_HOOK, NULL);
 
     g_arch_operand_print(operand->base, line, syntax);
 
     if (!operand->not_post_indexed)
-        g_buffer_line_insert_text(line, BLC_ASSEMBLY, "]", 1, RTT_HOOK);
+        g_buffer_line_append_text(line, BLC_ASSEMBLY, "]", 1, RTT_HOOK, NULL);
 
     if (operand->offset != NULL)
     {
-        g_buffer_line_insert_text(line, BLC_ASSEMBLY, ",", 1, RTT_PUNCT);
-        g_buffer_line_insert_text(line, BLC_ASSEMBLY, " ", 1, RTT_RAW);
+        g_buffer_line_append_text(line, BLC_ASSEMBLY, ",", 1, RTT_PUNCT, NULL);
+        g_buffer_line_append_text(line, BLC_ASSEMBLY, " ", 1, RTT_RAW, NULL);
 
         g_arch_operand_print(operand->offset, line, syntax);
 
@@ -231,18 +231,18 @@ static void g_armv7_maccess_operand_print(const GArmV7MAccessOperand *operand, G
 
     if (operand->shift != NULL)
     {
-        g_buffer_line_insert_text(line, BLC_ASSEMBLY, ",", 1, RTT_PUNCT);
-        g_buffer_line_insert_text(line, BLC_ASSEMBLY, " ", 1, RTT_RAW);
+        g_buffer_line_append_text(line, BLC_ASSEMBLY, ",", 1, RTT_PUNCT, NULL);
+        g_buffer_line_append_text(line, BLC_ASSEMBLY, " ", 1, RTT_RAW, NULL);
 
         g_arch_operand_print(operand->shift, line, syntax);
 
     }
 
     if (operand->not_post_indexed)
-        g_buffer_line_insert_text(line, BLC_ASSEMBLY, "]", 1, RTT_HOOK);
+        g_buffer_line_append_text(line, BLC_ASSEMBLY, "]", 1, RTT_HOOK, NULL);
 
     if (operand->write_back)
-        g_buffer_line_insert_text(line, BLC_ASSEMBLY, "!", 1, RTT_PUNCT);
+        g_buffer_line_append_text(line, BLC_ASSEMBLY, "!", 1, RTT_PUNCT, NULL);
 
 }
 
diff --git a/src/arch/arm/v7/operands/offset.c b/src/arch/arm/v7/operands/offset.c
index 9a9506a..03d69d8 100644
--- a/src/arch/arm/v7/operands/offset.c
+++ b/src/arch/arm/v7/operands/offset.c
@@ -198,7 +198,7 @@ GArchOperand *g_armv7_offset_operand_new(bool positive, GArchOperand *value)
 static void g_armv7_offset_operand_print(const GArmV7OffsetOperand *operand, GBufferLine *line, AsmSyntax syntax)
 {
     if (!operand->positive)
-        g_buffer_line_insert_text(line, BLC_ASSEMBLY, "-", 1, RTT_KEY_WORD);
+        g_buffer_line_append_text(line, BLC_ASSEMBLY, "-", 1, RTT_KEY_WORD, NULL);
 
     g_arch_operand_print(operand->value, line, syntax);
 
diff --git a/src/arch/arm/v7/operands/reglist.c b/src/arch/arm/v7/operands/reglist.c
index a54d148..7ad72d0 100644
--- a/src/arch/arm/v7/operands/reglist.c
+++ b/src/arch/arm/v7/operands/reglist.c
@@ -206,21 +206,21 @@ static void g_armv7_reglist_operand_print(const GArmV7RegListOperand *operand, G
 {
     size_t i;                               /* Boucle de parcours          */
 
-    g_buffer_line_insert_text(line, BLC_ASSEMBLY, "{", 1, RTT_HOOK);
+    g_buffer_line_append_text(line, BLC_ASSEMBLY, "{", 1, RTT_HOOK, NULL);
 
     for (i = 0; i < operand->count; i++)
     {
         if (i > 0)
         {
-            g_buffer_line_insert_text(line, BLC_ASSEMBLY, ",", 1, RTT_PUNCT);
-            g_buffer_line_insert_text(line, BLC_ASSEMBLY, " ", 1, RTT_RAW);
+            g_buffer_line_append_text(line, BLC_ASSEMBLY, ",", 1, RTT_PUNCT, NULL);
+            g_buffer_line_append_text(line, BLC_ASSEMBLY, " ", 1, RTT_RAW, NULL);
         }
 
         g_arch_register_print(G_ARCH_REGISTER(operand->registers[i]), line, syntax);
 
     }
 
-    g_buffer_line_insert_text(line, BLC_ASSEMBLY, "}", 1, RTT_HOOK);
+    g_buffer_line_append_text(line, BLC_ASSEMBLY, "}", 1, RTT_HOOK, NULL);
 
 }
 
diff --git a/src/arch/arm/v7/operands/rotation.c b/src/arch/arm/v7/operands/rotation.c
index 1532270..22f53c3 100644
--- a/src/arch/arm/v7/operands/rotation.c
+++ b/src/arch/arm/v7/operands/rotation.c
@@ -194,9 +194,9 @@ GArchOperand *g_armv7_rotation_operand_new(GArchOperand *value)
 
 static void g_armv7_rotation_operand_print(const GArmV7RotationOperand *operand, GBufferLine *line, AsmSyntax syntax)
 {
-    g_buffer_line_insert_text(line, BLC_ASSEMBLY, "ror", 3, RTT_KEY_WORD);
+    g_buffer_line_append_text(line, BLC_ASSEMBLY, "ror", 3, RTT_KEY_WORD, NULL);
 
-    g_buffer_line_insert_text(line, BLC_ASSEMBLY, " ", 1, RTT_RAW);
+    g_buffer_line_append_text(line, BLC_ASSEMBLY, " ", 1, RTT_RAW, NULL);
 
     g_arch_operand_print(operand->value, line, syntax);
 
diff --git a/src/arch/arm/v7/operands/shift.c b/src/arch/arm/v7/operands/shift.c
index 7a90a70..9a9035c 100644
--- a/src/arch/arm/v7/operands/shift.c
+++ b/src/arch/arm/v7/operands/shift.c
@@ -199,23 +199,23 @@ static void g_armv7_shift_operand_print(const GArmV7ShiftOperand *operand, GBuff
     switch (operand->shift_type)
     {
         case SRType_LSL:
-            g_buffer_line_insert_text(line, BLC_ASSEMBLY, "lsl", 3, RTT_KEY_WORD);
+            g_buffer_line_append_text(line, BLC_ASSEMBLY, "lsl", 3, RTT_KEY_WORD, NULL);
             break;
         case SRType_LSR:
-            g_buffer_line_insert_text(line, BLC_ASSEMBLY, "lsr", 3, RTT_KEY_WORD);
+            g_buffer_line_append_text(line, BLC_ASSEMBLY, "lsr", 3, RTT_KEY_WORD, NULL);
             break;
         case SRType_ASR:
-            g_buffer_line_insert_text(line, BLC_ASSEMBLY, "asr", 3, RTT_KEY_WORD);
+            g_buffer_line_append_text(line, BLC_ASSEMBLY, "asr", 3, RTT_KEY_WORD, NULL);
             break;
         case SRType_ROR:
-            g_buffer_line_insert_text(line, BLC_ASSEMBLY, "ror", 3, RTT_KEY_WORD);
+            g_buffer_line_append_text(line, BLC_ASSEMBLY, "ror", 3, RTT_KEY_WORD, NULL);
             break;
         case SRType_RRX:
-            g_buffer_line_insert_text(line, BLC_ASSEMBLY, "rrx", 3, RTT_KEY_WORD);
+            g_buffer_line_append_text(line, BLC_ASSEMBLY, "rrx", 3, RTT_KEY_WORD, NULL);
             break;
     }
 
-    g_buffer_line_insert_text(line, BLC_ASSEMBLY, " ", 1, RTT_RAW);
+    g_buffer_line_append_text(line, BLC_ASSEMBLY, " ", 1, RTT_RAW, NULL);
 
     g_arch_operand_print(operand->shift_value, line, syntax);
 
diff --git a/src/arch/arm/v7/register.c b/src/arch/arm/v7/register.c
index 31073ee..7b91260 100644
--- a/src/arch/arm/v7/register.c
+++ b/src/arch/arm/v7/register.c
@@ -224,6 +224,6 @@ static void g_armv7_register_print(const GArmV7Register *reg, GBufferLine *line,
             break;
     }
 
-    g_buffer_line_insert_text(line, BLC_ASSEMBLY, key, klen, RTT_REGISTER);
+    g_buffer_line_append_text(line, BLC_ASSEMBLY, key, klen, RTT_REGISTER, NULL);
 
 }
diff --git a/src/arch/dalvik/operands/args.c b/src/arch/dalvik/operands/args.c
index 2897698..c03d951 100644
--- a/src/arch/dalvik/operands/args.c
+++ b/src/arch/dalvik/operands/args.c
@@ -201,7 +201,7 @@ static void g_dalvik_args_operand_print(const GDalvikArgsOperand *operand, GBuff
 {
     size_t i;                               /* Boucle de parcours          */
 
-    g_buffer_line_insert_text(line, BLC_ASSEMBLY, "{", 1, RTT_HOOK);
+    g_buffer_line_append_text(line, BLC_ASSEMBLY, "{", 1, RTT_HOOK, NULL);
 
     if (operand->count > 0)
     {
@@ -209,8 +209,8 @@ static void g_dalvik_args_operand_print(const GDalvikArgsOperand *operand, GBuff
 
         for (i = 1; i < operand->count; i++)
         {
-            g_buffer_line_insert_text(line, BLC_ASSEMBLY, ",", 1, RTT_PUNCT);
-            g_buffer_line_insert_text(line, BLC_ASSEMBLY, " ", 1, RTT_RAW);
+            g_buffer_line_append_text(line, BLC_ASSEMBLY, ",", 1, RTT_PUNCT, NULL);
+            g_buffer_line_append_text(line, BLC_ASSEMBLY, " ", 1, RTT_RAW, NULL);
 
             g_arch_operand_print(operand->args[i], line, syntax);
 
@@ -218,7 +218,7 @@ static void g_dalvik_args_operand_print(const GDalvikArgsOperand *operand, GBuff
 
     }
 
-    g_buffer_line_insert_text(line, BLC_ASSEMBLY, "}", 1, RTT_HOOK);
+    g_buffer_line_append_text(line, BLC_ASSEMBLY, "}", 1, RTT_HOOK, NULL);
 
 }
 
diff --git a/src/arch/dalvik/operands/pool.c b/src/arch/dalvik/operands/pool.c
index 5f98a04..b84d655 100644
--- a/src/arch/dalvik/operands/pool.c
+++ b/src/arch/dalvik/operands/pool.c
@@ -243,7 +243,7 @@ static void g_dalvik_pool_operand_print(const GDalvikPoolOperand *operand, GBuff
     switch (operand->type)
     {
         case DPT_NONE:
-            g_buffer_line_insert_text(line, BLC_ASSEMBLY, "????", 4, RTT_ERROR);
+            g_buffer_line_append_text(line, BLC_ASSEMBLY, "????", 4, RTT_ERROR, NULL);
             break;
 
         case DPT_STRING:
@@ -252,14 +252,14 @@ static void g_dalvik_pool_operand_print(const GDalvikPoolOperand *operand, GBuff
 
             if (string != NULL)
             {
-                g_buffer_line_insert_text(line, BLC_ASSEMBLY, "\"", 1, RTT_STRING);
+                g_buffer_line_append_text(line, BLC_ASSEMBLY, "\"", 1, RTT_STRING, NULL);
 
                 len = strlen(string);
 
                 if (len > 0)
-                    g_buffer_line_insert_text(line, BLC_ASSEMBLY, string, len, RTT_STRING);
+                    g_buffer_line_append_text(line, BLC_ASSEMBLY, string, len, RTT_STRING, NULL);
 
-                g_buffer_line_insert_text(line, BLC_ASSEMBLY, "\"", 1, RTT_STRING);
+                g_buffer_line_append_text(line, BLC_ASSEMBLY, "\"", 1, RTT_STRING, NULL);
 
             }
             else
@@ -268,7 +268,7 @@ static void g_dalvik_pool_operand_print(const GDalvikPoolOperand *operand, GBuff
                 tmp = calloc(len, sizeof(char));
                 snprintf(tmp, len, _("<bad string index (%d)>"), operand->index);
 
-                g_buffer_line_insert_text(line, BLC_ASSEMBLY, tmp, len - 1, RTT_ERROR);
+                g_buffer_line_append_text(line, BLC_ASSEMBLY, tmp, len - 1, RTT_ERROR, NULL);
 
                 free(tmp);
 
@@ -285,9 +285,9 @@ static void g_dalvik_pool_operand_print(const GDalvikPoolOperand *operand, GBuff
                 tmp = g_data_type_to_string(type);
                 g_object_unref(G_OBJECT(type));
 
-                g_buffer_line_insert_text(line, BLC_ASSEMBLY, "<", 1, RTT_HOOK);
-                g_buffer_line_insert_text(line, BLC_ASSEMBLY, tmp, strlen(tmp), RTT_VAR_NAME);
-                g_buffer_line_insert_text(line, BLC_ASSEMBLY, ">", 1, RTT_HOOK);
+                g_buffer_line_append_text(line, BLC_ASSEMBLY, "<", 1, RTT_HOOK, NULL);
+                g_buffer_line_append_text(line, BLC_ASSEMBLY, tmp, strlen(tmp), RTT_VAR_NAME, NULL);
+                g_buffer_line_append_text(line, BLC_ASSEMBLY, ">", 1, RTT_HOOK, NULL);
 
             }
             else
@@ -296,7 +296,7 @@ static void g_dalvik_pool_operand_print(const GDalvikPoolOperand *operand, GBuff
                 tmp = calloc(len, sizeof(char));
                 snprintf(tmp, len, _("<bad type index (%d)>"), operand->index);
 
-                g_buffer_line_insert_text(line, BLC_ASSEMBLY, tmp, len - 1, RTT_ERROR);
+                g_buffer_line_append_text(line, BLC_ASSEMBLY, tmp, len - 1, RTT_ERROR, NULL);
 
             }
 
@@ -305,7 +305,7 @@ static void g_dalvik_pool_operand_print(const GDalvikPoolOperand *operand, GBuff
             break;
 
         case DPT_PROTO:
-            g_buffer_line_insert_text(line, BLC_ASSEMBLY, "proto(/*TODO*/)", 5, RTT_SECTION);
+            g_buffer_line_append_text(line, BLC_ASSEMBLY, "proto(/*TODO*/)", 5, RTT_SECTION, NULL);
             break;
 
         case DPT_FIELD:
@@ -317,9 +317,9 @@ static void g_dalvik_pool_operand_print(const GDalvikPoolOperand *operand, GBuff
                 tmp = g_binary_variable_to_string(field, false);
                 g_object_unref(G_OBJECT(field));
 
-                g_buffer_line_insert_text(line, BLC_ASSEMBLY, "<", 1, RTT_HOOK);
-                g_buffer_line_insert_text(line, BLC_ASSEMBLY, tmp, strlen(tmp), RTT_VAR_NAME);
-                g_buffer_line_insert_text(line, BLC_ASSEMBLY, ">", 1, RTT_HOOK);
+                g_buffer_line_append_text(line, BLC_ASSEMBLY, "<", 1, RTT_HOOK, NULL);
+                g_buffer_line_append_text(line, BLC_ASSEMBLY, tmp, strlen(tmp), RTT_VAR_NAME, NULL);
+                g_buffer_line_append_text(line, BLC_ASSEMBLY, ">", 1, RTT_HOOK, NULL);
 
             }
             else
@@ -328,7 +328,7 @@ static void g_dalvik_pool_operand_print(const GDalvikPoolOperand *operand, GBuff
                 tmp = calloc(len, sizeof(char));
                 snprintf(tmp, len, _("<bad field index (%d)>"), operand->index);
 
-                g_buffer_line_insert_text(line, BLC_ASSEMBLY, tmp, len - 1, RTT_ERROR);
+                g_buffer_line_append_text(line, BLC_ASSEMBLY, tmp, len - 1, RTT_ERROR, NULL);
 
             }
 
@@ -350,9 +350,9 @@ static void g_dalvik_pool_operand_print(const GDalvikPoolOperand *operand, GBuff
                 tmp = g_binary_routine_to_string(routine);
                 g_object_unref(G_OBJECT(routine));
 
-                g_buffer_line_insert_text(line, BLC_ASSEMBLY, "<", 1, RTT_HOOK);
-                g_buffer_line_insert_text(line, BLC_ASSEMBLY, tmp, strlen(tmp), RTT_VAR_NAME);
-                g_buffer_line_insert_text(line, BLC_ASSEMBLY, ">", 1, RTT_HOOK);
+                g_buffer_line_append_text(line, BLC_ASSEMBLY, "<", 1, RTT_HOOK, NULL);
+                g_buffer_line_append_text(line, BLC_ASSEMBLY, tmp, strlen(tmp), RTT_VAR_NAME, NULL);
+                g_buffer_line_append_text(line, BLC_ASSEMBLY, ">", 1, RTT_HOOK, NULL);
 
             }
             else
@@ -361,7 +361,7 @@ static void g_dalvik_pool_operand_print(const GDalvikPoolOperand *operand, GBuff
                 tmp = calloc(len, sizeof(char));
                 snprintf(tmp, len, _("<bad method index (%d)>"), operand->index);
 
-                g_buffer_line_insert_text(line, BLC_ASSEMBLY, tmp, len - 1, RTT_ERROR);
+                g_buffer_line_append_text(line, BLC_ASSEMBLY, tmp, len - 1, RTT_ERROR, NULL);
 
             }
 
diff --git a/src/arch/dalvik/register.c b/src/arch/dalvik/register.c
index 7c0b601..35e8f58 100644
--- a/src/arch/dalvik/register.c
+++ b/src/arch/dalvik/register.c
@@ -237,6 +237,6 @@ void g_dalvik_register_print(const GDalvikRegister *reg, GBufferLine *line, AsmS
 
     }
 
-    g_buffer_line_insert_text(line, BLC_ASSEMBLY, key, klen, RTT_REGISTER);
+    g_buffer_line_append_text(line, BLC_ASSEMBLY, key, klen, RTT_REGISTER, NULL);
 
 }
diff --git a/src/arch/instruction.c b/src/arch/instruction.c
index 1bdb50e..8264f5b 100644
--- a/src/arch/instruction.c
+++ b/src/arch/instruction.c
@@ -1056,7 +1056,7 @@ static GBufferLine *_g_arch_instruction_print(GArchInstruction *instr, GCodeBuff
     key = g_arch_instruction_get_keyword(instr, syntax);
     klen = strlen(key);
 
-    g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, key, klen, RTT_INSTRUCTION);
+    g_buffer_line_append_text(result, BLC_ASSEMBLY_HEAD, key, klen, RTT_INSTRUCTION, NULL);
 
     if (instr->operands_count > 0)
     {
@@ -1064,8 +1064,8 @@ static GBufferLine *_g_arch_instruction_print(GArchInstruction *instr, GCodeBuff
 
         for (i = 1; i < instr->operands_count; i++)
         {
-            g_buffer_line_insert_text(result, BLC_ASSEMBLY, ",", 1, RTT_PUNCT);
-            g_buffer_line_insert_text(result, BLC_ASSEMBLY, " ", 1, RTT_RAW);
+            g_buffer_line_append_text(result, BLC_ASSEMBLY, ",", 1, RTT_PUNCT, NULL);
+            g_buffer_line_append_text(result, BLC_ASSEMBLY, " ", 1, RTT_RAW, NULL);
 
             g_arch_operand_print(instr->operands[i], result, syntax);
 
diff --git a/src/arch/operand.c b/src/arch/operand.c
index 5b36e13..a84018f 100644
--- a/src/arch/operand.c
+++ b/src/arch/operand.c
@@ -212,10 +212,11 @@ void g_arch_operand_set_alt_text(GArchOperand *operand, const char *text, Render
 void g_arch_operand_print(const GArchOperand *operand, GBufferLine *line, AsmSyntax syntax)
 {
     if (operand->alt_text != NULL)
-        g_buffer_line_insert_text(line, BLC_ASSEMBLY,
+        g_buffer_line_append_text(line, BLC_ASSEMBLY,
                                   operand->alt_text,
                                   operand->alt_len,
-                                  operand->alt_tag);
+                                  operand->alt_tag,
+                                  NULL);
 
     else
         G_ARCH_OPERAND_GET_CLASS(operand)->print(operand, line, syntax);
diff --git a/src/arch/raw.c b/src/arch/raw.c
index 67d2507..356f809 100644
--- a/src/arch/raw.c
+++ b/src/arch/raw.c
@@ -456,10 +456,10 @@ static GBufferLine *g_raw_instruction_print(GRawInstruction *instr, GCodeBuffer
         key = g_arch_instruction_get_keyword(base, syntax);
         klen = strlen(key);
 
-        g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, key, klen, RTT_INSTRUCTION);
+        g_buffer_line_append_text(result, BLC_ASSEMBLY_HEAD, key, klen, RTT_INSTRUCTION, NULL);
 
         if (instr->is_padding)
-            g_buffer_line_insert_text(result, BLC_ASSEMBLY, "...", 3, RTT_RAW);
+            g_buffer_line_append_text(result, BLC_ASSEMBLY, "...", 3, RTT_RAW, NULL);
 
         else /*if (instr->is_string)*/
         {
@@ -483,15 +483,15 @@ static GBufferLine *g_raw_instruction_print(GRawInstruction *instr, GCodeBuffer
                     {
                         if (!first)
                         {
-                            g_buffer_line_insert_text(result, BLC_ASSEMBLY, ",", 1, RTT_PUNCT);
-                            g_buffer_line_insert_text(result, BLC_ASSEMBLY, " ", 1, RTT_RAW);
+                            g_buffer_line_append_text(result, BLC_ASSEMBLY, ",", 1, RTT_PUNCT, NULL);
+                            g_buffer_line_append_text(result, BLC_ASSEMBLY, " ", 1, RTT_RAW, NULL);
                         }
                         else
                             first = false;
 
                         string[iter++] = '"';
 
-                        g_buffer_line_insert_text(result, BLC_ASSEMBLY, string, iter, RTT_STRING);
+                        g_buffer_line_append_text(result, BLC_ASSEMBLY, string, iter, RTT_STRING, NULL);
 
                         iter = 1;
 
@@ -501,8 +501,8 @@ static GBufferLine *g_raw_instruction_print(GRawInstruction *instr, GCodeBuffer
 
                     if (!first)
                     {
-                        g_buffer_line_insert_text(result, BLC_ASSEMBLY, ",", 1, RTT_PUNCT);
-                        g_buffer_line_insert_text(result, BLC_ASSEMBLY, " ", 1, RTT_RAW);
+                        g_buffer_line_append_text(result, BLC_ASSEMBLY, ",", 1, RTT_PUNCT, NULL);
+                        g_buffer_line_append_text(result, BLC_ASSEMBLY, " ", 1, RTT_RAW, NULL);
                     }
                     else
                         first = false;
@@ -521,15 +521,15 @@ static GBufferLine *g_raw_instruction_print(GRawInstruction *instr, GCodeBuffer
             {
                 if (!first)
                 {
-                    g_buffer_line_insert_text(result, BLC_ASSEMBLY, ",", 1, RTT_PUNCT);
-                    g_buffer_line_insert_text(result, BLC_ASSEMBLY, " ", 1, RTT_RAW);
+                    g_buffer_line_append_text(result, BLC_ASSEMBLY, ",", 1, RTT_PUNCT, NULL);
+                    g_buffer_line_append_text(result, BLC_ASSEMBLY, " ", 1, RTT_RAW, NULL);
                 }
                 else
                     first = false;
 
                 string[iter++] = '"';
 
-                g_buffer_line_insert_text(result, BLC_ASSEMBLY, string, iter, RTT_STRING);
+                g_buffer_line_append_text(result, BLC_ASSEMBLY, string, iter, RTT_STRING, NULL);
 
             }
 
diff --git a/src/arch/target.c b/src/arch/target.c
index 0517062..7ad9e62 100644
--- a/src/arch/target.c
+++ b/src/arch/target.c
@@ -219,7 +219,7 @@ static void g_target_operand_print(const GTargetOperand *operand, GBufferLine *l
     if (operand->symbol != NULL /* FIXME */ && g_binary_symbol_get_label(operand->symbol) != NULL /* FIXME */)
     {
         if (operand->diff > 0)
-            g_buffer_line_insert_text(line, BLC_MAIN, "<", 1, RTT_LTGT);
+            g_buffer_line_append_text(line, BLC_MAIN, "<", 1, RTT_LTGT, NULL);
 
         label = g_binary_symbol_get_label(operand->symbol);
         g_buffer_line_append_text(line, BLC_MAIN, label, strlen(label), RTT_LABEL, G_OBJECT(operand));
@@ -233,7 +233,7 @@ static void g_target_operand_print(const GTargetOperand *operand, GBufferLine *l
 
             g_buffer_line_append_text(line, BLC_MAIN, value, len, RTT_LABEL, G_OBJECT(operand));
 
-            g_buffer_line_insert_text(line, BLC_MAIN, ">", 1, RTT_LTGT);
+            g_buffer_line_append_text(line, BLC_MAIN, ">", 1, RTT_LTGT, NULL);
 
         }
 
diff --git a/src/arch/undefined.c b/src/arch/undefined.c
index 9c944bc..e69a399 100644
--- a/src/arch/undefined.c
+++ b/src/arch/undefined.c
@@ -254,7 +254,7 @@ static GBufferLine *g_undef_instruction_print(GUndefInstruction *instr, GCodeBuf
     key = g_arch_instruction_get_keyword(base, syntax);
     klen = strlen(key);
 
-    g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, key, klen, RTT_ERROR);
+    g_buffer_line_append_text(result, BLC_ASSEMBLY_HEAD, key, klen, RTT_ERROR, NULL);
 
     return result;
 
diff --git a/src/arch/x86/register.c b/src/arch/x86/register.c
index 0e65e58..740ec3f 100644
--- a/src/arch/x86/register.c
+++ b/src/arch/x86/register.c
@@ -530,7 +530,7 @@ void g_x86_pool_operand_print(const GX86Register *reg, GBufferLine *line, AsmSyn
 
     }
 
-    g_buffer_line_insert_text(line, BLC_ASSEMBLY, key, klen, RTT_REGISTER);
+    g_buffer_line_append_text(line, BLC_ASSEMBLY, key, klen, RTT_REGISTER, NULL);
 
 }
 
diff --git a/src/decomp/expr/access.c b/src/decomp/expr/access.c
index 0af60c7..d7d354d 100644
--- a/src/decomp/expr/access.c
+++ b/src/decomp/expr/access.c
@@ -239,7 +239,7 @@ static GBufferLine *g_access_expression_print(const GAccessExpression *expr, GCo
     result = g_dec_instruction_print(G_DEC_INSTRUCTION(expr->owner),
                                      buffer, line, output);
 
-    g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, ".", 3, RTT_PUNCT);
+    g_buffer_line_append_text(result, BLC_ASSEMBLY_HEAD, ".", 3, RTT_PUNCT, NULL);
 
     result = g_dec_instruction_print(G_DEC_INSTRUCTION(expr->target),
                                      buffer, result, output);
diff --git a/src/decomp/expr/arithm.c b/src/decomp/expr/arithm.c
index f14086d..7314dde 100644
--- a/src/decomp/expr/arithm.c
+++ b/src/decomp/expr/arithm.c
@@ -276,7 +276,7 @@ static GBufferLine *g_arithm_expression_print(const GArithmExpression *expr, GCo
             break;
     }
 
-    g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, sign, 3, RTT_SIGNS);
+    g_buffer_line_append_text(result, BLC_ASSEMBLY_HEAD, sign, 3, RTT_SIGNS, NULL);
 
     result = g_dec_instruction_print(G_DEC_INSTRUCTION(expr->op2),
                                      buffer, result, output);
diff --git a/src/decomp/expr/array.c b/src/decomp/expr/array.c
index d335f61..5c18c11 100644
--- a/src/decomp/expr/array.c
+++ b/src/decomp/expr/array.c
@@ -239,12 +239,12 @@ static GBufferLine *g_array_access_print(const GArrayAccess *expr, GCodeBuffer *
     result = g_dec_instruction_print(G_DEC_INSTRUCTION(expr->array),
                                      buffer, line, output);
 
-    g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, "[", 1, RTT_RAW);
+    g_buffer_line_append_text(result, BLC_ASSEMBLY_HEAD, "[", 1, RTT_RAW, NULL);
 
     result = g_dec_instruction_print(G_DEC_INSTRUCTION(expr->index),
                                      buffer, result, output);
 
-    g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, "]", 1, RTT_RAW);
+    g_buffer_line_append_text(result, BLC_ASSEMBLY_HEAD, "]", 1, RTT_RAW, NULL);
 
     return result;
 
diff --git a/src/decomp/expr/assign.c b/src/decomp/expr/assign.c
index 9a5b308..f4ab149 100644
--- a/src/decomp/expr/assign.c
+++ b/src/decomp/expr/assign.c
@@ -239,7 +239,7 @@ static GBufferLine *g_assign_expression_print(const GAssignExpression *expr, GCo
     result = g_dec_instruction_print(G_DEC_INSTRUCTION(expr->dest),
                                      buffer, line, output);
 
-    g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, " = ", 3, RTT_SIGNS);
+    g_buffer_line_append_text(result, BLC_ASSEMBLY_HEAD, " = ", 3, RTT_SIGNS, NULL);
 
     result = g_dec_instruction_print(G_DEC_INSTRUCTION(expr->src),
                                      buffer, result, output);
diff --git a/src/decomp/expr/call.c b/src/decomp/expr/call.c
index 8382b6d..7a09c37 100644
--- a/src/decomp/expr/call.c
+++ b/src/decomp/expr/call.c
@@ -238,9 +238,9 @@ static GBufferLine *g_routine_call_print(const GRoutineCall *call, GCodeBuffer *
     size_t i;                               /* Boucle de parcours          */
 
     name = g_binary_routine_get_name(call->routine);
-    g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, name, strlen(name), RTT_RAW);
+    g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, name, strlen(name), RTT_RAW, NULL);
 
-    g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "(", 1, RTT_PUNCT);
+    g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, "(", 1, RTT_PUNCT, NULL);
 
     if (call->count > 0)
     {
@@ -248,8 +248,8 @@ static GBufferLine *g_routine_call_print(const GRoutineCall *call, GCodeBuffer *
 
         for (i = 1; i < call->count; i++)
         {
-            g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, ",", 1, RTT_PUNCT);
-            g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, " ", 1, RTT_RAW);
+            g_buffer_line_append_text(result, BLC_ASSEMBLY_HEAD, ",", 1, RTT_PUNCT, NULL);
+            g_buffer_line_append_text(result, BLC_ASSEMBLY_HEAD, " ", 1, RTT_RAW, NULL);
 
             g_dec_instruction_print(call->args[i], buffer, result, output);
 
@@ -258,7 +258,7 @@ static GBufferLine *g_routine_call_print(const GRoutineCall *call, GCodeBuffer *
     }
     else result = line;
 
-    g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, ")", 1, RTT_PUNCT);
+    g_buffer_line_append_text(result, BLC_ASSEMBLY_HEAD, ")", 1, RTT_PUNCT, NULL);
 
     return result;
 
diff --git a/src/decomp/expr/dalvik/array.c b/src/decomp/expr/dalvik/array.c
index 018952a..7806349 100644
--- a/src/decomp/expr/dalvik/array.c
+++ b/src/decomp/expr/dalvik/array.c
@@ -148,8 +148,8 @@ static void g_dalvik_alength_print(const GDalvikALength *expr, GCodeBuffer *buff
     g_dec_instruction_print(G_DEC_INSTRUCTION(expr->array),
                             buffer, line, output);
 
-    g_buffer_line_insert_text(line, BLC_ASSEMBLY, ".", 1, RTT_RAW);
+    g_buffer_line_append_text(line, BLC_ASSEMBLY, ".", 1, RTT_RAW, NULL);
 
-    g_buffer_line_insert_text(line, BLC_ASSEMBLY, "length", 6, RTT_RAW);
+    g_buffer_line_append_text(line, BLC_ASSEMBLY, "length", 6, RTT_RAW, NULL);
 
 }
diff --git a/src/decomp/expr/pseudo.c b/src/decomp/expr/pseudo.c
index 85a9e72..0ee83b9 100644
--- a/src/decomp/expr/pseudo.c
+++ b/src/decomp/expr/pseudo.c
@@ -179,13 +179,13 @@ static GBufferLine *g_pseudo_register_print(const GPseudoRegister *reg, GCodeBuf
     if (reg->var != NULL)
     {
         name = g_binary_variable_to_string(reg->var, true);
-        g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, name, strlen(name), RTT_RAW);
+        g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, name, strlen(name), RTT_RAW, NULL);
         free(name);
     }
     else
     {
         snprintf(label, 32, "%s%zu", reg->name, reg->index);
-        g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, label, strlen(label), RTT_RAW);
+        g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, label, strlen(label), RTT_RAW, NULL);
     }
 
     return line;
diff --git a/src/decomp/expr/return.c b/src/decomp/expr/return.c
index b61eb39..8758042 100644
--- a/src/decomp/expr/return.c
+++ b/src/decomp/expr/return.c
@@ -226,11 +226,11 @@ static GBufferLine *g_return_expression_print(const GReturnExpression *expr, GCo
 {
     GBufferLine *result;                    /* Ligne à retourner           */
 
-    g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "return", 6, RTT_KEY_WORD);
+    g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, "return", 6, RTT_KEY_WORD, NULL);
 
     if (expr->payload != NULL)
     {
-        g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, " ", 1, RTT_RAW);
+        g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, " ", 1, RTT_RAW, NULL);
 
         result = g_dec_instruction_print(G_DEC_INSTRUCTION(expr->payload),
                                          buffer, line, output);
diff --git a/src/decomp/expr/text.c b/src/decomp/expr/text.c
index 9991b85..d4d5f85 100644
--- a/src/decomp/expr/text.c
+++ b/src/decomp/expr/text.c
@@ -150,9 +150,9 @@ GDecInstruction *g_str_expression_new(const char *value)
 
 static GBufferLine *g_str_expression_print(const GStrExpression *expr, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output)
 {
-    g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "\"", 1, RTT_STRING);
-    g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, expr->value, expr->len, RTT_STRING);
-    g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "\"", 1, RTT_STRING);
+    g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, "\"", 1, RTT_STRING, NULL);
+    g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, expr->value, expr->len, RTT_STRING, NULL);
+    g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, "\"", 1, RTT_STRING, NULL);
 
     return line;
 
diff --git a/src/decomp/expression.c b/src/decomp/expression.c
index e8bdbd9..ff2c0da 100644
--- a/src/decomp/expression.c
+++ b/src/decomp/expression.c
@@ -98,7 +98,7 @@ static GBufferLine *g_dec_expression_neg_print(const GDecExpression *expr, GCode
 {
     GBufferLine *result;                    /* Ligne à retourner           */
 
-    g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "!", 1, RTT_KEY_WORD);
+    g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, "!", 1, RTT_KEY_WORD, NULL);
 
     result = expr->original_print(G_DEC_INSTRUCTION(expr), buffer, line, output);
 
diff --git a/src/decomp/instr/ite.c b/src/decomp/instr/ite.c
index eedd7b4..b6391d5 100644
--- a/src/decomp/instr/ite.c
+++ b/src/decomp/instr/ite.c
@@ -241,7 +241,7 @@ static GBufferLine *g_ite_instruction_print(const GITEInstruction *instr, GCodeB
 {
     GBufferLine *result;                    /* Ligne à retourner           */
 
-    g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "if ", 3, RTT_KEY_WORD);
+    g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, "if ", 3, RTT_KEY_WORD, NULL);
 
     result = g_dec_instruction_print(G_DEC_INSTRUCTION(instr->cond),
                                      buffer, line, output);
@@ -250,7 +250,7 @@ static GBufferLine *g_ite_instruction_print(const GITEInstruction *instr, GCodeB
 
     if (instr->false_branch != NULL)
     {
-        g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, "else", 4, RTT_KEY_WORD);
+        g_buffer_line_append_text(result, BLC_ASSEMBLY_HEAD, "else", 4, RTT_KEY_WORD, NULL);
         result = g_dec_instruction_print(instr->false_branch, buffer, result, output);
     }
 
diff --git a/src/decomp/instr/keyword.c b/src/decomp/instr/keyword.c
index 3ed12fb..aec6897 100644
--- a/src/decomp/instr/keyword.c
+++ b/src/decomp/instr/keyword.c
@@ -148,11 +148,11 @@ static GBufferLine *g_keyword_instruction_print(const GKeywordInstruction *instr
     switch (instr->keyword)
     {
         case DKW_BREAK:
-            g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "break", 5, RTT_KEY_WORD);
+            g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, "break", 5, RTT_KEY_WORD, NULL);
             break;
 
         case DKW_CONTINUE:
-            g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "continue", 8, RTT_KEY_WORD);
+            g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, "continue", 8, RTT_KEY_WORD, NULL);
             break;
 
     }
diff --git a/src/decomp/instr/switch.c b/src/decomp/instr/switch.c
index a01c28c..eb93bb2 100644
--- a/src/decomp/instr/switch.c
+++ b/src/decomp/instr/switch.c
@@ -246,17 +246,17 @@ static GBufferLine *g_switch_instruction_print(const GSwitchInstruction *instr,
     size_t i;                               /* Boucle de parcours #1       */
     size_t j;                               /* Boucle de parcours #2       */
 
-    g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "switch", 9, RTT_KEY_WORD);
+    g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, "switch", 9, RTT_KEY_WORD, NULL);
 
-    g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, " ", 1, RTT_RAW);
-    g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "(", 1, RTT_PUNCT);
+    g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, " ", 1, RTT_RAW, NULL);
+    g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, "(", 1, RTT_PUNCT, NULL);
 
     result = g_dec_instruction_print(G_DEC_INSTRUCTION(instr->value), buffer, line, output);
 
-    g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, ")", 1, RTT_PUNCT);
+    g_buffer_line_append_text(result, BLC_ASSEMBLY_HEAD, ")", 1, RTT_PUNCT, NULL);
 
-    g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, " ", 1, RTT_RAW);
-    g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, "{", 1, RTT_HOOK);
+    g_buffer_line_append_text(result, BLC_ASSEMBLY_HEAD, " ", 1, RTT_RAW, NULL);
+    g_buffer_line_append_text(result, BLC_ASSEMBLY_HEAD, "{", 1, RTT_HOOK, NULL);
 
     g_code_buffer_inc_indentation(buffer);
 
@@ -268,13 +268,13 @@ static GBufferLine *g_switch_instruction_print(const GSwitchInstruction *instr,
         {
             result = g_code_buffer_append_new_line_fixme(buffer);
 
-            g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, "case", 4, RTT_KEY_WORD);
-            g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, " ", 1, RTT_RAW);
+            g_buffer_line_append_text(result, BLC_ASSEMBLY_HEAD, "case", 4, RTT_KEY_WORD, NULL);
+            g_buffer_line_append_text(result, BLC_ASSEMBLY_HEAD, " ", 1, RTT_RAW, NULL);
 
             result = g_dec_instruction_print(G_DEC_INSTRUCTION(instr->cases[i].values[j])
                                              , buffer, result, output);
 
-            g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, ":", 1, RTT_PUNCT);
+            g_buffer_line_append_text(result, BLC_ASSEMBLY_HEAD, ":", 1, RTT_PUNCT, NULL);
 
         }
 
@@ -288,8 +288,8 @@ static GBufferLine *g_switch_instruction_print(const GSwitchInstruction *instr,
     {
         result = g_code_buffer_append_new_line_fixme(buffer);
 
-        g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, "default", 7, RTT_KEY_WORD);
-        g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, ":", 1, RTT_PUNCT);
+        g_buffer_line_append_text(result, BLC_ASSEMBLY_HEAD, "default", 7, RTT_KEY_WORD, NULL);
+        g_buffer_line_append_text(result, BLC_ASSEMBLY_HEAD, ":", 1, RTT_PUNCT, NULL);
 
         result = g_dec_instruction_print(instr->def_case, buffer, result, output);
 
@@ -301,7 +301,7 @@ static GBufferLine *g_switch_instruction_print(const GSwitchInstruction *instr,
 
     result = g_code_buffer_append_new_line_fixme(buffer);
 
-    g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, "}", 1, RTT_HOOK);
+    g_buffer_line_append_text(result, BLC_ASSEMBLY_HEAD, "}", 1, RTT_HOOK, NULL);
 
     return result;
 
diff --git a/src/decomp/lang/asm.c b/src/decomp/lang/asm.c
index bafef2e..069d0c4 100644
--- a/src/decomp/lang/asm.c
+++ b/src/decomp/lang/asm.c
@@ -165,10 +165,10 @@ static GBufferLine *g_asm_output_write_comments(GAsmOutput *output, GCodeBuffer
 
     result = g_code_buffer_append_new_line_fixme(buffer);
 
-    g_buffer_line_insert_text(result, BLC_COMMENTS, "; ", 2, RTT_COMMENT);
+    g_buffer_line_append_text(result, BLC_COMMENTS, "; ", 2, RTT_COMMENT, NULL);
 
     if (length > 0)
-        g_buffer_line_insert_text(result, BLC_COMMENTS, text, length, RTT_COMMENT);
+        g_buffer_line_append_text(result, BLC_COMMENTS, text, length, RTT_COMMENT, NULL);
 
     return result;
 
@@ -191,34 +191,34 @@ static GBufferLine *g_asm_output_write_comments(GAsmOutput *output, GCodeBuffer
 
 static void g_asm_output_write_comp_sign(GAsmOutput *output, GBufferLine *line, CompSignType sign)
 {
-    g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, " ", 1, RTT_RAW);
+    g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, " ", 1, RTT_RAW, NULL);
 
     switch (sign)
     {
         case CST_EQ:
-            g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "==", 2, RTT_SIGNS);
+            g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, "==", 2, RTT_SIGNS, NULL);
             break;
         case CST_NE:
-            g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "!=", 2, RTT_SIGNS);
+            g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, "!=", 2, RTT_SIGNS, NULL);
             break;
         case CST_LT:
-            g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "<", 1, RTT_SIGNS);
+            g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, "<", 1, RTT_SIGNS, NULL);
             break;
         case CST_GE:
-            g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, ">=", 2, RTT_SIGNS);
+            g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, ">=", 2, RTT_SIGNS, NULL);
             break;
         case CST_GT:
-            g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, ">", 1, RTT_SIGNS);
+            g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, ">", 1, RTT_SIGNS, NULL);
             break;
         case CST_LE:
-            g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "<=", 2, RTT_SIGNS);
+            g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, "<=", 2, RTT_SIGNS, NULL);
             break;
         default:
-            g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "?", 1, RTT_SIGNS);
+            g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, "?", 1, RTT_SIGNS, NULL);
             break;
     }
 
-    g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, " ", 1, RTT_RAW);
+    g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, " ", 1, RTT_RAW, NULL);
 
 }
 
@@ -242,7 +242,7 @@ static GBufferLine *g_asm_output_start_routine_info(const GAsmOutput *output, GC
 
     result = g_code_buffer_append_new_line_fixme(buffer);
 
-    g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, "; ", 2, RTT_COMMENT);
+    g_buffer_line_append_text(result, BLC_ASSEMBLY_HEAD, "; ", 2, RTT_COMMENT, NULL);
 
     return result;
 
@@ -270,7 +270,7 @@ static GBufferLine *g_asm_output_start_routine_prototype(GAsmOutput *output, GCo
     result = g_code_buffer_append_new_line_fixme(buffer);
 
     /* TODO */
-    g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, "XXX", 3, RTT_COMMENT);
+    g_buffer_line_append_text(result, BLC_ASSEMBLY_HEAD, "XXX", 3, RTT_COMMENT, NULL);
 
     return result;
 
@@ -293,6 +293,6 @@ static GBufferLine *g_asm_output_start_routine_prototype(GAsmOutput *output, GCo
 
 static void g_asm_output_end_routine_prototype(GAsmOutput *output, GCodeBuffer *buffer, GBufferLine *line)
 {
-    g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, ";", 1, RTT_COMMENT);
+    g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, ";", 1, RTT_COMMENT, NULL);
 
 }
diff --git a/src/decomp/lang/java.c b/src/decomp/lang/java.c
index d3db691..f8954a8 100644
--- a/src/decomp/lang/java.c
+++ b/src/decomp/lang/java.c
@@ -204,7 +204,7 @@ static GBufferLine *g_java_output_start_comments(GJavaOutput *output, GCodeBuffe
 
     result = g_code_buffer_append_new_line_fixme(buffer);
 
-    g_buffer_line_insert_text(result, BLC_COMMENTS, "/**", 3, RTT_COMMENT);
+    g_buffer_line_append_text(result, BLC_COMMENTS, "/**", 3, RTT_COMMENT, NULL);
 
     return result;
 
@@ -232,10 +232,10 @@ static GBufferLine *g_java_output_continue_comments(GJavaOutput *output, GCodeBu
 
     result = g_code_buffer_append_new_line_fixme(buffer);
 
-    g_buffer_line_insert_text(result, BLC_COMMENTS, " * ", 3, RTT_COMMENT);
+    g_buffer_line_append_text(result, BLC_COMMENTS, " * ", 3, RTT_COMMENT, NULL);
 
     if (length > 0)
-        g_buffer_line_insert_text(result, BLC_COMMENTS, text, length, RTT_COMMENT);
+        g_buffer_line_append_text(result, BLC_COMMENTS, text, length, RTT_COMMENT, NULL);
 
     return result;
 
@@ -261,7 +261,7 @@ static GBufferLine *g_java_output_end_comments(GJavaOutput *output, GCodeBuffer
 
     result = g_code_buffer_append_new_line_fixme(buffer);
 
-    g_buffer_line_insert_text(result, BLC_COMMENTS, " */", 3, RTT_COMMENT);
+    g_buffer_line_append_text(result, BLC_COMMENTS, " */", 3, RTT_COMMENT, NULL);
 
     return result;
 
@@ -289,10 +289,10 @@ static GBufferLine *g_java_output_write_comments(GJavaOutput *output, GCodeBuffe
 
     result = g_code_buffer_append_new_line_fixme(buffer);
 
-    g_buffer_line_insert_text(result, BLC_COMMENTS, "// ", 3, RTT_COMMENT);
+    g_buffer_line_append_text(result, BLC_COMMENTS, "// ", 3, RTT_COMMENT, NULL);
 
     if (length > 0)
-        g_buffer_line_insert_text(result, BLC_COMMENTS, text, length, RTT_COMMENT);
+        g_buffer_line_append_text(result, BLC_COMMENTS, text, length, RTT_COMMENT, NULL);
 
     return result;
 
@@ -315,34 +315,34 @@ static GBufferLine *g_java_output_write_comments(GJavaOutput *output, GCodeBuffe
 
 static void g_java_output_write_comp_sign(GJavaOutput *output, GBufferLine *line, CompSignType sign)
 {
-    g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, " ", 1, RTT_RAW);
+    g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, " ", 1, RTT_RAW, NULL);
 
     switch (sign)
     {
         case CST_EQ:
-            g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "==", 2, RTT_SIGNS);
+            g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, "==", 2, RTT_SIGNS, NULL);
             break;
         case CST_NE:
-            g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "!=", 2, RTT_SIGNS);
+            g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, "!=", 2, RTT_SIGNS, NULL);
             break;
         case CST_LT:
-            g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "<", 1, RTT_SIGNS);
+            g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, "<", 1, RTT_SIGNS, NULL);
             break;
         case CST_GE:
-            g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, ">=", 2, RTT_SIGNS);
+            g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, ">=", 2, RTT_SIGNS, NULL);
             break;
         case CST_GT:
-            g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, ">", 1, RTT_SIGNS);
+            g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, ">", 1, RTT_SIGNS, NULL);
             break;
         case CST_LE:
-            g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "<=", 2, RTT_SIGNS);
+            g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, "<=", 2, RTT_SIGNS, NULL);
             break;
         default:
-            g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "?", 1, RTT_SIGNS);
+            g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, "?", 1, RTT_SIGNS, NULL);
             break;
     }
 
-    g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, " ", 1, RTT_RAW);
+    g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, " ", 1, RTT_RAW, NULL);
 
 }
 
@@ -363,22 +363,22 @@ static void g_java_output_write_comp_sign(GJavaOutput *output, GBufferLine *line
 
 static void g_java_output_write_cond_operator(GLangOutput *output, GBufferLine *line, CondOperatorType op)
 {
-    g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, " ", 1, RTT_RAW);
+    g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, " ", 1, RTT_RAW, NULL);
 
     switch (op)
     {
         case COT_AND:
-            g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "&&", 2, RTT_SIGNS);
+            g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, "&&", 2, RTT_SIGNS, NULL);
             break;
         case COT_OR:
-            g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "||", 2, RTT_SIGNS);
+            g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, "||", 2, RTT_SIGNS, NULL);
             break;
         default:
-            g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "??", 2, RTT_SIGNS);
+            g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, "??", 2, RTT_SIGNS, NULL);
             break;
     }
 
-    g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, " ", 1, RTT_RAW);
+    g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, " ", 1, RTT_RAW, NULL);
 
 }
 
@@ -404,15 +404,15 @@ static GBufferLine *g_java_output_start_class(GJavaOutput *output, GCodeBuffer *
 
     result = g_code_buffer_append_new_line_fixme(buffer);
 
-    g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, "class", 5, RTT_KEY_WORD);
-    g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, " ", 1, RTT_RAW);
+    g_buffer_line_append_text(result, BLC_ASSEMBLY_HEAD, "class", 5, RTT_KEY_WORD, NULL);
+    g_buffer_line_append_text(result, BLC_ASSEMBLY_HEAD, " ", 1, RTT_RAW, NULL);
 
     name = _g_data_type_to_string(type, true);
-    g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, name, strlen(name), RTT_RAW);
+    g_buffer_line_append_text(result, BLC_ASSEMBLY_HEAD, name, strlen(name), RTT_RAW, NULL);
     free(name);
 
-    g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, " ", 1, RTT_RAW);
-    g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, "{", 1, RTT_HOOK);
+    g_buffer_line_append_text(result, BLC_ASSEMBLY_HEAD, " ", 1, RTT_RAW, NULL);
+    g_buffer_line_append_text(result, BLC_ASSEMBLY_HEAD, "{", 1, RTT_HOOK, NULL);
 
     result = g_code_buffer_append_new_line_fixme(buffer);
 
@@ -444,7 +444,7 @@ static void g_java_output_end_class(GJavaOutput *output, GCodeBuffer *buffer)
 
     result = g_code_buffer_append_new_line_fixme(buffer);
 
-    g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, "}", 1, RTT_HOOK);
+    g_buffer_line_append_text(result, BLC_ASSEMBLY_HEAD, "}", 1, RTT_HOOK, NULL);
 
     result = g_code_buffer_append_new_line_fixme(buffer);
 
@@ -474,7 +474,7 @@ static GBufferLine *g_java_output_start_routine_prototype(GJavaOutput *output, G
     result = g_code_buffer_append_new_line_fixme(buffer);
 
     /* TODO */
-    g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, "XXX", 3, RTT_RAW);
+    g_buffer_line_append_text(result, BLC_ASSEMBLY_HEAD, "XXX", 3, RTT_RAW, NULL);
 
     return result;
 
@@ -497,7 +497,7 @@ static GBufferLine *g_java_output_start_routine_prototype(GJavaOutput *output, G
 
 static void g_java_output_end_routine_prototype(GJavaOutput *output, GCodeBuffer *buffer, GBufferLine *line)
 {
-    g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, ";", 1, RTT_PUNCT);
+    g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, ";", 1, RTT_PUNCT, NULL);
 
 }
 
@@ -519,8 +519,8 @@ static void g_java_output_end_routine_prototype(GJavaOutput *output, GCodeBuffer
 static void g_java_output_start_routine_body(GJavaOutput *output, GCodeBuffer *buffer, GBufferLine *line)
 {
     /*
-    g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, " ", 1, RTT_RAW);
-    g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "{", 1, RTT_HOOK);
+    g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, " ", 1, RTT_RAW, NULL);
+    g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, "{", 1, RTT_HOOK, NULL);
 
     g_code_buffer_inc_indentation(buffer);
     */
@@ -548,7 +548,7 @@ static void g_java_output_end_routine_body(GJavaOutput *output, GCodeBuffer *buf
 
     line = g_code_buffer_append_new_line_fixme(buffer);
 
-    g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "}", 1, RTT_HOOK);
+    g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, "}", 1, RTT_HOOK, NULL);
     */
 }
 
@@ -574,8 +574,8 @@ static GBufferLine *g_java_output_start_code_block(GJavaOutput *output, GCodeBuf
 
     if (count > 1)
     {
-        g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, " ", 1, RTT_RAW);
-        g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "{", 1, RTT_HOOK);
+        g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, " ", 1, RTT_RAW, NULL);
+        g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, "{", 1, RTT_HOOK, NULL);
     }
 
     g_code_buffer_inc_indentation(buffer);
@@ -612,8 +612,8 @@ static GBufferLine *g_java_output_end_code_block(GJavaOutput *output, GCodeBuffe
 
     if (count > 1)
     {
-        g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, "}", 1, RTT_HOOK);
-        g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, " ", 1, RTT_RAW);
+        g_buffer_line_append_text(result, BLC_ASSEMBLY_HEAD, "}", 1, RTT_HOOK, NULL);
+        g_buffer_line_append_text(result, BLC_ASSEMBLY_HEAD, " ", 1, RTT_RAW, NULL);
     }
 
     return result;
@@ -643,9 +643,9 @@ static GBufferLine *g_java_output_encapsulate_condition(GLangOutput *output, GCo
     result = line;
 
     if (opening)
-        g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, "(", 1, RTT_HOOK);
+        g_buffer_line_append_text(result, BLC_ASSEMBLY_HEAD, "(", 1, RTT_HOOK, NULL);
     else
-        g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, ")", 1, RTT_HOOK);
+        g_buffer_line_append_text(result, BLC_ASSEMBLY_HEAD, ")", 1, RTT_HOOK, NULL);
 
     return result;
 
diff --git a/src/format/dex/class.c b/src/format/dex/class.c
index 454cc40..a507e39 100644
--- a/src/format/dex/class.c
+++ b/src/format/dex/class.c
@@ -534,7 +534,7 @@ GBufferLine *line, GLangOutput *output)
 
     type = get_type_from_dex_pool(format, class->definition.class_idx);
 
-    //g_buffer_line_insert_text(line, BLC_ASSEMBLY, "{", 3, RTT_SIGNS);
+    //g_buffer_line_append_text(line, BLC_ASSEMBLY, "{", 3, RTT_SIGNS, NULL);
 
     //printf("Output :: %s\n", _g_data_type_to_string(type, true));
 
diff --git a/src/glibext/Makefile.am b/src/glibext/Makefile.am
index a88b7d9..aa7a9a3 100644
--- a/src/glibext/Makefile.am
+++ b/src/glibext/Makefile.am
@@ -10,11 +10,12 @@ libglibext_la_SOURCES =					\
 	delayed.h delayed.c					\
 	gbinportion.h gbinportion.c			\
 	gbufferline.h gbufferline.c			\
-	gbuffersegment.h gbuffersegment.c	\
 	gbufferview.h gbufferview.c			\
 	gcodebuffer.h gcodebuffer.c			\
 	gnhash.h gnhash.c					\
 	gwidthtracker.h gwidthtracker.c		\
+	linecolumn.h linecolumn.c			\
+	linesegment.h linesegment.c			\
 	proto.h								\
 	signal.h signal.c
 
diff --git a/src/glibext/gbinportion.c b/src/glibext/gbinportion.c
index 454fc6b..4851a08 100644
--- a/src/glibext/gbinportion.c
+++ b/src/glibext/gbinportion.c
@@ -549,8 +549,8 @@ void g_binary_portion_print(const GBinPortion *portion, GCodeBuffer *buffer, Mem
     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_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD,
+                              "; ======================================================", 56, RTT_COMMENT, NULL);
 
     g_code_buffer_append_new_line(buffer, line);
 
@@ -560,7 +560,7 @@ void g_binary_portion_print(const GBinPortion *portion, GCodeBuffer *buffer, Mem
     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_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, "; ", 2, RTT_COMMENT, NULL);
 
     g_code_buffer_append_new_line(buffer, line);
 
@@ -571,9 +571,9 @@ void g_binary_portion_print(const GBinPortion *portion, GCodeBuffer *buffer, Mem
 
     g_buffer_line_start_merge_at(line, BLC_ASSEMBLY_HEAD);
 
-    g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "; ", 2, RTT_COMMENT);
+    g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, "; ", 2, RTT_COMMENT, NULL);
 
-    g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, portion->desc, strlen(portion->desc), RTT_COMMENT);
+    g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, portion->desc, strlen(portion->desc), RTT_COMMENT, NULL);
 
     snprintf(rights, sizeof(rights), " (%s%s%s%s)",
              _("rights: "),
@@ -581,7 +581,7 @@ void g_binary_portion_print(const GBinPortion *portion, GCodeBuffer *buffer, Mem
              portion->rights & PAC_WRITE ? "w" : "-",
              portion->rights & PAC_EXEC ? "x" : "-");
 
-    g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, rights, strlen(rights), RTT_COMMENT);
+    g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, rights, strlen(rights), RTT_COMMENT, NULL);
 
     g_code_buffer_append_new_line(buffer, line);
 
@@ -591,7 +591,7 @@ void g_binary_portion_print(const GBinPortion *portion, GCodeBuffer *buffer, Mem
     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_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, "; ", 2, RTT_COMMENT, NULL);
 
     g_code_buffer_append_new_line(buffer, line);
 
diff --git a/src/glibext/gbufferline.c b/src/glibext/gbufferline.c
index a33817b..d03dfaf 100644
--- a/src/glibext/gbufferline.c
+++ b/src/glibext/gbufferline.c
@@ -27,84 +27,18 @@
 #include <assert.h>
 #include <malloc.h>
 #include <string.h>
-#include <gtk/gtk.h>    /* Récupération du langage par défaut ; FIXME ? */
 
 
 #include "chrysamarshal.h"
+#include "linecolumn.h"
 #include "../common/extstr.h"
 #include "../gtkext/support.h"
 
 
 
-/* ---------------------------- REGROUPEMENT PAR COLONNE ---------------------------- */
-
-
-/* Informations sur le contenu d'une colonne */
-typedef struct _buffer_line_column
-{
-    GBufferSegment **segments;
-    size_t count;
-
-    int max_width;                          /* Largeur max. de l'espace    */
-
-} buffer_line_column;
-
-
-/* Réinitialise une colonne de ligne. */
-static void reset_column(buffer_line_column *);
-
-/* Recalcule la largeur d'une colonne de segments. */
-static void refresh_column_width(buffer_line_column *);
-
-/* Fournit la quantité de pixels requise pour l'impression. */
-static gint get_column_width(const buffer_line_column *);
-
-/* Ajoute un fragment de texte à une colonne de ligne. */
-static void add_segment_to_column(buffer_line_column *, GBufferSegment *) __attribute__ ((deprecated));
-
-/* Ajoute un fragment de texte à une colonne de ligne. */
-static size_t append_text_to_line_column(buffer_line_column *, const char *, size_t, RenderingTagType);
-
-/* Valide ou non la présence d'un segment dans une colonne. */
-static bool column_has_segment(const buffer_line_column *, const GBufferSegment *, size_t *);
-
-/* Indique l'indice du premier contenu de la colonne. */
-static bool get_column_first_content_index(const buffer_line_column *, size_t *);
-
-/* Indique l'indice du dernier contenu de la colonne. */
-static bool get_column_last_content_index(const buffer_line_column *, size_t *);
-
-#define get_first_segment(col) ((col)->count > 0 ? (col)->segments[0] : NULL)
-#define get_last_segment(col) ((col)->count > 0 ? (col)->segments[(col)->count - 1] : NULL)
-
-/* Indique l'indice du contenu de colonne à une abscisse donnée. */
-static bool get_column_content_index_at(const buffer_line_column *, gint *, GdkScrollDirection, gint *, size_t *);
-
-/* Donne le segment d'une colonne présent à un indice donné. */
-static GBufferSegment *get_column_content_from_index(const buffer_line_column *, size_t);
-
-/* Fournit le segment voisin d'un autre segment identifié. */
-static GBufferSegment *find_near_segment(const buffer_line_column *, GBufferSegment *, GdkScrollDirection);
-
-/* Imprime le contenu d'une colonne de ligne de texte. */
-static void draw_segments_of_column(buffer_line_column *, cairo_t *, gint, gint, const segcnt_list *);
-
-/* Exporte la ligne de texte représentée. */
-static void export_segments_of_column(buffer_line_column *, buffer_export_context *, BufferExportType, int);
-
-
-
 /* ---------------------------- GESTION DE LINE COMPLETE ---------------------------- */
 
 
-/* Identification d'un contenu de colonne */
-typedef struct _col_coord_t
-{
-    BufferLineColumn column;                /* Colonne concernée           */
-    size_t index;                           /* Indice d'insertion          */
-
-} col_coord_t;
-
 /* Mémorisation des origines de texte */
 typedef struct _content_origin
 {
@@ -122,7 +56,7 @@ struct _GBufferLine
     mrange_t range;                         /* Couverture geographique     */
     BufferLineColumn main_column;           /* Colonne principale          */
 
-    buffer_line_column columns[BLC_COUNT];  /* Répartition du texte        */
+    line_column columns[BLC_COUNT];  /* Répartition du texte        */
     BufferLineColumn merge_start;           /* Début de la zone globale    */
     BufferLineColumn last_used;             /* Dernière colonne utilisée   */
 
@@ -153,7 +87,7 @@ struct _GBufferLineClass
 
     /* Signaux */
 
-    void (* content_changed) (GBufferLine *, GBufferSegment *);
+    void (* content_changed) (GBufferLine *, line_segment *);
 
     void (* flip_flag) (GBufferLine *, BufferLineFlags, BufferLineFlags);
 
@@ -172,465 +106,6 @@ static void g_buffer_line_dispose(GBufferLine *);
 /* Procède à la libération totale de la mémoire. */
 static void g_buffer_line_finalize(GBufferLine *);
 
-/* Réagit au changement de contenu d'un segment encapsulé. */
-static void on_line_segment_changed(GBufferSegment *, GBufferLine *);
-
-/* Fournit les coordonnées correspondant à une abscisse donnée. */
-static bool g_buffer_line_get_coord_at(const GBufferLine *, const line_width_summary *, const bool *, gint *, gint *, GdkScrollDirection, bool, col_coord_t *);
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/*                              REGROUPEMENT PAR COLONNE                              */
-/* ---------------------------------------------------------------------------------- */
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : column  = colonne de ligne à mettre à jour.                  *
-*                                                                             *
-*  Description : Réinitialise une colonne de ligne.                           *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-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;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : column  = colonne de ligne à mettre à jour.                  *
-*                                                                             *
-*  Description : Recalcule la largeur d'une colonne de segments.              *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void refresh_column_width(buffer_line_column *column)
-{
-    size_t i;                               /* Boucle de parcours          */
-
-    column->max_width = 0;
-
-    for (i = 0; i < column->count; i++)
-        column->max_width += g_buffer_segment_get_width(column->segments[i]);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : column  = colonne de ligne à consulter.                      *
-*                                                                             *
-*  Description : Fournit la quantité de pixels requise pour l'impression.     *
-*                                                                             *
-*  Retour      : Largeur requise par la colonne, en pixel.                    *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static gint get_column_width(const buffer_line_column *column)
-{
-    return column->max_width;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : column  = colonne de ligne à venir compléter.                *
-*                segment = fragment de texte à ajouter à la colonne.          *
-*                                                                             *
-*  Description : Ajoute un fragment de texte à une colonne de ligne.          *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void add_segment_to_column(buffer_line_column *column, GBufferSegment *segment)
-{
-
-    /* FIXME : à remplacer */
-
-
-    column->segments = (GBufferSegment **)realloc(column->segments, ++column->count * sizeof(GBufferSegment *));
-
-
-    column->segments[column->count - 1] = segment;
-
-
-    column->max_width += g_buffer_segment_get_width(segment);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : column  = colonne de ligne à venir compléter.                *
-*                text    = texte à insérer dans l'existant.                   *
-*                length  = taille du texte à traiter.                         *
-*                type    = type de décorateur à utiliser.                     *
-*                                                                             *
-*  Description : Ajoute un fragment de texte à une colonne de ligne.          *
-*                                                                             *
-*  Retour      : Indice du point d'insertion.                                 *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static size_t append_text_to_line_column(buffer_line_column *column, const char *text, size_t length, RenderingTagType type)
-{
-    size_t result;                          /* Indice à retourner          */
-    GBufferSegment *content;                /* Contenu à représenter       */
-
-    result = column->count;
-
-    content = g_buffer_segment_new(type, text, length);
-
-    column->segments = (GBufferSegment **)realloc(column->segments, ++column->count * sizeof(GBufferSegment *));
-
-    column->segments[result] = content;
-
-    column->max_width += g_buffer_segment_get_width(content);
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : column  = colonne de ligne à venir consulter.                *
-*                segment = fragment de texte à trouver dans la colonne.       *
-*                index   = indice du segment retrouvé ou NULL. [OUT]          *
-*                                                                             *
-*  Description : Valide ou non la présence d'un segment dans une colonne.     *
-*                                                                             *
-*  Retour      : Statut de présence du segment indiqué.                       *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static bool column_has_segment(const buffer_line_column *column, const GBufferSegment *segment, size_t *index)
-{
-    size_t i;                               /* Boucle de parcours          */
-
-    for (i = 0; i < column->count; i++)
-        if (column->segments[i] == segment)
-        {
-            if (index != NULL) *index = i;
-            break;
-        }
-
-    return (i < column->count);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : column = colonne de ligne de texte à consulter.              *
-*                index  = indice du contenu enregistré à la position. [OUT]   *
-*                                                                             *
-*  Description : Indique l'indice du premier contenu de la colonne.           *
-*                                                                             *
-*  Retour      : Validité de l'indice renseigné.                              *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static bool get_column_first_content_index(const buffer_line_column *column, size_t *index)
-{
-    bool result;                            /* Bilan à retourner           */
-
-    result = (column->count > 0);
-
-    if (result)
-        *index = 0;
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : column = colonne de ligne de texte à consulter.              *
-*                index  = indice du contenu enregistré à la position. [OUT]   *
-*                                                                             *
-*  Description : Indique l'indice du dernier contenu de la colonne.           *
-*                                                                             *
-*  Retour      : Validité de l'indice renseigné.                              *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static bool get_column_last_content_index(const buffer_line_column *column, size_t *index)
-{
-    bool result;                            /* Bilan à retourner           */
-
-    result = (column->count > 0);
-
-    if (result)
-        *index = column->count - 1;
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : column   = colonne de ligne de texte à consulter.            *
-*                x        = position de recherche, puis position locale. [OUT]*
-*                dir      = direction d'un éventuel déplacement en cours.     *
-*                consumed = distance pour arriver à la base du segment. [OUT] *
-*                index    = indice du contenu enregistré à la position. [OUT] *
-*                                                                             *
-*  Description : Indique l'indice du contenu de colonne à une abscisse donnée.*
-*                                                                             *
-*  Retour      : Validité de l'indice renseigné.                              *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static bool get_column_content_index_at(const buffer_line_column *column, gint *x, GdkScrollDirection dir, gint *consumed, size_t *index)
-{
-    bool result;                            /* Bilan à retourner           */
-    size_t i;                               /* Boucle de parcours          */
-    gint width;                             /* Largeur à retirer           */
-    bool included;                          /* Appartenance à une largeur ?*/
-
-    result = false;
-    *consumed = 0;
-
-    for (i = 0; i < column->count && !result; i++)
-    {
-        width = g_buffer_segment_get_width(column->segments[i]);
-
-        /**
-         * Soit une limite entre deux segments A et B :
-         *
-         *  - dans le cas d'un déplacement vers la gauche, on part de cette limite
-         *    pour progresser à l'intérieur de A. Donc la limite fait partie de A.
-         *
-         *  - dans le cas d'un déplacement vers la droite, on part de cette limite
-         *    pour progresser à l'intérieur de B. Donc la limite ne fait pas partie de A.
-         */
-        if (dir == GDK_SCROLL_LEFT) included = (width >= *x);
-        else included = (width > *x);
-
-        if (included)
-        {
-            *index = i;
-            result = true;
-        }
-
-        else if ((i + 1) == column->count)
-        {
-            *index = i;
-            result = true;
-            *x = width;
-        }
-
-        else
-        {
-            *x -= width;
-            *consumed += width;
-        }
-
-    }
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : column = colonne de ligne de texte à consulter.              *
-*                index  = indice du contenu à fournir.                        *
-*                                                                             *
-*  Description : Donne le segment d'une colonne présent à un indice donné.    *
-*                                                                             *
-*  Retour      : Segment trouvé ou NULL si hors borne.                        *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static GBufferSegment *get_column_content_from_index(const buffer_line_column *column, size_t index)
-{
-    GBufferSegment *result;                 /* Trouvaille à retourner      */
-
-    assert(index < column->count);
-
-    result = column->segments[index];
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : column = colonne de ligne de texte à consulter.              *
-*                target = segment dont un voisin est à retourner.             *
-*                dir    = orientation des recherches.                         *
-*                                                                             *
-*  Description : Fournit le segment voisin d'un autre segment identifié.      *
-*                                                                             *
-*  Retour      : Segment trouvé ou NULL si hors borne ou inconnu.             *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static GBufferSegment *find_near_segment(const buffer_line_column *column, GBufferSegment *target, GdkScrollDirection dir)
-{
-    GBufferSegment *result;                 /* Trouvaille à retourner      */
-    bool found;                             /* Le segment est bien présent */
-    size_t i;                               /* Boucle de parcours          */
-
-    result = NULL;
-
-    found = column_has_segment(column, target, &i);
-
-    if (found)
-        switch (dir)
-        {
-            case GDK_SCROLL_LEFT:
-                if (i > 0)
-                    result = column->segments[i - 1];
-                break;
-
-            case GDK_SCROLL_RIGHT:
-                if ((i + 1) < column->count)
-                    result = column->segments[i + 1];
-                break;
-
-            default:
-                break;
-
-        }
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : column = colonne de ligne de texte à manipuler.              *
-*                cairo  = contexte graphique à utiliser pour les pinceaux.    *
-*                x_init = abscisse du point d'impression de départ.           *
-*                y      = ordonnée du point d'impression.                     *
-*                list   = liste de contenus à mettre en évidence.             *
-*                                                                             *
-*  Description : Imprime le contenu d'une colonne de ligne de texte.          *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void draw_segments_of_column(buffer_line_column *column, cairo_t *cairo, gint x_init, gint y, const segcnt_list *list)
-{
-    gint x;                                 /* Abscisse d'impression       */
-    size_t i;                               /* Boucle de parcours          */
-
-    x = x_init;
-
-    for (i = 0; i < column->count; i++)
-        g_buffer_segment_draw(column->segments[i], cairo, &x, y, list);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : column = colonne de ligne de texte à manipuler.              *
-*                ctx    = éléments à disposition pour l'exportation.          *
-*                type   = type d'exportation attendue.                        *
-*                span   = fusion de colonnes au sein des cellules ?           *
-*                                                                             *
-*  Description : Exporte la ligne de texte représentée.                       *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void export_segments_of_column(buffer_line_column *column, buffer_export_context *ctx, BufferExportType type, int span)
-{
-    size_t i;                               /* Boucle de parcours          */
-
-    switch (type)
-    {
-        case BET_HTML:
-            switch (span)
-            {
-                case 0:
-                    break;
-                case 1:
-                    dprintf(ctx->fd, "\t\t<TD>");
-                    break;
-                default:
-                    if (span > 0) dprintf(ctx->fd, "\t\t<TD colspan=\"%d\">", span);
-                    break;
-            }
-            break;
-        default:
-            break;
-    }
-
-    for (i = 0; i < column->count; i++)
-        g_buffer_segment_export(column->segments[i], ctx, type);
-
-    switch (type)
-    {
-        case BET_HTML:
-            if (span < 0 || span == 1) dprintf(ctx->fd, "</TD>\n");
-            break;
-        default:
-            break;
-    }
-
-}
-
 
 
 /* ---------------------------------------------------------------------------------- */
@@ -715,7 +190,7 @@ static void g_buffer_line_init(GBufferLine *line)
     BufferLineColumn i;                     /* Boucle de parcours          */
 
     for (i = 0; i < BLC_COUNT; i++)
-        reset_column(&line->columns[i]);
+        init_line_column(&line->columns[i]);
 
     line->merge_start = BLC_COUNT;
     line->last_used = BLC_COUNT;
@@ -851,16 +326,16 @@ void g_buffer_line_fill_mrange(GBufferLine *line, MemoryDataSize psize, MemoryDa
 			if (address[i] != '0') break;
 
 		if (i == len)
-			g_buffer_line_insert_text(line, BLC_PHYSICAL, address, len, RTT_PHYS_ADDR_PAD);
+			g_buffer_line_append_text(line, BLC_PHYSICAL, address, len, RTT_PHYS_ADDR_PAD, NULL);
 
 		else
 		{
-			g_buffer_line_insert_text(line, BLC_PHYSICAL, address, 2, RTT_PHYS_ADDR);
+			g_buffer_line_append_text(line, BLC_PHYSICAL, address, 2, RTT_PHYS_ADDR, NULL);
 
             if (i > 2)
-                g_buffer_line_insert_text(line, BLC_PHYSICAL, &address[2], i - 2, RTT_PHYS_ADDR_PAD);
+                g_buffer_line_append_text(line, BLC_PHYSICAL, &address[2], i - 2, RTT_PHYS_ADDR_PAD, NULL);
 
-            g_buffer_line_insert_text(line, BLC_PHYSICAL, &address[i], len - i, RTT_PHYS_ADDR);
+            g_buffer_line_append_text(line, BLC_PHYSICAL, &address[i], len - i, RTT_PHYS_ADDR, NULL);
 
 		}
 
@@ -876,16 +351,16 @@ void g_buffer_line_fill_mrange(GBufferLine *line, MemoryDataSize psize, MemoryDa
 			if (address[i] != '0') break;
 
 		if (i == len)
-			g_buffer_line_insert_text(line, BLC_VIRTUAL, address, len, RTT_VIRT_ADDR_PAD);
+			g_buffer_line_append_text(line, BLC_VIRTUAL, address, len, RTT_VIRT_ADDR_PAD, NULL);
 
 		else
 		{
-			g_buffer_line_insert_text(line, BLC_VIRTUAL, address, 2, RTT_VIRT_ADDR);
+			g_buffer_line_append_text(line, BLC_VIRTUAL, address, 2, RTT_VIRT_ADDR, NULL);
 
             if (i > 2)
-                g_buffer_line_insert_text(line, BLC_VIRTUAL, &address[2], i - 2, RTT_VIRT_ADDR_PAD);
+                g_buffer_line_append_text(line, BLC_VIRTUAL, &address[2], i - 2, RTT_VIRT_ADDR_PAD, NULL);
 
-            g_buffer_line_insert_text(line, BLC_VIRTUAL, &address[i], len - i, RTT_VIRT_ADDR);
+            g_buffer_line_append_text(line, BLC_VIRTUAL, &address[i], len - i, RTT_VIRT_ADDR, NULL);
 
 		}
 
@@ -987,7 +462,7 @@ void g_buffer_line_fill_for_instr(GBufferLine *line, MemoryDataSize psize, Memor
 
     /* Conclusion */
 
-    g_buffer_line_insert_text(line, BLC_BINARY, bin_code, iter - bin_code, RTT_RAW_CODE);
+    g_buffer_line_append_text(line, BLC_BINARY, bin_code, iter - bin_code, RTT_RAW_CODE, NULL);
 
     if (bin_code != static_buffer)
         free(bin_code);
@@ -1033,91 +508,12 @@ GObject *g_buffer_line_find_first_segment_creator(const GBufferLine *line, Buffe
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : line    = ligne à venir consulter.                           *
-*                creator = créateur à l'origine du segment recherché.         *
-*                                                                             *
-*  Description : Fournit le segment créé par un objet particulier.            *
-*                                                                             *
-*  Retour      : Segment trouvé dans la ligne ou NULL.                        *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-GBufferSegment *g_buffer_line_find_segment_from_creator(const GBufferLine *line, GObject *creator)
-{
-    GBufferSegment *result;                 /* Trouvaille à retourner      */
-    size_t i;                               /* Boucle de parcours          */
-    const col_coord_t *coord;               /* Emplacement du contenu visé */
-
-    result = NULL;
-
-    for (i = 0; i < line->ocount; i++)
-    {
-        if (line->origins[i].creator == creator)
-        {
-            coord = &line->origins[i].coord;
-
-            result = get_column_content_from_index(&line->columns[coord->column], coord->index);
-
-            break;
-
-        }
-
-    }
-
-    if (result != NULL)
-        g_object_ref(G_OBJECT(result));
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : segment = segment de texte dont le contenu vient de changer. *
-*                line    = ligne contenant ce segment.                        *
-*                                                                             *
-*  Description : Réagit au changement de contenu d'un segment encapsulé.      *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void on_line_segment_changed(GBufferSegment *segment, GBufferLine *line)
-{
-    BufferLineColumn i;                     /* Boucle de parcours          */
-    buffer_line_column *column;
-
-    /* Actualisation de la largeur de la colonne */
-
-    for (i = 0; i < BLC_COUNT; i++)
-    {
-        column = &line->columns[i];
-
-        if (column_has_segment(column, segment, NULL))
-        {
-            refresh_column_width(column);
-            break;
-        }
-
-    }
-
-    g_signal_emit_by_name(line, "content-changed", segment);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : line   = ligne à venir compléter.                            *
-*                column = colonne de la ligne visée par l'insertion.          *
-*                text   = texte à insérer dans l'existant.                    *
-*                length = taille du texte à traiter.                          *
-*                type   = type de décorateur à utiliser.                      *
+*  Paramètres  : line    = ligne à venir compléter.                           *
+*                column  = colonne de la ligne visée par l'insertion.         *
+*                text    = texte à insérer dans l'existant.                   *
+*                length  = taille du texte à traiter.                         *
+*                type    = type de décorateur à utiliser.                     *
+*                creator = instance GLib quelconque à associer.               *
 *                                                                             *
 *  Description : Ajoute du texte à formater dans une ligne donnée.            *
 *                                                                             *
@@ -1127,9 +523,10 @@ static void on_line_segment_changed(GBufferSegment *segment, GBufferLine *line)
 *                                                                             *
 ******************************************************************************/
 
-GBufferSegment *g_buffer_line_insert_text(GBufferLine *line, BufferLineColumn column, const char *text, size_t length, RenderingTagType type)
+void g_buffer_line_append_text(GBufferLine *line, BufferLineColumn column, const char *text, size_t length, RenderingTagType type, GObject *creator)
 {
-    GBufferSegment *result;                 /* Portion de texte à renvoyer */
+    size_t index;                           /* Indice d'insertion          */
+    content_origin *origin;                 /* Définition d'une origine    */
 
     assert(length > 0);
 
@@ -1141,13 +538,21 @@ GBufferSegment *g_buffer_line_insert_text(GBufferLine *line, BufferLineColumn co
     else
         line->last_used = column;
 
-    result = g_buffer_segment_new(type, text, length);
+    index = append_text_to_line_column(&line->columns[column], text, length, type);
 
-    add_segment_to_column(&line->columns[column], result);
+    if (creator != NULL)
+    {
+        line->origins = (content_origin *)realloc(line->origins, ++line->ocount * sizeof(content_origin));
 
-    g_signal_connect(result, "content-changed", G_CALLBACK(on_line_segment_changed), line);
+        origin = &line->origins[line->ocount - 1];
 
-    return result;
+        origin->coord.column = column;
+        origin->coord.index = index;
+
+        origin->creator = creator;
+        g_object_ref(G_OBJECT(creator));
+
+    }
 
 }
 
@@ -1155,51 +560,44 @@ GBufferSegment *g_buffer_line_insert_text(GBufferLine *line, BufferLineColumn co
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : line    = ligne à venir compléter.                           *
-*                column  = colonne de la ligne visée par l'insertion.         *
+*                creator = instance GLib quelconque identifiant un segment.   *
 *                text    = texte à insérer dans l'existant.                   *
 *                length  = taille du texte à traiter.                         *
-*                type    = type de décorateur à utiliser.                     *
-*                creator = instance GLib quelconque à associer.               *
 *                                                                             *
-*  Description : Ajoute du texte à formater dans une ligne donnée.            *
+*  Description : Remplace du texte dans une ligne donnée.                     *
 *                                                                             *
-*  Retour      : Portion de texte mis en place, voire NULL.                   *
+*  Retour      : Bilan de l'opération.                                        *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-void g_buffer_line_append_text(GBufferLine *line, BufferLineColumn column, const char *text, size_t length, RenderingTagType type, GObject *creator)
+bool g_buffer_line_replace_text(GBufferLine *line, const GObject *creator, const char *text, size_t length)
 {
-    size_t index;                           /* Indice d'insertion          */
-    content_origin *origin;                 /* Définition d'une origine    */
-
-    assert(length > 0);
-
-    if (column == BLC_MAIN)
-        column = line->main_column;
-
-    if (column == BLC_LAST_USED)
-        column = line->last_used;
-    else
-        line->last_used = column;
+    bool result;                            /* Bilan à retourner            */
+    size_t i;                               /* Boucle de parcours          */
+    const col_coord_t *coord;               /* Emplacement du contenu visé */
 
-    index = append_text_to_line_column(&line->columns[column], text, length, type);
+    result = false;
 
-    if (creator != NULL)
+    for (i = 0; i < line->ocount && !result; i++)
     {
-        line->origins = (content_origin *)realloc(line->origins, ++line->ocount * sizeof(content_origin));
+        if (line->origins[i].creator == creator)
+        {
+            coord = &line->origins[i].coord;
 
-        origin = &line->origins[line->ocount - 1];
+            replace_text_in_line_column(&line->columns[coord->column], coord->index, text, length);
 
-        origin->coord.column = column;
-        origin->coord.index = index;
+            g_signal_emit_by_name(line, "content-changed", NULL);
 
-        origin->creator = creator;
-        g_object_ref(G_OBJECT(creator));
+            result = true;
+
+        }
 
     }
 
+    return result;
+
 }
 
 
@@ -1267,7 +665,7 @@ char *g_buffer_line_get_text(const GBufferLine *line, BufferLineColumn first, Bu
 
         for (j = 0; j < line->columns[i].count; j++)
         {
-            extra = g_buffer_segment_get_text(line->columns[i].segments[j], markup);
+            extra = get_line_segment_text(line->columns[i].segments[j], markup);
 
             if (result == NULL)
                 result = extra;
@@ -1307,7 +705,7 @@ void g_buffer_line_delete_text(GBufferLine *line, BufferLineColumn first, Buffer
     assert(first < end);
 
     for (i = first; i < end; i++)
-        reset_column(&line->columns[i]);
+        reset_line_column(&line->columns[i]);
 
 }
 
@@ -1469,7 +867,7 @@ void g_buffer_line_export(GBufferLine *line, buffer_export_context *ctx, BufferE
 
         /**
          * Pour la signification des différentes valeurs assignées,
-         * se référer au code de export_segments_of_column().
+         * se référer au code de export_line_column_segments().
          *
          * En gros :
          *   - 1  = rien de spécial.
@@ -1490,7 +888,7 @@ void g_buffer_line_export(GBufferLine *line, buffer_export_context *ctx, BufferE
         else
             col_span = ((i + 1) == BLC_COUNT ? -1 : 0);
 
-        export_segments_of_column(&line->columns[i], ctx, type, col_span);
+        export_line_column_segments(&line->columns[i], ctx, type, col_span);
 
     }
 
@@ -1591,6 +989,32 @@ gint g_buffer_line_compute_max_width(const GBufferLine *line, BufferLineColumn i
 }
 
 
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : line  = ligne à venir consulter.                             *
+*                coord = coordonnées interne du segment à retrouver.          *
+*                                                                             *
+*  Description : Fournit le segment présent à une position donnée.            *
+*                                                                             *
+*  Retour      : Segment trouvé ou NULL si hors borne.                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+const line_segment *g_buffer_line_get_segment_from_coord(const GBufferLine *line, const col_coord_t *coord)
+{
+    line_segment *result;                   /* Trouvaille à retourner      */
+
+    result = get_line_column_content_from_index(&line->columns[coord->column], coord->index);
+
+    return result;
+
+}
+
+
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : line    = ligne à venir consulter.                           *
@@ -1610,7 +1034,7 @@ gint g_buffer_line_compute_max_width(const GBufferLine *line, BufferLineColumn i
 *                                                                             *
 ******************************************************************************/
 
-static bool g_buffer_line_get_coord_at(const GBufferLine *line, const line_width_summary *summary, const bool *display, gint *base, gint *offset, GdkScrollDirection dir, bool force, col_coord_t *coord)
+bool g_buffer_line_get_coord_at(const GBufferLine *line, const line_width_summary *summary, const bool *display, gint *base, gint *offset, GdkScrollDirection dir, bool force, col_coord_t *coord)
 {
     bool result;                            /* Bilan à retourner           */
     BufferLineColumn last;                  /* Dernière colonne remplie    */
@@ -1687,7 +1111,7 @@ static bool g_buffer_line_get_coord_at(const GBufferLine *line, const line_width
              */
             if (*offset < 0) *offset = 0;
 
-            result = get_column_content_index_at(&line->columns[i], offset, dir, &consumed, &coord->index);
+            result = get_line_column_content_index_at(&line->columns[i], offset, dir, &consumed, &coord->index);
 
             if (result)
             {
@@ -1720,7 +1144,7 @@ static bool g_buffer_line_get_coord_at(const GBufferLine *line, const line_width
                     else
                         *base += get_column_width(&line->columns[i - 1]);
 
-                    result = get_column_first_content_index(&line->columns[i], &coord->index);
+                    result = get_line_column_first_content_index(&line->columns[i], &coord->index);
 
                     if (result)
                         coord->column = i;
@@ -1747,7 +1171,7 @@ static bool g_buffer_line_get_coord_at(const GBufferLine *line, const line_width
 
             if (last != BLC_COUNT)
             {
-                result = get_column_last_content_index(&line->columns[last], &coord->index);
+                result = get_line_column_last_content_index(&line->columns[last], &coord->index);
 
                 if (result)
                 {
@@ -1791,16 +1215,16 @@ static bool g_buffer_line_get_coord_at(const GBufferLine *line, const line_width
 *                                                                             *
 ******************************************************************************/
 
-GBufferSegment *g_buffer_line_get_segment_at(const GBufferLine *line, const line_width_summary *summary, const bool *display, gint *base, gint *offset, GdkScrollDirection dir, bool force)
+const line_segment *g_buffer_line_get_segment_at(const GBufferLine *line, const line_width_summary *summary, const bool *display, gint *base, gint *offset, GdkScrollDirection dir, bool force)
 {
-    GBufferSegment *result;                 /* Trouvaille à retourner      */
+    const 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, display, base, offset, dir, force, &coord);
 
     if (status)
-        result = get_column_content_from_index(&line->columns[coord.column], coord.index);
+        result = g_buffer_line_get_segment_from_coord(line, &coord);
 
     return result;
 
@@ -1861,43 +1285,40 @@ GObject *g_buffer_line_get_creator_at(const GBufferLine *line, const line_width_
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : line    = ligne à venir consulter.                           *
-*                target  = segment dont un voisin est à retourner.            *
+*                coord   = cordonnées à consulter puis renseigner. [OUT]      *
 *                summary = résumé des largeurs maximales.                     *
 *                display = règles d'affichage des colonnes modulables.        *
 *                dir     = orientation des recherches.                        *
 *                offset  = décalage pour amener à l'extrémité nouvelle. [OUT] *
 *                                                                             *
-*  Description : Fournit le segment voisin d'un autre segment identifié.      *
+*  Description : Fournit des coordonnées voisines selon une direction donnée. *
 *                                                                             *
-*  Retour      : Segment trouvé dans la ligne ou NULL.                        *
+*  Retour      : true si des coordonnées valides ont été renseignées.         *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-GBufferSegment *g_buffer_line_find_near_segment(const GBufferLine *line, GBufferSegment *target, const line_width_summary *summary, const bool *display, GdkScrollDirection dir, gint *offset)
+bool g_buffer_line_find_near_coord(const GBufferLine *line, col_coord_t *coord, const line_width_summary *summary, const bool *display, GdkScrollDirection dir, gint *offset)
 {
-    GBufferSegment *result;                 /* Trouvaille à retourner      */
+    bool result;                            /* Bilan à retourner           */
     BufferLineColumn i;                     /* Boucle de parcours #1       */
     bool displayed;                         /* Confort de lecture          */
     BufferLineColumn k;                     /* Boucle de parcours #2       */
 
-    result = NULL;
+    result = false;
 
     /* Recherche dans la colonne de départ */
 
-    for (i = 0; i < BLC_COUNT; i++)
-        if (column_has_segment(&line->columns[i], target, NULL))
-            break;
+    i = coord->column;
 
-    if (i == BLC_COUNT) return NULL;
+    if (i == BLC_COUNT) return false;
 
-    result = find_near_segment(&line->columns[i], target, dir);
-    if (result != NULL) return result;
+    result = find_near_segment(&line->columns[i], &coord->index, dir);
 
     /* Recherche dans la direction des colonnes voisines */
 
-    if (result == NULL)
+    if (!result)
         switch (dir)
         {
             case GDK_SCROLL_LEFT:
@@ -1906,12 +1327,18 @@ GBufferSegment *g_buffer_line_find_near_segment(const GBufferLine *line, GBuffer
                 if (i == 0) break;
 
                 /* On s'assure que la colonne précédente est visible et peuplée */
-                for (; i > BLC_FIRST && result == NULL; i--)
+                for (; i > BLC_FIRST && !result; i--)
                 {
                     displayed = (i <= BLC_DISPLAY ? display[i - 1] : true);
 
                     if (displayed)
-                        result = get_last_segment(&line->columns[i - 1]);
+                    {
+                        result = get_line_column_first_content_index(&line->columns[i - 1], &coord->index);
+
+                        if (result)
+                            coord->column = i - 1;
+
+                    }
 
                 }
 
@@ -1919,16 +1346,19 @@ GBufferSegment *g_buffer_line_find_near_segment(const GBufferLine *line, GBuffer
 
             case GDK_SCROLL_RIGHT:
 
-                /* Si on a atteint la dernière colonne sans trouver... */
-                /*if (i == BLC_COUNT) break;*/
-
                 /* On s'assure que la colonne suivante est visible et peuplée */
-                for (; (i + 1) < BLC_COUNT && result == NULL; i++)
+                for (; (i + 1) < BLC_COUNT && !result; i++)
                 {
                     displayed = ((i + 1) < BLC_DISPLAY ? display[i + 1] : true);
 
                     if (displayed)
-                        result = get_first_segment(&line->columns[i + 1]);
+                    {
+                        result = get_line_column_first_content_index(&line->columns[i + 1], &coord->index);
+
+                        if (result)
+                            coord->column = i + 1;
+
+                    }
 
                 }
 
@@ -1941,7 +1371,7 @@ GBufferSegment *g_buffer_line_find_near_segment(const GBufferLine *line, GBuffer
 
     /* Calcul de la position finale */
 
-    if (result != NULL)
+    if (result)
     {
         *offset = 0;
 
@@ -2033,7 +1463,7 @@ void g_buffer_line_draw(GBufferLine *line, cairo_t *cairo, const line_width_summ
     {
         if (i < BLC_DISPLAY && !display[i]) continue;
 
-        draw_segments_of_column(&line->columns[i], cairo, x, y, list);
+        draw_line_column_segments(&line->columns[i], cairo, x, y, list);
 
         if (i < line->merge_start)
         {
diff --git a/src/glibext/gbufferline.h b/src/glibext/gbufferline.h
index 9403d80..b5d70b2 100644
--- a/src/glibext/gbufferline.h
+++ b/src/glibext/gbufferline.h
@@ -29,7 +29,7 @@
 #include <stdbool.h>
 
 
-#include "gbuffersegment.h"
+#include "linesegment.h"
 #include "../analysis/content.h"
 #include "../arch/archbase.h"
 #include "../arch/vmpa.h"
@@ -117,15 +117,12 @@ void g_buffer_line_fill_for_instr(GBufferLine *, MemoryDataSize, MemoryDataSize,
 /* Recherche le premier créateur enregistré dans des segments. */
 GObject *g_buffer_line_find_first_segment_creator(const GBufferLine *, BufferLineColumn);
 
-/* Fournit le segment créé par un objet particulier. */
-GBufferSegment *g_buffer_line_find_segment_from_creator(const GBufferLine *, GObject *);
-
-/* Ajoute du texte à formater dans une ligne donnée. */
-GBufferSegment *g_buffer_line_insert_text(GBufferLine *, BufferLineColumn, const char *, size_t, RenderingTagType) __attribute__ ((deprecated));
-
 /* Ajoute du texte à formater dans une ligne donnée. */
 void g_buffer_line_append_text(GBufferLine *, BufferLineColumn, const char *, size_t, RenderingTagType, GObject *);
 
+/* Remplace du texte dans une ligne donnée. */
+bool g_buffer_line_replace_text(GBufferLine *, const GObject *, const char *, size_t);
+
 /* Indique si du texte est présent dans une ligne de tampon. */
 bool g_buffer_line_has_text(const GBufferLine *, BufferLineColumn, BufferLineColumn);
 
@@ -177,6 +174,14 @@ typedef struct _line_width_summary
 
 } line_width_summary;
 
+/* Identification d'un contenu de colonne */
+typedef struct _col_coord_t
+{
+    BufferLineColumn column;                /* Colonne concernée           */
+    size_t index;                           /* Indice d'insertion          */
+
+} col_coord_t;
+
 
 /* Fait remonter les largeurs requises par une ligne donnée. */
 void g_buffer_line_collect_widths(GBufferLine *, line_width_summary *);
@@ -184,14 +189,20 @@ 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 *);
 
+/* Fournit le segment présent à une position donnée. */
+const 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 bool *, gint *, gint *, GdkScrollDirection, bool, col_coord_t *);
+
 /* Donne le segment présent à une abscisse donnée. */
-GBufferSegment *g_buffer_line_get_segment_at(const GBufferLine *, const line_width_summary *, const bool *, gint *, gint *, GdkScrollDirection, bool);
+const line_segment *g_buffer_line_get_segment_at(const GBufferLine *, const line_width_summary *, const bool *, 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 bool *, gint *, gint *, GdkScrollDirection, bool);
 
-/* Fournit le segment voisin d'un autre segment identifié. */
-GBufferSegment *g_buffer_line_find_near_segment(const GBufferLine *, GBufferSegment *, const line_width_summary *, const bool *, GdkScrollDirection, gint *);
+/* 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 bool *, 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 bool *, const segcnt_list *);
diff --git a/src/glibext/gbuffersegment.c b/src/glibext/gbuffersegment.c
deleted file mode 100644
index dfa8c41..0000000
--- a/src/glibext/gbuffersegment.c
+++ /dev/null
@@ -1,1333 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * gbuffersegment.c - concentration d'un fragment de caractères aux propriétés communes
- *
- * Copyright (C) 2010-2014 Cyrille Bagard
- *
- *  This file is part of Chrysalide.
- *
- *  OpenIDA is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 3 of the License, or
- *  (at your option) any later version.
- *
- *  OpenIDA is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#include "gbuffersegment.h"
-
-
-#include <assert.h>
-#include <limits.h>
-#include <malloc.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include <string.h>
-
-
-#include "../common/extstr.h"
-#include "../common/fnv1a.h"
-#include "../gtkext/gtkblockview.h"
-#include "../gtkext/support.h"
-
-
-
-/* ----------------------- ISOLATION DE CONTENUS PARTAGEABLES ----------------------- */
-
-
-/* Propriétés de rendu */
-
-typedef struct _rendering_color_t
-{
-    GdkRGBA color;                          /* Couleur de rendu            */
-    bool has_color;                         /* Définition en place ?       */
-
-} rendering_color_t;
-
-typedef struct _rendering_pattern_t
-{
-    rendering_color_t foreground;           /* Couleur d'impression        */
-    rendering_color_t inverted;             /* Couleur inversée pour sél.  */
-
-    cairo_font_slant_t slant;               /* Style d'impression          */
-    cairo_font_weight_t weight;             /* Poids de la police          */
-
-} rendering_pattern_t;
-
-/* Contenu brut pour segment, potentiellement commun */
-typedef struct _seg_content
-{
-    unsigned int ref_count;                 /* Compteur de références      */
-
-    rendering_pattern_t *pattern;           /* Propriétés du rendu         */
-
-    fnv64_t hash;                           /* Empreinte pour comparaisons */
-    char text[0];                           /* Texte brut conservé         */
-
-} seg_content;
-
-
-/* Conservation de toutes les créations partagées */
-static GHashTable *_segcnt_htable;
-
-
-/* Fournit l'empreinte d'un contenu pour segments. */
-static guint get_seg_content_hash(const seg_content *);
-
-/* Détermine si deux contenus pour segments sont identiques. */
-static bool is_seg_content_equal(const seg_content *, const seg_content *);
-
-/* Détermine si deux contenus pour segments sont identiques. */
-static seg_content *get_shared_content(const seg_content *);
-
-/* Abandonne un contenu pour segments. */
-static void release_shared_content(seg_content *);
-
-
-
-/* -------------------- NATURE DE BASE POUR UN FRAGMENT DE TEXTE -------------------- */
-
-
-/* Nom des éléments CSS */
-
-#define SEGMENT_NAME(s) "segment-" s
-
-static const char *_segment_names[RTT_COUNT] = {
-
-    [RTT_RAW]           = SEGMENT_NAME("raw"),
-    [RTT_COMMENT]       = SEGMENT_NAME("comment"),
-    [RTT_INDICATION]    = SEGMENT_NAME("indication"),
-    [RTT_PHYS_ADDR_PAD] = SEGMENT_NAME("phys-addr-padding"),
-    [RTT_PHYS_ADDR]     = SEGMENT_NAME("phys-addr"),
-    [RTT_VIRT_ADDR_PAD] = SEGMENT_NAME("virt-addr-padding"),
-    [RTT_VIRT_ADDR]     = SEGMENT_NAME("virt-addr"),
-    [RTT_RAW_CODE]      = SEGMENT_NAME("raw-code"),
-    [RTT_LABEL]         = SEGMENT_NAME("label"),
-    [RTT_INSTRUCTION]   = SEGMENT_NAME("instruction"),
-    [RTT_IMMEDIATE]     = SEGMENT_NAME("immediate"),
-    [RTT_REGISTER]      = SEGMENT_NAME("register"),
-    [RTT_PUNCT]         = SEGMENT_NAME("punct"),
-    [RTT_HOOK]          = SEGMENT_NAME("hooks"),
-    [RTT_SIGNS]         = SEGMENT_NAME("signs"),
-    [RTT_LTGT]          = SEGMENT_NAME("ltgt"),
-    [RTT_SECTION]       = SEGMENT_NAME("section"),
-    [RTT_SEGMENT]       = SEGMENT_NAME("segment"),
-    [RTT_STRING]        = SEGMENT_NAME("string"),
-    [RTT_VAR_NAME]      = SEGMENT_NAME("var-name"),
-    [RTT_KEY_WORD]      = SEGMENT_NAME("keyword"),
-    [RTT_ERROR]         = SEGMENT_NAME("error"),
-
-};
-
-/* Compléments à Cairo */
-
-#define CAIRO_FONT_SLANT_COUNT  3
-#define CAIRO_FONT_WEIGHT_COUNT 2
-
-#define CAIRO_FONTS_COUNT (CAIRO_FONT_SLANT_COUNT * CAIRO_FONT_WEIGHT_COUNT)
-#define CAIRO_FONT_INDEX(s, w) ((s) + (w) * CAIRO_FONT_WEIGHT_COUNT)
-
-/* Fragment de caractères aux propriétés communes (instance) */
-struct _GBufferSegment
-{
-    GObject parent;                         /* A laisser en premier        */
-
-    seg_content *content;                   /* Contenu, partagé ou non     */
-
-};
-
-/* Fragment de caractères aux propriétés communes (classe) */
-struct _GBufferSegmentClass
-{
-    GObjectClass parent;                    /* A laisser en premier        */
-
-    rendering_color_t selection_bg;         /* Fond d'impression           */
-
-    cairo_t *font_ctxts[CAIRO_FONTS_COUNT]; /* Contextes de police         */
-    double x_advances[CAIRO_FONTS_COUNT];   /* Largeurs par caractère      */
-    rendering_pattern_t patterns[RTT_COUNT];/* Modèles d'impression        */
-
-    /* Signaux */
-
-    void (* content_changed) (GBufferSegment *);
-
-};
-
-
-/* Procède à l'initialisation d'une classe de fragment de texte. */
-static void g_buffer_segment_class_init(GBufferSegmentClass *);
-
-/* Procède à l'initialisation d'un fragment de texte. */
-static void g_buffer_segment_init(GBufferSegment *);
-
-/* Supprime toutes les références externes. */
-static void g_buffer_segment_dispose(GBufferSegment *);
-
-/* Procède à la libération totale de la mémoire. */
-static void g_buffer_segment_finalize(GBufferSegment *);
-
-/* Met à jour le contenu d'un fragment de texte. */
-void g_buffer_segment_set_text(GBufferSegment *, rendering_pattern_t *, const char *, size_t);
-
-
-
-/* -------------------- GESTION OPTIMALE D'UNE LISTE DE CONTENUS -------------------- */
-
-
-/* Liste identifiant un ensemble de segments */
-struct _segcnt_list
-{
-    fnv64_t *hashes;                        /* Empreinte pour comparaisons */
-    size_t count;                           /* Nommbre de ces empreintes   */
-
-};
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/*                         ISOLATION DE CONTENUS PARTAGEABLES                         */
-/* ---------------------------------------------------------------------------------- */
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : -                                                            *
-*                                                                             *
-*  Description : Initialise la table mémorisant les contenus pour segments.   *
-*                                                                             *
-*  Retour      : Bilan de l'opération.                                        *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-bool init_segment_content_hash_table(void)
-{
-    _segcnt_htable = g_hash_table_new_full((GHashFunc)get_seg_content_hash,
-                                           (GEqualFunc)is_seg_content_equal,
-                                           free, NULL);
-
-    return (_segcnt_htable != NULL);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : -                                                            *
-*                                                                             *
-*  Description : Organise la sortie de la table des contenus pour segments.   *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-void exit_segment_content_hash_table(void)
-{
-    assert(g_hash_table_size(_segcnt_htable) == 0);
-
-    g_hash_table_unref(_segcnt_htable);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : content = contenu pour segment à consulter.                  *
-*                                                                             *
-*  Description : Fournit l'empreinte d'un contenu pour segments.              *
-*                                                                             *
-*  Retour      : Empreinte de lu contenu représenté.                          *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static guint get_seg_content_hash(const seg_content *content)
-{
-    return content->hash;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : content = premier contenu pour segment à analyser.           *
-*                other   = second contenu pour segment à analyser.            *
-*                                                                             *
-*  Description : Détermine si deux contenus pour segments sont identiques.    *
-*                                                                             *
-*  Retour      : Bilan de la comparaison.                                     *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static bool is_seg_content_equal(const seg_content *content, const seg_content *other)
-{
-    bool result;                            /* Résultat à retourner        */
-
-    result = (content->pattern == other->pattern);
-
-    result &= (cmp_fnv_64a(content->hash, other->hash) == 0);
-
-    result &= (strcmp(content->text, other->text) == 0);
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : content = premier contenu pour segment à analyser.           *
-*                other   = second contenu pour segment à analyser.            *
-*                                                                             *
-*  Description : Détermine si deux contenus pour segments sont identiques.    *
-*                                                                             *
-*  Retour      : Bilan de la comparaison.                                     *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static seg_content *get_shared_content(const seg_content *content)
-{
-    seg_content *result;                    /* Contenu partagé à renvoyer  */
-    gboolean found;                         /* Le contenu existe déjà ?    */
-    size_t allocated;                       /* Besoin complet en mémoire   */
-#ifndef NDEBUG
-    gboolean created;                       /* Validation de mise en place */
-#endif
-
-    /**
-     * On considère qu'il n'y a pas besoin de mutex ici, puisque toutes les
-     * opérations se réalisent à priori dans le seul thread principal pour l'affichage.
-     */
-
-    found = g_hash_table_lookup_extended(_segcnt_htable, content, (gpointer *)&result, NULL);
-
-    if (!found)
-    {
-        allocated = sizeof(seg_content) + strlen(content->text) + 1;
-
-        result = (seg_content *)malloc(allocated);
-
-        memcpy(result, content, allocated);
-
-        result->ref_count = 1;
-
-#ifndef NDEBUG
-        created = g_hash_table_insert(_segcnt_htable, result, result);
-        assert(created);
-#else
-        g_hash_table_insert(_segcnt_htable, result, result);
-#endif
-
-    }
-
-    else
-    {
-        assert(result->ref_count < UINT_MAX);
-
-        result->ref_count++;
-
-    }
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : content = contenu pour segments à délaisser.                 *
-*                                                                             *
-*  Description : Abandonne un contenu pour segments.                          *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void release_shared_content(seg_content *content)
-{
-#ifndef NDEBUG
-    gboolean deleted;                       /* Validation de suppression   */
-#endif
-
-    /**
-     * On considère qu'il n'y a pas besoin de mutex ici, puisque toutes les
-     * opérations se réalisent à priori dans le seul thread principal pour l'affichage.
-     */
-
-    if (--content->ref_count == 0)
-    {
-#ifndef NDEBUG
-        deleted = g_hash_table_remove(_segcnt_htable, content);
-        assert(deleted);
-#else
-        g_hash_table_remove(_segcnt_htable, content);
-#endif
-    }
-
-}
-
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/*                      NATURE DE BASE POUR UN FRAGMENT DE TEXTE                      */
-/* ---------------------------------------------------------------------------------- */
-
-
-/* Détermine le type du fragment de caractères aux propriétés communes. */
-G_DEFINE_TYPE(GBufferSegment, g_buffer_segment, G_TYPE_OBJECT);
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : class = classe de composant GTK à initialiser.               *
-*                                                                             *
-*  Description : Procède à l'initialisation d'une classe de fragment de texte.*
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void g_buffer_segment_class_init(GBufferSegmentClass *class)
-{
-    GObjectClass *object;                   /* Autre version de la classe  */
-    GtkStyleContext *context;               /* Contexte pour les styles    */
-    GtkWidgetPath *path;                    /* Chemin d'accès aux thèmes   */
-    gchar *filename;                        /* Accès à une image 1x1       */
-    cairo_font_slant_t s;                   /* Boucle de parcours #1       */
-    cairo_font_weight_t w;                  /* Boucle de parcours #2       */
-    cairo_t **cr;                           /* Contexte à créer            */
-    cairo_surface_t *surface;               /* Surface pour dessin Cairo   */
-    cairo_text_extents_t extents;           /* Couverture des caractères   */
-    RenderingTagType i;                     /* Boucle de parcours          */
-
-    object = G_OBJECT_CLASS(class);
-
-    object->dispose = (GObjectFinalizeFunc/* ! */)g_buffer_segment_dispose;
-    object->finalize = (GObjectFinalizeFunc)g_buffer_segment_finalize;
-
-    /* Création d'un contexte d'accès */
-
-    path = gtk_widget_path_new();
-    gtk_widget_path_append_type(path, G_TYPE_OBJECT);
-
-    context = gtk_style_context_new();
-    gtk_style_context_set_path(context, path);
-    gtk_style_context_set_screen(context, gdk_screen_get_default());
-
-    /* Contextes pour les mesures initiales */
-
-    filename = find_pixmap_file("nil.png");
-    if (filename == NULL) abort();
-
-    for (s = CAIRO_FONT_SLANT_NORMAL; s < CAIRO_FONT_SLANT_COUNT; s++)
-        for (w = CAIRO_FONT_WEIGHT_NORMAL; w < CAIRO_FONT_WEIGHT_COUNT; w++)
-        {
-            cr = &class->font_ctxts[CAIRO_FONT_INDEX(s, w)];
-
-            surface = cairo_image_surface_create_from_png(filename);
-            *cr = cairo_create(surface);
-            cairo_surface_destroy(surface);
-
-            cairo_select_font_face(*cr, "mono", s, w);
-            cairo_set_font_size(*cr, 13);
-
-            cairo_text_extents(*cr, "A", &extents);
-            class->x_advances[CAIRO_FONT_INDEX(s, w)] = extents.x_advance;
-
-        }
-
-    g_free(filename);
-
-    /* Fond d'impression */
-
-    class->selection_bg.has_color = true;
-    class->selection_bg.color.red = 0.5;
-    class->selection_bg.color.green = 0.5;
-    class->selection_bg.color.blue = 0.5;
-    class->selection_bg.color.alpha = 1.0;
-
-    /* Chargement des définitions utiles */
-
-    void define_rendering_pattern(GtkStyleContext *ctx, const char *name, rendering_pattern_t *pattern)
-    {
-        GdkRGBA *tmp_color;                 /* Description d'une couleur   */
-        PangoFontDescription *font_desc;    /* Description d'une police    */
-
-        gtk_style_context_save(ctx);
-
-        gtk_style_context_add_class(context, name);
-
-        gtk_style_context_get(ctx, GTK_STATE_NORMAL, GTK_STYLE_PROPERTY_COLOR, &tmp_color, NULL);
-
-        pattern->foreground.has_color = true;
-        pattern->foreground.color = *tmp_color;
-
-        pattern->inverted.has_color = true;
-        pattern->inverted.color.red = 1.0 - tmp_color->red;
-        pattern->inverted.color.green = 1.0 - tmp_color->green;
-        pattern->inverted.color.blue = 1.0 - tmp_color->blue;
-        pattern->inverted.color.alpha = tmp_color->alpha;
-
-        gdk_rgba_free(tmp_color);
-
-        gtk_style_context_get(context, GTK_STATE_FLAG_NORMAL, GTK_STYLE_PROPERTY_FONT, &font_desc, NULL);
-
-        switch (pango_font_description_get_style(font_desc))
-        {
-            case PANGO_STYLE_NORMAL:
-                pattern->slant = CAIRO_FONT_SLANT_NORMAL;
-                break;
-            case PANGO_STYLE_ITALIC:
-                pattern->slant = CAIRO_FONT_SLANT_ITALIC;
-                break;
-            case PANGO_STYLE_OBLIQUE:
-                pattern->slant = CAIRO_FONT_SLANT_OBLIQUE;
-                break;
-        }
-
-        switch (pango_font_description_get_weight(font_desc))
-        {
-            case PANGO_WEIGHT_THIN:
-            case PANGO_WEIGHT_ULTRALIGHT:	
-            case PANGO_WEIGHT_LIGHT:
-            case PANGO_WEIGHT_SEMILIGHT:
-            case PANGO_WEIGHT_BOOK:
-            case PANGO_WEIGHT_NORMAL:
-            case PANGO_WEIGHT_MEDIUM:
-                pattern->weight = CAIRO_FONT_WEIGHT_NORMAL;
-                break;
-            case PANGO_WEIGHT_SEMIBOLD:
-            case PANGO_WEIGHT_BOLD:
-            case PANGO_WEIGHT_ULTRABOLD:
-            case PANGO_WEIGHT_HEAVY:
-            case PANGO_WEIGHT_ULTRAHEAVY:
-                pattern->weight = CAIRO_FONT_WEIGHT_BOLD;
-                break;
-        }
-
-        pango_font_description_free(font_desc);
-
-        gtk_style_context_restore(context);
-
-    }
-
-    for (i = 0; i < RTT_COUNT; i++)
-        define_rendering_pattern(context, _segment_names[i], &class->patterns[i]);
-
-    /* Nettoyages finaux... */
-
-    gtk_widget_path_free(path);
-    g_object_unref(context);
-
-    /* Signaux */
-
-    g_signal_new("content-changed",
-                 G_TYPE_BUFFER_SEGMENT,
-                 G_SIGNAL_RUN_LAST,
-                 G_STRUCT_OFFSET(GBufferSegmentClass, content_changed),
-                 NULL, NULL,
-                 g_cclosure_marshal_VOID__VOID,
-                 G_TYPE_NONE, 0);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : segment = composant GTK à initialiser.                       *
-*                                                                             *
-*  Description : Procède à l'initialisation d'un fragment de texte.           *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void g_buffer_segment_init(GBufferSegment *segment)
-{
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : segment = instance d'objet GLib à traiter.                   *
-*                                                                             *
-*  Description : Supprime toutes les références externes.                     *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void g_buffer_segment_dispose(GBufferSegment *segment)
-{
-    release_shared_content(segment->content);
-
-    G_OBJECT_CLASS(g_buffer_segment_parent_class)->dispose(G_OBJECT(segment));
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : segment = instance d'objet GLib à traiter.                   *
-*                                                                             *
-*  Description : Procède à la libération totale de la mémoire.                *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void g_buffer_segment_finalize(GBufferSegment *segment)
-{
-    G_OBJECT_CLASS(g_buffer_segment_parent_class)->finalize(G_OBJECT(segment));
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : type   = propriétés de la zone de texte.                     *
-*                text   = chaîne de caractères à traiter.                     *
-*                length = quantité de ces caractères.                         *
-*                                                                             *
-*  Description : Crée un nouveau fragment de texte avec des propriétés.       *
-*                                                                             *
-*  Retour      : Composant GTK créé.                                          *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-GBufferSegment *g_buffer_segment_new(RenderingTagType type, const char *text, size_t length)
-{
-    GBufferSegment *result;                 /* Composant à retourner       */
-    GBufferSegmentClass *class;             /* Stockage de styles préparés */ 
-
-    result = g_object_new(G_TYPE_BUFFER_SEGMENT, NULL);
-
-    class = G_BUFFER_SEGMENT_GET_CLASS(result);
-
-    g_buffer_segment_set_text(result, &class->patterns[type], text, length);
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : segment = fragment de texte à mettre à jour.                 *
-*                pattern = paramètres d'impression du texte.                  *
-*                text    = chaîne de caractères à traiter.                    *
-*                length  = quantité de ces caractères.                        *
-*                                                                             *
-*  Description : Met à jour le contenu d'un fragment de texte.                *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-void g_buffer_segment_set_text(GBufferSegment *segment, rendering_pattern_t *pattern, const char *text, size_t length)
-{
-    char atmp[sizeof(seg_content) + 128];   /* Allocation static facile    */
-    seg_content *content;                   /* Contenu à mettre en place ? */
-
-    if (length < (sizeof(atmp) - sizeof(seg_content)))
-        content = (seg_content *)atmp;
-    else
-        content = (seg_content *)malloc(sizeof(seg_content) + length + 1);
-
-    content->pattern = pattern;
-
-    content->hash = fnv_64a_hash(text);
-
-    memcpy(content->text, text, length);
-    content->text[length] = '\0';
-
-    segment->content = get_shared_content(content);
-
-    if (content != (seg_content *)atmp)
-        free(content);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : segment = fragment de texte à mettre à jour.                 *
-*                text    = chaîne de caractères à traiter.                    *
-*                length  = quantité de ces caractères.                        *
-*                                                                             *
-*  Description : Met à jour le contenu d'un fragment de texte.                *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-void g_buffer_segment_update_text(GBufferSegment *segment, const char *text, size_t length)
-{
-    rendering_pattern_t *pattern;           /* Conservation des paramètres */
-
-    /* Destruction */
-
-    pattern = segment->content->pattern;
-
-    release_shared_content(segment->content);
-
-    /* Création */
-
-    g_buffer_segment_set_text(segment, pattern, text, length);
-
-    g_signal_emit_by_name(segment, "content-changed");
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : segment = fragment de texte à consulter.                     *
-*                ref     = segment de référence servant à la comparaison.     *
-*                                                                             *
-*  Description : Indique si les textes de deux segments sont identiques.      *
-*                                                                             *
-*  Retour      : Bilan de la comparaison.                                     *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-bool g_buffer_segment_compare(const GBufferSegment *segment, const GBufferSegment *ref)
-{
-    bool result;                            /* Bilan à retourner           */
-
-    result = is_seg_content_equal(segment->content, ref->content);
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : segment = fragment de texte à consulter.                     *
-*                markup  = indique si le texte doit être décoré ou non.       *
-*                                                                             *
-*  Description : Fournit le texte brut conservé dans le segment.              *
-*                                                                             *
-*  Retour      : Texte conservé en interne.                                   *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-char *g_buffer_segment_get_text(const GBufferSegment *segment, bool markup)
-{
-    char *result;                           /* Description à renvoyer      */
-    const seg_content *content;             /* Accès au contenu            */
-    char color[7];                          /* Couleur hexadécimale        */
-    char *valid;
-
-    content = segment->content;
-
-    /* Résolution du cas simple */
-    if (!markup)
-        return strdup(content->text);
-
-    result = strdup("<span ");
-
-    /* Couleur */
-
-    result = stradd(result, "foreground=\"#");
-
-    snprintf(color, sizeof(color), "%02hhx%02hhx%02hhx",
-             (unsigned char)(content->pattern->foreground.color.red * 255),
-             (unsigned char)(content->pattern->foreground.color.green * 255),
-             (unsigned char)(content->pattern->foreground.color.blue * 255));
-
-    result = stradd(result, color);
-
-    result = stradd(result, "\"");
-
-    /* Style */
-
-    result = stradd(result, "style=\"");
-
-    switch (content->pattern->slant)
-    {
-        case CAIRO_FONT_SLANT_NORMAL:
-            result = stradd(result, "normal");
-            break;
-
-        case CAIRO_FONT_SLANT_ITALIC:
-            result = stradd(result, "italic");
-            break;
-
-        case CAIRO_FONT_SLANT_OBLIQUE:
-            result = stradd(result, "oblique");
-            break;
-
-    }
-
-    result = stradd(result, "\"");
-
-    /* Epaisseur */
-
-    result = stradd(result, "weight=\"");
-
-    switch (content->pattern->weight)
-    {
-        case CAIRO_FONT_WEIGHT_NORMAL:
-            result = stradd(result, "normal");
-            break;
-
-        case CAIRO_FONT_WEIGHT_BOLD:
-            result = stradd(result, "bold");
-            break;
-
-    }
-
-    result = stradd(result, "\"");
-
-    /* Conclusion */
-
-    result = stradd(result, ">");
-
-    valid = strdup(content->text);
-    valid = strrpl(valid, "<", "&lt;");
-    valid = strrpl(valid, "&", "&amp;");
-
-    result = stradd(result, valid);
-
-    free(valid);
-
-    result = stradd(result, "</span>");
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : segment = fragment de texte à consulter.                     *
-*                                                                             *
-*  Description : Fournit la quantité de pixels requise pour l'impression.     *
-*                                                                             *
-*  Retour      : Largeur requise par la colonne, en pixel.                    *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-gint g_buffer_segment_get_width(const GBufferSegment *segment)
-{
-    gint result;                            /* Largeur à retourner         */
-    GBufferSegmentClass *class;             /* Classe associée à l'instance*/
-    const seg_content *content;             /* Accès au contenu            */
-    cairo_font_slant_t slant;               /* Style d'impression          */
-    cairo_font_weight_t weight;             /* Poids de la police          */
-
-    class = G_BUFFER_SEGMENT_GET_CLASS(segment);
-
-    content = segment->content;
-
-    slant = content->pattern->slant;
-    weight = content->pattern->weight;
-
-    result = class->x_advances[CAIRO_FONT_INDEX(slant, weight)] * strlen(content->text);
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : segment = fragment de texte à consulter.                     *
-*                x       = position horizontale au niveau du segment.         *
-*                                                                             *
-*  Description : Fournit la position idéale pour un marqueur.                 *
-*                                                                             *
-*  Retour      : Position dans le segment donné.                              *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-gint g_buffer_segment_get_caret_position(const GBufferSegment *segment, gint x)
-{
-    gint result;                            /* Position à retourner        */
-    gint width;                             /* Largeur du segment          */
-    gint char_width;                        /* Largeur de police fixe      */
-
-    width = g_buffer_segment_get_width(segment);
-
-    if (x <= 0)
-        result = 0;
-
-    else if (x >= width)
-        result = width;
-
-    else
-    {
-        char_width = width / strlen(segment->content->text);
-
-        result = (x / char_width) * char_width;
-        if ((x % char_width) > (char_width / 2))
-            result += char_width;
-
-    }
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : segment = fragment de texte à manipuler.                     *
-*                x       = position du curseur à faire évoluer. [OUT]         *
-*                ctrl    = indique la demande d'un parcours rapide.           *
-*                dir     = direction du parcours.                             *
-*                                                                             *
-*  Description : Déplace le curseur au sein d'un segment de tampon.           *
-*                                                                             *
-*  Retour      : true si un déplacement a été effectué, false sinon.          *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-bool g_buffer_segment_move_caret(const GBufferSegment *segment, gint *x, bool ctrl, GdkScrollDirection dir)
-{
-    bool result;                            /* Bilan d'opération à renvoyer*/
-    gint width;                             /* Largeur du segment          */
-    gint char_width;                        /* Largeur de police fixe      */
-
-    result = false;
-
-    width = g_buffer_segment_get_width(segment);
-    char_width = width / strlen(segment->content->text);
-
-    if (dir == GDK_SCROLL_LEFT)
-    {
-        printf(">>>>> left ::: x=%d  width=%d  char=%d\n", *x, width, char_width);
-
-        if (*x > width) *x = width + char_width;
-
-        if (*x == 0) goto gbsmc_done;
-
-        if (ctrl) *x = 0;
-        else *x = MAX(0, *x - char_width);
-
-        result = true;
-
-    }
-
-    else if (dir == GDK_SCROLL_RIGHT)
-    {
-
-        printf(">>>>> right ::: x=%d  width=%d  char=%d\n", *x, width, char_width);
-
-        if (*x == width) goto gbsmc_done;
-
-        if (ctrl) *x = width;
-        else *x = MIN(width, *x + char_width);
-
-        result = true;
-
-    }
-
- gbsmc_done:
-
-    printf(">>>>> result ::: %d\n", result);
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : segment = fragment de texte à manipuler.                     *
-*                cr      = contexte graphique à utiliser pour les pinceaux.   *
-*                x       = abscisse du point d'impression (à maj). [OUT]      *
-*                y       = ordonnée du point d'impression.                    *
-*                list    = liste de contenus à mettre en évidence.            *
-*                                                                             *
-*  Description : Imprime le fragment de texte représenté.                     *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-void g_buffer_segment_draw(GBufferSegment *segment, cairo_t *cr, gint *x, gint y, const segcnt_list *list)
-{
-    bool selected;                          /* Marquer une sélection ?     */
-    gint width;                             /* Largeur du segment          */
-    GBufferSegmentClass *class;             /* Accès aux infos globales    */
-    cairo_operator_t old;                   /* Sauvegarde avant changement */
-    const seg_content *content;             /* Accès au contenu            */
-    const rendering_color_t *used_fg;       /* Couleur d'impression utile  */
-
-    selected = selection_list_has_segment_content(list, segment);
-
-    width = g_buffer_segment_get_width(segment);
-
-    /* Fond du texte */
-    if (selected)
-    {
-        class = G_BUFFER_SEGMENT_GET_CLASS(segment);
-
-        cairo_set_source_rgba(cr,
-                              class->selection_bg.color.red,
-                              class->selection_bg.color.green,
-                              class->selection_bg.color.blue,
-                              class->selection_bg.color.alpha);
-
-        cairo_rectangle(cr, *x, y, width, 17);
-
-        old = cairo_get_operator(cr);
-        cairo_set_operator(cr, CAIRO_OPERATOR_DIFFERENCE);
-        cairo_fill(cr);
-        cairo_set_operator(cr, old);
-
-    }
-
-    /* Couleur d'impression */
-
-    content = segment->content;
-
-    if (selected)
-        used_fg = &content->pattern->inverted;
-    else
-        used_fg = &content->pattern->foreground;
-
-    if (used_fg->has_color)
-        cairo_set_source_rgba(cr,
-                              used_fg->color.red,
-                              used_fg->color.green,
-                              used_fg->color.blue,
-                              used_fg->color.alpha);
-    else
-        cairo_set_source_rgb(cr, 0, 0, 0);
-
-    /* Impression du texte */
-
-    cairo_select_font_face(cr, "mono", content->pattern->slant, content->pattern->weight);
-    cairo_set_font_size(cr, 13);
-
-    cairo_move_to(cr, *x, y + 17 - 3);  /* 3 = font extents.descent */
-
-    cairo_show_text(cr, content->text);
-
-    *x += width;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : ctx  = éléments à disposition pour l'exportation.            *
-*                type = type d'exportation attendue.                          *
-*                                                                             *
-*  Description : Exporte tous les styles utilisés par des segments.           *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-void g_buffer_segment_export_style(buffer_export_context *ctx, BufferExportType type)
-{
-    GBufferSegment *dummy;                  /* Segment servant de sujet    */
-    GBufferSegmentClass *class;             /* Classe des segments         */
-    size_t i;                               /* Boucle de parcours          */
-    const rendering_pattern_t *pattern;     /* Modèle à transcrire         */
-
-    dummy = g_object_new(G_TYPE_BUFFER_SEGMENT, NULL);
-    class = G_BUFFER_SEGMENT_GET_CLASS(dummy);
-
-    for (i = 0; i < RTT_COUNT; i++)
-    {
-        pattern = &class->patterns[i];
-
-        switch (type)
-        {
-            case BET_HTML:
-
-                dprintf(ctx->fd, ".%s {\n", _segment_names[i]);
-
-                if (pattern->foreground.has_color)
-                    dprintf(ctx->fd, "\tcolor: #%02hhx%02hhx%02hhx;\n",
-                            (unsigned char)(pattern->foreground.color.red * 255),
-                            (unsigned char)(pattern->foreground.color.green * 255),
-                            (unsigned char)(pattern->foreground.color.blue * 255));
-
-                switch (pattern->slant)
-                {
-                    case CAIRO_FONT_SLANT_ITALIC:
-                        dprintf(ctx->fd, "\tfont-style: italic;\n");
-                        break;
-                    case CAIRO_FONT_SLANT_OBLIQUE:
-                        dprintf(ctx->fd, "\tfont-style: oblique;\n");
-                        break;
-                    default:
-                        dprintf(ctx->fd, "\tfont-style: normal;\n");
-                        break;
-                }
-
-                switch (pattern->weight)
-                {
-                    case CAIRO_FONT_WEIGHT_BOLD:
-                        dprintf(ctx->fd, "\tfont-weight: bold;\n");
-                        break;
-                    default:
-                        dprintf(ctx->fd, "\tfont-weight: normal;\n");
-                        break;
-                }
-
-                dprintf(ctx->fd, "}\n");
-
-                break;
-
-            default:
-                break;
-
-        }
-
-    }
-
-    g_object_unref(G_OBJECT(dummy));
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : segment = fragment de texte à manipuler.                     *
-*                ctx     = éléments à disposition pour l'exportation.         *
-*                type    = type d'exportation attendue.                       *
-*                                                                             *
-*  Description : Exporte le fragment de texte représenté.                     *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-void g_buffer_segment_export(const GBufferSegment *segment, buffer_export_context *ctx, BufferExportType type)
-{
-    const seg_content *content;             /* Accès au contenu            */
-    GBufferSegmentClass *class;             /* Classe des segments         */
-    size_t index;                           /* Indice du modèle de rendu   */
-
-    content = segment->content;
-
-    switch (type)
-    {
-        case BET_HTML:
-            class = G_BUFFER_SEGMENT_GET_CLASS(segment);
-            index = (content->pattern - class->patterns);
-            dprintf(ctx->fd, "<SPAN class=\"%s\">", _segment_names[index]);
-            break;
-        default:
-            break;
-    }
-
-    dprintf(ctx->fd, "%s", content->text);
-
-    switch (type)
-    {
-        case BET_HTML:
-            dprintf(ctx->fd, "</SPAN>");
-            break;
-        default:
-            break;
-    }
-
-}
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/*                      GESTION OPTIMALE D'UNE LISTE DE CONTENUS                      */
-/* ---------------------------------------------------------------------------------- */
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : -                                                            *
-*                                                                             *
-*  Description : Initilise une liste de contenus de segments.                 *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-segcnt_list *init_segment_content_list(void)
-{
-    segcnt_list *result;                    /* Structure à retourner       */
-
-    result = (segcnt_list *)calloc(1, sizeof(segcnt_list));
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : list = ensemble de références de contenus à traiter.         *
-*                                                                             *
-*  Description : Libère la mémoire occupée par une liste de contenus.         *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-void exit_segment_content_list(segcnt_list *list)
-{
-    reset_segment_content_list(list);
-
-    free(list);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : list = ensemble de références de contenus à manipuler.       *
-*                                                                             *
-*  Description : Vide, si besoin est, une liste de contenus de segments.      *
-*                                                                             *
-*  Retour      : true si des éléments ont été purgés, false sinon.            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-bool reset_segment_content_list(segcnt_list *list)
-{
-    bool result;                            /* Bilan d'action à renvoyer   */
-
-    result = (list->count > 0);
-
-    if (list->hashes != NULL)
-    {
-        free(list->hashes);
-        list->hashes = NULL;
-    }
-
-    list->count = 0;
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : list    = ensemble de références de contenus à manipuler.    *
-*                segment = fragment de texte à conservr.                      *
-*                                                                             *
-*  Description : Marque le contenu d'un segment comme remarquable.            *
-*                                                                             *
-*  Retour      : true si la liste a été complétée, false sinon.               *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-bool add_segment_content_to_selection_list(segcnt_list *list, const GBufferSegment *segment)
-{
-    bool result;                            /* Bilan à retourner           */
-    const seg_content *content;             /* Accès au contenu            */
-    size_t i;                               /* Boucle de parcours          */
-
-    static const char white_list[] = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
-
-    result = false;
-
-    content = segment->content;
-
-    for (i = 0; i < (sizeof(white_list) - 1) && !result; i++)
-        result = (strchr(content->text, white_list[i]) != NULL);
-
-    if (result)
-    {
-        list->hashes = (fnv64_t *)realloc(list->hashes, ++list->count * sizeof(fnv64_t));
-
-        list->hashes[list->count - 1] = content->hash;
-
-    }
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : list    = ensemble de références de contenus à consulter.    *
-*                segment = fragment de texte à comparer.                      *
-*                                                                             *
-*  Description : Indique si le contenu d'un segment est notable ou non.       *
-*                                                                             *
-*  Retour      : true si le segment a un contenu présent dans la sélection.   *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-bool selection_list_has_segment_content(const segcnt_list *list, const GBufferSegment *segment)
-{
-    bool result;                            /* Bilan à retourner           */
-    size_t i;                               /* Boucle de parcours          */
-
-    result = false;
-
-    for (i = 0; i < list->count && !result; i++)
-        result = (cmp_fnv_64a(list->hashes[i], segment->content->hash) == 0);
-
-    return result;
-
-}
diff --git a/src/glibext/gbuffersegment.h b/src/glibext/gbuffersegment.h
deleted file mode 100644
index 01fb2ea..0000000
--- a/src/glibext/gbuffersegment.h
+++ /dev/null
@@ -1,203 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * gbuffersegment.h - prototypes pour la concentration d'un fragment de caractères aux propriétés communes
- *
- * Copyright (C) 2010-2014 Cyrille Bagard
- *
- *  This file is part of Chrysalide.
- *
- *  OpenIDA is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 3 of the License, or
- *  (at your option) any later version.
- *
- *  OpenIDA is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#ifndef _GLIBEXT_GBUFFERSEGMENT_H
-#define _GLIBEXT_GBUFFERSEGMENT_H
-
-
-#include <glib-object.h>
-#include <stdbool.h>
-#include <gdk/gdk.h>
-#include <pango/pango.h>
-
-
-
-/* Liste identifiant un ensemble de segments */
-typedef struct _segcnt_list segcnt_list;
-
-
-
-/* ----------------------- ISOLATION DE CONTENUS PARTAGEABLES ----------------------- */
-
-
-/* Initialise la table mémorisant les contenus pour segments. */
-bool init_segment_content_hash_table(void);
-
-/* Organise la sortie de la table des contenus pour segments. */
-void exit_segment_content_hash_table(void);
-
-
-
-/* -------------------- NATURE DE BASE POUR UN FRAGMENT DE TEXTE -------------------- */
-
-
-#define G_TYPE_BUFFER_SEGMENT                  (g_buffer_segment_get_type())
-#define G_BUFFER_SEGMENT(obj)                  (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_BUFFER_SEGMENT, GBufferSegment))
-#define G_BUFFER_SEGMENT_CLASS(klass)          (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_BUFFER_SEGMENT, GBufferSegmentClass))
-#define G_IS_BUFFER_SEGMENT(obj)               (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_BUFFER_SEGMENT))
-#define G_IS_BUFFER_SEGMENT_CLASS(klass)       (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_BUFFER_SEGMENT))
-#define G_BUFFER_SEGMENT_GET_CLASS(obj)        (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_BUFFER_SEGMENT, GBufferSegmentClass))
-
-
-/* Types de partie de rendu */
-typedef enum _RenderingTagType
-{
-    RTT_RAW,                                /* Contenu brut                */
-
-    RTT_COMMENT,                            /* Commentaire                 */
-    RTT_INDICATION,                         /* Aide à la lecture           */
-
-    RTT_PHYS_ADDR_PAD,                      /* Position physique (début)   */
-    RTT_PHYS_ADDR,                          /* Position physique           */
-    RTT_VIRT_ADDR_PAD,                      /* Adresse virtuelle (début)   */
-    RTT_VIRT_ADDR,                          /* Adresse virtuelle           */
-    RTT_RAW_CODE,                           /* Code binaire brut           */
-
-    RTT_LABEL,                              /* Etiquette sur une adresse   */
-
-    RTT_INSTRUCTION,                        /* Code binaire brut           */
-
-    RTT_IMMEDIATE,                          /* Valeur immédiate            */
-
-    RTT_REGISTER,                           /* Registre                    */
-
-    RTT_PUNCT,                              /* Signes de ponctuation       */
-    RTT_HOOK,                               /* Crochets '[' et ']'         */
-    RTT_SIGNS,                              /* Signes '+', '-' et '*'      */
-    RTT_LTGT,                               /* Caractères '<' et '>'       */
-
-    RTT_SECTION,                            /* Identifiant de section      */
-    RTT_SEGMENT,                            /* Indication de segment       */
-    RTT_STRING,                             /* Chaîne de caractères avec " */
-
-    RTT_VAR_NAME,                           /* Nom de variable             */
-
-    RTT_KEY_WORD,                           /* Mot clef de langage         */
-
-    RTT_ERROR,                              /* Erreur "interne"            */
-
-    RTT_COUNT
-
-} RenderingTagType;
-
-
-/* Fragment de caractères aux propriétés communes (instance) */
-typedef struct _GBufferSegment GBufferSegment;
-
-/* Fragment de caractères aux propriétés communes (classe) */
-typedef struct _GBufferSegmentClass GBufferSegmentClass;
-
-
-
-/* Détermine le type du fragment de caractères aux propriétés communes. */
-GType g_buffer_segment_get_type(void);
-
-/* Crée un nouveau fragment de texte avec des propriétés. */
-GBufferSegment *g_buffer_segment_new(RenderingTagType, const char *, size_t);
-
-/* Met à jour le contenu d'un fragment de texte. */
-void g_buffer_segment_update_text(GBufferSegment *, const char *, size_t);
-
-/* Indique si les textes de deux segments sont identiques. */
-bool g_buffer_segment_compare(const GBufferSegment *, const GBufferSegment *);
-
-/* Fournit le texte brut conservé dans le segment. */
-char *g_buffer_segment_get_text(const GBufferSegment *, bool);
-
-/* Fournit la quantité de pixels requise pour l'impression. */
-gint g_buffer_segment_get_width(const GBufferSegment *);
-
-/* Fournit la position idéale pour un marqueur. */
-gint g_buffer_segment_get_caret_position(const GBufferSegment *, gint);
-
-/* Déplace le curseur au sein d'un segment de tampon. */
-bool g_buffer_segment_move_caret(const GBufferSegment *, gint *, bool, GdkScrollDirection);
-
-/* Imprime le fragment de texte représenté. */
-void g_buffer_segment_draw(GBufferSegment *, cairo_t *, gint *, gint, const segcnt_list *);
-
-/* Types d'exportation */
-typedef enum _BufferExportType
-{
-    BET_TEXT,                               /* Exportation en texte brut   */
-    BET_HTML,                               /* Exportation en HTML         */
-
-    BET_COUNT
-
-} BufferExportType;
-
-/* Elements sur lesquels une exportation peut s'appuyer */
-typedef struct _buffer_export_context
-{
-    union
-    {
-        int fd;                             /* Flux ouvert en écriture     */
-
-    };
-
-    union
-    {
-        /* BET_TEXT */
-        const char *sep;                    /* Séparation entre colonnes   */
-
-        /* BET_HTML */
-        struct
-        {
-            const char *font_name;          /* Police d'impression         */
-            const char *bg_color;           /* Fond du tableau HTML        */
-
-        };
-
-    };
-
-} buffer_export_context;
-
-/* Exporte tous les styles utilisés par des segments. */
-void g_buffer_segment_export_style(buffer_export_context *, BufferExportType);
-
-/* Exporte le fragment de texte représenté. */
-void g_buffer_segment_export(const GBufferSegment *, buffer_export_context *, BufferExportType);
-
-
-
-/* -------------------- GESTION OPTIMALE D'UNE LISTE DE CONTENUS -------------------- */
-
-
-/* Initilise une liste de contenus de segments. */
-segcnt_list *init_segment_content_list(void);
-
-/* Libère la mémoire occupée par une liste de contenus. */
-void exit_segment_content_list(segcnt_list *);
-
-/* Vide, si besoin est, une liste de contenus de segments. */
-bool reset_segment_content_list(segcnt_list *);
-
-/* Marque le contenu d'un segment comme remarquable. */
-bool add_segment_content_to_selection_list(segcnt_list *, const GBufferSegment *);
-
-/* Indique si le contenu d'un segment est notable ou non. */
-bool selection_list_has_segment_content(const segcnt_list *, const GBufferSegment *);
-
-
-
-#endif  /* _GLIBEXT_GBUFFERSEGMENT_H */
diff --git a/src/glibext/gbufferview.c b/src/glibext/gbufferview.c
index 2deeffe..9f17e24 100644
--- a/src/glibext/gbufferview.c
+++ b/src/glibext/gbufferview.c
@@ -84,7 +84,7 @@ static void g_buffer_view_finalize(GBufferView *);
 static void on_buffer_size_changed(const GCodeBuffer *, bool, size_t, size_t, GBufferView *);
 
 /* Réagit à un changement de contenu d'une ligne donnée. */
-static void on_buffer_line_changed(GCodeBuffer *, GBufferLine *, GBufferSegment *, GBufferView *);
+static void on_buffer_line_changed(GCodeBuffer *, GBufferLine *, line_segment *, GBufferView *);
 
 /* Déplace le curseur au sein d'une vue de tampon. */
 static bool _g_buffer_view_move_caret(GBufferView *, const GBufferLine *, size_t, GdkRectangle *, bool, GdkScrollDirection, const bool *);
@@ -362,7 +362,7 @@ static void on_buffer_size_changed(const GCodeBuffer *buffer, bool added, size_t
 *                                                                             *
 ******************************************************************************/
 
-static void on_buffer_line_changed(GCodeBuffer *buffer, GBufferLine *line, GBufferSegment *segment, GBufferView *view)
+static void on_buffer_line_changed(GCodeBuffer *buffer, GBufferLine *line, line_segment *segment, GBufferView *view)
 {
     const vmpa2t *addr;                     /* Localisation de ligne       */
 
@@ -588,31 +588,22 @@ const vmpa2t *g_buffer_view_compute_caret(GBufferView *view, gint x, gint y, con
     gint remaining;                         /* Copie de travail modifiable */
     size_t index;                           /* Indice de ligne de tampon   */
     GBufferLine *line;                      /* Ligne à la position courante*/
-    GBufferSegment *segment;                /* Segment présent sur la place*/
+    const line_segment *segment;            /* Segment présent sur la place*/
     GBufferViewClass *class;                /* Classe pour les vues        */
 
     remaining = x;
 
     line = g_buffer_view_find_line_and_segment_at(view, &remaining, y, &index, display, &segment);
 
+    /* FIXME : unref() ! */
     if (line == NULL) return NULL;
     if (segment == NULL) printf(" -- no segment\n");
     if (segment == NULL) return NULL;
 
 
-
-
-
-    printf("\n[BASE]  orig = %d   tronc = %d   reste = %d   dernier = %d   largeur = %d\n",
-           x, x - remaining, remaining, g_buffer_segment_get_caret_position(segment, remaining),
-           g_buffer_segment_get_width(segment));
-
-    printf("        '%s'\n", g_buffer_segment_get_text(segment, false));
-
-
     class = G_BUFFER_VIEW_GET_CLASS(view);
 
-    caret->x = /*view->left_text +*/ (x - remaining) + g_buffer_segment_get_caret_position(segment, remaining);
+    caret->x = /*view->left_text +*/ (x - remaining) + get_caret_position_from_line_segment(segment, remaining);
 
     caret->y = (index - view->first) * class->line_height;
 
@@ -647,10 +638,7 @@ const vmpa2t *g_buffer_view_compute_caret_full(GBufferView *view, GBufferLine *l
     gint offset;                            /* Point de travail modifiable */
     line_width_summary summary;             /* Résumé concis des largeurs  */
     gint base;                              /* Position absolue de segment */
-    GBufferSegment *segment;                /* Segment visé par le pointeur*/
-
-
-
+    bool status;                            /* Bilan de la localisation    */
 
     class = G_BUFFER_VIEW_GET_CLASS(view);
 
@@ -661,13 +649,13 @@ const vmpa2t *g_buffer_view_compute_caret_full(GBufferView *view, GBufferLine *l
 
     g_width_tracker_get_local_width_summary(view->tracker, index, &summary);
 
-    segment = g_buffer_line_get_segment_at(line, &summary, display, &base, &offset, GDK_SCROLL_LEFT, true);
-    if (segment == NULL) return NULL;
+    /* Traitement pour mise à jour de l'abscisse uniquement */
+    status = g_buffer_line_get_coord_at(line, &summary, display, &base, &offset,
+                                        GDK_SCROLL_LEFT, true, (col_coord_t []) { { 0 } });
+    if (!status) return NULL;
 
     caret->x = class->left_text + base + offset;
 
-    printf("caret Y : %zu -> %zu\n", view->first, index);
-
     caret->y = (index - view->first) * class->line_height;
 
     caret->width = 2;
@@ -702,9 +690,8 @@ static bool _g_buffer_view_move_caret(GBufferView *view, const GBufferLine *line
     gint offset;                            /* Point de travail modifiable */
     line_width_summary summary;             /* Résumé concis des largeurs  */
     gint base;                              /* Position absolue de segment */
-    GBufferSegment *segment;                /* Segment visé par le pointeur*/
-
-
+    col_coord_t coord;                      /* Coordonnées en interne      */
+    const line_segment *segment;            /* Bribe de texte trouvée      */
 
     offset = caret->x;
 
@@ -713,64 +700,29 @@ static bool _g_buffer_view_move_caret(GBufferView *view, const GBufferLine *line
 
     g_width_tracker_get_local_width_summary(view->tracker, index, &summary);
 
-    segment = g_buffer_line_get_segment_at(line, &summary, display, &base, &offset, dir, false);
-
-    if (segment == NULL) printf(" ===== NO SEG...\n");
-
-    if (segment == NULL) return false;
-
-
-    printf(" ====== FIRST SEG :: %p ('%s')\n", segment, g_buffer_segment_get_text(segment, false));
-
-
-
+    /* Déplacement au sein du segment courant ? */
 
+    result = g_buffer_line_get_coord_at(line, &summary, display, &base, &offset, dir, false, &coord);
 
+    if (result)
+    {
+        segment = g_buffer_line_get_segment_from_coord(line, &coord);
 
-    //if (dir == GDK_SCROLL_LEFT || dir == GDK_SCROLL_RIGHT)
-        result = g_buffer_segment_move_caret(segment, &offset, ctrl, dir);
-    //else
-        //result = true;
+        result = move_caret_on_line_segment(segment, &offset, ctrl, dir);
 
-    printf(" ====== MOVE 1 ? %d\n", result);
+    }
 
-    ///////////////////
+    /* Tentative de déplacement chez le segment voisin ? */
 
     if (!result)
     {
         base = 0;
 
-        segment = g_buffer_line_find_near_segment(line, segment, &summary, display, dir, &offset);
-
-
-        printf(" ====== NEAR SEG :: %p ('%s')\n", segment, segment ? g_buffer_segment_get_text(segment, false) : NULL);
-
-        if (segment != NULL)
-        {
-
-            result = true;
-            //result = g_buffer_segment_move_caret(segment, &offset, ctrl, dir);
-
-            /*
-            if (result)
-                caret->x -= COL_MARGIN;
-            */
-
-            printf(" ====== MOVE 2 ? %d (offset=%d)\n", result, offset);
-
-
-        }
-
+        result = g_buffer_line_find_near_coord(line, &coord, &summary, display, dir, &offset);
 
     }
 
-
-    if (result)
-        printf(" ====== NEW CARET: %d -> %d\n", caret->x, G_BUFFER_VIEW_GET_CLASS(view)->left_text + base + offset);
-    else
-        printf(" ====== NO NEW CARET!\n");
-
-
+    /* Mise à jour éventuelle */
 
     if (result)
         caret->x = G_BUFFER_VIEW_GET_CLASS(view)->left_text + base + offset;
@@ -804,7 +756,6 @@ const vmpa2t *g_buffer_view_move_caret(GBufferView *view, GdkRectangle *caret, b
 
 
     line_width_summary summary;             /* Résumé concis des largeurs  */
-    bool computed;                          /* Récursivité pris en compte  */
     gint left_pos;                          /* Retour à la ligne           */
     gint right_pos;                         /* Position d'extrème droite   */
     BufferLineColumn i;                     /* Boucle de parcours          */
@@ -833,8 +784,6 @@ const vmpa2t *g_buffer_view_move_caret(GBufferView *view, GdkRectangle *caret, b
 
     g_width_tracker_get_local_width_summary(view->tracker, index, &summary);
 
-    computed = false;
-
     switch (dir)
     {
         case GDK_SCROLL_UP:
@@ -933,17 +882,6 @@ BufferLineColumn g_buffer_line_get_merge_start(const GBufferLine *line)
 
     }
 
-    /*
-    printf(" --- CARET ---   moved = %d   index = %d   result = %p\n",
-           moved, index, result);
-    */
-
-
-    /*
-    if (result && !computed)
-        result = g_buffer_view_compute_caret_full(view, caret->x, caret->y, caret, display, NULL);
-    */
-
     return result;
 
 }
@@ -990,7 +928,7 @@ bool g_buffer_view_unhighlight_segments(GBufferView *view)
 bool g_buffer_view_highlight_segments(GBufferView *view, gint x, gint y, const bool *display)
 {
     bool need_redraw;                       /* Besoin d'actualisation ?    */
-    GBufferSegment *segment;                /* Segment sélectionnable      */
+    const line_segment *segment;            /* Segment sélectionnable      */
 
     if (view->highlighted != NULL)
         need_redraw = g_buffer_view_unhighlight_segments(view);
@@ -1199,6 +1137,8 @@ GBufferLine *g_buffer_view_find_line_at(GBufferView *view, gint y, size_t *idx)
 
     if (index <= view->last)
         result = g_code_buffer_find_line_by_index(view->buffer, index);
+    else
+        result = NULL;
 
     if (result != NULL && idx != NULL)
         *idx = index;
@@ -1225,7 +1165,7 @@ GBufferLine *g_buffer_view_find_line_at(GBufferView *view, gint y, size_t *idx)
 *                                                                             *
 ******************************************************************************/
 
-GBufferLine *g_buffer_view_find_line_and_segment_at(GBufferView *view, gint *x, gint y, size_t *idx, const bool *display, GBufferSegment **segment)
+GBufferLine *g_buffer_view_find_line_and_segment_at(GBufferView *view, gint *x, gint y, size_t *idx, const bool *display, const line_segment **segment)
 {
     GBufferLine *result;                    /* Ligne trouvée à retourner   */
     size_t index;                           /* Indice de la ligne trouvée  */
diff --git a/src/glibext/gbufferview.h b/src/glibext/gbufferview.h
index d5bfd3d..6f7aff4 100644
--- a/src/glibext/gbufferview.h
+++ b/src/glibext/gbufferview.h
@@ -102,7 +102,7 @@ GBufferLine *g_buffer_view_find_line_by_index(const GBufferView *, size_t );
 GBufferLine *g_buffer_view_find_line_at(GBufferView *, gint, size_t *);
 
 /* Fournit la ligne et son segment présents à une position. */
-GBufferLine *g_buffer_view_find_line_and_segment_at(GBufferView *, gint *, gint, size_t *, const bool *, GBufferSegment **);
+GBufferLine *g_buffer_view_find_line_and_segment_at(GBufferView *, gint *, gint, size_t *, const bool *, const line_segment **);
 
 /* Fournit la ligne et son segment présents à une position. */
 GBufferLine *g_buffer_view_find_line_and_creator_at(GBufferView *, gint *, gint, size_t *, const bool *, GObject **);
diff --git a/src/glibext/gcodebuffer.c b/src/glibext/gcodebuffer.c
index 9961cbc..f73a6f9 100644
--- a/src/glibext/gcodebuffer.c
+++ b/src/glibext/gcodebuffer.c
@@ -136,7 +136,7 @@ struct _GCodeBufferClass
 
     /* Signaux */
 
-    void (* line_changed) (GCodeBuffer *, GBufferLine *, GBufferSegment *);
+    void (* line_changed) (GCodeBuffer *, GBufferLine *, line_segment *);
 
 };
 
@@ -152,7 +152,7 @@ static void g_code_buffer_class_init(GCodeBufferClass *);
 static void g_code_buffer_init(GCodeBuffer *);
 
 /* Réagit à un changement de contenu d'une ligne donnée. */
-static void on_line_content_change(GBufferLine *, GBufferSegment *, GCodeBuffer *);
+static void on_line_content_change(GBufferLine *, line_segment *, GCodeBuffer *);
 
 /* Réagit à un changement de propriété rattachée à une ligne. */
 static void on_line_flag_flip(GBufferLine *, BufferLineFlags, BufferLineFlags, GCodeBuffer *);
@@ -529,7 +529,7 @@ GBufferLine *g_code_buffer_prepare_new_line(GCodeBuffer *buffer, const mrange_t
     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);
+        g_buffer_line_append_text(result, BLC_ASSEMBLY_HEAD, "    ", 4, RTT_RAW, NULL);
 
     return result;
 
@@ -550,7 +550,7 @@ GBufferLine *g_code_buffer_prepare_new_line(GCodeBuffer *buffer, const mrange_t
 *                                                                             *
 ******************************************************************************/
 
-static void on_line_content_change(GBufferLine *line, GBufferSegment *segment, GCodeBuffer *buffer)
+static void on_line_content_change(GBufferLine *line, line_segment *segment, GCodeBuffer *buffer)
 {
     g_signal_emit_by_name(buffer, "line-changed", line, segment);
 
diff --git a/src/glibext/linecolumn.c b/src/glibext/linecolumn.c
new file mode 100644
index 0000000..22c1e44
--- /dev/null
+++ b/src/glibext/linecolumn.c
@@ -0,0 +1,480 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * linecolumn.h - prototypes pour le regroupement des segments de texte par colonnes
+ *
+ * Copyright (C) 2016 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  OpenIDA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  OpenIDA is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "linecolumn.h"
+
+
+#include <assert.h>
+#include <malloc.h>
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : column = colonne de ligne à initialiser.                     *
+*                                                                             *
+*  Description : Initialise une colonne de ligne.                             *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void init_line_column(line_column *column)
+{
+    column->segments = NULL;
+    column->count = 0;
+
+    column->max_width = 0;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : column = colonne de ligne à mettre à jour.                   *
+*                                                                             *
+*  Description : Réinitialise une colonne de ligne.                           *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void reset_line_column(line_column *column)
+{
+    size_t i;                               /* Boucle de parcours          */
+
+    for (i = 0; i < column->count; i++)
+        release_line_segment(column->segments[i]);
+
+    if (column->segments != NULL)
+    {
+        free(column->segments);
+        column->segments = NULL;
+    }
+
+    column->count = 0;
+
+    column->max_width = 0;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : column = colonne de ligne à mettre à jour.                   *
+*                                                                             *
+*  Description : Recalcule la largeur d'une colonne de segments.              *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void refresh_line_column_width(line_column *column)
+{
+    size_t i;                               /* Boucle de parcours          */
+
+    column->max_width = 0;
+
+    for (i = 0; i < column->count; i++)
+        column->max_width += get_line_segment_width(column->segments[i]);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : column  = colonne de ligne à consulter.                      *
+*                                                                             *
+*  Description : Fournit la quantité de pixels requise pour l'impression.     *
+*                                                                             *
+*  Retour      : Largeur requise par la colonne, en pixel.                    *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+gint get_column_width(const line_column *column)
+{
+    return column->max_width;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : column  = colonne de ligne à venir compléter.                *
+*                text    = texte à insérer dans l'existant.                   *
+*                length  = taille du texte à traiter.                         *
+*                type    = type de décorateur à utiliser.                     *
+*                                                                             *
+*  Description : Ajoute un fragment de texte à une colonne de ligne.          *
+*                                                                             *
+*  Retour      : Indice du point d'insertion.                                 *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+size_t append_text_to_line_column(line_column *column, const char *text, size_t length, RenderingTagType type)
+{
+    size_t result;                          /* Indice à retourner          */
+    line_segment *segment;                  /* Contenu à représenter       */
+
+    result = column->count;
+
+    segment = get_new_line_segment(type, text, length);
+
+    column->segments = (line_segment **)realloc(column->segments, ++column->count * sizeof(line_segment *));
+
+    column->segments[result] = segment;
+
+    column->max_width += get_line_segment_width(segment);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : column  = colonne de ligne à venir compléter.                *
+*                index   = indice du frament de texte à remplacer.            *
+*                text    = texte à insérer dans l'existant.                   *
+*                length  = taille du texte à traiter.                         *
+*                                                                             *
+*  Description : Remplace un fragment de texte dans une colonne de ligne.     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void replace_text_in_line_column(line_column *column, size_t index, const char *text, size_t length)
+{
+    RenderingTagType type;                  /* Type de rendu à conserver   */
+    line_segment *segment;                  /* Contenu à représenter       */
+
+    assert(index < column->count);
+
+    /* Retrait */
+
+    segment = column->segments[index];
+
+    type = get_line_segment_type(segment);
+
+    release_line_segment(segment);
+
+    /* Ajout */
+
+    segment = get_new_line_segment(type, text, length);
+
+    column->segments[index] = segment;
+
+    refresh_line_column_width(column);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : column = colonne de ligne de texte à consulter.              *
+*                index  = indice du contenu enregistré à la position. [OUT]   *
+*                                                                             *
+*  Description : Indique l'indice du premier contenu de la colonne.           *
+*                                                                             *
+*  Retour      : Validité de l'indice renseigné.                              *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool get_line_column_first_content_index(const line_column *column, size_t *index)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    result = (column->count > 0);
+
+    if (result)
+        *index = 0;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : column = colonne de ligne de texte à consulter.              *
+*                index  = indice du contenu enregistré à la position. [OUT]   *
+*                                                                             *
+*  Description : Indique l'indice du dernier contenu de la colonne.           *
+*                                                                             *
+*  Retour      : Validité de l'indice renseigné.                              *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool get_line_column_last_content_index(const line_column *column, size_t *index)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    result = (column->count > 0);
+
+    if (result)
+        *index = column->count - 1;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : column = colonne de ligne de texte à consulter.              *
+*                index  = indice à consulter puis renseigner. [OUT]           *
+*                dir    = orientation des recherches.                         *
+*                                                                             *
+*  Description : Fournit le segment voisin d'un autre segment identifié.      *
+*                                                                             *
+*  Retour      : Validité de l'indice renseigné.                              *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool find_near_segment(const line_column *column, size_t *index, GdkScrollDirection dir)
+{
+    bool result;                            /* Bilan à faire remonter      */
+
+    result = false;
+
+    switch (dir)
+    {
+        case GDK_SCROLL_LEFT:
+            if (*index > 0)
+            {
+                (*index)--;
+                result = true;
+            }
+            break;
+
+        case GDK_SCROLL_RIGHT:
+            if ((*index + 1) < column->count)
+            {
+                (*index)++;
+                result = true;
+            }
+            break;
+
+        default:
+            break;
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : column   = colonne de ligne de texte à consulter.            *
+*                x        = position de recherche, puis position locale. [OUT]*
+*                dir      = direction d'un éventuel déplacement en cours.     *
+*                consumed = distance pour arriver à la base du segment. [OUT] *
+*                index    = indice du contenu enregistré à la position. [OUT] *
+*                                                                             *
+*  Description : Indique l'indice du contenu de colonne à une abscisse donnée.*
+*                                                                             *
+*  Retour      : Validité de l'indice renseigné.                              *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool get_line_column_content_index_at(const line_column *column, gint *x, GdkScrollDirection dir, gint *consumed, size_t *index)
+{
+    bool result;                            /* Bilan à retourner           */
+    size_t i;                               /* Boucle de parcours          */
+    gint width;                             /* Largeur à retirer           */
+    bool included;                          /* Appartenance à une largeur ?*/
+
+    result = false;
+    *consumed = 0;
+
+    for (i = 0; i < column->count && !result; i++)
+    {
+        width = get_line_segment_width(column->segments[i]);
+
+        /**
+         * Soit une limite entre deux segments A et B :
+         *
+         *  - dans le cas d'un déplacement vers la gauche, on part de cette limite
+         *    pour progresser à l'intérieur de A. Donc la limite fait partie de A.
+         *
+         *  - dans le cas d'un déplacement vers la droite, on part de cette limite
+         *    pour progresser à l'intérieur de B. Donc la limite ne fait pas partie de A.
+         */
+        if (dir == GDK_SCROLL_LEFT) included = (width >= *x);
+        else included = (width > *x);
+
+        if (included)
+        {
+            *index = i;
+            result = true;
+        }
+
+        else if ((i + 1) == column->count)
+        {
+            *index = i;
+            result = true;
+            *x = width;
+        }
+
+        else
+        {
+            *x -= width;
+            *consumed += width;
+        }
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : column = colonne de ligne de texte à consulter.              *
+*                index  = indice du contenu à fournir.                        *
+*                                                                             *
+*  Description : Donne le segment d'une colonne présent à un indice donné.    *
+*                                                                             *
+*  Retour      : Segment trouvé ou NULL si hors borne.                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+line_segment *get_line_column_content_from_index(const line_column *column, size_t index)
+{
+    line_segment *result;                   /* Trouvaille à retourner      */
+
+    assert(index < column->count);
+
+    result = column->segments[index];
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : column = colonne de ligne de texte à manipuler.              *
+*                cairo  = contexte graphique à utiliser pour les pinceaux.    *
+*                x_init = abscisse du point d'impression de départ.           *
+*                y      = ordonnée du point d'impression.                     *
+*                list   = liste de contenus à mettre en évidence.             *
+*                                                                             *
+*  Description : Imprime le contenu d'une colonne de ligne de texte.          *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void draw_line_column_segments(const line_column *column, cairo_t *cairo, gint x_init, gint y, const segcnt_list *list)
+{
+    gint x;                                 /* Abscisse d'impression       */
+    size_t i;                               /* Boucle de parcours          */
+
+    x = x_init;
+
+    for (i = 0; i < column->count; i++)
+        draw_line_segment(column->segments[i], cairo, &x, y, list);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : column = colonne de ligne de texte à manipuler.              *
+*                ctx    = éléments à disposition pour l'exportation.          *
+*                type   = type d'exportation attendue.                        *
+*                span   = fusion de colonnes au sein des cellules ?           *
+*                                                                             *
+*  Description : Exporte la ligne de texte représentée.                       *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void export_line_column_segments(const line_column *column, buffer_export_context *ctx, BufferExportType type, int span)
+{
+    size_t i;                               /* Boucle de parcours          */
+
+    switch (type)
+    {
+        case BET_HTML:
+            switch (span)
+            {
+                case 0:
+                    break;
+                case 1:
+                    dprintf(ctx->fd, "\t\t<TD>");
+                    break;
+                default:
+                    if (span > 0) dprintf(ctx->fd, "\t\t<TD colspan=\"%d\">", span);
+                    break;
+            }
+            break;
+        default:
+            break;
+    }
+
+    for (i = 0; i < column->count; i++)
+        export_line_segment(column->segments[i], ctx, type);
+
+    switch (type)
+    {
+        case BET_HTML:
+            if (span < 0 || span == 1) dprintf(ctx->fd, "</TD>\n");
+            break;
+        default:
+            break;
+    }
+
+}
diff --git a/src/glibext/linecolumn.h b/src/glibext/linecolumn.h
new file mode 100644
index 0000000..849c076
--- /dev/null
+++ b/src/glibext/linecolumn.h
@@ -0,0 +1,93 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * linecolumn.h - prototypes pour le regroupement des segments de texte par colonnes
+ *
+ * Copyright (C) 2016 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  OpenIDA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  OpenIDA is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GLIBEXT_LINECOLUMN_H
+#define _GLIBEXT_LINECOLUMN_H
+
+
+#include <stdbool.h>
+#include <glib-object.h>
+#include <gdk/gdk.h>
+
+
+#include "linesegment.h"
+
+
+
+/* Informations sur le contenu d'une colonne */
+typedef struct _line_column line_column;
+
+
+/* Informations sur le contenu d'une colonne */
+struct _line_column
+{
+    line_segment **segments;                /* Liste des segments contenus */
+    size_t count;                           /* Taille de cette liste       */
+
+    int max_width;                          /* Largeur max. de l'espace    */
+
+};
+
+
+/* Initialise une colonne de ligne. */
+void init_line_column(line_column *);
+
+/* Réinitialise une colonne de ligne. */
+void reset_line_column(line_column *);
+
+/* Recalcule la largeur d'une colonne de segments. */
+void refresh_line_column_width(line_column *);
+
+/* Fournit la quantité de pixels requise pour l'impression. */
+gint get_column_width(const line_column *);
+
+/* Ajoute un fragment de texte à une colonne de ligne. */
+size_t append_text_to_line_column(line_column *, const char *, size_t, RenderingTagType);
+
+/* Remplace un fragment de texte dans une colonne de ligne. */
+void replace_text_in_line_column(line_column *, size_t, const char *, size_t);
+
+/* Indique l'indice du premier contenu de la colonne. */
+bool get_line_column_first_content_index(const line_column *, size_t *);
+
+/* Indique l'indice du dernier contenu de la colonne. */
+bool get_line_column_last_content_index(const line_column *, size_t *);
+
+/* Fournit le segment voisin d'un autre segment identifié. */
+bool find_near_segment(const line_column *, size_t *, GdkScrollDirection);
+
+/* Indique l'indice du contenu de colonne à une abscisse donnée. */
+bool get_line_column_content_index_at(const line_column *, gint *, GdkScrollDirection, gint *, size_t *);
+
+/* Donne le segment d'une colonne présent à un indice donné. */
+line_segment *get_line_column_content_from_index(const line_column *, size_t);
+
+/* Imprime le contenu d'une colonne de ligne de texte. */
+void draw_line_column_segments(const line_column *, cairo_t *, gint, gint, const segcnt_list *);
+
+/* Exporte la ligne de texte représentée. */
+void export_line_column_segments(const line_column *, buffer_export_context *, BufferExportType, int);
+
+
+
+#endif  /* _GLIBEXT_LINECOLUMN_H */
diff --git a/src/glibext/linesegment.c b/src/glibext/linesegment.c
new file mode 100644
index 0000000..e233b00
--- /dev/null
+++ b/src/glibext/linesegment.c
@@ -0,0 +1,1155 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * linesegment.c - concentration d'un fragment de caractères aux propriétés communes
+ *
+ * Copyright (C) 2010-2014 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  OpenIDA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  OpenIDA is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "linesegment.h"
+
+
+#include <assert.h>
+#include <limits.h>
+#include <malloc.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+#include "../common/extstr.h"
+#include "../common/fnv1a.h"
+#include "../gtkext/support.h"
+
+
+
+/* ------------------------ NATURE POUR UN FRAGMENT DE TEXTE ------------------------ */
+
+
+/* Nom des éléments CSS */
+
+#define SEGMENT_NAME(s) "segment-" s
+
+static const char *_segment_names[RTT_COUNT] = {
+
+    [RTT_RAW]           = SEGMENT_NAME("raw"),
+    [RTT_COMMENT]       = SEGMENT_NAME("comment"),
+    [RTT_INDICATION]    = SEGMENT_NAME("indication"),
+    [RTT_PHYS_ADDR_PAD] = SEGMENT_NAME("phys-addr-padding"),
+    [RTT_PHYS_ADDR]     = SEGMENT_NAME("phys-addr"),
+    [RTT_VIRT_ADDR_PAD] = SEGMENT_NAME("virt-addr-padding"),
+    [RTT_VIRT_ADDR]     = SEGMENT_NAME("virt-addr"),
+    [RTT_RAW_CODE]      = SEGMENT_NAME("raw-code"),
+    [RTT_LABEL]         = SEGMENT_NAME("label"),
+    [RTT_INSTRUCTION]   = SEGMENT_NAME("instruction"),
+    [RTT_IMMEDIATE]     = SEGMENT_NAME("immediate"),
+    [RTT_REGISTER]      = SEGMENT_NAME("register"),
+    [RTT_PUNCT]         = SEGMENT_NAME("punct"),
+    [RTT_HOOK]          = SEGMENT_NAME("hooks"),
+    [RTT_SIGNS]         = SEGMENT_NAME("signs"),
+    [RTT_LTGT]          = SEGMENT_NAME("ltgt"),
+    [RTT_SECTION]       = SEGMENT_NAME("section"),
+    [RTT_SEGMENT]       = SEGMENT_NAME("segment"),
+    [RTT_STRING]        = SEGMENT_NAME("string"),
+    [RTT_VAR_NAME]      = SEGMENT_NAME("var-name"),
+    [RTT_KEY_WORD]      = SEGMENT_NAME("keyword"),
+    [RTT_ERROR]         = SEGMENT_NAME("error"),
+
+};
+
+/* Compléments à Cairo */
+
+#define CAIRO_FONT_SLANT_COUNT  3
+#define CAIRO_FONT_WEIGHT_COUNT 2
+
+#define CAIRO_FONTS_COUNT (CAIRO_FONT_SLANT_COUNT * CAIRO_FONT_WEIGHT_COUNT)
+#define CAIRO_FONT_INDEX(s, w) ((s) + (w) * CAIRO_FONT_WEIGHT_COUNT)
+
+
+/* Propriétés de rendu */
+
+typedef struct _rendering_color_t
+{
+    GdkRGBA color;                          /* Couleur de rendu            */
+    bool has_color;                         /* Définition en place ?       */
+
+} rendering_color_t;
+
+typedef struct _rendering_pattern_t
+{
+    rendering_color_t foreground;           /* Couleur d'impression        */
+    rendering_color_t inverted;             /* Couleur inversée pour sél.  */
+
+    cairo_font_slant_t slant;               /* Style d'impression          */
+    cairo_font_weight_t weight;             /* Poids de la police          */
+
+} rendering_pattern_t;
+
+typedef struct _segment_rendering
+{
+    rendering_color_t selection_bg;         /* Fond d'impression           */
+
+    cairo_t *font_ctxts[CAIRO_FONTS_COUNT]; /* Contextes de police         */
+    double x_advances[CAIRO_FONTS_COUNT];   /* Largeurs par caractère      */
+    rendering_pattern_t patterns[RTT_COUNT];/* Modèles d'impression        */
+
+} segment_rendering;
+
+
+/* Configuration globale des rendus */
+static segment_rendering _seg_params;
+
+
+
+/* ----------------------- ISOLATION DE CONTENUS PARTAGEABLES ----------------------- */
+
+
+/* Fragment de caractères aux propriétés potentiellement partagées */
+struct _line_segment
+{
+    unsigned int ref_count;                 /* Compteur de références      */
+
+    rendering_pattern_t *pattern;           /* Propriétés du rendu         */
+
+    fnv64_t hash;                           /* Empreinte pour comparaisons */
+    char text[0];                           /* Texte brut conservé         */
+
+};
+
+
+/* Conservation de toutes les créations partagées */
+static GHashTable *_segcnt_htable;
+
+
+/* Fournit l'empreinte d'un contenu pour segments. */
+static guint get_line_segment_hash(const line_segment *);
+
+/* Détermine si deux contenus pour segments sont identiques. */
+static bool is_line_segment_equal(const line_segment *, const line_segment *);
+
+/* Détermine si deux contenus pour segments sont identiques. */
+static line_segment *get_shared_segment_content(const line_segment *);
+
+/* Abandonne un contenu pour segments. */
+static void release_shared_segment_content(line_segment *);
+
+
+
+/* -------------------- GESTION OPTIMALE D'UNE LISTE DE CONTENUS -------------------- */
+
+
+/* Liste identifiant un ensemble de segments */
+struct _segcnt_list
+{
+    fnv64_t *hashes;                        /* Empreinte pour comparaisons */
+    size_t count;                           /* Nommbre de ces empreintes   */
+
+};
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                          NATURE POUR UN FRAGMENT DE TEXTE                          */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Procède à l'initialisation des paramètres de rendu de texte. *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool load_segment_rendering_parameters(void)
+{
+    GtkStyleContext *context;               /* Contexte pour les styles    */
+    GtkWidgetPath *path;                    /* Chemin d'accès aux thèmes   */
+    gchar *filename;                        /* Accès à une image 1x1       */
+    cairo_font_slant_t s;                   /* Boucle de parcours #1       */
+    cairo_font_weight_t w;                  /* Boucle de parcours #2       */
+    cairo_t **cr;                           /* Contexte à créer            */
+    cairo_surface_t *surface;               /* Surface pour dessin Cairo   */
+    cairo_text_extents_t extents;           /* Couverture des caractères   */
+    RenderingTagType i;                     /* Boucle de parcours          */
+
+    /* Création d'un contexte d'accès */
+
+    path = gtk_widget_path_new();
+    gtk_widget_path_append_type(path, G_TYPE_OBJECT);
+
+    context = gtk_style_context_new();
+    gtk_style_context_set_path(context, path);
+    gtk_style_context_set_screen(context, gdk_screen_get_default());
+
+    /* Contextes pour les mesures initiales */
+
+    filename = find_pixmap_file("nil.png");
+    if (filename == NULL) abort();
+
+    for (s = CAIRO_FONT_SLANT_NORMAL; s < CAIRO_FONT_SLANT_COUNT; s++)
+        for (w = CAIRO_FONT_WEIGHT_NORMAL; w < CAIRO_FONT_WEIGHT_COUNT; w++)
+        {
+            cr = &_seg_params.font_ctxts[CAIRO_FONT_INDEX(s, w)];
+
+            surface = cairo_image_surface_create_from_png(filename);
+            *cr = cairo_create(surface);
+            cairo_surface_destroy(surface);
+
+            cairo_select_font_face(*cr, "mono", s, w);
+            cairo_set_font_size(*cr, 13);
+
+            cairo_text_extents(*cr, "A", &extents);
+            _seg_params.x_advances[CAIRO_FONT_INDEX(s, w)] = extents.x_advance;
+
+        }
+
+    g_free(filename);
+
+    /* Fond d'impression */
+
+    _seg_params.selection_bg.has_color = true;
+    _seg_params.selection_bg.color.red = 0.5;
+    _seg_params.selection_bg.color.green = 0.5;
+    _seg_params.selection_bg.color.blue = 0.5;
+    _seg_params.selection_bg.color.alpha = 1.0;
+
+    /* Chargement des définitions utiles */
+
+    void define_rendering_pattern(GtkStyleContext *ctx, const char *name, rendering_pattern_t *pattern)
+    {
+        GdkRGBA *tmp_color;                 /* Description d'une couleur   */
+        PangoFontDescription *font_desc;    /* Description d'une police    */
+
+        gtk_style_context_save(ctx);
+
+        gtk_style_context_add_class(context, name);
+
+        gtk_style_context_get(ctx, GTK_STATE_NORMAL, GTK_STYLE_PROPERTY_COLOR, &tmp_color, NULL);
+
+        pattern->foreground.has_color = true;
+        pattern->foreground.color = *tmp_color;
+
+        pattern->inverted.has_color = true;
+        pattern->inverted.color.red = 1.0 - tmp_color->red;
+        pattern->inverted.color.green = 1.0 - tmp_color->green;
+        pattern->inverted.color.blue = 1.0 - tmp_color->blue;
+        pattern->inverted.color.alpha = tmp_color->alpha;
+
+        gdk_rgba_free(tmp_color);
+
+        gtk_style_context_get(context, GTK_STATE_FLAG_NORMAL, GTK_STYLE_PROPERTY_FONT, &font_desc, NULL);
+
+        switch (pango_font_description_get_style(font_desc))
+        {
+            case PANGO_STYLE_NORMAL:
+                pattern->slant = CAIRO_FONT_SLANT_NORMAL;
+                break;
+            case PANGO_STYLE_ITALIC:
+                pattern->slant = CAIRO_FONT_SLANT_ITALIC;
+                break;
+            case PANGO_STYLE_OBLIQUE:
+                pattern->slant = CAIRO_FONT_SLANT_OBLIQUE;
+                break;
+        }
+
+        switch (pango_font_description_get_weight(font_desc))
+        {
+            case PANGO_WEIGHT_THIN:
+            case PANGO_WEIGHT_ULTRALIGHT:	
+            case PANGO_WEIGHT_LIGHT:
+            case PANGO_WEIGHT_SEMILIGHT:
+            case PANGO_WEIGHT_BOOK:
+            case PANGO_WEIGHT_NORMAL:
+            case PANGO_WEIGHT_MEDIUM:
+                pattern->weight = CAIRO_FONT_WEIGHT_NORMAL;
+                break;
+            case PANGO_WEIGHT_SEMIBOLD:
+            case PANGO_WEIGHT_BOLD:
+            case PANGO_WEIGHT_ULTRABOLD:
+            case PANGO_WEIGHT_HEAVY:
+            case PANGO_WEIGHT_ULTRAHEAVY:
+                pattern->weight = CAIRO_FONT_WEIGHT_BOLD;
+                break;
+        }
+
+        pango_font_description_free(font_desc);
+
+        gtk_style_context_restore(context);
+
+    }
+
+    for (i = 0; i < RTT_COUNT; i++)
+        define_rendering_pattern(context, _segment_names[i], &_seg_params.patterns[i]);
+
+    /* Nettoyages finaux... */
+
+    gtk_widget_path_free(path);
+    g_object_unref(context);
+
+    return true;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                         ISOLATION DE CONTENUS PARTAGEABLES                         */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Initialise la table mémorisant les contenus pour segments.   *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool init_segment_content_hash_table(void)
+{
+    _segcnt_htable = g_hash_table_new_full((GHashFunc)get_line_segment_hash,
+                                           (GEqualFunc)is_line_segment_equal,
+                                           free, NULL);
+
+    return (_segcnt_htable != NULL);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Organise la sortie de la table des contenus pour segments.   *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void exit_segment_content_hash_table(void)
+{
+    assert(g_hash_table_size(_segcnt_htable) == 0);
+
+    g_hash_table_unref(_segcnt_htable);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : content = contenu pour segment à consulter.                  *
+*                                                                             *
+*  Description : Fournit l'empreinte d'un contenu pour segments.              *
+*                                                                             *
+*  Retour      : Empreinte de lu contenu représenté.                          *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static guint get_line_segment_hash(const line_segment *content)
+{
+    return content->hash;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : content = premier contenu pour segment à analyser.           *
+*                other   = second contenu pour segment à analyser.            *
+*                                                                             *
+*  Description : Détermine si deux contenus pour segments sont identiques.    *
+*                                                                             *
+*  Retour      : Bilan de la comparaison.                                     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool is_line_segment_equal(const line_segment *content, const line_segment *other)
+{
+    bool result;                            /* Résultat à retourner        */
+
+    result = (content->pattern == other->pattern);
+
+    result &= (cmp_fnv_64a(content->hash, other->hash) == 0);
+
+    result &= (strcmp(content->text, other->text) == 0);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : content = premier contenu pour segment à analyser.           *
+*                other   = second contenu pour segment à analyser.            *
+*                                                                             *
+*  Description : Détermine si deux contenus pour segments sont identiques.    *
+*                                                                             *
+*  Retour      : Bilan de la comparaison.                                     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static line_segment *get_shared_segment_content(const line_segment *content)
+{
+    line_segment *result;                    /* Contenu partagé à renvoyer  */
+    gboolean found;                         /* Le contenu existe déjà ?    */
+    size_t allocated;                       /* Besoin complet en mémoire   */
+#ifndef NDEBUG
+    gboolean created;                       /* Validation de mise en place */
+#endif
+
+    /**
+     * On considère qu'il n'y a pas besoin de mutex ici, puisque toutes les
+     * opérations se réalisent à priori dans le seul thread principal pour l'affichage.
+     */
+
+    found = g_hash_table_lookup_extended(_segcnt_htable, content, (gpointer *)&result, NULL);
+
+    if (!found)
+    {
+        allocated = sizeof(line_segment) + strlen(content->text) + 1;
+
+        result = (line_segment *)malloc(allocated);
+
+        memcpy(result, content, allocated);
+
+        result->ref_count = 1;
+
+#ifndef NDEBUG
+        created = g_hash_table_insert(_segcnt_htable, result, result);
+        assert(created);
+#else
+        g_hash_table_insert(_segcnt_htable, result, result);
+#endif
+
+    }
+
+    else
+    {
+        assert(result->ref_count < UINT_MAX);
+
+        result->ref_count++;
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : content = contenu pour segments à délaisser.                 *
+*                                                                             *
+*  Description : Abandonne un contenu pour segments.                          *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void release_shared_segment_content(line_segment *content)
+{
+#ifndef NDEBUG
+    gboolean deleted;                       /* Validation de suppression   */
+#endif
+
+    /**
+     * On considère qu'il n'y a pas besoin de mutex ici, puisque toutes les
+     * opérations se réalisent à priori dans le seul thread principal pour l'affichage.
+     */
+
+    if (--content->ref_count == 0)
+    {
+#ifndef NDEBUG
+        deleted = g_hash_table_remove(_segcnt_htable, content);
+        assert(deleted);
+#else
+        g_hash_table_remove(_segcnt_htable, content);
+#endif
+    }
+
+}
+
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                      NATURE DE BASE POUR UN FRAGMENT DE TEXTE                      */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : type   = propriétés de la zone de texte.                     *
+*                text   = chaîne de caractères à traiter.                     *
+*                length = quantité de ces caractères.                         *
+*                                                                             *
+*  Description : Crée un nouveau fragment de texte avec des propriétés.       *
+*                                                                             *
+*  Retour      : Elément créé ou recyclé.                                     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+line_segment *get_new_line_segment(RenderingTagType type, const char *text, size_t length)
+{
+    line_segment *result;                   /* Elément à retourner         */
+    char atmp[sizeof(line_segment) + 128];  /* Allocation static facile    */
+    line_segment *content;                  /* Contenu à mettre en place ? */
+
+    if (length < (sizeof(atmp) - sizeof(line_segment)))
+        content = (line_segment *)atmp;
+    else
+        content = (line_segment *)malloc(sizeof(line_segment) + length + 1);
+
+    content->pattern = &_seg_params.patterns[type];
+
+    content->hash = fnv_64a_hash(text);
+
+    memcpy(content->text, text, length);
+    content->text[length] = '\0';
+
+    result = get_shared_segment_content(content);
+
+    if (content != (line_segment *)atmp)
+        free(content);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : segment = fragment de texte à libérer de la mémoire.         *
+*                                                                             *
+*  Description : Retire une utilisation à un fragment de texte.               *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void release_line_segment(line_segment *segment)
+{
+    release_shared_segment_content(segment);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : segment = fragment de texte à consulter.                     *
+*                                                                             *
+*  Description : Indique le type de rendu associé à un segment de ligne.      *
+*                                                                             *
+*  Retour      : Identifiant de type de rendu.                                *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+RenderingTagType get_line_segment_type(const line_segment *segment)
+{
+    RenderingTagType result;                /* Résultat à renvoyer         */
+
+    result = (RenderingTagType)(segment->pattern - _seg_params.patterns);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : segment = fragment de texte à consulter.                     *
+*                markup  = indique si le texte doit être décoré ou non.       *
+*                                                                             *
+*  Description : Fournit le texte brut conservé dans le segment.              *
+*                                                                             *
+*  Retour      : Texte conservé en interne.                                   *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+char *get_line_segment_text(const line_segment *segment, bool markup)
+{
+    char *result;                           /* Description à renvoyer      */
+    char color[7];                          /* Couleur hexadécimale        */
+    char *valid;
+
+    /* Résolution du cas simple */
+    if (!markup)
+        return strdup(segment->text);
+
+    result = strdup("<span ");
+
+    /* Couleur */
+
+    result = stradd(result, "foreground=\"#");
+
+    snprintf(color, sizeof(color), "%02hhx%02hhx%02hhx",
+             (unsigned char)(segment->pattern->foreground.color.red * 255),
+             (unsigned char)(segment->pattern->foreground.color.green * 255),
+             (unsigned char)(segment->pattern->foreground.color.blue * 255));
+
+    result = stradd(result, color);
+
+    result = stradd(result, "\"");
+
+    /* Style */
+
+    result = stradd(result, "style=\"");
+
+    switch (segment->pattern->slant)
+    {
+        case CAIRO_FONT_SLANT_NORMAL:
+            result = stradd(result, "normal");
+            break;
+
+        case CAIRO_FONT_SLANT_ITALIC:
+            result = stradd(result, "italic");
+            break;
+
+        case CAIRO_FONT_SLANT_OBLIQUE:
+            result = stradd(result, "oblique");
+            break;
+
+    }
+
+    result = stradd(result, "\"");
+
+    /* Epaisseur */
+
+    result = stradd(result, "weight=\"");
+
+    switch (segment->pattern->weight)
+    {
+        case CAIRO_FONT_WEIGHT_NORMAL:
+            result = stradd(result, "normal");
+            break;
+
+        case CAIRO_FONT_WEIGHT_BOLD:
+            result = stradd(result, "bold");
+            break;
+
+    }
+
+    result = stradd(result, "\"");
+
+    /* Conclusion */
+
+    result = stradd(result, ">");
+
+    valid = strdup(segment->text);
+    valid = strrpl(valid, "<", "&lt;");
+    valid = strrpl(valid, "&", "&amp;");
+
+    result = stradd(result, valid);
+
+    free(valid);
+
+    result = stradd(result, "</span>");
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : segment = fragment de texte à consulter.                     *
+*                                                                             *
+*  Description : Fournit la quantité de pixels requise pour l'impression.     *
+*                                                                             *
+*  Retour      : Largeur requise par la colonne, en pixel.                    *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+gint get_line_segment_width(const line_segment *segment)
+{
+    gint result;                            /* Largeur à retourner         */
+    cairo_font_slant_t slant;               /* Style d'impression          */
+    cairo_font_weight_t weight;             /* Poids de la police          */
+
+    slant = segment->pattern->slant;
+    weight = segment->pattern->weight;
+
+    result = _seg_params.x_advances[CAIRO_FONT_INDEX(slant, weight)] * strlen(segment->text);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : segment = fragment de texte à consulter.                     *
+*                x       = position horizontale au niveau du segment.         *
+*                                                                             *
+*  Description : Fournit la position idéale pour un marqueur.                 *
+*                                                                             *
+*  Retour      : Position dans le segment donné.                              *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+gint get_caret_position_from_line_segment(const line_segment *segment, gint x)
+{
+    gint result;                            /* Position à retourner        */
+    gint width;                             /* Largeur du segment          */
+    gint char_width;                        /* Largeur de police fixe      */
+
+    width = get_line_segment_width(segment);
+
+    if (x <= 0)
+        result = 0;
+
+    else if (x >= width)
+        result = width;
+
+    else
+    {
+        char_width = width / strlen(segment->text);
+
+        result = (x / char_width) * char_width;
+        if ((x % char_width) > (char_width / 2))
+            result += char_width;
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : segment = fragment de texte à manipuler.                     *
+*                x       = position du curseur à faire évoluer. [OUT]         *
+*                ctrl    = indique la demande d'un parcours rapide.           *
+*                dir     = direction du parcours.                             *
+*                                                                             *
+*  Description : Déplace le curseur au sein d'un segment de tampon.           *
+*                                                                             *
+*  Retour      : true si un déplacement a été effectué, false sinon.          *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool move_caret_on_line_segment(const line_segment *segment, gint *x, bool ctrl, GdkScrollDirection dir)
+{
+    bool result;                            /* Bilan d'opération à renvoyer*/
+    gint width;                             /* Largeur du segment          */
+    gint char_width;                        /* Largeur de police fixe      */
+
+    result = false;
+
+    width = get_line_segment_width(segment);
+    char_width = width / strlen(segment->text);
+
+    if (dir == GDK_SCROLL_LEFT)
+    {
+        if (*x > width) *x = width + char_width;
+
+        if (*x == 0) goto gbsmc_done;
+
+        if (ctrl) *x = 0;
+        else *x = MAX(0, *x - char_width);
+
+        result = true;
+
+    }
+
+    else if (dir == GDK_SCROLL_RIGHT)
+    {
+        if (*x == width) goto gbsmc_done;
+
+        if (ctrl) *x = width;
+        else *x = MIN(width, *x + char_width);
+
+        result = true;
+
+    }
+
+ gbsmc_done:
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : segment = fragment de texte à manipuler.                     *
+*                cr      = contexte graphique à utiliser pour les pinceaux.   *
+*                x       = abscisse du point d'impression (à maj). [OUT]      *
+*                y       = ordonnée du point d'impression.                    *
+*                list    = liste de contenus à mettre en évidence.            *
+*                                                                             *
+*  Description : Imprime le fragment de texte représenté.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void draw_line_segment(const line_segment *segment, cairo_t *cr, gint *x, gint y, const segcnt_list *list)
+{
+    bool selected;                          /* Marquer une sélection ?     */
+    gint width;                             /* Largeur du segment          */
+    cairo_operator_t old;                   /* Sauvegarde avant changement */
+    const rendering_color_t *used_fg;       /* Couleur d'impression utile  */
+
+    selected = selection_list_has_segment_content(list, segment);
+
+    width = get_line_segment_width(segment);
+
+    /* Fond du texte */
+    if (selected)
+    {
+        cairo_set_source_rgba(cr,
+                              _seg_params.selection_bg.color.red,
+                              _seg_params.selection_bg.color.green,
+                              _seg_params.selection_bg.color.blue,
+                              _seg_params.selection_bg.color.alpha);
+
+        cairo_rectangle(cr, *x, y, width, 17);
+
+        old = cairo_get_operator(cr);
+        cairo_set_operator(cr, CAIRO_OPERATOR_DIFFERENCE);
+        cairo_fill(cr);
+        cairo_set_operator(cr, old);
+
+    }
+
+    /* Couleur d'impression */
+
+    if (selected)
+        used_fg = &segment->pattern->inverted;
+    else
+        used_fg = &segment->pattern->foreground;
+
+    if (used_fg->has_color)
+        cairo_set_source_rgba(cr,
+                              used_fg->color.red,
+                              used_fg->color.green,
+                              used_fg->color.blue,
+                              used_fg->color.alpha);
+    else
+        cairo_set_source_rgb(cr, 0, 0, 0);
+
+    /* Impression du texte */
+
+    cairo_select_font_face(cr, "mono", segment->pattern->slant, segment->pattern->weight);
+    cairo_set_font_size(cr, 13);
+
+    cairo_move_to(cr, *x, y + 17 - 3);  /* 3 = font extents.descent */
+
+    cairo_show_text(cr, segment->text);
+
+    *x += width;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : ctx  = éléments à disposition pour l'exportation.            *
+*                type = type d'exportation attendue.                          *
+*                                                                             *
+*  Description : Exporte tous les styles utilisés par des segments.           *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void export_line_segment_style(buffer_export_context *ctx, BufferExportType type)
+{
+    size_t i;                               /* Boucle de parcours          */
+    const rendering_pattern_t *pattern;     /* Modèle à transcrire         */
+
+    for (i = 0; i < RTT_COUNT; i++)
+    {
+        pattern = &_seg_params.patterns[i];
+
+        switch (type)
+        {
+            case BET_HTML:
+
+                dprintf(ctx->fd, ".%s {\n", _segment_names[i]);
+
+                if (pattern->foreground.has_color)
+                    dprintf(ctx->fd, "\tcolor: #%02hhx%02hhx%02hhx;\n",
+                            (unsigned char)(pattern->foreground.color.red * 255),
+                            (unsigned char)(pattern->foreground.color.green * 255),
+                            (unsigned char)(pattern->foreground.color.blue * 255));
+
+                switch (pattern->slant)
+                {
+                    case CAIRO_FONT_SLANT_ITALIC:
+                        dprintf(ctx->fd, "\tfont-style: italic;\n");
+                        break;
+                    case CAIRO_FONT_SLANT_OBLIQUE:
+                        dprintf(ctx->fd, "\tfont-style: oblique;\n");
+                        break;
+                    default:
+                        dprintf(ctx->fd, "\tfont-style: normal;\n");
+                        break;
+                }
+
+                switch (pattern->weight)
+                {
+                    case CAIRO_FONT_WEIGHT_BOLD:
+                        dprintf(ctx->fd, "\tfont-weight: bold;\n");
+                        break;
+                    default:
+                        dprintf(ctx->fd, "\tfont-weight: normal;\n");
+                        break;
+                }
+
+                dprintf(ctx->fd, "}\n");
+
+                break;
+
+            default:
+                break;
+
+        }
+
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : segment = fragment de texte à manipuler.                     *
+*                ctx     = éléments à disposition pour l'exportation.         *
+*                type    = type d'exportation attendue.                       *
+*                                                                             *
+*  Description : Exporte le fragment de texte représenté.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void export_line_segment(const line_segment *segment, buffer_export_context *ctx, BufferExportType type)
+{
+    size_t index;                           /* Indice du modèle de rendu   */
+
+    switch (type)
+    {
+        case BET_HTML:
+            index = (segment->pattern - _seg_params.patterns);
+            dprintf(ctx->fd, "<SPAN class=\"%s\">", _segment_names[index]);
+            break;
+        default:
+            break;
+    }
+
+    dprintf(ctx->fd, "%s", segment->text);
+
+    switch (type)
+    {
+        case BET_HTML:
+            dprintf(ctx->fd, "</SPAN>");
+            break;
+        default:
+            break;
+    }
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                      GESTION OPTIMALE D'UNE LISTE DE CONTENUS                      */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Initilise une liste de contenus de segments.                 *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+segcnt_list *init_segment_content_list(void)
+{
+    segcnt_list *result;                    /* Structure à retourner       */
+
+    result = (segcnt_list *)calloc(1, sizeof(segcnt_list));
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : list = ensemble de références de contenus à traiter.         *
+*                                                                             *
+*  Description : Libère la mémoire occupée par une liste de contenus.         *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void exit_segment_content_list(segcnt_list *list)
+{
+    reset_segment_content_list(list);
+
+    free(list);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : list = ensemble de références de contenus à manipuler.       *
+*                                                                             *
+*  Description : Vide, si besoin est, une liste de contenus de segments.      *
+*                                                                             *
+*  Retour      : true si des éléments ont été purgés, false sinon.            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool reset_segment_content_list(segcnt_list *list)
+{
+    bool result;                            /* Bilan d'action à renvoyer   */
+
+    result = (list->count > 0);
+
+    if (list->hashes != NULL)
+    {
+        free(list->hashes);
+        list->hashes = NULL;
+    }
+
+    list->count = 0;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : list    = ensemble de références de contenus à manipuler.    *
+*                segment = fragment de texte à conservr.                      *
+*                                                                             *
+*  Description : Marque le contenu d'un segment comme remarquable.            *
+*                                                                             *
+*  Retour      : true si la liste a été complétée, false sinon.               *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool add_segment_content_to_selection_list(segcnt_list *list, const line_segment *segment)
+{
+    bool result;                            /* Bilan à retourner           */
+    size_t i;                               /* Boucle de parcours          */
+
+    static const char white_list[] = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
+    result = false;
+
+    for (i = 0; i < (sizeof(white_list) - 1) && !result; i++)
+        result = (strchr(segment->text, white_list[i]) != NULL);
+
+    if (result)
+    {
+        list->hashes = (fnv64_t *)realloc(list->hashes, ++list->count * sizeof(fnv64_t));
+
+        list->hashes[list->count - 1] = segment->hash;
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : list    = ensemble de références de contenus à consulter.    *
+*                segment = fragment de texte à comparer.                      *
+*                                                                             *
+*  Description : Indique si le contenu d'un segment est notable ou non.       *
+*                                                                             *
+*  Retour      : true si le segment a un contenu présent dans la sélection.   *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool selection_list_has_segment_content(const segcnt_list *list, const line_segment *segment)
+{
+    bool result;                            /* Bilan à retourner           */
+    size_t i;                               /* Boucle de parcours          */
+
+    result = false;
+
+    for (i = 0; i < list->count && !result; i++)
+        result = (cmp_fnv_64a(list->hashes[i], segment->hash) == 0);
+
+    return result;
+
+}
diff --git a/src/glibext/linesegment.h b/src/glibext/linesegment.h
new file mode 100644
index 0000000..7a5551d
--- /dev/null
+++ b/src/glibext/linesegment.h
@@ -0,0 +1,196 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * linesegment.h - prototypes pour la concentration d'un fragment de caractères aux propriétés communes
+ *
+ * Copyright (C) 2010-2014 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  OpenIDA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  OpenIDA is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GLIBEXT_LINESEGMENT_H
+#define _GLIBEXT_LINESEGMENT_H
+
+
+#include <glib-object.h>
+#include <stdbool.h>
+#include <gdk/gdk.h>
+#include <pango/pango.h>
+
+
+
+/* Liste identifiant un ensemble de segments */
+typedef struct _segcnt_list segcnt_list;
+
+
+
+/* ------------------------ NATURE POUR UN FRAGMENT DE TEXTE ------------------------ */
+
+
+/* Procède à l'initialisation des paramètres de rendu de texte. */
+bool load_segment_rendering_parameters(void);
+
+
+
+/* ----------------------- ISOLATION DE CONTENUS PARTAGEABLES ----------------------- */
+
+
+/* Fragment de caractères aux propriétés potentiellement partagées */
+typedef struct _line_segment line_segment;
+
+
+/* Initialise la table mémorisant les contenus pour segments. */
+bool init_segment_content_hash_table(void);
+
+/* Organise la sortie de la table des contenus pour segments. */
+void exit_segment_content_hash_table(void);
+
+
+
+/* -------------------- NATURE DE BASE POUR UN FRAGMENT DE TEXTE -------------------- */
+
+
+/* Types de partie de rendu */
+typedef enum _RenderingTagType
+{
+    RTT_RAW,                                /* Contenu brut                */
+
+    RTT_COMMENT,                            /* Commentaire                 */
+    RTT_INDICATION,                         /* Aide à la lecture           */
+
+    RTT_PHYS_ADDR_PAD,                      /* Position physique (début)   */
+    RTT_PHYS_ADDR,                          /* Position physique           */
+    RTT_VIRT_ADDR_PAD,                      /* Adresse virtuelle (début)   */
+    RTT_VIRT_ADDR,                          /* Adresse virtuelle           */
+    RTT_RAW_CODE,                           /* Code binaire brut           */
+
+    RTT_LABEL,                              /* Etiquette sur une adresse   */
+
+    RTT_INSTRUCTION,                        /* Code binaire brut           */
+
+    RTT_IMMEDIATE,                          /* Valeur immédiate            */
+
+    RTT_REGISTER,                           /* Registre                    */
+
+    RTT_PUNCT,                              /* Signes de ponctuation       */
+    RTT_HOOK,                               /* Crochets '[' et ']'         */
+    RTT_SIGNS,                              /* Signes '+', '-' et '*'      */
+    RTT_LTGT,                               /* Caractères '<' et '>'       */
+
+    RTT_SECTION,                            /* Identifiant de section      */
+    RTT_SEGMENT,                            /* Indication de segment       */
+    RTT_STRING,                             /* Chaîne de caractères avec " */
+
+    RTT_VAR_NAME,                           /* Nom de variable             */
+
+    RTT_KEY_WORD,                           /* Mot clef de langage         */
+
+    RTT_ERROR,                              /* Erreur "interne"            */
+
+    RTT_COUNT
+
+} RenderingTagType;
+
+
+/* Crée un nouveau fragment de texte avec des propriétés. */
+line_segment *get_new_line_segment(RenderingTagType, const char *, size_t);
+
+/* Retire une utilisation à un fragment de texte. */
+void release_line_segment(line_segment *);
+
+/* Indique le type de rendu associé à un segment de ligne. */
+RenderingTagType get_line_segment_type(const line_segment *);
+
+/* Fournit le texte brut conservé dans le segment. */
+char *get_line_segment_text(const line_segment *, bool);
+
+/* Fournit la quantité de pixels requise pour l'impression. */
+gint get_line_segment_width(const line_segment *);
+
+/* Fournit la position idéale pour un marqueur. */
+gint get_caret_position_from_line_segment(const line_segment *, gint);
+
+/* Déplace le curseur au sein d'un segment de tampon. */
+bool move_caret_on_line_segment(const line_segment *, gint *, bool, GdkScrollDirection);
+
+/* Imprime le fragment de texte représenté. */
+void draw_line_segment(const line_segment *, cairo_t *, gint *, gint, const segcnt_list *);
+
+/* Types d'exportation */
+typedef enum _BufferExportType
+{
+    BET_TEXT,                               /* Exportation en texte brut   */
+    BET_HTML,                               /* Exportation en HTML         */
+
+    BET_COUNT
+
+} BufferExportType;
+
+/* Elements sur lesquels une exportation peut s'appuyer */
+typedef struct _buffer_export_context
+{
+    union
+    {
+        int fd;                             /* Flux ouvert en écriture     */
+
+    };
+
+    union
+    {
+        /* BET_TEXT */
+        const char *sep;                    /* Séparation entre colonnes   */
+
+        /* BET_HTML */
+        struct
+        {
+            const char *font_name;          /* Police d'impression         */
+            const char *bg_color;           /* Fond du tableau HTML        */
+
+        };
+
+    };
+
+} buffer_export_context;
+
+/* Exporte tous les styles utilisés par des segments. */
+void export_line_segment_style(buffer_export_context *, BufferExportType);
+
+/* Exporte le fragment de texte représenté. */
+void export_line_segment(const line_segment *, buffer_export_context *, BufferExportType);
+
+
+
+/* -------------------- GESTION OPTIMALE D'UNE LISTE DE CONTENUS -------------------- */
+
+
+/* Initilise une liste de contenus de segments. */
+segcnt_list *init_segment_content_list(void);
+
+/* Libère la mémoire occupée par une liste de contenus. */
+void exit_segment_content_list(segcnt_list *);
+
+/* Vide, si besoin est, une liste de contenus de segments. */
+bool reset_segment_content_list(segcnt_list *);
+
+/* Marque le contenu d'un segment comme remarquable. */
+bool add_segment_content_to_selection_list(segcnt_list *, const line_segment *);
+
+/* Indique si le contenu d'un segment est notable ou non. */
+bool selection_list_has_segment_content(const segcnt_list *, const line_segment *);
+
+
+
+#endif  /* _GLIBEXT_LINESEGMENT_H */
diff --git a/src/gtkext/gtkbufferview.c b/src/gtkext/gtkbufferview.c
index 2d1b51c..ea5d023 100644
--- a/src/gtkext/gtkbufferview.c
+++ b/src/gtkext/gtkbufferview.c
@@ -686,8 +686,11 @@ static gboolean gtk_buffer_view_query_tooltip(GtkWidget *widget, gint x, gint y,
     if (creator != NULL)
         g_object_unref(creator);
 
+    /*
+      FIXME : ref() !
     if (line != NULL)
         g_object_unref(G_OBJECT(line));
+    */
 
     return result;
 
diff --git a/src/gui/core/core.c b/src/gui/core/core.c
index dbff1b8..c2a235f 100644
--- a/src/gui/core/core.c
+++ b/src/gui/core/core.c
@@ -28,7 +28,7 @@
 
 
 #include "../../core/params.h"
-#include "../../glibext/gbuffersegment.h"
+#include "../../glibext/linesegment.h"
 
 
 
@@ -48,7 +48,9 @@ bool load_all_gui_components(GObject *ref)
 {
     bool result;                            /* Bilan à retourner           */
 
-    result = init_segment_content_hash_table();
+    result = load_segment_rendering_parameters();
+
+    result &= init_segment_content_hash_table();
 
     if (result)
         load_main_panels(ref);
diff --git a/src/gui/dialogs/export.c b/src/gui/dialogs/export.c
index 0d7a12b..5f05031 100644
--- a/src/gui/dialogs/export.c
+++ b/src/gui/dialogs/export.c
@@ -338,7 +338,7 @@ static void do_binary_export(GCodeBuffer *buffer, const vmpa2t *start, const vmp
             dprintf(ctx->fd, "\tpadding-left: 8px;\n");
             dprintf(ctx->fd, "\tpadding-right: 8px;\n");
             dprintf(ctx->fd, "}\n");
-            g_buffer_segment_export_style(ctx, type);
+            export_line_segment_style(ctx, type);
             dprintf(ctx->fd, "</STYLE>\n");
             dprintf(ctx->fd, "<TABLE>\n");
             break;
-- 
cgit v0.11.2-87-g4458