From 0bd8f885b20c1d660507c62e35410e2e5a958066 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Fri, 24 Jul 2015 21:53:29 +0000
Subject: Applied or canceled the effect of collected items on a given binary.

git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@556 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
---
 ChangeLog                        |  29 +++++++++
 src/analysis/binary.c            |  60 +----------------
 src/analysis/db/collection-int.h |   2 +
 src/analysis/db/collection.c     |  65 ++++++++++++++++++-
 src/analysis/db/collection.h     |   6 +-
 src/analysis/db/item-int.h       |  10 +++
 src/analysis/db/item.c           |  56 ++++++++++++++++
 src/analysis/db/item.h           |  10 +++
 src/analysis/db/items/bookmark.c | 113 ++++++++++++++++++++++++++++++++
 src/analysis/db/items/switcher.c | 135 ++++++++++++++++++++++++++++++++++++---
 src/analysis/db/items/switcher.h |  23 +------
 src/arch/immediate.h             |  13 ++--
 src/gui/menus/edition.c          |  14 ++--
 13 files changed, 430 insertions(+), 106 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index b0756b3..1463aad 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,34 @@
 15-07-24  Cyrille Bagard <nocbos@gmail.com>
 
+	* src/analysis/binary.c:
+	Remove bookmarks direct handling. Attach the current binary to collections.
+
+	* src/analysis/db/collection.c:
+	* src/analysis/db/collection.h:
+	* src/analysis/db/collection-int.h:
+	Allow to link a binary with collections. Run items on this binary when
+	needed.
+
+	* src/analysis/db/item.c:
+	* src/analysis/db/item.h:
+	* src/analysis/db/item-int.h:
+	Apply or cancel the effect of collected items on a given binary.
+
+	* src/analysis/db/items/bookmark.c:
+	* src/analysis/db/items/switcher.c:
+	Update code.
+
+	* src/analysis/db/items/switcher.h:
+	Remove the useless 'ImmSwitchType' enumeration.
+
+	* src/arch/immediate.h:
+	Extend the types of display. Typo.
+
+	* src/gui/menus/edition.c:
+	Update code.
+
+15-07-24  Cyrille Bagard <nocbos@gmail.com>
+
 	* plugins/mobicore/annotations.c:
 	* plugins/mobicore/mclf.c:
 	* plugins/mobicore/mclf-int.c:
diff --git a/src/analysis/binary.c b/src/analysis/binary.c
index 06f6b13..ea18425 100644
--- a/src/analysis/binary.c
+++ b/src/analysis/binary.c
@@ -36,7 +36,6 @@
 #include "binary-int.h"
 #include "routine.h"
 #include "binaries/file.h"
-#include "db/items/bookmark.h"
 #include "decomp/decompiler.h"
 #include "disass/disassembler.h"
 #include "../common/extstr.h"
@@ -82,10 +81,6 @@ static bool g_loaded_binary_save_storage(const GLoadedBinary *, xmlDocPtr, xmlXP
 /* -------------------------- MANIPULATION DES COLLECTIONS -------------------------- */
 
 
-/* Actualise suite à un changement affectant les signets. */
-static void on_binary_bookmarks_change(GDbCollection *, DBAction, GDbBookmark *, GLoadedBinary *);
-
-
 
 
 
@@ -148,8 +143,6 @@ static void g_loaded_binary_class_init(GLoadedBinaryClass *klass)
 
 static void g_loaded_binary_init(GLoadedBinary *binary)
 {
-    GDbCollection *collec;                  /* Collection à lister ici     */
-
     binary->username = strdup("default");
 
     binary->remote_host = strdup("localhost");
@@ -161,9 +154,7 @@ static void g_loaded_binary_init(GLoadedBinary *binary)
     binary->storages[DBF_BOOKMARKS] = DBS_ALL_LOCAL;
 
     binary->collections = create_collections_list();
-
-    collec = g_loaded_binary_find_collection(binary, DBF_BOOKMARKS);
-    g_signal_connect(collec, "content-changed", G_CALLBACK(on_binary_bookmarks_change), binary);
+    attach_binary_to_collections(binary->collections, binary);
 
     binary->col_display[BVW_BLOCK][BLC_PHYSICAL] = true;
     binary->col_display[BVW_BLOCK][BLC_VIRTUAL] = true;
@@ -829,55 +820,6 @@ bool _g_loaded_binary_add_to_collection(GLoadedBinary *binary, DBFeatures featur
 
 
 
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : collec   = collection dont le contenu vient de changer.      *
-*                action   = type de modification notifiée par la collection.  *
-*                bookmark = élément en cause dans le changement survenu.      *
-*                binary   = structure contenant les informations maîtresses.  *
-*                                                                             *
-*  Description : Actualise suite à un changement affectant les signets.       *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void on_binary_bookmarks_change(GDbCollection *collec, DBAction action, GDbBookmark *bookmark, GLoadedBinary *binary)
-{
-    const vmpa2t *addr;                     /* Adressse associée au signet */
-    GBufferLine *line;                      /* Ligne de tampon à marquer   */
-
-    addr = g_db_bookmark_get_address(bookmark);
-
-    line = g_code_buffer_find_line_by_addr(binary->disass_buffer, addr, BLF_HAS_CODE, NULL);
-
-    if (line != NULL)
-    {
-        if (action == DBA_ADD_ITEM)
-            g_buffer_line_add_flag(line, BLF_BOOKMARK);
-
-        else /*if (action == DBA_REM_ITEM)*/
-            g_buffer_line_remove_flag(line, BLF_BOOKMARK);
-
-        g_object_unref(G_OBJECT(line));
-
-    }
-
-}
-
-
-
-
-
-
-
-
-
-
-
-
 
 
 
diff --git a/src/analysis/db/collection-int.h b/src/analysis/db/collection-int.h
index 93e0ef8..0b326a9 100644
--- a/src/analysis/db/collection-int.h
+++ b/src/analysis/db/collection-int.h
@@ -55,6 +55,8 @@ struct _GDbCollection
     GType type;                             /* Identifiant GLib équivalent */
     const char *name;                       /* Nom en base de données      */
 
+    GLoadedBinary *binary;                  /* Binaire rattaché éventuel   */
+
     GList *items;                           /* Eléments rassemblés         */
     GList *sorted;                          /* Eléments triés              */
     GRWLock params_access;                  /* Verrou de protection        */
diff --git a/src/analysis/db/collection.c b/src/analysis/db/collection.c
index 27f4ddb..c3b9f2c 100644
--- a/src/analysis/db/collection.c
+++ b/src/analysis/db/collection.c
@@ -124,6 +124,8 @@ static void g_db_collection_class_init(GDbCollectionClass *klass)
 
 static void g_db_collection_init(GDbCollection *collec)
 {
+    collec->binary = NULL;
+
     g_rw_lock_init(&collec->params_access);
 
 }
@@ -198,8 +200,26 @@ GDbCollection *g_db_collection_new(uint32_t id, GType type, const char *name)
 }
 
 
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : collec = collection générique d'éléments à compléter.        *
+*                binary = binaire sur lequel appliquer les éléments.          *
+*                                                                             *
+*  Description : Attache à une collection un binaire pour les éléments listés.*
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_db_collection_link_to_binary(GDbCollection *collec, GLoadedBinary *binary)
+{
+    g_object_ref(G_OBJECT(binary));
 
+    collec->binary = binary;
 
+}
 
 
 /******************************************************************************
@@ -273,9 +293,20 @@ bool g_db_collection_recv(GDbCollection *collec, int fd, sqlite3 *db)
     switch (action)
     {
         case DBA_ADD_ITEM:
+
             result = g_db_collection_add_item(collec, item);
-            if (result && db != NULL)
-                result = g_db_collection_store_item(collec, item, db);
+
+            if (result)
+            {
+                if (collec->binary != NULL)
+                    result = g_db_item_apply(item, collec->binary);
+                if (db != NULL)
+                    result &= g_db_collection_store_item(collec, item, db);
+            }
+
+            if (!result)
+                /* TODO : retirer l'élémnt */;
+
             break;
 
         case DBA_REM_ITEM:
@@ -352,6 +383,8 @@ bool g_db_collection_send_all_updates(GDbCollection *collec, int fd)
 
     result = true;
 
+    /* TODO : lock ? */
+
     for (iter = g_list_first(collec->items);
          iter != NULL && result;
          iter = g_list_next(iter))
@@ -914,6 +947,34 @@ static bool g_db_collection_store_item(const GDbCollection *collec, const GDbIte
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : list   = ensemble de collectons à parcourir.                 *
+*                binary = binaire sur lequel appliquer les éléments.          *
+*                                                                             *
+*  Description : Attache un binaire à une série de collections.               *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void attach_binary_to_collections(GList *list, GLoadedBinary *binary)
+{
+    GList *iter;                            /* Boucle de parcours          */
+
+    for (iter = g_list_first(list);
+         iter != NULL;
+         iter = g_list_next(iter))
+    {
+        g_db_collection_link_to_binary(G_DB_COLLECTION(iter->data), binary);
+
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : list = ensemble de collectons à parcourir.                   *
 *                id   = identifiant interne du type d'éléments groupés.       *
 *                                                                             *
diff --git a/src/analysis/db/collection.h b/src/analysis/db/collection.h
index f190acc..e550009 100644
--- a/src/analysis/db/collection.h
+++ b/src/analysis/db/collection.h
@@ -60,7 +60,8 @@ GType g_db_collection_get_type(void);
 /* Prépare la mise en place d'une nouvelle collection. */
 GDbCollection *g_db_collection_new(uint32_t, GType, const char *);
 
-
+/* Attache à une collection un binaire pour les éléments listés. */
+void g_db_collection_link_to_binary(GDbCollection *, GLoadedBinary *);
 
 /* Décrit le type des éléments rassemblées dans une collection. */
 uint32_t g_db_collection_get_feature(const GDbCollection *);
@@ -125,6 +126,9 @@ bool g_db_collection_load_all_items(GDbCollection *, sqlite3 *);
 /* ------------------- CREATION DE L'ABSTRACTION POUR COLLECTIONS ------------------- */
 
 
+/* Attache un binaire à une série de collections. */
+void attach_binary_to_collections(GList *, GLoadedBinary *);
+
 /* Recherche une collection correspondant à un type donné. */
 GDbCollection *find_collection_in_list(GList *, uint32_t);
 
diff --git a/src/analysis/db/item-int.h b/src/analysis/db/item-int.h
index 7b99f4a..12c69f3 100644
--- a/src/analysis/db/item-int.h
+++ b/src/analysis/db/item-int.h
@@ -32,6 +32,7 @@
 
 
 #include "misc/rlestr.h"
+#include "../binary.h"
 
 
 
@@ -41,6 +42,9 @@ typedef bool (* recv_db_item_fc) (GDbItem *, int, int);
 /* Exporte la définition d'une base d'éléments pour collection. */
 typedef bool (* send_db_item_fc) (const GDbItem *, int, int);
 
+/* Exécute un élément de collection sur un binaire. */
+typedef bool (* run_item_fc) (GDbItem *, GLoadedBinary *);
+
 /* Constitue les champs destinés à une insertion / modification. */
 typedef bool (* prepare_db_statement) (const GDbItem *, bound_value **, size_t *);
 
@@ -63,6 +67,10 @@ struct _GDbItem
 
     bool is_volatile;                       /* Pas besoin de sauvegarde ?  */
 
+#ifdef DEBUG
+    bool applied;                           /* L'élément a été appliqué    */
+#endif
+
 };
 
 /* Base d'un élément pour collection générique (classe) */
@@ -74,6 +82,8 @@ struct _GDbItemClass
 
     recv_db_item_fc recv;                   /* Réception depuis le réseau  */
     send_db_item_fc send;                   /* Emission depuis le réseau   */
+    run_item_fc apply;                      /* Application de l'élément    */
+    run_item_fc cancel;                     /* Retrait de l'élément        */
 
     prepare_db_statement prepare_stmt;      /* Préparation d'une requête   */
     load_db_item_fc load;                   /* Chargement à partir d'une BD*/
diff --git a/src/analysis/db/item.c b/src/analysis/db/item.c
index 746ca27..d2f87c3 100644
--- a/src/analysis/db/item.c
+++ b/src/analysis/db/item.c
@@ -361,6 +361,62 @@ bool g_db_item_send(const GDbItem *item, int fd, int flags)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : item   = élément de collection à manipuler.                  *
+*                binary = binaire chargé en mémoire à modifier.               *
+*                                                                             *
+*  Description : Applique un élément de collection sur un binaire.            *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_db_item_apply(GDbItem *item, GLoadedBinary *binary)
+{
+    bool result;                            /* Bilan à faire remonter      */
+
+    result = G_DB_ITEM_GET_CLASS(item)->apply(item, binary);
+
+#ifdef DEBUG
+    item->applied = true;
+#endif
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : item   = élément de collection à manipuler.                  *
+*                binary = binaire chargé en mémoire à modifier.               *
+*                                                                             *
+*  Description : Annule une bascule d'affichage d'opérande sur un binaire.    *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_db_item_cancel(GDbItem *item, GLoadedBinary *binary)
+{
+    bool result;                            /* Bilan à faire remonter      */
+
+#ifdef DEBUG
+    assert(item->applied);
+#endif
+
+    result = G_DB_ITEM_GET_CLASS(item)->cancel(item, binary);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : item        = base d'éléments à modifier.                    *
 *                is_volatile = état du besoin en sauvegarde.                  *
 *                                                                             *
diff --git a/src/analysis/db/item.h b/src/analysis/db/item.h
index c70eefa..09ac45c 100644
--- a/src/analysis/db/item.h
+++ b/src/analysis/db/item.h
@@ -33,6 +33,10 @@
 
 
 
+/* Depuis ../binary.h : description de fichier binaire (instance) */
+typedef struct _GLoadedBinary GLoadedBinary;
+
+
 #define G_TYPE_DB_ITEM               g_db_item_get_type()
 #define G_DB_ITEM(obj)               (G_TYPE_CHECK_INSTANCE_CAST((obj), g_db_item_get_type(), GDbItem))
 #define G_IS_DB_ITEM(obj)            (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_db_item_get_type()))
@@ -60,6 +64,12 @@ bool g_db_item_recv(GDbItem *, int, int);
 /* Exporte la définition d'une base d'éléments pour collection. */
 bool g_db_item_send(const GDbItem *, int, int);
 
+/* Applique un élément de collection sur un binaire. */
+bool g_db_item_apply(GDbItem *, GLoadedBinary *);
+
+/* Annule une bascule d'affichage d'opérande sur un binaire. */
+bool g_db_item_cancel(GDbItem *, GLoadedBinary *);
+
 /* Définit si l'élément contient des données à oublier ou non. */
 void g_db_item_set_volatile(GDbItem *, bool);
 
diff --git a/src/analysis/db/items/bookmark.c b/src/analysis/db/items/bookmark.c
index c9d7b7a..8512406 100644
--- a/src/analysis/db/items/bookmark.c
+++ b/src/analysis/db/items/bookmark.c
@@ -44,6 +44,8 @@ struct _GDbBookmark
     vmpa2t addr;                            /* Adresse du signet           */
     rle_string comment;                     /* Eventuel commentaire associé*/
 
+    bool prev_state;                        /* Drapeau déjà présent avant ?*/
+
 };
 
 /* Signet à l'intérieur d'une zone de texte (classe) */
@@ -75,6 +77,15 @@ 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);
+
+/* Applique un signet sur un tampon de binaire chargé. */
+static bool g_db_bookmark_apply(GDbBookmark *, GLoadedBinary *);
+
+/* Annule un signet sur un tampon de binaire chargé. */
+static bool g_db_bookmark_cancel(GDbBookmark *, GLoadedBinary *);
+
 /* Constitue les champs destinés à une insertion / modification. */
 static bool g_db_bookmark_prepare_db_statement(const GDbBookmark *, bound_value **, size_t *);
 
@@ -161,6 +172,8 @@ 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->apply = (run_item_fc)g_db_bookmark_apply;
+    item->cancel = (run_item_fc)g_db_bookmark_cancel;
 
     item->prepare_stmt = (prepare_db_statement)g_db_bookmark_prepare_db_statement;
     item->load = (load_db_item_fc)g_db_bookmark_load;
@@ -350,6 +363,106 @@ static bool g_db_bookmark_send_to_fd(const GDbBookmark *bookmark, int fd, int fl
 
 /******************************************************************************
 *                                                                             *
+*  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.        *
+*                                                                             *
+*  Description : Exécute un signet sur un tampon de binaire chargé.           *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_db_bookmark_run(GDbBookmark *bookmark, GLoadedBinary *binary, bool *prev, bool set)
+{
+    bool result;                            /* Bilan à faire remonter      */
+    GCodeBuffer *buffer;                    /* Tampon de lignes à traiter  */
+    GBufferLine *line;                      /* Ligne de tampon à marquer   */
+
+    result = true;
+
+    buffer = g_loaded_binary_get_disassembled_buffer(binary);
+
+    line = g_code_buffer_find_line_by_addr(buffer, &bookmark->addr, BLF_HAS_CODE, NULL);
+    if (line == NULL)
+    {
+        result = false;
+        goto exit;
+    }
+
+    *prev = g_buffer_line_get_flags(line) & BLF_BOOKMARK;
+
+    if (set)
+        g_buffer_line_add_flag(line, BLF_BOOKMARK);
+
+    else
+        g_buffer_line_remove_flag(line, BLF_BOOKMARK);
+
+    g_object_unref(G_OBJECT(line));
+
+ exit:
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : bookmark = signet à manipuler.                               *
+*                binary   = binaire chargé en mémoire à modifier.             *
+*                                                                             *
+*  Description : Applique un signet sur un tampon de binaire chargé.          *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_db_bookmark_apply(GDbBookmark *bookmark, GLoadedBinary *binary)
+{
+    bool result;                            /* Bilan à faire remonter      */
+
+    result = g_db_bookmark_run(bookmark, binary, &bookmark->prev_state, true);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : bookmark = signet à manipuler.                               *
+*                binary   = binaire chargé en mémoire à modifier.             *
+*                                                                             *
+*  Description : Annule un signet sur un tampon de binaire chargé.            *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_db_bookmark_cancel(GDbBookmark *bookmark, GLoadedBinary *binary)
+{
+    bool result;                            /* Bilan à faire remonter      */
+
+    if (!bookmark->prev_state)
+        result = g_db_bookmark_run(bookmark, binary, (bool []) { 0 }, false);
+    else
+        result = true;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : bookmark = base d'éléments sur laquelle s'appuyer.           *
 *                values   = couples de champs et de valeurs à lier. [OUT]     *
 *                count    = nombre de ces couples. [OUT]                      *
diff --git a/src/analysis/db/items/switcher.c b/src/analysis/db/items/switcher.c
index 5063a9c..2168e6b 100644
--- a/src/analysis/db/items/switcher.c
+++ b/src/analysis/db/items/switcher.c
@@ -24,6 +24,7 @@
 #include "switcher.h"
 
 
+#include <assert.h>
 #include <stdio.h>
 #include <sys/socket.h>
 
@@ -47,7 +48,8 @@ struct _GDbSwitcher
     vmpa2t addr;                            /* Adresse de l'instruction    */
     size_t index;                           /* Indice de l'opérande visé   */
 
-    ImmSwitchType type;                     /* Type de bascule             */
+    ImmOperandDisplay display;              /* Type de bascule             */
+    ImmOperandDisplay old;                  /* Type de bascule précédente  */
 
 };
 
@@ -81,6 +83,15 @@ 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);
 
+/* Exécute une bascule d'affichage d'opérande sur un binaire. */
+static bool g_db_switcher_run(GDbSwitcher *, GLoadedBinary *, ImmOperandDisplay *, ImmOperandDisplay);
+
+/* Applique une bascule d'affichage d'opérande sur un binaire. */
+static bool g_db_switcher_apply(GDbSwitcher *, GLoadedBinary *);
+
+/* Annule une bascule d'affichage d'opérande sur un binaire. */
+static bool g_db_switcher_cancel(GDbSwitcher *, GLoadedBinary *);
+
 /* Constitue les champs destinés à une insertion / modification. */
 static bool g_db_switcher_prepare_db_statement(const GDbSwitcher *, bound_value **, size_t *);
 
@@ -168,6 +179,8 @@ 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->apply = (run_item_fc)g_db_switcher_apply;
+    item->cancel = (run_item_fc)g_db_switcher_cancel;
 
     item->prepare_stmt = (prepare_db_statement)g_db_switcher_prepare_db_statement;
     item->load = (load_db_item_fc)g_db_switcher_load;
@@ -244,7 +257,7 @@ static void g_db_switcher_finalize(GDbSwitcher *switcher)
 *                                                                             *
 ******************************************************************************/
 
-GDbSwitcher *g_db_switcher_new(const GArchInstruction *instr, const GImmOperand *imm, ImmSwitchType type)
+GDbSwitcher *g_db_switcher_new(const GArchInstruction *instr, const GImmOperand *imm, ImmOperandDisplay display)
 {
     GDbSwitcher *result;                      /* Instance à retourner        */
     size_t count;                           /* Nombre d'opérandes à visiter*/
@@ -271,7 +284,7 @@ GDbSwitcher *g_db_switcher_new(const GArchInstruction *instr, const GImmOperand
 
     result->index = i;
 
-    result->type = type;
+    result->display = display;
 
     /* Création d'un intitulé adapté */
 
@@ -315,10 +328,10 @@ static gint g_db_switcher_cmp(GDbSwitcher *a, GDbSwitcher *b)
 
     if (result == 0)
     {
-        if (a->type < b->type)
+        if (a->display < b->display)
             result = -1;
 
-        else if (a->type > b->type)
+        else if (a->display > b->display)
             result = 1;
 
     }
@@ -365,9 +378,9 @@ static bool g_db_switcher_recv_from_fd(GDbSwitcher *switcher, int fd, int flags)
     got = safe_recv(fd, &val32, sizeof(uint32_t), MSG_WAITALL);
     if (got != sizeof(uint32_t)) return false;
 
-    switcher->type = be32toh(val32);
+    switcher->display = be32toh(val32);
 
-    if (switcher->type >= IST_COUNT)
+    if (switcher->display >= IOD_COUNT)
         return false;
 
     return true;
@@ -402,7 +415,7 @@ static bool g_db_switcher_send_to_fd(const GDbSwitcher *switcher, int fd, int fl
     status = safe_send(fd, (uint32_t []) { htobe32(switcher->index) }, sizeof(uint32_t), MSG_MORE | flags);
     if (!status) return false;
 
-    status = safe_send(fd, (uint32_t []) { htobe32(switcher->type) }, sizeof(uint32_t), flags);
+    status = safe_send(fd, (uint32_t []) { htobe32(switcher->display) }, sizeof(uint32_t), flags);
     if (!status) return false;
 
     return true;
@@ -412,6 +425,108 @@ static bool g_db_switcher_send_to_fd(const GDbSwitcher *switcher, int fd, int fl
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : switcher = bascule d'affichage à manipuler.                  *
+*                binary   = binaire chargé en mémoire à modifier.             *
+*                old      = état précédent à conserver.                       *
+*                new      = nouvel état à appliquer.                          *
+*                                                                             *
+*  Description : Exécute une bascule d'affichage d'opérande sur un binaire.   *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_db_switcher_run(GDbSwitcher *switcher, GLoadedBinary *binary, ImmOperandDisplay *old, ImmOperandDisplay new)
+{
+    bool result;                            /* Bilan à faire remonter      */
+    GArchProcessor *proc;                   /* Propriétaire d'instructions */
+    GArchInstruction *instr;                /* Instruction à traiter       */
+    GArchOperand *op;                       /* Opérande à modifier         */
+
+    result = true;
+
+    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;
+    }
+
+    op = g_arch_instruction_get_operand(instr, switcher->index);
+    if (op == NULL)
+    {
+        result = false;
+        goto exit;
+    }
+
+    result = G_IS_IMM_OPERAND(op);
+
+    if (result)
+        g_imm_operand_set_display(G_IMM_OPERAND(op), new);
+
+ exit:
+
+    g_object_unref(G_OBJECT(proc));
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : switcher = bascule d'affichage à manipuler.                  *
+*                binary   = binaire chargé en mémoire à modifier.             *
+*                                                                             *
+*  Description : Applique une bascule d'affichage d'opérande sur un binaire.  *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_db_switcher_apply(GDbSwitcher *switcher, GLoadedBinary *binary)
+{
+    bool result;                            /* Bilan à faire remonter      */
+
+    result = g_db_switcher_run(switcher, binary, &switcher->old, switcher->display);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : switcher = bascule d'affichage à manipuler.                  *
+*                binary   = binaire chargé en mémoire à modifier.             *
+*                                                                             *
+*  Description : Annule une bascule d'affichage d'opérande sur un binaire.    *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_db_switcher_cancel(GDbSwitcher *switcher, GLoadedBinary *binary)
+{
+    bool result;                            /* Bilan à faire remonter      */
+
+    result = g_db_switcher_run(switcher, binary, (ImmOperandDisplay []) { 0 }, switcher->old);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : switcher = base d'éléments sur laquelle s'appuyer.           *
 *                values   = couples de champs et de valeurs à lier. [OUT]     *
 *                count    = nombre de ces couples. [OUT]                      *
@@ -449,7 +564,7 @@ static bool g_db_switcher_prepare_db_statement(const GDbSwitcher *switcher, boun
 
     value->name = "type";
     value->type = SQLITE_INTEGER;
-    value->integer = switcher->type;
+    value->integer = switcher->display;
     value->delete = NULL;
 
     return true;
@@ -496,7 +611,7 @@ static bool g_db_switcher_load(GDbSwitcher *switcher, const bound_value *values,
         result = (value != NULL && value->type == SQLITE_INTEGER);
 
         if (result)
-            switcher->type = value->integer;
+            switcher->display = value->integer;
 
     }
 
diff --git a/src/analysis/db/items/switcher.h b/src/analysis/db/items/switcher.h
index a839b3a..a2bff7e 100644
--- a/src/analysis/db/items/switcher.h
+++ b/src/analysis/db/items/switcher.h
@@ -35,30 +35,9 @@
 
 
 
-/* Crée la table des signets dans une base de données. */
-bool create_switcher_db_table(sqlite3 *);
-
-
-
-
-
 /* --------------------- ELABORATION D'UN ELEMENT DE COLLECTION --------------------- */
 
 
-/* Basculement d'affichage de valeurs immédiates */
-typedef enum _ImmSwitchType
-{
-    IST_DEFAULT,                            /* Impression par défaut       */
-    IST_HEXDECIMAL,                         /* Impression en hexadécimal   */
-    IST_DECIMAL,                            /* Impression en décimal       */
-    IST_OCTAL,                              /* Impression en octal         */
-    IST_BINARY,                             /* Impression en binaire       */
-
-    IST_COUNT
-
-} ImmSwitchType;
-
-
 #define G_TYPE_DB_SWITCHER               g_db_switcher_get_type()
 #define G_DB_SWITCHER(obj)               (G_TYPE_CHECK_INSTANCE_CAST((obj), g_db_switcher_get_type(), GDbSwitcher))
 #define G_IS_DB_SWITCHER(obj)            (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_db_switcher_get_type()))
@@ -78,7 +57,7 @@ typedef struct _GDbSwitcherClass GDbSwitcherClass;
 GType g_db_switcher_get_type(void);
 
 /* Crée une définition d'un signet dans une zone de texte. */
-GDbSwitcher *g_db_switcher_new(const GArchInstruction *, const GImmOperand *, ImmSwitchType);
+GDbSwitcher *g_db_switcher_new(const GArchInstruction *, const GImmOperand *, ImmOperandDisplay);
 
 #if 0
 /* Fournit l'adresse associée à un signet. */
diff --git a/src/arch/immediate.h b/src/arch/immediate.h
index 6d1d62e..2393b49 100644
--- a/src/arch/immediate.h
+++ b/src/arch/immediate.h
@@ -40,10 +40,13 @@
 /* Grande ligne d'un format d'affichage */
 typedef enum _ImmOperandDisplay
 {
-    IOD_CHAR,
-    IOD_DEC,
-    IOD_HEX,
-    IOD_OCT
+    IOD_BIN,                                /* Impression en binaire       */
+    IOD_OCT,                                /* Impression en octal         */
+    IOD_DEC,                                /* Impression en décimal       */
+    IOD_HEX,                                /* Impression en hexadécimal   */
+    IOD_CHAR,                               /* Impression en base 26       */
+
+    IOD_COUNT
 
 } ImmOperandDisplay;
 
@@ -97,7 +100,7 @@ void g_imm_operand_pad(GImmOperand *, bool);
 bool g_imm_operand_does_padding(const GImmOperand *);
 
 /* Définit la grande ligne du format textuel de la valeur. */
-void g_imm_operand_set_display(GImmOperand *operand, ImmOperandDisplay display);
+void g_imm_operand_set_display(GImmOperand *, ImmOperandDisplay);
 
 /* Indique la grande ligne du format textuel de la valeur. */
 ImmOperandDisplay g_imm_operand_get_display(const GImmOperand *);
diff --git a/src/gui/menus/edition.c b/src/gui/menus/edition.c
index d49f794..bc55478 100644
--- a/src/gui/menus/edition.c
+++ b/src/gui/menus/edition.c
@@ -103,25 +103,25 @@ GtkWidget *build_menu_edition(GObject *ref, GtkAccelGroup *accgroup, GMenuBar *b
     deepmenuitem = qck_create_menu_item(NULL, NULL, _("Hexadecimal"),
                                         G_CALLBACK(mcb_edition_switch_numeric_operand), bar);
     add_accelerator_to_menu_item(deepmenuitem, "H", accgroup);
-    g_object_set_data(G_OBJECT(deepmenuitem), "kind_of_switch", GUINT_TO_POINTER(IST_HEXDECIMAL));
+    g_object_set_data(G_OBJECT(deepmenuitem), "kind_of_switch", GUINT_TO_POINTER(IOD_HEX));
     gtk_container_add(GTK_CONTAINER(deepmenubar), deepmenuitem);
 
     deepmenuitem = qck_create_menu_item(NULL, NULL, _("Decimal"),
                                         G_CALLBACK(mcb_edition_switch_numeric_operand), bar);
     add_accelerator_to_menu_item(deepmenuitem, "D", accgroup);
-    g_object_set_data(G_OBJECT(deepmenuitem), "kind_of_switch", GUINT_TO_POINTER(IST_DECIMAL));
+    g_object_set_data(G_OBJECT(deepmenuitem), "kind_of_switch", GUINT_TO_POINTER(IOD_DEC));
     gtk_container_add(GTK_CONTAINER(deepmenubar), deepmenuitem);
 
     deepmenuitem = qck_create_menu_item(NULL, NULL, _("Octal"),
                                         G_CALLBACK(mcb_edition_switch_numeric_operand), bar);
     add_accelerator_to_menu_item(deepmenuitem, "O", accgroup);
-    g_object_set_data(G_OBJECT(deepmenuitem), "kind_of_switch", GUINT_TO_POINTER(IST_OCTAL));
+    g_object_set_data(G_OBJECT(deepmenuitem), "kind_of_switch", GUINT_TO_POINTER(IOD_OCT));
     gtk_container_add(GTK_CONTAINER(deepmenubar), deepmenuitem);
 
     deepmenuitem = qck_create_menu_item(NULL, NULL, _("Binary"),
                                         G_CALLBACK(mcb_edition_switch_numeric_operand), bar);
     add_accelerator_to_menu_item(deepmenuitem, "B", accgroup);
-    g_object_set_data(G_OBJECT(deepmenuitem), "kind_of_switch", GUINT_TO_POINTER(IST_BINARY));
+    g_object_set_data(G_OBJECT(deepmenuitem), "kind_of_switch", GUINT_TO_POINTER(IOD_BIN));
     gtk_container_add(GTK_CONTAINER(deepmenubar), deepmenuitem);
 
     deepmenuitem = qck_create_menu_separator();
@@ -129,7 +129,7 @@ GtkWidget *build_menu_edition(GObject *ref, GtkAccelGroup *accgroup, GMenuBar *b
 
     deepmenuitem = qck_create_menu_item(NULL, NULL, _("Default"),
                                         G_CALLBACK(mcb_edition_switch_numeric_operand), bar);
-    g_object_set_data(G_OBJECT(deepmenuitem), "kind_of_switch", GUINT_TO_POINTER(IST_DEFAULT));
+    g_object_set_data(G_OBJECT(deepmenuitem), "kind_of_switch", GUINT_TO_POINTER(IOD_COUNT));
     gtk_container_add(GTK_CONTAINER(deepmenubar), deepmenuitem);
 
     submenuitem = qck_create_menu_separator();
@@ -218,7 +218,7 @@ static void mcb_edition_goto(GtkMenuItem *menuitem, GMenuBar *bar)
 
 static void mcb_edition_switch_numeric_operand(GtkMenuItem *menuitem, GMenuBar *bar)
 {
-    ImmSwitchType type;                     /* Type de basculement         */
+    ImmOperandDisplay display;              /* Type de basculement         */
     GtkViewPanel *vpanel;                   /* Afficheur effectif de code  */
     GBufferLine *line;                      /* Ligne de position courante  */
     GBufferSegment *segment;                /* Segment actif s'il existe   */
@@ -226,7 +226,7 @@ static void mcb_edition_switch_numeric_operand(GtkMenuItem *menuitem, GMenuBar *
     virt_t virt;                            /* Adresse virtuelle           */
     vmpa2t addr;                            /* Adresse de destination      */
 
-    type = GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(menuitem), "kind_of_switch"));
+    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));
 
-- 
cgit v0.11.2-87-g4458