From 52ac5b1b340335f56ceb599dba63164a26f10b10 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Sat, 16 Jan 2016 22:12:08 +0100
Subject: Changed the display of a segment containing the value of an
 immediate.

---
 ChangeLog                        |  46 +++++++++++++
 src/analysis/db/collection.c     |  46 +++++++++++--
 src/analysis/db/items/bookmark.c |  52 +++++++--------
 src/analysis/db/items/comment.c  |   4 --
 src/analysis/db/items/switcher.c | 138 ++++++++++++++++++++++++++++++++++-----
 src/analysis/db/misc/rlestr.c    |   6 +-
 src/analysis/db/misc/timestamp.c |   6 +-
 src/arch/immediate.c             |  86 ++++++++++++++++++++++--
 src/arch/immediate.h             |  15 +++++
 src/arch/vmpa.c                  |  14 +++-
 src/common/sqlite.h              |   5 +-
 src/format/symbol.h              |  13 ++--
 src/glibext/gbufferline.c        | 115 ++++++++++++++++++++++++++++++--
 src/glibext/gbufferline.h        |   3 +
 src/glibext/gbuffersegment.c     |  42 ++++++++++++
 src/glibext/gbuffersegment.h     |   3 +
 src/glibext/gcodebuffer.c        | 132 +++++++++++++++++++++++++++++++++++--
 src/gui/menus/edition.c          |  38 ++++++-----
 tools/d2c/syntax.c               |   2 +-
 19 files changed, 662 insertions(+), 104 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index c83a6b2..2f3e291 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,49 @@
+16-01-16  Cyrille Bagard <nocbos@gmail.com>
+
+	* src/analysis/db/collection.c:
+	Remove debug code. Deal with simple integer values and SQLite.
+
+	* src/analysis/db/items/bookmark.c:
+	Clean the code. Set DBF_BOOKMARKS as feature of the collection.
+
+	* src/analysis/db/items/comment.c:
+	Typo.
+
+	* src/analysis/db/items/switcher.c:
+	Change the display of a segment containing the value of an immediate.
+
+	* src/analysis/db/misc/rlestr.c:
+	* src/analysis/db/misc/timestamp.c:
+	Define the expected type of the loaded values.
+
+	* src/arch/immediate.c:
+	* src/arch/immediate.h:
+	Add (useless ?) signals. Define a default display for immediate values.
+	Fix the binary display output. Prevent an overflow when displaying in
+	binary mode.
+
+	* src/arch/vmpa.c:
+	Define the expected type of the loaded values.
+
+	* src/common/sqlite.h:
+	Rely on SQLite DB types using a new macro called SQLITE_NATIVE.
+
+	* src/format/symbol.h:
+	Update code when displaying immediate values.
+
+	* src/glibext/gbufferline.c:
+	* src/glibext/gbufferline.h:
+	* src/glibext/gbuffersegment.c:
+	* src/glibext/gbuffersegment.h:
+	* src/glibext/gcodebuffer.c:
+	Allow to update a text segment and refresh the display automatically.
+
+	* src/gui/menus/edition.c:
+	Use the DB connection as proxy when changing an immediate value display.
+
+	* tools/d2c/syntax.c:
+	Update code when displaying immediate values.
+
 16-01-12  Cyrille Bagard <nocbos@gmail.com>
 
 	* src/arch/Makefile.am:
diff --git a/src/analysis/db/collection.c b/src/analysis/db/collection.c
index 117a2d5..d5518dd 100644
--- a/src/analysis/db/collection.c
+++ b/src/analysis/db/collection.c
@@ -559,12 +559,8 @@ bool g_db_collection_has_item(GDbCollection *collec, GDbItem *item)
      * Il n'y a pas d'assert() possible pour le vérifier...
      */
 
-    printf(" --- has\n");
-
     found = g_list_find_custom(collec->items, item, (GCompareFunc)g_db_item_compare_with_timestamp);
 
-    printf(" --- has: %p\n", found);
-
     result = (found != NULL);
 
     return result;
@@ -950,6 +946,7 @@ bool g_db_collection_load_all_items(GDbCollection *collec, sqlite3 *db)
     size_t i;                               /* Boucle de parcours          */
     sqlite3_stmt *stmt;                     /* Déclaration mise en place   */
     int ret;                                /* Bilan d'un appel à SQLite   */
+    int native_type;                        /* Type de valeur dans la base */
     GDbItem *new;                           /* Nouvel élément à insérer    */
 
     if (!g_db_collection_setup_load(collec, &values, &count))
@@ -990,12 +987,39 @@ bool g_db_collection_load_all_items(GDbCollection *collec, sqlite3 *db)
 
         for (i = 0; i < count; i++)
         {
-            values[i].type = sqlite3_column_type(stmt, i);
+            native_type = sqlite3_column_type(stmt, i);
+
+            /**
+             * On réalise une petite conversion selon le champ.
+             *
+             * Le filtre SQLITE_NATIVE est destiné à conserver un champ sur 32 bits
+             * quand il s'agit du format utilisé, même si toutes les valeurs sont
+             * enregistrées en 64 bits.
+             *
+             * C'est par exemple le cas dans les bascules d'affichage.
+             *
+             * D'autres éléments, comme les localisations en mémoire, peuvent
+             * avoir un champ éventuellement nul, donc la définition à partir des
+             * indications de la base de données reste importante.
+             */
+
+            if (native_type == SQLITE_INTEGER)
+                native_type = SQLITE_INT64;
+
+            if (values[i].type == SQLITE_NATIVE)
+                values[i].type = native_type;
+
+            else
+                assert(values[i].type == native_type || values[i].type == SQLITE_INTEGER);
+
 
             switch (values[i].type)
             {
                 case SQLITE_INTEGER:
-                    values[i].type = SQLITE_INT64;
+                    values[i].integer = (int)sqlite3_column_int64(stmt, i);
+                    break;
+
+                case SQLITE_INT64:
                     values[i].integer64 = sqlite3_column_int64(stmt, i);
                     break;
 
@@ -1118,6 +1142,11 @@ static bool g_db_collection_store_item(const GDbCollection *collec, const GDbIte
     {
         switch (values[i].type)
         {
+            case SQLITE_INTEGER:
+                ret = sqlite3_bind_int(stmt, index, values[i].integer);
+                index++;
+                break;
+
             case SQLITE_INT64:
                 ret = sqlite3_bind_int64(stmt, index, values[i].integer64);
                 index++;
@@ -1272,6 +1301,11 @@ static bool g_db_collection_store_updated_item(const GDbCollection *collec, cons
 
         switch (values[i].type)
         {
+            case SQLITE_INTEGER:
+                ret = sqlite3_bind_int(stmt, index, values[i].integer);
+                index++;
+                break;
+
             case SQLITE_INT64:
                 ret = sqlite3_bind_int64(stmt, index, values[i].integer64);
                 index++;
diff --git a/src/analysis/db/items/bookmark.c b/src/analysis/db/items/bookmark.c
index ba64491..6914bc3 100644
--- a/src/analysis/db/items/bookmark.c
+++ b/src/analysis/db/items/bookmark.c
@@ -80,12 +80,12 @@ static bool g_db_bookmark_recv_from_fd(GDbBookmark *, int, int);
 /* Exporte la définition d'un signet dans un flux réseau. */
 static bool g_db_bookmark_send_to_fd(const GDbBookmark *, int, int);
 
-/* Exécute un signet sur un tampon de binaire chargé. */
-static bool g_db_bookmark_run(GDbBookmark *, GLoadedBinary *, bool *, bool);
-
 /* Construit la description humaine d'un signet sur un tampon. */
 static void g_db_bookmark_build_label(GDbBookmark *);
 
+/* Exécute un signet sur un tampon de binaire chargé. */
+static bool g_db_bookmark_run(GDbBookmark *, GLoadedBinary *, bool *, bool);
+
 /* Applique un signet sur un tampon de binaire chargé. */
 static bool g_db_bookmark_apply(GDbBookmark *, GLoadedBinary *);
 
@@ -179,7 +179,7 @@ static void g_db_bookmark_class_init(GDbBookmarkClass *klass)
     item->recv = (recv_db_item_fc)g_db_bookmark_recv_from_fd;
     item->send = (send_db_item_fc)g_db_bookmark_send_to_fd;
 
-    item->build_label = (build_item_label_fc)g_db_bookmark_build_label; 
+    item->build_label = (build_item_label_fc)g_db_bookmark_build_label;
     item->apply = (run_item_fc)g_db_bookmark_apply;
     item->cancel = (run_item_fc)g_db_bookmark_cancel;
 
@@ -373,6 +373,25 @@ static bool g_db_bookmark_send_to_fd(const GDbBookmark *bookmark, int fd, int fl
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : bookmark = signet à manipuler.                               *
+*                                                                             *
+*  Description : Construit la description humaine d'un signet sur un tampon.  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_db_bookmark_build_label(GDbBookmark *bookmark)
+{
+    asprintf(&G_DB_ITEM(bookmark)->label, _("Bookmark \"%s\""), get_rle_string(&bookmark->comment));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : bookmark = signet à manipuler.                               *
 *                binary   = binaire chargé en mémoire à modifier.             *
 *                prev     = état précédent de la présence du drapeau.         *
 *                set      = précision quant au nouvel état du drapeau.        *
@@ -422,25 +441,6 @@ static bool g_db_bookmark_run(GDbBookmark *bookmark, GLoadedBinary *binary, bool
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : bookmark = signet à manipuler.                               *
-*                                                                             *
-*  Description : Construit la description humaine d'un signet sur un tampon.  *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void g_db_bookmark_build_label(GDbBookmark *bookmark)
-{
-    asprintf(&G_DB_ITEM(bookmark)->label, _("Bookmark \"%s\""), get_rle_string(&bookmark->comment));
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : bookmark = signet à manipuler.                               *
 *                binary   = binaire chargé en mémoire à modifier.             *
 *                                                                             *
 *  Description : Applique un signet sur un tampon de binaire chargé.          *
@@ -663,14 +663,10 @@ static void g_bookmark_collection_class_init(GBookmarkCollectionClass *klass)
 
 static void g_bookmark_collection_init(GBookmarkCollection *collec)
 {
-
-
-    G_DB_COLLECTION(collec)->featuring = 0;
+    G_DB_COLLECTION(collec)->featuring = DBF_BOOKMARKS;
     G_DB_COLLECTION(collec)->type = G_TYPE_DB_BOOKMARK;
     G_DB_COLLECTION(collec)->name = "Bookmarks";
 
-
-
 }
 
 
diff --git a/src/analysis/db/items/comment.c b/src/analysis/db/items/comment.c
index 249620b..9212cae 100644
--- a/src/analysis/db/items/comment.c
+++ b/src/analysis/db/items/comment.c
@@ -526,14 +526,10 @@ static void g_comment_collection_class_init(GCommentCollectionClass *klass)
 
 static void g_comment_collection_init(GCommentCollection *collec)
 {
-
-
     G_DB_COLLECTION(collec)->featuring = 0;
     G_DB_COLLECTION(collec)->type = G_TYPE_DB_COMMENT;
     G_DB_COLLECTION(collec)->name = "Comments";
 
-
-
 }
 
 
diff --git a/src/analysis/db/items/switcher.c b/src/analysis/db/items/switcher.c
index 67187aa..7b72cf2 100644
--- a/src/analysis/db/items/switcher.c
+++ b/src/analysis/db/items/switcher.c
@@ -29,6 +29,9 @@
 #include <sys/socket.h>
 
 
+#include <i18n.h>
+
+
 #include "../collection-int.h"
 #include "../item-int.h"
 #include "../../../common/io.h"
@@ -83,6 +86,9 @@ static bool g_db_switcher_recv_from_fd(GDbSwitcher *, int, int);
 /* Exporte la définition d'un signet dans un flux réseau. */
 static bool g_db_switcher_send_to_fd(const GDbSwitcher *, int, int);
 
+/* Construit la description humaine d'un signet sur un tampon. */
+static void g_db_switcher_build_label(GDbSwitcher *);
+
 /* Exécute une bascule d'affichage d'opérande sur un binaire. */
 static bool g_db_switcher_run(GDbSwitcher *, GLoadedBinary *, ImmOperandDisplay *, ImmOperandDisplay);
 
@@ -180,6 +186,7 @@ static void g_db_switcher_class_init(GDbSwitcherClass *klass)
     item->recv = (recv_db_item_fc)g_db_switcher_recv_from_fd;
     item->send = (send_db_item_fc)g_db_switcher_send_to_fd;
 
+    item->build_label = (build_item_label_fc)g_db_switcher_build_label;
     item->apply = (run_item_fc)g_db_switcher_apply;
     item->cancel = (run_item_fc)g_db_switcher_cancel;
 
@@ -364,7 +371,6 @@ static bool g_db_switcher_recv_from_fd(GDbSwitcher *switcher, int fd, int flags)
 {
     bool status;                            /* Bilan d'opération initiale  */
     uint32_t val32;                         /* Valeur sur 32 bits          */
-    ssize_t got;                            /* Quantité de données reçues  */
 
     status = G_DB_ITEM_CLASS(g_db_switcher_parent_class)->recv(G_DB_ITEM(switcher), fd, flags);
     if (!status) return false;
@@ -372,17 +378,17 @@ static bool g_db_switcher_recv_from_fd(GDbSwitcher *switcher, int fd, int flags)
     if (!recv_vmpa(&switcher->addr, fd, flags))
         return false;
 
-    got = safe_recv(fd, &val32, sizeof(uint32_t), MSG_WAITALL);
-    if (got != sizeof(uint32_t)) return false;
+    status = safe_recv(fd, &val32, sizeof(uint32_t), MSG_WAITALL | flags);
+    if (!status) return false;
 
     switcher->index = be32toh(val32);
 
-    got = safe_recv(fd, &val32, sizeof(uint32_t), MSG_WAITALL);
-    if (got != sizeof(uint32_t)) return false;
+    status = safe_recv(fd, &val32, sizeof(uint32_t), MSG_WAITALL | flags);
+    if (!status) return false;
 
     switcher->display = be32toh(val32);
 
-    if (switcher->display >= IOD_COUNT)
+    if (switcher->display > IOD_COUNT)
         return false;
 
     return true;
@@ -428,6 +434,52 @@ static bool g_db_switcher_send_to_fd(const GDbSwitcher *switcher, int fd, int fl
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : switcher = bascule d'affichage à manipuler.                  *
+*                                                                             *
+*  Description : Construit la description humaine d'un signet sur un tampon.  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_db_switcher_build_label(GDbSwitcher *switcher)
+{
+    VMPA_BUFFER(loc);                       /* Indication de position      */
+
+    if (has_virt_addr(&switcher->addr))
+        vmpa2_virt_to_string(&switcher->addr, MDS_UNDEFINED, loc, NULL);
+    else
+        vmpa2_phys_to_string(&switcher->addr, MDS_UNDEFINED, loc, NULL);
+
+    switch (switcher->display)
+    {
+        case IOD_BIN:
+            asprintf(&G_DB_ITEM(switcher)->label, _("Switch to binary display at %s"), loc);
+            break;
+        case IOD_OCT:
+            asprintf(&G_DB_ITEM(switcher)->label, _("Switch to octal display at %s"), loc);
+            break;
+        case IOD_DEC:
+            asprintf(&G_DB_ITEM(switcher)->label, _("Switch to octal display at %s"), loc);
+            break;
+        case IOD_HEX:
+            asprintf(&G_DB_ITEM(switcher)->label, _("Switch to octal display at %s"), loc);
+            break;
+        case IOD_COUNT:
+            asprintf(&G_DB_ITEM(switcher)->label, _("Reset to default display at %s"), loc);
+            break;
+        default:
+            assert(false);
+            break;
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : switcher = bascule d'affichage à manipuler.                  *
 *                binary   = binaire chargé en mémoire à modifier.             *
 *                old      = état précédent à conserver.                       *
 *                new      = nouvel état à appliquer.                          *
@@ -446,31 +498,78 @@ static bool g_db_switcher_run(GDbSwitcher *switcher, GLoadedBinary *binary, ImmO
     GArchProcessor *proc;                   /* Propriétaire d'instructions */
     GArchInstruction *instr;                /* Instruction à traiter       */
     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é  */
 
     result = true;
 
+    /* Traitement au niveau des instructions */
+
     proc = g_loaded_binary_get_processor(binary);
 
     instr = g_arch_processor_find_instr_by_address(proc, &switcher->addr);
     if (instr == NULL)
     {
         result = false;
-        goto exit;
+        goto exit_instr;
     }
 
     op = g_arch_instruction_get_operand(instr, switcher->index);
     if (op == NULL)
     {
         result = false;
-        goto exit;
+        goto exit_instr;
     }
 
     result = G_IS_IMM_OPERAND(op);
+    if (!result) goto exit_instr;
+
+    /* Traitement au niveau du rendu graphique */
+
+    buffer = g_loaded_binary_get_disassembled_buffer(binary);
+
+    line = g_code_buffer_find_line_by_addr(buffer, &switcher->addr, BLF_HAS_CODE, NULL);
+    if (line == NULL)
+    {
+        result = false;
+        goto exit_gui;
+    }
+
+    segment = g_buffer_line_find_segment_from_creator(line, G_OBJECT(op));
+    result = (segment != NULL);
+
+    /* Applications globales finales */
 
     if (result)
-        g_imm_operand_set_display(G_IMM_OPERAND(op), new);
+    {
+        operand = G_IMM_OPERAND(op);
+
+        *old = g_imm_operand_get_display(operand);
+
+        if (new == IOD_COUNT)
+            new = g_imm_operand_get_default_display(operand);
+
+        g_imm_operand_set_display(operand, new);
+
+        len = g_imm_operand_to_string(operand, ASX_INTEL, value);
+
+        g_buffer_segment_update_text(segment, value, len);
+
+        g_object_unref(G_OBJECT(segment));
+
+    }
 
- exit:
+    g_object_unref(G_OBJECT(line));
+
+ exit_gui:
+
+    /* TODO g_object_unref(G_OBJECT(buffer));*/
+
+ exit_instr:
 
     g_object_unref(G_OBJECT(proc));
 
@@ -562,7 +661,7 @@ static bool g_db_switcher_prepare_db_statement(const GDbSwitcher *switcher, boun
     value->integer = switcher->index;
     value->delete = NULL;
 
-    value = &(*values)[*count - 2];
+    value = &(*values)[*count - 1];
 
     value->name = "type";
     value->type = SQLITE_INTEGER;
@@ -677,14 +776,10 @@ static void g_switcher_collection_class_init(GSwitcherCollectionClass *klass)
 
 static void g_switcher_collection_init(GSwitcherCollection *collec)
 {
-
-
-    G_DB_COLLECTION(collec)->featuring = 0;
+    G_DB_COLLECTION(collec)->featuring = DBF_DISPLAY_SWITCHERS;
     G_DB_COLLECTION(collec)->type = G_TYPE_DB_SWITCHER;
     G_DB_COLLECTION(collec)->name = "Switchers";
 
-
-
 }
 
 
@@ -804,6 +899,7 @@ static bool g_switcher_collection_create_db_table(const GSwitcherCollection *col
 static bool g_switcher_collection_setup_load(GSwitcherCollection *collec, bound_value **values, size_t *count)
 {
     bool status;                            /* Bilan d'une préparation     */
+    bound_value *value;                     /* Valeur à éditer / définir   */
 
     status = G_DB_COLLECTION_CLASS(g_switcher_collection_parent_class)->setup_load(G_DB_COLLECTION(collec), \
                                                                                    values, count);
@@ -815,9 +911,15 @@ static bool g_switcher_collection_setup_load(GSwitcherCollection *collec, bound_
     *count += 2;
     *values = (bound_value *)realloc(*values, *count * sizeof(bound_value));
 
-    (*values)[*count - 2].name = "op_index";
+    value = &(*values)[*count - 2];
+
+    value->name = "op_index";
+    value->type = SQLITE_INTEGER;
+
+    value = &(*values)[*count - 1];
 
-    (*values)[*count - 1].name = "type";
+    value->name = "type";
+    value->type = SQLITE_INTEGER;
 
     return true;
 
diff --git a/src/analysis/db/misc/rlestr.c b/src/analysis/db/misc/rlestr.c
index cbf9291..3f45df6 100644
--- a/src/analysis/db/misc/rlestr.c
+++ b/src/analysis/db/misc/rlestr.c
@@ -294,9 +294,13 @@ bool prepare_db_statement_for_rle_string(const rle_string *str, const char *name
 
 bool setup_load_of_rle_string(const rle_string *str, const char *name, bound_value **values, size_t *count)
 {
+    bound_value *value;                     /* Valeur à éditer / définir   */
+
     *values = (bound_value *)realloc(*values, ++(*count) * sizeof(bound_value));
+    value = &(*values)[*count - 1];
 
-    (*values)[*count - 1].name = name;
+    value->name = name;
+    value->type = SQLITE_NATIVE;
 
     return true;
 
diff --git a/src/analysis/db/misc/timestamp.c b/src/analysis/db/misc/timestamp.c
index 624c811..d3ff474 100644
--- a/src/analysis/db/misc/timestamp.c
+++ b/src/analysis/db/misc/timestamp.c
@@ -223,9 +223,13 @@ bool prepare_db_statement_for_timestamp(const timestamp_t *timestamp, const char
 
 bool setup_load_of_timestamp(const timestamp_t *timestamp, const char *name, bound_value **values, size_t *count)
 {
+    bound_value *value;                     /* Valeur à éditer / définir   */
+
     *values = (bound_value *)realloc(*values, ++(*count) * sizeof(bound_value));
+    value = &(*values)[*count - 1];
 
-    (*values)[*count - 1].name = name;
+    value->name = name;
+    value->type = SQLITE_INT64;
 
     return true;
 
diff --git a/src/arch/immediate.c b/src/arch/immediate.c
index 4c9ea84..288b364 100644
--- a/src/arch/immediate.c
+++ b/src/arch/immediate.c
@@ -24,6 +24,7 @@
 #include "immediate.h"
 
 
+#include <assert.h>
 #include <inttypes.h>
 #include <malloc.h>
 #include <stdarg.h>
@@ -71,6 +72,7 @@ struct _GImmOperand
     } signed_imm;
 
     bool zpad;                              /* Ajoute des 0 à l'impression */
+    ImmOperandDisplay def_display;          /* Type par défaut d'affichage */
     ImmOperandDisplay display;              /* Format général d'affichage  */
 
 };
@@ -81,6 +83,11 @@ struct _GImmOperandClass
 {
     GArchOperandClass parent;               /* Classe parente              */
 
+    /* Signaux */
+
+    void (* value_changed) (GImmOperand *);
+    void (* output_changed) (GImmOperand *);
+
 };
 
 
@@ -96,9 +103,6 @@ static void g_imm_operand_dispose(GImmOperand *);
 /* Procède à la libération totale de la mémoire. */
 static void g_imm_operand_finalize(GImmOperand *);
 
-/* Construit la chaîne de caractères correspondant à l'opérande. */
-static size_t g_imm_operand_to_string(const GImmOperand *, AsmSyntax, char [VMPA_MAX_SIZE]);
-
 /* Traduit un opérande en version humainement lisible. */
 static void g_imm_operand_print(const GImmOperand *, GBufferLine *, AsmSyntax);
 
@@ -134,6 +138,22 @@ static void g_imm_operand_class_init(GImmOperandClass *klass)
 
     operand->print = (operand_print_fc)g_imm_operand_print;
 
+    g_signal_new("value-changed",
+                 G_TYPE_IMM_OPERAND,
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET(GImmOperandClass, value_changed),
+                 NULL, NULL,
+                 g_cclosure_marshal_VOID__VOID,
+                 G_TYPE_NONE, 0);
+
+    g_signal_new("output-changed",
+                 G_TYPE_IMM_OPERAND,
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET(GImmOperandClass, output_changed),
+                 NULL, NULL,
+                 g_cclosure_marshal_VOID__VOID,
+                 G_TYPE_NONE, 0);
+
 }
 
 
@@ -575,6 +595,8 @@ bool g_imm_operand_set_value(GImmOperand *operand, MemoryDataSize size, uint64_t
     operand->size = size;
     operand->raw = value;
 
+    g_signal_emit_by_name(operand, "value-changed");
+
     return true;
 
 }
@@ -597,6 +619,8 @@ void g_imm_operand_pad(GImmOperand *operand, bool state)
 {
     operand->zpad = state;
 
+    g_signal_emit_by_name(operand, "output-changed");
+
 }
 
 
@@ -621,6 +645,45 @@ bool g_imm_operand_does_padding(const GImmOperand *operand)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : operand = structure dont le contenu par défaut est à définir.*
+*                display = format global d'un affichage de valeur.            *
+*                                                                             *
+*  Description : Définit le format textuel par défaut de la valeur.           *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_imm_operand_set_default_display(GImmOperand *operand, ImmOperandDisplay display)
+{
+    operand->def_display = display;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : operand = structure dont le contenu est à consulter.         *
+*                                                                             *
+*  Description : Indique le format textuel par défaut de la valeur.           *
+*                                                                             *
+*  Retour      : Format global d'un affichage de valeur.                      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+ImmOperandDisplay g_imm_operand_get_default_display(const GImmOperand *operand)
+{
+    return operand->def_display;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : operand = structure dont le contenu est à définir.           *
 *                display = format global d'un affichage de valeur.            *
 *                                                                             *
@@ -636,6 +699,8 @@ void g_imm_operand_set_display(GImmOperand *operand, ImmOperandDisplay display)
 {
     operand->display = display;
 
+    g_signal_emit_by_name(operand, "output-changed");
+
 }
 
 
@@ -730,13 +795,14 @@ bool g_imm_operand_is_null(const GImmOperand *operand)
 *                                                                             *
 ******************************************************************************/
 
-static size_t g_imm_operand_to_string(const GImmOperand *operand, AsmSyntax syntax, char value[VMPA_MAX_SIZE])
+size_t g_imm_operand_to_string(const GImmOperand *operand, AsmSyntax syntax, char value[IMM_MAX_SIZE])
 {
     size_t result;                          /* Longueur à retourner        */
     unsigned int range;                     /* Catégorie de la taille      */
     const char *prefix;                     /* Entrée en matière           */
     const char *suffix;                     /* Sortie de matière           */
     const char *alternate;                  /* Préfixe de forme alternative*/
+    const char *intro;                      /* Introduction du formatage   */
     const char *zpad;                       /* Remplissage par des zéros   */
     const char *lmod;                       /* Modification de longueur    */
     const char *conv;                       /* Opérateur de conversion     */
@@ -783,6 +849,12 @@ static size_t g_imm_operand_to_string(const GImmOperand *operand, AsmSyntax synt
             break;
     }
 
+    /* Va-t-on réellement avoir besoin d'un formatage ? */
+    if (operand->display != IOD_BIN)
+        intro = "%";
+    else
+        intro = "";
+
     /* Drapeau de remplissage ? */
     switch (operand->display)
     {
@@ -838,7 +910,7 @@ static size_t g_imm_operand_to_string(const GImmOperand *operand, AsmSyntax synt
 
     /* Impression finale */
 
-    snprintf(format, sizeof(format), "%s%s%%%s%s%s%s", prefix, alternate, zpad, lmod, conv, suffix);
+    snprintf(format, sizeof(format), "%s%s%s%s%s%s%s", prefix, alternate, intro, zpad, lmod, conv, suffix);
 
     switch (operand->size)
     {
@@ -888,6 +960,8 @@ static size_t g_imm_operand_to_string(const GImmOperand *operand, AsmSyntax synt
 
     }
 
+    assert(((int)result) > 0);
+
     return result;
 
 }
@@ -909,7 +983,7 @@ static size_t g_imm_operand_to_string(const GImmOperand *operand, AsmSyntax synt
 
 static void g_imm_operand_print(const GImmOperand *operand, GBufferLine *line, AsmSyntax syntax)
 {
-    char value[VMPA_MAX_SIZE];              /* Chaîne à imprimer           */
+    char value[IMM_MAX_SIZE];               /* Chaîne à imprimer           */
     size_t len;                             /* Taille de l'élément inséré  */
     GBufferSegment *segment;                /* Nouveau segment mis en place*/
 
diff --git a/src/arch/immediate.h b/src/arch/immediate.h
index 1a587ad..32d2a07 100644
--- a/src/arch/immediate.h
+++ b/src/arch/immediate.h
@@ -98,6 +98,12 @@ void g_imm_operand_pad(GImmOperand *, bool);
 /* Indique le signe d'une valeur immédiate. */
 bool g_imm_operand_does_padding(const GImmOperand *);
 
+/* Définit le format textuel par défaut de la valeur. */
+void g_imm_operand_set_default_display(GImmOperand *, ImmOperandDisplay);
+
+/* Indique le format textuel par défaut de la valeur. */
+ImmOperandDisplay g_imm_operand_get_default_display(const GImmOperand *);
+
 /* Définit la grande ligne du format textuel de la valeur. */
 void g_imm_operand_set_display(GImmOperand *, ImmOperandDisplay);
 
@@ -110,6 +116,15 @@ bool g_imm_operand_is_negative(const GImmOperand *);
 /* Indique si une valeur immédiate est nulle ou non. */
 bool g_imm_operand_is_null(const GImmOperand *);
 
+/**
+ * La taille d'impression d'un opérande n'est pas VMPA_MAX_SIZE,
+ * mais 1 + 64 caractères + octet nul final en cas d'impression en binaire.
+ */
+#define IMM_MAX_SIZE 66
+
+/* Construit la chaîne de caractères correspondant à l'opérande. */
+size_t g_imm_operand_to_string(const GImmOperand *, AsmSyntax, char [IMM_MAX_SIZE]);
+
 /* Convertit une valeur immédiate en adresse de type virt_t. */
 bool g_imm_operand_to_virt_t(const GImmOperand *, virt_t *);
 
diff --git a/src/arch/vmpa.c b/src/arch/vmpa.c
index 25b01c3..3b1bcec 100644
--- a/src/arch/vmpa.c
+++ b/src/arch/vmpa.c
@@ -566,12 +566,20 @@ vmpa2t *string_to_vmpa_virt(const char *buffer)
 
 bool setup_load_for_vmpa(const vmpa2t *addr, bound_value **values, size_t *count)
 {
-    (*count) += 2;
+    bound_value *value;                     /* Valeur à éditer / définir   */
 
+    (*count) += 2;
     *values = (bound_value *)realloc(*values, (*count) * sizeof(bound_value));
 
-    (*values)[*count - 2].name = "phys";
-    (*values)[*count - 1].name = "virt";
+    value = &(*values)[*count - 2];
+
+    value->name = "phys";
+    value->type = SQLITE_NATIVE;
+
+    value = &(*values)[*count - 1];
+
+    value->name = "virt";
+    value->type = SQLITE_NATIVE;
 
     return true;
 
diff --git a/src/common/sqlite.h b/src/common/sqlite.h
index 26dbd33..2036589 100644
--- a/src/common/sqlite.h
+++ b/src/common/sqlite.h
@@ -31,8 +31,9 @@
 
 
 /* Type pour les insertions brutes */
-#define SQLITE_RAW      0
-#define SQLITE_INT64    10
+#define SQLITE_RAW      0                   /* En dur dans une requête     */
+#define SQLITE_INT64    10                  /* Entier sur 64 bits          */
+#define SQLITE_NATIVE   11                  /* Déterminé par la base       */
 
 
 /* Description des champs et de leur valeur associée */
diff --git a/src/format/symbol.h b/src/format/symbol.h
index 6f38020..94003bb 100644
--- a/src/format/symbol.h
+++ b/src/format/symbol.h
@@ -120,12 +120,13 @@ GDbComment *g_binary_symbol_get_comment(const GBinSymbol *);
  * Confort pour l'ajout de symboles basés sur des formats.
  */
 
-#define SET_IMM_DISPLAY(_ins, _op, _idx, _dsp)                  \
-    do                                                          \
-    {                                                           \
-        _op = g_arch_instruction_get_operand(_ins, _idx);       \
-        g_imm_operand_set_display(G_IMM_OPERAND(_op), _dsp);    \
-    }                                                           \
+#define SET_IMM_DISPLAY(_ins, _op, _idx, _dsp)                          \
+    do                                                                  \
+    {                                                                   \
+        _op = g_arch_instruction_get_operand(_ins, _idx);               \
+        g_imm_operand_set_default_display(G_IMM_OPERAND(_op), _dsp);    \
+        g_imm_operand_set_display(G_IMM_OPERAND(_op), _dsp);            \
+    }                                                                   \
     while (0)
 
 #define ADD_RAW_AS_SYM(_fmt, _sym, _pos, _ins, _cmt, _txt)      \
diff --git a/src/glibext/gbufferline.c b/src/glibext/gbufferline.c
index 2680dae..1a17a9c 100644
--- a/src/glibext/gbufferline.c
+++ b/src/glibext/gbufferline.c
@@ -74,6 +74,9 @@ static GBufferSegment *get_segment_at(const buffer_line_column *, gint *, GdkScr
 /* Fournit le segment voisin d'un autre segment identifié. */
 static GBufferSegment *find_near_segment(const buffer_line_column *, GBufferSegment *, GdkScrollDirection);
 
+/* Fournit le segment créé par un objet particulier. */
+static GBufferSegment *find_segment_from_creator(const buffer_line_column *, GObject *);
+
 /* 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 *);
 
@@ -121,6 +124,8 @@ struct _GBufferLineClass
 
     /* Signaux */
 
+    void (* content_changed) (GBufferLine *, GBufferSegment *);
+
     void (* flip_flag) (GBufferLine *, BufferLineFlags, BufferLineFlags);
 
 };
@@ -138,6 +143,9 @@ 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 *);
+
 
 
 /* ---------------------------------------------------------------------------------- */
@@ -145,9 +153,6 @@ static void g_buffer_line_finalize(GBufferLine *);
 /* ---------------------------------------------------------------------------------- */
 
 
-
-
-
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : column  = colonne de ligne à mettre à jour.                  *
@@ -333,13 +338,14 @@ static GBufferSegment *get_segment_at(const buffer_line_column *column, gint *x,
 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;
 
-    column_has_segment(column, target, &i);
+    found = column_has_segment(column, target, &i);
 
-    if (i < column->count)
+    if (found)
         switch (dir)
         {
             case GDK_SCROLL_LEFT:
@@ -364,6 +370,41 @@ static GBufferSegment *find_near_segment(const buffer_line_column *column, GBuff
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : column  = colonne de ligne de texte à consulter.             *
+*                creator = créateur à l'origine du segment recherché.         *
+*                                                                             *
+*  Description : Fournit le segment créé par un objet particulier.            *
+*                                                                             *
+*  Retour      : Segment trouvé ou NULL.                                      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static GBufferSegment *find_segment_from_creator(const buffer_line_column *column, GObject *creator)
+{
+    GBufferSegment *result;                 /* Trouvaille à retourner      */
+    size_t i;                               /* Boucle de parcours #1       */
+    GBufferSegment *iter;                   /* Boucle de parcours #2       */
+
+    result = NULL;
+
+    for (i = 0; i < column->count && result == NULL; i++)
+    {
+        iter = column->segments[i];
+
+        if (g_buffer_segment_get_creator(iter) == creator)
+            result = iter;
+
+    }
+
+    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.           *
@@ -491,6 +532,14 @@ static void g_buffer_line_class_init(GBufferLineClass *class)
 
     g_free(filename);
 
+    g_signal_new("content-changed",
+                 G_TYPE_BUFFER_LINE,
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET(GBufferLineClass, content_changed),
+                 NULL, NULL,
+                 g_cclosure_marshal_VOID__OBJECT,
+                 G_TYPE_NONE, 1, G_TYPE_OBJECT);
+
     g_signal_new("flip-flag",
                  G_TYPE_BUFFER_LINE,
                  G_SIGNAL_RUN_LAST,
@@ -1097,6 +1146,57 @@ GBufferSegment *g_buffer_line_find_near_segment(const GBufferLine *line, GBuffer
 
 /******************************************************************************
 *                                                                             *
+*  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      */
+    BufferLineColumn i;                     /* Boucle de parcours          */
+
+    result = NULL;
+
+    for (i = 0; i < BLC_COUNT && result == NULL; i++)
+        result = find_segment_from_creator(&line->columns[i], creator);
+
+    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)
+{
+    g_signal_emit_by_name(line, "content-changed");
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : line   = ligne à venir compléter.                            *
 *                column = colonne de la ligne visée par l'insertion.          *
 *                text   = texte à insérer dans l'existant.                    *
@@ -1115,8 +1215,7 @@ GBufferSegment *g_buffer_line_insert_text(GBufferLine *line, BufferLineColumn co
 {
     GBufferSegment *result;                 /* Portion de texte à renvoyer */
 
-    if (length == 0)
-        return;
+    assert(length > 0);
 
     if (column == BLC_MAIN)
         column = line->main_column;
@@ -1129,6 +1228,8 @@ GBufferSegment *g_buffer_line_insert_text(GBufferLine *line, BufferLineColumn co
     result = g_buffer_segment_new(type, text, length);
     g_buffer_line_add_segment(line, column, result);
 
+    g_signal_connect(result, "content-changed", G_CALLBACK(on_line_segment_changed), line);
+
     return result;
 
 }
diff --git a/src/glibext/gbufferline.h b/src/glibext/gbufferline.h
index 7ba5467..13ba87b 100644
--- a/src/glibext/gbufferline.h
+++ b/src/glibext/gbufferline.h
@@ -122,6 +122,9 @@ GBufferSegment *g_buffer_line_get_segment_at(const GBufferLine *, const gint [BL
 /* Fournit le segment voisin d'un autre segment identifié. */
 GBufferSegment *g_buffer_line_find_near_segment(const GBufferLine *, GBufferSegment *, const gint [BLC_COUNT], const bool *, GdkScrollDirection, gint *);
 
+/* 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);
 
diff --git a/src/glibext/gbuffersegment.c b/src/glibext/gbuffersegment.c
index 8e7613f..af77c38 100644
--- a/src/glibext/gbuffersegment.c
+++ b/src/glibext/gbuffersegment.c
@@ -125,6 +125,10 @@ struct _GBufferSegmentClass
     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 *);
+
 };
 
 
@@ -296,6 +300,16 @@ static void g_buffer_segment_class_init(GBufferSegmentClass *class)
     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);
+
 }
 
 
@@ -478,6 +492,34 @@ GObject *g_buffer_segment_get_creator(const GBufferSegment *segment)
 
 /******************************************************************************
 *                                                                             *
+*  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)
+{
+    free(segment->text);
+
+    segment->text = strndup(text, length);
+    segment->hash = fnv_64a_hash(segment->text);
+
+    g_buffer_segment_prepare(segment, 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.     *
 *                                                                             *
diff --git a/src/glibext/gbuffersegment.h b/src/glibext/gbuffersegment.h
index 67091fb..57e3575 100644
--- a/src/glibext/gbuffersegment.h
+++ b/src/glibext/gbuffersegment.h
@@ -109,6 +109,9 @@ void g_buffer_segment_set_creator(GBufferSegment *, GObject *);
 /* Renvoie vers un éventuel objet lié en tant que créateur. */
 GObject *g_buffer_segment_get_creator(const GBufferSegment *);
 
+/* 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 *);
 
diff --git a/src/glibext/gcodebuffer.c b/src/glibext/gcodebuffer.c
index b211c4a..1654a72 100644
--- a/src/glibext/gcodebuffer.c
+++ b/src/glibext/gcodebuffer.c
@@ -111,6 +111,10 @@ struct _GCodeBufferClass
 {
     GObjectClass parent;                    /* A laisser en premier        */
 
+    /* Signaux */
+
+    void (* line_changed) (GCodeBuffer *, GBufferLine *, GBufferSegment *);
+
 };
 
 
@@ -136,6 +140,15 @@ static size_t g_code_buffer_get_index_from_address(GCodeBuffer *, const vmpa2t *
 /* Actualise les largeurs maximales par groupes de lignes. */
 static void g_code_buffer_update_line_max_widths(const GCodeBuffer *, size_t, size_t);
 
+/* Réagit à un changement de contenu d'une ligne donnée. */
+static void on_line_content_change(GBufferLine *, GBufferSegment *, GCodeBuffer *);
+
+/* Réagit à un changement de propriété rattachée à une ligne. */
+static void on_line_flag_flip(GBufferLine *, BufferLineFlags, BufferLineFlags, GCodeBuffer *);
+
+/* Ajoute une nouvelle ligne à une position donnée. */
+static GBufferLine *g_code_buffer_create_new_line(GCodeBuffer *, size_t, const mrange_t *);
+
 
 
 /* ---------------------- VUE PARTICULIERE D'UN TAMPON DE CODE ---------------------- */
@@ -191,6 +204,9 @@ static void g_buffer_view_dispose(GBufferView *);
 /* Procède à la libération totale de la mémoire. */
 static void g_buffer_view_finalize(GBufferView *);
 
+/* Réagit à un changement de contenu d'une ligne donnée. */
+static void on_buffer_line_changed(GCodeBuffer *, GBufferLine *, GBufferSegment *, GBufferView *);
+
 /* Réinitialise le cache de la hauteur des lignes. */
 static void g_buffer_view_reset_required_height(GBufferView *);
 
@@ -366,6 +382,13 @@ G_DEFINE_TYPE(GCodeBuffer, g_code_buffer, G_TYPE_OBJECT);
 
 static void g_code_buffer_class_init(GCodeBufferClass *class)
 {
+    g_signal_new("line-changed",
+                 G_TYPE_CODE_BUFFER,
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET(GCodeBufferClass, line_changed),
+                 NULL, NULL,
+                 g_cclosure_user_marshal_VOID__OBJECT_OBJECT,
+                 G_TYPE_NONE, 2, G_TYPE_OBJECT, G_TYPE_OBJECT);
 
 }
 
@@ -691,10 +714,53 @@ static void g_code_buffer_update_line_max_widths(const GCodeBuffer *buffer, size
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : buffer = composant GTK à mettre à jour.                      *
+*  Paramètres  : line    = ligne dont la définition vient d'évoluer.          *
+*                segment = éventuel segment qui vient d'évoluer ou NULL.      *
+*                buffer  = tampon de lignes cohérentes à manipuler.           *
+*                                                                             *
+*  Description : Réagit à un changement de contenu d'une ligne donnée.        *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void on_line_content_change(GBufferLine *line, GBufferSegment *segment, GCodeBuffer *buffer)
+{
+    g_signal_emit_by_name(buffer, "line-changed", line, segment);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : line   = ligne dont la définition vient d'évoluer.           *
+*                old    = ancien groupe de propriétés associées.              *
+*                old    = nouveau groupe de propriétés associées.             *
+*                buffer = tampon de lignes cohérentes à manipuler.            *
+*                                                                             *
+*  Description : Réagit à un changement de propriété rattachée à une ligne.   *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void on_line_flag_flip(GBufferLine *line, BufferLineFlags old, BufferLineFlags new, GCodeBuffer *buffer)
+{
+    g_signal_emit_by_name(buffer, "line-changed", line, NULL);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : buffer = composant GLib à mettre à jour.                     *
 *                range  = emplacement où va se situer la ligne.               *
 *                                                                             *
-*  Description : Ajoute une nouvelle ligne à un tampon pour code désassemblé. *
+*  Description : Ajoute une nouvelle ligne à une position donnée.             *
 *                                                                             *
 *  Retour      : Nouvelle ligne vierge à écrire.                              *
 *                                                                             *
@@ -702,7 +768,7 @@ static void g_code_buffer_update_line_max_widths(const GCodeBuffer *buffer, size
 *                                                                             *
 ******************************************************************************/
 
-GBufferLine *g_code_buffer_append_new_line(GCodeBuffer *buffer, const mrange_t *range)
+static GBufferLine *g_code_buffer_create_new_line(GCodeBuffer *buffer, size_t index, const mrange_t *range)
 {
     GBufferLine *result;                    /* Instance à retourner        */
     size_t i;                               /* Boucle de parcours          */
@@ -714,12 +780,42 @@ GBufferLine *g_code_buffer_append_new_line(GCodeBuffer *buffer, const mrange_t *
                                                 buffer->count * sizeof(GBufferLine *));
     }
 
+    buffer->used++;
+    assert(index < buffer->used);
+
     result = g_buffer_line_new(range, buffer->main_column);
-    buffer->lines[buffer->used++] = result;
+    buffer->lines[index] = result;
 
     for (i = 0; i < buffer->indent; i++)
         g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, "    ", 4, RTT_RAW);
 
+    g_signal_connect(result, "content-changed", G_CALLBACK(on_line_content_change), buffer);
+    g_signal_connect(result, "flip-flag", G_CALLBACK(on_line_flag_flip), buffer);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : buffer = composant GLib à mettre à jour.                     *
+*                range  = emplacement où va se situer la ligne.               *
+*                                                                             *
+*  Description : Ajoute une nouvelle ligne à un tampon pour code désassemblé. *
+*                                                                             *
+*  Retour      : Nouvelle ligne vierge à écrire.                              *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GBufferLine *g_code_buffer_append_new_line(GCodeBuffer *buffer, const mrange_t *range)
+{
+    GBufferLine *result;                    /* Instance à retourner        */
+
+    result = g_code_buffer_create_new_line(buffer, buffer->used, range);
+
     return result;
 
 }
@@ -1031,6 +1127,8 @@ static void g_buffer_view_init(GBufferView *buffer)
 
 static void g_buffer_view_dispose(GBufferView *view)
 {
+    g_object_unref(G_OBJECT(view->buffer));
+
     G_OBJECT_CLASS(g_buffer_view_parent_class)->dispose(G_OBJECT(view));
 
 }
@@ -1083,6 +1181,8 @@ GBufferView *g_buffer_view_new(GCodeBuffer *buffer, segcnt_list *highlighted)
 
     g_buffer_view_restrict(result, NULL, NULL);
 
+    g_signal_connect(buffer, "line-changed", G_CALLBACK(on_buffer_line_changed), result);
+
     if (highlighted != NULL)
         result->highlighted = highlighted;
     else
@@ -1097,6 +1197,30 @@ GBufferView *g_buffer_view_new(GCodeBuffer *buffer, segcnt_list *highlighted)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : buffer  = tampon de lignes cohérentes à manipuler.           *
+*                line    = ligne dont la définition vient d'évoluer.          *
+*                segment = éventuel segment qui vient d'évoluer ou NULL.      *
+*                view    = vue active du tampon de lignes concerné.           *
+*                                                                             *
+*  Description : Réagit à un changement de contenu d'une ligne donnée.        *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void on_buffer_line_changed(GCodeBuffer *buffer, GBufferLine *line, GBufferSegment *segment, GBufferView *view)
+{
+    /* TODO : regarder si la vue et concernée et cibler d'avantage l'actualisation */
+
+    g_signal_emit_by_name(view, "need-redraw");
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : view  = visualisateur à mettre à jour.                       *
 *                first = première ligne à imprimer.                           *
 *                last  = première ligne hors cadre.                           *
diff --git a/src/gui/menus/edition.c b/src/gui/menus/edition.c
index 9e4077d..c524891 100644
--- a/src/gui/menus/edition.c
+++ b/src/gui/menus/edition.c
@@ -219,41 +219,45 @@ static void mcb_edition_goto(GtkMenuItem *menuitem, GMenuBar *bar)
 static void mcb_edition_switch_numeric_operand(GtkMenuItem *menuitem, GMenuBar *bar)
 {
     ImmOperandDisplay display;              /* Type de basculement         */
+    GEditorItem *editem;                    /* Autre version de la barre   */
     GtkViewPanel *vpanel;                   /* Afficheur effectif de code  */
     GBufferLine *line;                      /* Ligne de position courante  */
     GBufferSegment *segment;                /* Segment actif s'il existe   */
     GObject *creator;                       /* Créateur à l'orgine du seg. */
-    virt_t virt;                            /* Adresse virtuelle           */
-    vmpa2t addr;                            /* Adresse de destination      */
+    GDbSwitcher *switcher;                  /* Bascule à mettre en place   */
+    const mrange_t *range;                  /* Emplacement de la ligne     */
+    GLoadedBinary *binary;                  /* Binaire en cours d'étude    */
+    GArchProcessor *proc;                   /* Propriétaire d'instructions */
+    GArchInstruction *instr;                /* Instruction liée à la ligne */
 
     display = GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(menuitem), "kind_of_switch"));
 
-    vpanel = g_editor_item_get_current_view(G_EDITOR_ITEM(bar));
+    editem = G_EDITOR_ITEM(bar);
+
+    vpanel = g_editor_item_get_current_view(editem);
 
     if (gtk_view_panel_get_position(vpanel, &line, &segment))
     {
-        if (segment != NULL)
-            creator = g_buffer_segment_get_creator(segment);
-        else
-            creator = NULL;
-
-        if (creator != NULL)
-        {
-            assert(G_IS_TARGET_OPERAND(creator));
-
-
-
+        creator = g_buffer_segment_get_creator(segment);
+        assert(G_IS_IMM_OPERAND(creator));
 
+        range = g_buffer_line_get_range(line);
 
+        binary = g_editor_item_get_current_binary(editem);
+        proc = g_loaded_binary_get_processor(binary);
 
+        instr = g_arch_processor_find_instr_by_address(proc, get_mrange_addr(range));
+        assert(instr != NULL);
 
+        switcher = g_db_switcher_new(instr, G_IMM_OPERAND(creator), display);
 
+        g_loaded_binary_add_to_collection(binary, DBF_DISPLAY_SWITCHERS, G_DB_ITEM(switcher));
 
-            g_object_unref(creator);
+        g_object_unref(G_OBJECT(proc));
 
-        }
+        g_object_unref(creator);
 
-        if (segment != NULL) g_object_unref(G_OBJECT(segment));
+        g_object_unref(G_OBJECT(segment));
         g_object_unref(G_OBJECT(line));
 
     }
diff --git a/tools/d2c/syntax.c b/tools/d2c/syntax.c
index 2dad772..96fffc5 100644
--- a/tools/d2c/syntax.c
+++ b/tools/d2c/syntax.c
@@ -365,7 +365,7 @@ bool define_syntax_items(const asm_syntax *syntax, int fd, const char *arch, con
                     dprintf(fd, "\n");
 
                     if (item->flags & SIF_DECIMAL)
-                        dprintf(fd, "\t\tg_imm_operand_set_display(G_IMM_OPERAND(op), IOD_DEC);\n");
+                        dprintf(fd, "\t\tg_imm_operand_set_default_display(G_IMM_OPERAND(op), IOD_DEC);\n");
 
                     dprintf(fd, "\t\tg_arch_instruction_attach_extra_operand(instr, op);\n");
 
-- 
cgit v0.11.2-87-g4458