From 7c40b70d6c1e1e13dadf876c8dda60b525616d47 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Wed, 16 Dec 2015 18:20:06 +0100
Subject: Built a new improved status bar for instructions information.

---
 ChangeLog                   |  25 ++
 src/analysis/disass/area.c  |   5 +-
 src/format/format.c         | 126 +++++----
 src/format/format.h         |   6 +-
 src/glibext/gbinportion.c   |   2 +-
 src/gtkext/Makefile.am      |   1 +
 src/gtkext/gtkstatusstack.c | 609 ++++++++++++++++++++++++++++++++++++++++++++
 src/gtkext/gtkstatusstack.h |  79 ++++++
 src/gui/editor.c            |   2 +-
 src/gui/status.c            | 163 +-----------
 10 files changed, 802 insertions(+), 216 deletions(-)
 create mode 100644 src/gtkext/gtkstatusstack.c
 create mode 100644 src/gtkext/gtkstatusstack.h

diff --git a/ChangeLog b/ChangeLog
index bb9f0d5..f116419 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,28 @@
+15-12-16  Cyrille Bagard <nocbos@gmail.com>
+
+	* src/analysis/disass/area.c:
+	Update code.
+
+	* src/format/format.c:
+	* src/format/format.h:
+	Remove old code for resolving symbols and improve the current one.
+
+	* src/glibext/gbinportion.c:
+	Typo.
+
+	* src/gtkext/Makefile.am:
+	Add the 'gtkstatusstack.[ch]' files from libgtkext_la_SOURCES.
+
+	* src/gtkext/gtkstatusstack.c:
+	* src/gtkext/gtkstatusstack.h:
+	New entries: build a new improved status bar for instructions information.
+
+	* src/gui/editor.c:
+	Give less space between widgets.
+
+	* src/gui/status.c:
+	Update code.
+
 15-12-15  Cyrille Bagard <nocbos@gmail.com>
 
 	* src/arch/arm/v7/instruction.c:
diff --git a/src/analysis/disass/area.c b/src/analysis/disass/area.c
index 86c41d3..d2a03c6 100644
--- a/src/analysis/disass/area.c
+++ b/src/analysis/disass/area.c
@@ -1485,7 +1485,6 @@ static bool mark_range_in_mem_area_as_processed(mem_area *area, phys_t start, ph
 static void update_address_as_routine(GBinFormat *format, const vmpa2t *addr)
 {
     GBinSymbol *symbol;                     /* Symbole présent ou créé     */
-    phys_t offset;                          /* Décallage trouvé            */
     bool found;                             /* Détection de symbole        */
     SymbolType sym_type;                    /* Type de symbole en place    */
     bool wrong_type;                        /* Analyse plus fine de ce type*/
@@ -1494,7 +1493,7 @@ static void update_address_as_routine(GBinFormat *format, const vmpa2t *addr)
     char name[5 + VMPA_MAX_LEN];            /* Nom de symbole nouveau      */
     GBinRoutine *routine;                   /* Nouvelle routine trouvée    */
 
-    found = g_binary_format_resolve_symbol(format, addr, &symbol, &offset);
+    found = g_binary_format_find_symbol_at(format, addr, &symbol);
 
     if (found)
     {
@@ -1502,7 +1501,7 @@ static void update_address_as_routine(GBinFormat *format, const vmpa2t *addr)
         wrong_type = (sym_type != STP_ROUTINE && sym_type != STP_ENTRY_POINT);
     }
 
-    if (!found || (found && offset == 0 && wrong_type))
+    if (!found || (found && wrong_type))
     {
         init_mrange(&range, addr, 0);
 
diff --git a/src/format/format.c b/src/format/format.c
index 9c42508..82d9e42 100644
--- a/src/format/format.c
+++ b/src/format/format.c
@@ -52,6 +52,9 @@ static void g_binary_format_init(GBinFormat *);
 /* Retire un symbole de la collection du format binaire. */
 static void _g_binary_format_remove_symbol(GBinFormat *, size_t);
 
+/* Recherche le symbole associé à une adresse. */
+static bool _g_binary_format_find_symbol(const GBinFormat *, const vmpa2t *, __compar_fn_t, GBinSymbol **);
+
 
 
 /* Indique le type défini pour un format binaire générique. */
@@ -623,9 +626,10 @@ bool g_binary_format_find_symbol_by_label(const GBinFormat *format, const char *
 *                                                                             *
 *  Paramètres  : format = informations chargées à consulter.                  *
 *                addr   = adresse à cibler lors des recherches.               *
+*                fn     = méthode de comparaison des symboles.                *
 *                symbol = éventuel symbole trouvé à déréfenrencer. [OUT]      *
 *                                                                             *
-*  Description : Recherche le symbole correspondant à une adresse.            *
+*  Description : Recherche le symbole associé à une adresse.                  *
 *                                                                             *
 *  Retour      : true si l'opération a été un succès, false sinon.            *
 *                                                                             *
@@ -633,7 +637,7 @@ bool g_binary_format_find_symbol_by_label(const GBinFormat *format, const char *
 *                                                                             *
 ******************************************************************************/
 
-bool g_binary_format_find_symbol_at(const GBinFormat *format, const vmpa2t *addr, GBinSymbol **symbol)
+static bool _g_binary_format_find_symbol(const GBinFormat *format, const vmpa2t *addr, __compar_fn_t fn, GBinSymbol **symbol)
 {
     bool result;                            /* Bilan à retourner           */
     void *found;                            /* Résultat de recherches      */
@@ -642,6 +646,40 @@ bool g_binary_format_find_symbol_at(const GBinFormat *format, const vmpa2t *addr
 
     *symbol = NULL; /* TODO : vérifier les doublons côtés appelants */
 
+    found = bsearch(addr, format->symbols, format->symbols_count, sizeof(GBinSymbol *), fn);
+
+    if (found != NULL)
+    {
+        *symbol = *(GBinSymbol **)found;
+
+        g_object_ref(G_OBJECT(*symbol));
+        result = true;
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = informations chargées à consulter.                  *
+*                addr   = adresse à cibler lors des recherches.               *
+*                symbol = éventuel symbole trouvé à déréfenrencer. [OUT]      *
+*                                                                             *
+*  Description : Recherche le symbole correspondant à une adresse.            *
+*                                                                             *
+*  Retour      : true si l'opération a été un succès, false sinon.            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_binary_format_find_symbol_at(const GBinFormat *format, const vmpa2t *addr, GBinSymbol **symbol)
+{
+    bool result;                            /* Bilan à retourner           */
+
     int find_symbol(const vmpa2t *addr, const GBinSymbol **sym)
     {
         const mrange_t *range;              /* Espace mémoire parcouru     */
@@ -652,19 +690,43 @@ bool g_binary_format_find_symbol_at(const GBinFormat *format, const vmpa2t *addr
 
     }
 
-    found = bsearch(addr, format->symbols,
-                    format->symbols_count, sizeof(GBinSymbol *),
-                    (__compar_fn_t)find_symbol);
+    result = _g_binary_format_find_symbol(format, addr, (__compar_fn_t)find_symbol, symbol);
 
-    if (found != NULL)
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = informations chargées à consulter.                  *
+*                addr   = adresse à cibler lors des recherches.               *
+*                symbol = éventuel symbole trouvé à déréfenrencer. [OUT]      *
+*                                                                             *
+*  Description : Recherche le symbole contenant une adresse.                  *
+*                                                                             *
+*  Retour      : true si l'opération a été un succès, false sinon.            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_binary_format_find_symbol_for(const GBinFormat *format, const vmpa2t *addr, GBinSymbol **symbol)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    int find_symbol(const vmpa2t *addr, const GBinSymbol **sym)
     {
-        *symbol = *(GBinSymbol **)found;
+        const mrange_t *range;              /* Espace mémoire parcouru     */
 
-        g_object_ref(G_OBJECT(*symbol));
-        result = true;
+        range = g_binary_symbol_get_range(*sym);
+
+        return cmp_mrange_with_vmpa(range, addr);
 
     }
 
+    result = _g_binary_format_find_symbol(format, addr, (__compar_fn_t)find_symbol, symbol);
+
     return result;
 
 }
@@ -734,7 +796,7 @@ bool g_binary_format_resolve_symbol(const GBinFormat *format, const vmpa2t *addr
      bool result;                            /* Bilan à retourner           */
      const mrange_t *range;                  /* Espace mémoire parcouru     */
 
-     result = g_binary_format_find_symbol_at(format, addr, symbol);
+     result = g_binary_format_find_symbol_for(format, addr, symbol);
 
      if (result)
      {
@@ -916,47 +978,3 @@ void g_binary_format_decompile(const GBinFormat *format, GCodeBuffer *buffer, co
     }
 
 }
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : format  = informations chargées à consulter.                 *
-*                label   = étiquette du symbole si trouvé. [OUT]              *
-*                address = adresse à cibler, puis décallage final. [OUT]      *
-*                                                                             *
-*  Description : Recherche une position dans une routine selon une adresse.   *
-*                                                                             *
-*  Retour      : true si l'opération a été un succès, false sinon.            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-bool g_binary_format_resolve_relative_routine(const GBinFormat *format, const char **label, vmpa_t *address)
-{
-    bool result;                            /* Bilan à retourner           */
-    size_t i;                               /* Boucle de parcours          */
-    vmpa_t addr;                            /* Adresse de symbole          */
-    off_t size;                             /* Taille du symole            */
-
-    result = false;
-
-    for (i = 0; i < format->routines_count && !result; i++)
-    {
-        addr = g_binary_routine_get_address(format->routines[i]);
-        size = g_binary_routine_get_size(format->routines[i]);
-
-        if (addr <= *address && *address < (addr + size))
-        {
-            *label = g_binary_routine_get_long_name(format->routines[i]);
-            *address -= addr;
-
-            result = true;
-
-        }
-
-    }
-
-    return result;
-
-}
diff --git a/src/format/format.h b/src/format/format.h
index 314306e..18dfda1 100644
--- a/src/format/format.h
+++ b/src/format/format.h
@@ -86,6 +86,9 @@ bool g_binary_format_find_symbol_by_label(const GBinFormat *, const char *, GBin
 /* Recherche le symbole correspondant à une adresse. */
 bool g_binary_format_find_symbol_at(const GBinFormat *, const vmpa2t *, GBinSymbol **);
 
+/* Recherche le symbole contenant une adresse. */
+bool g_binary_format_find_symbol_for(const GBinFormat *, const vmpa2t *, GBinSymbol **);
+
 /* Recherche le symbole suivant celui lié à une adresse. */
 bool g_binary_format_find_next_symbol_at(const GBinFormat *, const vmpa2t *, GBinSymbol **);
 
@@ -107,9 +110,6 @@ const char * const *g_binary_format_get_source_files(const GBinFormat *, size_t
 /* Procède à la décompilation complète du format. */
 void g_binary_format_decompile(const GBinFormat *, GCodeBuffer *, const char *filename);
 
-/* Recherche une position dans une routine selon une adresse. */
-bool g_binary_format_resolve_relative_routine(const GBinFormat *, const char **, vmpa_t *);
-
 
 
 #endif  /* _FORMAT_FORMAT_H */
diff --git a/src/glibext/gbinportion.c b/src/glibext/gbinportion.c
index bd4702b..920fcfe 100644
--- a/src/glibext/gbinportion.c
+++ b/src/glibext/gbinportion.c
@@ -578,7 +578,7 @@ GBinPortion *g_binary_portion_find_at_addr(GBinPortion *portion, const vmpa2t *a
 
     result = NULL;
 
-    for (i = 0; i < portion->sub_count && !result; i++)
+    for (i = 0; i < portion->sub_count && result == NULL; i++)
     {
         sub = portion->sub_portions[i];
 
diff --git a/src/gtkext/Makefile.am b/src/gtkext/Makefile.am
index 6849585..bdd0a31 100644
--- a/src/gtkext/Makefile.am
+++ b/src/gtkext/Makefile.am
@@ -13,6 +13,7 @@ libgtkext_la_SOURCES =					\
 	gtkdockstation.h gtkdockstation.c	\
 	gtkgraphview.h gtkgraphview.c		\
 	gtksourceview.h gtksourceview.c		\
+	gtkstatusstack.h gtkstatusstack.c	\
 	gtkviewpanel-int.h					\
 	gtkviewpanel.h gtkviewpanel.c		\
 	support.h support.c					\
diff --git a/src/gtkext/gtkstatusstack.c b/src/gtkext/gtkstatusstack.c
new file mode 100644
index 0000000..e9a61d8
--- /dev/null
+++ b/src/gtkext/gtkstatusstack.c
@@ -0,0 +1,609 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * gtkstatusstack.c - empilement d'informations de statut
+ *
+ * Copyright (C) 2015 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  OpenIDA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  OpenIDA is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "gtkstatusstack.h"
+
+
+#include <inttypes.h>
+#include <malloc.h>
+#include <string.h>
+
+
+#include <i18n.h>
+
+
+#include "easygtk.h"
+#include "../common/extstr.h"
+
+
+
+/* ------------------------- GESTION EXTERIEURE DE LA BARRE ------------------------- */
+
+
+/* Navigation au sein d'assemblage */
+typedef struct _assembly_info assembly_info;
+
+
+/* Abstration d'une gestion de barre de statut (instance) */
+struct _GtkStatusStack
+{
+    GtkBin parent;                          /* A laisser en premier        */
+
+    GtkWidget *asm_status;                  /* Barre de status d'assemblage*/
+    assembly_info *asm_info;                /* Informations courantes      */
+
+};
+
+/* Abstration d'une gestion de barre de statut (classe) */
+struct _GtkStatusStackClass
+{
+    GtkBinClass parent;                     /* A laisser en premier        */
+
+};
+
+
+/* Initialise la classe des barres de statut améliorées. */
+static void gtk_status_stack_class_init(GtkStatusStackClass *);
+
+/* Initialise une instance de barre de statut améliorée. */
+static void gtk_status_stack_init(GtkStatusStack *);
+
+/* Supprime toutes les références externes. */
+static void gtk_status_stack_dispose(GtkStatusStack *);
+
+/* Procède à la libération totale de la mémoire. */
+static void gtk_status_stack_finalize(GtkStatusStack *);
+
+/* S'assure de l'affichage du niveau de pile attendu. */
+static void gtk_status_stack_switch(GtkStatusStack *, GtkWidget *);
+
+
+
+/* -------------------- STATUT DES INFORMATIONS DE DESASSEMBLAGE -------------------- */
+
+
+/* Navigation au sein d'assemblage */
+struct _assembly_info
+{
+    mrange_t current;                       /* Emplacement correspondant   */
+
+    char *segment;                          /* Segment d'appartenance      */
+
+    VMPA_BUFFER(phys);                      /* Localisation physique       */
+    VMPA_BUFFER(virt);                      /* Localisation virtuelle      */
+
+    char *symbol;                           /* Eventuel symbole concerné   */
+
+    const char *encoding;                   /* Encodage de l'instruction   */
+    phys_t size;                            /* Taille de l'instruction     */
+
+};
+
+
+/* Supprime l'empreinte mémoire d'informations d'assemblage. */
+static void reset_assembly_info(assembly_info *);
+
+/* Construit une barre d'état pour language d'assemblage. */
+static GtkWidget *build_assembly_status_stack(GtkStatusStack *);
+
+/* Réagit à un redimensionnement de la barre de désassemblage. */
+static void on_size_allocate_for_asm_status(GtkWidget *, GdkRectangle *, GObject *);
+
+/* Réagit à un clic sur l'icône de zoom. */
+static void on_zoom_icon_press(GtkEntry *, GtkEntryIconPosition, GdkEventButton *, GtkStatusStack *);
+
+/* S'assure de l'affichage à jour de la partie "assemblage". */
+static void gtk_status_stack_show_current_instruction(GtkStatusStack *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                           GESTION EXTERIEURE DE LA BARRE                           */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Détermine le type de la barre de statut améliorée. */
+G_DEFINE_TYPE(GtkStatusStack, gtk_status_stack, GTK_TYPE_BIN)
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe GTK à initialiser.                            *
+*                                                                             *
+*  Description : Initialise la classe des barres de statut améliorées.        *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void gtk_status_stack_class_init(GtkStatusStackClass *klass)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)gtk_status_stack_dispose;
+    object->finalize = (GObjectFinalizeFunc)gtk_status_stack_finalize;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : stack = instance GTK à initialiser.                          *
+*                                                                             *
+*  Description : Initialise une instance de barre de statut améliorée.        *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void gtk_status_stack_init(GtkStatusStack *stack)
+{
+    stack->asm_status = build_assembly_status_stack(stack);
+    stack->asm_info = (assembly_info *)calloc(1, sizeof(assembly_info));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : view = instance d'objet GLib à traiter.                      *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void gtk_status_stack_dispose(GtkStatusStack *stack)
+{
+    g_object_unref(G_OBJECT(stack->asm_status));
+
+    G_OBJECT_CLASS(gtk_status_stack_parent_class)->dispose(G_OBJECT(stack));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : view = instance d'objet GLib à traiter.                      *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void gtk_status_stack_finalize(GtkStatusStack *stack)
+{
+    reset_assembly_info(stack->asm_info);
+
+    free(stack->asm_info);
+
+    G_OBJECT_CLASS(gtk_status_stack_parent_class)->finalize(G_OBJECT(stack));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Crée une nouvelle instance de barre de statut.               *
+*                                                                             *
+*  Retour      : Composant GTK mis en place.                                  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GtkWidget *gtk_status_stack_new(void)
+{
+    return g_object_new(GTK_TYPE_STATUS_STACK, NULL);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : stack = pile de statuts à considérer.                        *
+*                next  = niveau de pile à afficher désormais.                 *
+*                                                                             *
+*  Description : S'assure de l'affichage du niveau de pile attendu.           *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void gtk_status_stack_switch(GtkStatusStack *stack, GtkWidget *next)
+{
+    GtkWidget *child;                       /* Support courant             */
+
+    child = gtk_bin_get_child(GTK_BIN(stack));
+
+    if (child != next)
+    {
+        if (child != NULL)
+            gtk_container_remove(GTK_CONTAINER(stack), child);
+
+        g_object_ref(G_OBJECT(next));
+        gtk_container_add(GTK_CONTAINER(stack), next);
+
+    }
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                      STATUT DES INFORMATIONS DE DESASSEMBLAGE                      */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : info = informations à réinitialiser.                         *
+*                                                                             *
+*  Description : Supprime l'empreinte mémoire d'informations d'assemblage.    *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void reset_assembly_info(assembly_info *info)
+{
+    if (info->segment != NULL)
+    {
+        free(info->segment);
+        info->segment = NULL;
+    }
+
+    if (info->symbol != NULL)
+    {
+        free(info->symbol);
+        info->symbol = NULL;
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : stack = composant global en cours de construction.           *
+*                                                                             *
+*  Description : Construit une barre d'état pour language d'assemblage.       *
+*                                                                             *
+*  Retour      : Composant GTK mis en place.                                  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static GtkWidget *build_assembly_status_stack(GtkStatusStack *stack)
+{
+    GtkWidget *result;                      /* Support à retourner         */
+    GObject *ref;                           /* Espace de référencements    */
+    GtkWidget *hbox;                        /* Sous-division horizontale   */
+    GtkWidget *label;                       /* Etiquette pour impression   */
+    GtkWidget *zoom;                        /* Sélection du zoom courant   */
+
+    result = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
+    gtk_widget_show(result);
+
+    ref = G_OBJECT(result);
+
+    g_signal_connect(result, "size-allocate", G_CALLBACK(on_size_allocate_for_asm_status), ref);
+
+    /* Première partie : navigation */
+
+    hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 16);
+    gtk_widget_show(hbox);
+    gtk_box_pack_start(GTK_BOX(result), hbox, TRUE, TRUE, 8);
+
+    label = qck_create_label(ref, "segment", NULL);
+    gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+
+    label = qck_create_label(ref, "phys", NULL);
+    gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+
+    label = qck_create_label(ref, "virt", NULL);
+    gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+
+    label = qck_create_label(ref, "offset", NULL);
+    gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+
+    /* Seconde partie : architecture */
+
+    hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8);
+    g_object_set_data(ref, "arch_box", hbox);
+    gtk_widget_show(hbox);
+    gtk_box_pack_start(GTK_BOX(result), hbox, FALSE, TRUE, 8);
+
+    label = qck_create_label(ref, "arch", NULL);
+    gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+
+    label = qck_create_label(ref, "size", NULL);
+    gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+
+    /* Troisième partie : affichage */
+
+    hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8);
+    gtk_widget_show(hbox);
+    gtk_box_pack_start(GTK_BOX(result), hbox, FALSE, FALSE, 8);
+
+    zoom = qck_create_entry(ref, "zoom", "100%");
+    gtk_entry_set_icon_from_icon_name(GTK_ENTRY(zoom), GTK_ENTRY_ICON_SECONDARY, "go-up-symbolic");
+
+    g_signal_connect(zoom, "icon-press", G_CALLBACK(on_zoom_icon_press), stack);
+
+    gtk_box_pack_start(GTK_BOX(hbox), zoom, FALSE, TRUE, 0);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : widget     = composant graphique qui vient d'évoluer.        *
+*                allocation = espace réservé pour le composant visé.          *
+*                ref        = espace de référencement global.                 *
+*                                                                             *
+*  Description : Réagit à un redimensionnement de la barre de désassemblage.  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void on_size_allocate_for_asm_status(GtkWidget *widget, GdkRectangle *allocation, GObject *ref)
+{
+    GtkWidget *hbox;                        /* Sous-division horizontale   */
+
+    hbox = GTK_WIDGET(g_object_get_data(ref, "arch_box"));
+
+    gtk_widget_set_size_request(hbox, (allocation->width * 40) / 100, -1);
+
+    /**
+     * On intervient après que le containeur soit passer collecter les tailles
+     * de ses enfants lors de son redimensionnement.
+     *
+     * Donc on force un prise en compte des changements.
+     */
+    gtk_container_check_resize(GTK_CONTAINER(widget));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : entry    = zone de texte visée par la procédure.             *
+*                icon_pos = position de l'image associée à l'entrée.          *
+*                event    = informations liées à l'événement.                 *
+*                stack    = composant graphique de gestion des statuts.       *
+*                                                                             *
+*  Description : Réagit à un clic sur l'icône de zoom.                        *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void on_zoom_icon_press(GtkEntry *entry, GtkEntryIconPosition icon_pos, GdkEventButton *event, GtkStatusStack *stack)
+{
+    GtkWidget *popup;                       /* Popup à faire surgir        */
+    GdkRectangle rect;                      /* Zone précise à cibler       */
+
+    if (event->button != GDK_BUTTON_PRIMARY)
+        return;
+
+    popup = gtk_popover_new(GTK_WIDGET(entry));
+
+    gtk_entry_get_icon_area(entry, GTK_ENTRY_ICON_SECONDARY, &rect);
+    gtk_popover_set_pointing_to(GTK_POPOVER(popup), &rect);
+
+    gtk_widget_show(popup);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : stack  = barre de statut à actualiser.                       *
+*                binary = binaire chargé rassemblant l'ensemble des infos.    *
+*                instr  = instruction désassemblée ciblée graphiquement.      *
+*                                                                             *
+*  Description : Actualise les informations liées une position d'assemblage.  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void gtk_status_stack_update_current_instruction(GtkStatusStack *stack, const GLoadedBinary *binary, const GArchInstruction *instr)
+{
+    assembly_info *info;                    /* Informations à constituer   */
+    GExeFormat *format;                     /* Format de binaire à traiter */
+    const mrange_t *range;                  /* Emplacement d'instruction   */
+    const vmpa2t *addr;                     /* Localisation de départ      */
+    GBinPortion *portions;                  /* Portions binaires existantes*/
+    GBinPortion *portion;                   /* Zone mémoire d'appartenance */
+    const char *text;                       /* Texte au contenu à copier   */
+    GBinSymbol *symbol;                     /* Symbole présent à l'adresse */
+    phys_t diff;                            /* Décallage de l'adresse      */
+    const char *label;                      /* Description d'un symbole    */
+    vmpa2t tmp;                             /* Zone de construction temp.  */
+    VMPA_BUFFER(offset);                    /* Décalage physique           */
+
+    info = stack->asm_info;
+
+    format = g_loaded_binary_get_format(binary);
+
+    /* Bascule vers une zone courante nouvelle ? */
+
+    range = g_arch_instruction_get_range(instr);
+    addr = get_mrange_addr(range);
+
+    if (cmp_mrange(&info->current, range) == 0)
+        goto gssuci_useless;
+
+    /* Réinitialisation */
+
+    reset_assembly_info(info);
+
+    copy_mrange(&info->current, range);
+
+    /* Zone d'appartenance */
+
+    portions = g_exe_format_get_portions(format);
+
+    portion = g_binary_portion_find_at_addr(portions, addr, (GdkRectangle []) { });
+
+    text = g_binary_portion_get_desc(portion);
+
+    if (text != NULL)
+        info->segment = strdup(text);
+    else
+        info->segment = strdup(_("Binary"));
+
+    /* Adresses de base */
+
+    vmpa2_phys_to_string(addr, MDS_UNDEFINED, info->phys, NULL);
+
+    vmpa2_virt_to_string(addr, MDS_UNDEFINED, info->virt, NULL);
+
+    info->encoding = g_arch_instruction_get_encoding(instr);
+
+    info->size = get_mrange_length(range);
+
+    /* Symbole concerné */
+
+    if (g_binary_format_resolve_symbol(G_BIN_FORMAT(format), addr, &symbol, &diff))
+    {
+        label = g_binary_symbol_get_label(symbol);
+
+        if (label != NULL)
+        {
+            info->symbol = strdup(label);
+
+            info->symbol = stradd(info->symbol, "+");
+
+            init_vmpa(&tmp, diff, VMPA_NO_VIRTUAL);
+            vmpa2_phys_to_string(&tmp, MDS_UNDEFINED, offset, NULL);
+
+            info->symbol = stradd(info->symbol, offset);
+
+        }
+
+        g_object_unref(G_OBJECT(symbol));
+
+    }
+
+    /* Nettoyage et conclusion */
+
+    gtk_status_stack_show_current_instruction(stack);
+
+ gssuci_useless:
+
+    //g_object_unref(G_OBJECT(format));
+
+    ;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : stack = pile de statuts à manipuler.                         *
+*                                                                             *
+*  Description : S'assure de l'affichage à jour de la partie "assemblage".    *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void gtk_status_stack_show_current_instruction(GtkStatusStack *stack)
+{
+    GObject *ref;                           /* Espace de référencements    */
+    assembly_info *info;                    /* Informations à consulter    */
+    GtkLabel *label;                        /* Etiquette à actualiser      */
+    char raw_pos[6 + VMPA_MAX_LEN + 1];     /* Formatage final en direct   */
+    char *content;                          /* Contenu dynamique           */
+
+    gtk_status_stack_switch(stack, stack->asm_status);
+
+    ref = G_OBJECT(stack->asm_status);
+    info = stack->asm_info;
+
+    /* Première partie : navigation */
+
+    label = GTK_LABEL(g_object_get_data(ref, "segment"));
+    gtk_label_set_text(label, info->segment);
+
+    snprintf(raw_pos, sizeof(raw_pos), "phys: %s", info->phys);
+
+    label = GTK_LABEL(g_object_get_data(ref, "phys"));
+    gtk_label_set_text(label, raw_pos);
+
+    snprintf(raw_pos, sizeof(raw_pos), "virt: %s", info->virt);
+
+    label = GTK_LABEL(g_object_get_data(ref, "virt"));
+    gtk_label_set_text(label, raw_pos);
+
+    label = GTK_LABEL(g_object_get_data(ref, "offset"));
+    gtk_label_set_text(label, info->symbol != NULL ? info->symbol : "");
+
+    /* Seconde partie : architecture */
+
+    label = GTK_LABEL(g_object_get_data(ref, "arch"));
+    gtk_label_set_text(label, info->encoding);
+
+    if (info->size > 1)
+        asprintf(&content, "%" PRIu64 " %s", (uint64_t)info->size, _("bytes"));
+    else
+        asprintf(&content, "%" PRIu64 " %s", (uint64_t)info->size, _("byte"));
+
+    label = GTK_LABEL(g_object_get_data(ref, "size"));
+    gtk_label_set_text(label, content);
+
+    free(content);
+
+}
diff --git a/src/gtkext/gtkstatusstack.h b/src/gtkext/gtkstatusstack.h
new file mode 100644
index 0000000..9d25c8f
--- /dev/null
+++ b/src/gtkext/gtkstatusstack.h
@@ -0,0 +1,79 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * gtkstatusstack.h - prototypes pour un empilement d'informations de statut
+ *
+ * Copyright (C) 2015 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  OpenIDA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  OpenIDA is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GTKEXT_GTKSTATUSSTACK_H
+#define _GTKEXT_GTKSTATUSSTACK_H
+
+
+
+#include <gtk/gtk.h>
+
+
+#include "../analysis/binary.h"
+
+
+
+/* FIXME */
+typedef int bstatus_id_t;
+
+
+
+
+/* ------------------------- GESTION EXTERIEURE DE LA BARRE ------------------------- */
+
+
+#define GTK_TYPE_STATUS_STACK            (gtk_status_stack_get_type())
+#define GTK_STATUS_STACK(obj)            (G_TYPE_CHECK_INSTANCE_CAST(obj, GTK_TYPE_STATUS_STACK, GtkStatusStack))
+#define GTK_STATUS_STACK_CLASS(klass)    (G_LOADED_BINARY_GET_CLASS(klass, GTK_TYPE_STATUS_STACK, GtkStatusStackClass))
+#define GTK_IS_STATUS_STACK(obj)         (G_TYPE_CHECK_INSTANCE_TYPE(obj, GTK_TYPE_STATUS_STACK))
+#define GTK_IS_STATUS_STACK_CLASS(obj)   (G_TYPE_CHECK_INSTANCE_TYPE(obj, GTK_TYPE_STATUS_STACK))
+#define GTK_STATUS_STACK_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_STATUS_STACK, GtkStatusStackClass))
+
+
+/* Abstration d'une gestion de barre de statut (instance) */
+typedef struct _GtkStatusStack GtkStatusStack;
+
+/* Abstration d'une gestion de barre de statut (classe) */
+typedef struct _GtkStatusStackClass GtkStatusStackClass;
+
+
+/* Détermine le type de la barre de statut améliorée. */
+GType gtk_status_stack_get_type(void);
+
+/* Crée une nouvelle instance de barre de statut. */
+GtkWidget *gtk_status_stack_new(void);
+
+
+
+/* -------------------- STATUT DES INFORMATIONS DE DESASSEMBLAGE -------------------- */
+
+
+/* Actualise les informations liées une position d'assemblage. */
+void gtk_status_stack_update_current_instruction(GtkStatusStack *, const GLoadedBinary *, const GArchInstruction *);
+
+
+
+
+
+
+#endif  /* _GTKEXT_GTKSTATUSSTACK_H */
diff --git a/src/gui/editor.c b/src/gui/editor.c
index 1742596..bc4f144 100644
--- a/src/gui/editor.c
+++ b/src/gui/editor.c
@@ -177,7 +177,7 @@ GtkWidget *create_editor(void)
 
 
 
-    vbox1 = gtk_box_new(GTK_ORIENTATION_VERTICAL, 8);
+    vbox1 = gtk_box_new(GTK_ORIENTATION_VERTICAL, 4);
     gtk_widget_show(vbox1);
     gtk_container_add(GTK_CONTAINER(result), vbox1);
 
diff --git a/src/gui/status.c b/src/gui/status.c
index 41cad1a..f466193 100644
--- a/src/gui/status.c
+++ b/src/gui/status.c
@@ -36,7 +36,7 @@
 #include "../common/extstr.h"
 #include "../gtkext/gtkbufferview.h"
 #include "../gtkext/gtkblockview.h"
-#include "../gtkext/gtkextstatusbar.h"
+#include "../gtkext/gtkstatusstack.h"
 
 
 
@@ -136,7 +136,7 @@ static void g_status_info_init(GStatusInfo *bar)
 
     item->name = "status";
 
-    item->widget = gtk_extended_status_bar_new();
+    item->widget = gtk_status_stack_new();
     gtk_widget_show(item->widget);
 
 }
@@ -271,89 +271,12 @@ static void track_caret_address_on_buffer_views(GtkBufferView *view, const vmpa2
 {
     GEditorItem *item;                      /* Autre version de l'élément  */
     GLoadedBinary *binary;                  /* Binaire courant             */
-    GExeFormat *format;                     /* Format du fichier binaire   */
-    GArchProcessor *proc;                   /* Architecture du binaire     */
-    MemoryDataSize msize;                   /* Taille par défaut           */
-    char *msg;                              /* Message à transmettre       */
-    VMPA_BUFFER(conv);                      /* Zone de conversion          */
-
-    vmpa_t rel;                             /* Adresse relative à un symb. */
-    const char *label;                      /* Désignation d'un symbole    */
 
     item = G_EDITOR_ITEM(info);
 
     binary = g_editor_item_get_current_binary(item);
 
-    proc = g_loaded_binary_get_processor(binary);
-    msize = g_arch_processor_get_memory_size(proc);
-    g_object_unref(G_OBJECT(proc));
-
-    /* Réinitiation seule si il n'y a plus d'adresse... */
-
-    if (addr == NULL)
-    {
-        if (info->msg_id > 0)
-            gtk_extended_status_bar_remove(GTK_EXT_STATUS_BAR(item->widget), info->msg_id);
-
-        return;
-
-    }
-
-    /* Adresse brute */
-
-    msize = g_arch_processor_get_memory_size(proc);
-
-    msg = strdup(_("Location phys:"));
-
-    vmpa2_phys_to_string(addr, msize, conv, NULL);
-    msg = stradd(msg, conv);
-
-    msg = stradd(msg, " virt:");
-
-    vmpa2_virt_to_string(addr, msize, conv, NULL);
-    msg = stradd(msg, conv);
-
-
-
-#if 0
-
-    /* Relation avec les symboles */
-
-    binary = G_LOADED_BINARY(g_object_get_data(item->ref, "current_binary"));
-    format = g_loaded_binary_get_format(binary);
-
-    rel = addr;
-
-    if (g_binary_format_resolve_relative_routine(G_BIN_FORMAT(format), &label, &rel))
-    {
-        msg = stradd(msg, _(" at "));
-        msg = stradd(msg, label);
-        msg = stradd(msg, _("+"));
-
-        snprintf(tmp, VMPA_MAX_SIZE, VMPA_FMT, rel);
-        msg = stradd(msg, tmp);
-
-    }
-
-#endif
-
-
-    /* Impression */
-
-    if (info->msg_id > 0)
-        gtk_extended_status_bar_remove(GTK_EXT_STATUS_BAR(item->widget), info->msg_id);
-
-    info->msg_id = gtk_extended_status_bar_push(GTK_EXT_STATUS_BAR(item->widget), msg, FALSE);
-
-
-    printf("---- moved to 0x%08llx\n", addr);
-
-    printf(" MSG '%s'\n", msg);
-
-    //update_menu_project_for_project(bar->project, project, bar);
-
-
-    free(msg);
+    focus_address_in_status_info(info, binary, addr);
 
 }
 
@@ -374,85 +297,17 @@ static void track_caret_address_on_buffer_views(GtkBufferView *view, const vmpa2
 
 static void focus_address_in_status_info(GStatusInfo *info, GLoadedBinary *binary, const vmpa2t *addr)
 {
-    GExeFormat *format;                     /* Format associé au binaire   */
     GArchProcessor *proc;                   /* Architecture du binaire     */
-    MemoryDataSize msize;                   /* Taille du bus d'adresses    */
-    char *msg;                              /* Message à transmettre       */
-    VMPA_BUFFER(tmp);                       /* Traduction d'adresses       */
-    GBinSymbol *symbol;                     /* Symbole présent à l'adresse */
-    phys_t diff;                            /* Décallage de l'adresse      */
-    const char *label;                      /* Description d'un symbole    */
-    GBinPortion *portions;                  /* Portions binaires existantes*/
-    GBinPortion *portion;                   /* Zone mémoire d'appartenance */
-    size_t len;                             /* Caractère à faire basculer  */
-
-    format = g_loaded_binary_get_format(binary);
+    GArchInstruction *instr;                /* Instruction présente        */
+    GEditorItem *item;                      /* Autre version de l'élément  */
 
     proc = g_loaded_binary_get_processor(binary);
-    msize = g_arch_processor_get_memory_size(proc);
-    g_object_unref(G_OBJECT(proc));
-
-    msg = strdup(_("Localisation:"));
-
-    /* Adresses de base */
-
-    msg = stradd(msg, " phys:");
-    vmpa2_phys_to_string(addr, msize, tmp, NULL);
-    msg = stradd(msg, tmp);
-
-    msg = stradd(msg, " virt:");
-    vmpa2_virt_to_string(addr, msize, tmp, NULL);
-    msg = stradd(msg, tmp);
-
-    /* Symbole présent ? */
-
-    if (g_binary_format_resolve_symbol(G_BIN_FORMAT(format), addr, &symbol, &diff))
-    {
-        label = g_binary_symbol_get_label(symbol);
-
-        if (label != NULL)
-        {
-            msg = stradd(msg, _(" at "));
-            msg = stradd(msg, label);
-            msg = stradd(msg, _("+"));
 
-            snprintf(tmp, VMPA_MAX_SIZE, "0x%x", diff);
-            msg = stradd(msg, tmp);
+    instr = g_arch_processor_find_instr_by_address(proc, addr);
 
-        }
-
-        g_object_unref(G_OBJECT(symbol));
-
-    }
-
-    /* Zone d'appartenance */
-
-    portions = g_exe_format_get_portions(format);
-
-    portion = g_binary_portion_find_at_addr(portions, addr, (GdkRectangle []) { });
-
-    label = g_binary_portion_get_desc(portion);
-
-    msg = stradd(msg, _(" ("));
-
-    /**
-     * Pas très propre : on bascule de majuscule en minuscule ici...
-     * FIXME ?
-     */
-
-    len = strlen(msg);
-    msg = stradd(msg, label);
-    msg[len] = tolower(msg[len]);
-
-    msg = stradd(msg, _(")"));
-
-    /* Impression */
-
-    if (info->msg_id > 0)
-        gtk_extended_status_bar_remove(GTK_EXT_STATUS_BAR(G_EDITOR_ITEM(info)->widget), info->msg_id);
-
-    info->msg_id = gtk_extended_status_bar_push(GTK_EXT_STATUS_BAR(G_EDITOR_ITEM(info)->widget), msg, FALSE);
+    item = G_EDITOR_ITEM(info);
+    gtk_status_stack_update_current_instruction(GTK_STATUS_STACK(item->widget), binary, instr);
 
-    free(msg);
+    g_object_unref(G_OBJECT(proc));
 
 }
-- 
cgit v0.11.2-87-g4458