From a7f73441a0d466824798a421f369628db0184030 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Mon, 4 Jun 2018 02:27:13 +0200
Subject: Loaded the biggest panel contents using threads.

---
 src/core/params.c            |    3 -
 src/core/params.h            |    1 -
 src/gtkext/gtkdockable-int.h |   12 +-
 src/gtkext/gtkdockable.c     |   65 +--
 src/gtkext/tmgt.c            |  118 ++++-
 src/gtkext/tmgt.h            |    5 +-
 src/gui/panels/Makefile.am   |    1 +
 src/gui/panels/bintree.c     |  922 ++++++++++++++++++++++++++++-------
 src/gui/panels/bintree.ui    |   59 ++-
 src/gui/panels/bookmarks.c   |   55 +--
 src/gui/panels/gresource.xml |    1 +
 src/gui/panels/panel-int.h   |   14 +-
 src/gui/panels/panel.c       |  102 +++-
 src/gui/panels/panel.h       |   12 +-
 src/gui/panels/strings.c     | 1109 ++++++++++++++++++++++++++++++------------
 src/gui/panels/strings.ui    |   93 ++++
 src/gui/panels/symbols.c     |  185 +++----
 17 files changed, 2016 insertions(+), 741 deletions(-)
 create mode 100644 src/gui/panels/strings.ui

diff --git a/src/core/params.c b/src/core/params.c
index ce8b9ce..1a724eb 100644
--- a/src/core/params.c
+++ b/src/core/params.c
@@ -195,9 +195,6 @@ bool load_main_config_parameters(void)
     param = g_generic_config_create_param(config, MPK_ELLIPSIS_TAB, CPT_INTEGER, 35);
     if (param == NULL) return false;
 
-    param = g_generic_config_create_param(config, MPK_DISPLAY_ON_SEL, CPT_BOOLEAN, false);
-    if (param == NULL) return false;
-
     param = g_generic_config_create_param(config, MPK_WELCOME_STARTUP, CPT_BOOLEAN, true);
     if (param == NULL) return false;
 
diff --git a/src/core/params.h b/src/core/params.h
index 4535b04..6fa39b2 100644
--- a/src/core/params.h
+++ b/src/core/params.h
@@ -59,7 +59,6 @@
 #define MPK_MAXIMIZED           "gui.editor.start_maximized"
 #define MPK_ELLIPSIS_HEADER     "gui.editor.panels.ellipsis_header"
 #define MPK_ELLIPSIS_TAB        "gui.editor.panels.ellipsis_tab"
-#define MPK_DISPLAY_ON_SEL      "gui.editor.panels.display_on_selection"
 #define MPK_WELCOME_STARTUP     "gui.editor.panels.welcome.show_at_startup"
 #define MPK_WELCOME_CHECK       "gui.editor.panels.welcome.check_version"
 #define MPK_SELECTION_LINE      "gui.editor.views.selection_line"
diff --git a/src/gtkext/gtkdockable-int.h b/src/gtkext/gtkdockable-int.h
index d9dbbd5..d4cd2d1 100644
--- a/src/gtkext/gtkdockable-int.h
+++ b/src/gtkext/gtkdockable-int.h
@@ -32,6 +32,12 @@
 
 
 
+/* Indique si le composant représenté à du contenu à fouiller. */
+typedef bool (* can_dockable_search_fc) (const GtkDockable *);
+
+/* Indique si le composant peut être désencapsulé manuellement. */
+typedef bool (* can_dockable_be_closed_fc) (const GtkDockable *);
+
 /* Fournit le nom court du composant encapsulable. */
 typedef const char * (* get_dockable_name_fc) (const GtkDockable *);
 
@@ -42,7 +48,7 @@ typedef const char * (* get_dockable_desc_fc) (const GtkDockable *);
 typedef GtkWidget * (* get_dockable_widget_fc) (const GtkDockable *);
 
 /* Démarre l'actualisation du filtrage des paramètres. */
-typedef void (* update_filtered_data_fc) (GtkDockable *, const regex_t *);
+typedef void (* update_filtered_data_fc) (GtkDockable *, char *);
 
 
 /* Elément accepté dans les rassemblements (interface) */
@@ -50,8 +56,8 @@ struct _GtkDockableIface
 {
     GTypeInterface base_iface;              /* A laisser en premier        */
 
-    bool can_search;                        /* Contenu fouillable ?        */
-    bool can_be_closed;                     /* Fermeture possible ?        */
+    can_dockable_search_fc can_search;      /* Contenu fouillable ?        */
+    can_dockable_be_closed_fc can_be_closed;/* Fermeture possible ?        */
 
     get_dockable_name_fc get_name;          /* Nom pour titre              */
     get_dockable_desc_fc get_desc;          /* Description humaine         */
diff --git a/src/gtkext/gtkdockable.c b/src/gtkext/gtkdockable.c
index cad9b43..3056402 100644
--- a/src/gtkext/gtkdockable.c
+++ b/src/gtkext/gtkdockable.c
@@ -33,6 +33,7 @@
 
 #include "easygtk.h"
 #include "gtkdockable-int.h"
+#include "tmgt.h"
 
 
 
@@ -197,11 +198,14 @@ const char *gtk_dockable_get_desc(const GtkDockable *dockable)
 
 bool gtk_dockable_can_search(const GtkDockable *dockable)
 {
+    bool result;                            /* Indication à retourner      */
     GtkDockableIface *iface;                /* Interface utilisée          */
 
     iface = GTK_DOCKABLE_GET_IFACE(dockable);
 
-    return iface->can_search;
+    result = iface->can_search(dockable);
+
+    return result;
 
 }
 
@@ -220,11 +224,14 @@ bool gtk_dockable_can_search(const GtkDockable *dockable)
 
 bool gtk_dockable_can_be_closed(const GtkDockable *dockable)
 {
+    bool result;                            /* Indication à retourner      */
     GtkDockableIface *iface;                /* Interface utilisée          */
 
     iface = GTK_DOCKABLE_GET_IFACE(dockable);
 
-    return iface->can_be_closed;
+    result = iface->can_be_closed(dockable);
+
+    return result;
 
 }
 
@@ -256,7 +263,7 @@ GtkWidget *gtk_dockable_build_widget(GtkDockable *dockable)
 
     /* Encapsulation avec un panneau coulissant ? */
 
-    if (iface->can_search)
+    if (gtk_dockable_can_search(dockable))
     {
         revealer = gtk_revealer_new();
         gtk_widget_show(revealer);
@@ -305,7 +312,7 @@ GtkWidget *gtk_dockable_decompose(GtkDockable *dockable, GtkWidget **support)
 
     result = iface->get_widget(dockable);
 
-    if (iface->can_search)
+    if (gtk_dockable_can_search(dockable))
         result = gtk_widget_get_parent(result);     /* GtkBox */
 
     if (support != NULL)
@@ -407,56 +414,12 @@ static GtkWidget *build_search_area(GtkDockable *dockable, GtkWidget **search)
 
 static void on_dockable_search_changed(GtkSearchEntry *entry, GtkDockable *dockable)
 {
-    regex_t *filter;                        /* Expression régulière        */
-    const gchar *text;                      /* Texte de l'utilisateur      */
-    GtkStyleContext *context;               /* Contexte du thème actuel    */
-    int ret;                                /* Bilan de mise en place      */
+    char *filter;                           /* Nouveau filtre à considérer */
     GtkDockableIface *iface;                /* Interface utilisée          */
 
-    filter = g_object_get_data(G_OBJECT(entry), "preg_filter");
-
-    text = gtk_entry_get_text(GTK_ENTRY(entry));
-
-    context = gtk_widget_get_style_context(GTK_WIDGET(entry));
-
-    /* Mise en place d'une nouvelle règle */
-    if (strlen(text) > 0)
-    {
-        if (filter == NULL)
-        {
-            void destroy_filter(regex_t *preg)
-            {
-                regfree(preg);
-                free(preg);
-            }
-
-            filter = (regex_t *)calloc(1, sizeof(regex_t));
-            g_object_set_data_full(G_OBJECT(entry), "preg_filter", filter, (GDestroyNotify)destroy_filter);
-
-        }
-        else
-            regfree(filter);
-
-        ret = regcomp(filter, text, REG_EXTENDED);
-
-        if (ret != 0)
-        {
-            gtk_style_context_add_class(context, "filter-error");
-            return;
-        }
-
-    }
-
-    /* Suppresion de toute règle existante */
-    else if (filter != NULL)
-    {
-        g_object_set_data(G_OBJECT(entry), "preg_filter", NULL);
-        filter = NULL;
-    }
-
-    /* Mises à jour */
+    filter = NULL;
 
-    gtk_style_context_remove_class(context, "filter-error");
+    update_regex_on_search_entry_changed(entry, &filter);
 
     iface = GTK_DOCKABLE_GET_IFACE(dockable);
 
diff --git a/src/gtkext/tmgt.c b/src/gtkext/tmgt.c
index 536adb0..7e815f6 100644
--- a/src/gtkext/tmgt.c
+++ b/src/gtkext/tmgt.c
@@ -24,6 +24,7 @@
 #include "tmgt.h"
 
 
+#include <assert.h>
 #include <malloc.h>
 #include <string.h>
 
@@ -45,41 +46,52 @@
 *                                                                             *
 ******************************************************************************/
 
-void update_regex_on_search_entry_changed(GtkSearchEntry *entry, regex_t **filter)
+void update_regex_on_search_entry_changed(GtkSearchEntry *entry, char **filter)
 {
     const gchar *text;                      /* Texte de l'utilisateur      */
-    GtkStyleContext *context;               /* Contexte du thème actuel    */
+    bool has_error;                         /* Détecttion d'une erreur     */
+    regex_t exp;                            /* Expression régulière créée  */
     int ret;                                /* Bilan de mise en place      */
+    GtkStyleContext *context;               /* Contexte du thème actuel    */
 
     if (*filter != NULL)
-    {
-        regfree(*filter);
         free(*filter);
-        *filter = NULL;
-    }
+
+    /* Validation et exportation des résultats */
 
     text = gtk_entry_get_text(GTK_ENTRY(entry));
 
-    context = gtk_widget_get_style_context(GTK_WIDGET(entry));
+    if (strlen(text) == 0)
+    {
+        has_error = false;
+        *filter = NULL;
+    }
 
-    if (strlen(text) > 0)
+    else
     {
-        *filter = (regex_t *)calloc(1, sizeof(regex_t));
-        ret = regcomp(*filter, text, REG_EXTENDED | REG_ICASE);
+        ret = regcomp(&exp, text, REG_EXTENDED | REG_ICASE);
 
-        if (ret != 0)
-        {
-            free(*filter);
-            *filter = NULL;
+        has_error = (ret != 0);
 
-            gtk_style_context_add_class(context, "filter-error");
-            return;
+        if (has_error)
+            *filter = NULL;
 
+        else
+        {
+            *filter = strdup(text);
+            regfree(&exp);
         }
 
     }
 
-    gtk_style_context_remove_class(context, "filter-error");
+    /* Indication à l'écran */
+
+    context = gtk_widget_get_style_context(GTK_WIDGET(entry));
+
+    if (has_error)
+        gtk_style_context_add_class(context, "filter-error");
+    else
+        gtk_style_context_remove_class(context, "filter-error");
 
 }
 
@@ -103,10 +115,11 @@ bool is_content_matching(const regex_t *filter, const char *content, regmatch_t
     bool result;                            /* Bilan à retourner           */
     int ret;                                /* Bilan du filtrage           */
 
-    memset(match, 0, sizeof(regmatch_t));
-
     if (filter == NULL)
+    {
+        memset(match, 0, sizeof(regmatch_t));
         result = true;
+    }
 
     else
     {
@@ -199,3 +212,70 @@ char *build_highlighted_name(const char *raw, const regmatch_t *match, size_t st
     return result;
 
 }
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : store = organisation des données sous forme arborescente.    *
+*                iter  = position du noeud courant à traiter.                 *
+*                show  = visibilité à obtenir pour le noeud final.            *
+*                                                                             *
+*  Description : Met à jour l'affichage des noeuds en fonction des besoin.    *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void update_node_visibility(GtkTreeStore *store, GtkTreeIter *iter, gint column, bool show)
+{
+    GtkTreeModel *model;                    /* Autre vision du gestionnaire*/
+    gint matched_col;                       /* Colonne de visibilité       */
+    gint points_col;                        /* Colonne des points          */
+    guint points;                           /* Compteur de besoins         */
+    GtkTreeIter parent;                     /* Position de noeuf parent    */
+    gboolean further;                       /* Poursuite de remontée       */
+
+    model = GTK_TREE_MODEL(store);
+
+    matched_col = column;
+    points_col = column + 1;
+
+    /* Enumération des besoins */
+
+    gtk_tree_model_get(model, iter, points_col, &points, -1);
+
+    if (show)
+        points++;
+
+    else
+    {
+        assert(points > 0);
+        points--;
+    }
+
+    gtk_tree_store_set(store, iter, points_col, points, -1);
+
+    /* Adaptation de l'affichage */
+
+    if (show)
+    {
+        if (points == 1)
+            gtk_tree_store_set(store, iter, matched_col, true, -1);
+    }
+
+    else
+    {
+        if (points == 0)
+            gtk_tree_store_set(store, iter, matched_col, false, -1);
+    }
+
+    /* Eventuel étage supérieur */
+
+    further = gtk_tree_model_iter_parent(model, &parent, iter);
+
+    if (further)
+        update_node_visibility(store, &parent, column, show);
+
+}
diff --git a/src/gtkext/tmgt.h b/src/gtkext/tmgt.h
index 189e704..3f3a4f3 100644
--- a/src/gtkext/tmgt.h
+++ b/src/gtkext/tmgt.h
@@ -32,7 +32,7 @@
 
 
 /* Met à jour un filtre selon un contenu recherché. */
-void update_regex_on_search_entry_changed(GtkSearchEntry *, regex_t **);
+void update_regex_on_search_entry_changed(GtkSearchEntry *, char **);
 
 /* Détermine si un contenu correspond à un filtre donné. */
 bool is_content_matching(const regex_t *, const char *, regmatch_t *);
@@ -40,6 +40,9 @@ bool is_content_matching(const regex_t *, const char *, regmatch_t *);
 /* Met en évidence le texte recherché en cas de correspondance. */
 char *build_highlighted_name(const char *, const regmatch_t *, size_t);
 
+/* Met à jour l'affichage des noeuds en fonction des besoin. */
+void update_node_visibility(GtkTreeStore *, GtkTreeIter *, gint, bool);
+
 
 
 #endif  /* _COMMON_TMGT_H */
diff --git a/src/gui/panels/Makefile.am b/src/gui/panels/Makefile.am
index de4c37d..b273f82 100644
--- a/src/gui/panels/Makefile.am
+++ b/src/gui/panels/Makefile.am
@@ -6,6 +6,7 @@ noinst_LTLIBRARIES  = libguipanels.la
 UI_FILES =								\
 	bintree.ui							\
 	errors.ui							\
+	strings.ui							\
 	symbols.ui							\
 	welcome.ui
 
diff --git a/src/gui/panels/bintree.c b/src/gui/panels/bintree.c
index c2caef7..642a71c 100644
--- a/src/gui/panels/bintree.c
+++ b/src/gui/panels/bintree.c
@@ -25,6 +25,7 @@
 #include "bintree.h"
 
 
+#include <assert.h>
 #include <malloc.h>
 #include <regex.h>
 
@@ -33,11 +34,15 @@
 
 
 #include "panel-int.h"
+#include "updating-int.h"
 #include "../core/global.h"
+#include "../../core/queue.h"
 #include "../../gtkext/tmgt.h"
 
 
 
+/* -------------------------- PARTIE PRINCIPALE DU PANNEAU -------------------------- */
+
 /* Origine de la dernière ouverture/fermeture reproductible */
 typedef enum _UserActionType
 {
@@ -47,18 +52,16 @@ typedef enum _UserActionType
 
 } UserActionType;
 
-
 /* Panneau de présentation des portions (instance) */
 struct _GBintreePanel
 {
     GPanelItem parent;                      /* A laisser en premier        */
 
     GLoadedBinary *binary;                  /* Binaire représenté          */
-    regex_t *filter;                        /* Filtre appliqué ou NULL     */
 
     UserActionType last;                    /* Dernière action             */
 
-    GtkTreeIter *top;                       /* Transfert de racine         */
+    size_t count;                           /* Quantité de portions utiles */
 
 };
 
@@ -73,6 +76,8 @@ struct _GBintreePanelClass
 /* Colonnes de la liste des messages */
 typedef enum _BinaryTreeColumn
 {
+    BTC_PORTION,                            /* Elément interne représenté  */
+
     BTC_ICON,                               /* Image de représentation     */
     BTC_CAPTION,                            /* Désignation de l'élément    */
     BTC_START,                              /* Position de départ          */
@@ -80,45 +85,122 @@ typedef enum _BinaryTreeColumn
     BTC_RIGHTS,                             /* Droits d'accès              */
 
     BTC_MATCHED,                            /* Correspondance établie ?    */
-    BTC_PORTION                             /* Elément interne représenté  */
+    BTC_MATCH_POINTS,                       /* Nombre de demandeurs        */
+
+    BTC_COUNT                               /* Nombre de colonnes          */
 
 } BinaryTreeColumn;
 
 
+/* Données utiles à la mise à jour */
+typedef struct _bintree_update_data bintree_update_data;
+
+
 /* Initialise la classe des panneaux d'affichage des portions. */
 static void g_bintree_panel_class_init(GBintreePanelClass *);
 
 /* Initialise une instance de panneau d'affichage des portions. */
 static void g_bintree_panel_init(GBintreePanel *);
 
+/* Procède à l'initialisation de l'interface de mise à jour. */
+static void g_bintree_panel_updatable_interface_init(GUpdatablePanelInterface *);
+
 /* Supprime toutes les références externes. */
 static void g_bintree_panel_dispose(GBintreePanel *);
 
 /* Procède à la libération totale de la mémoire. */
 static void g_bintree_panel_finalize(GBintreePanel *);
 
+/* Modifie la profondeur affichée des portions présentes. */
+static void on_depth_spin_value_changed(GtkSpinButton *, const GBintreePanel *);
+
+/* Réagit au changement de sélection des portions. */
+static void on_bintree_selection_changed(GtkTreeSelection *, gpointer);
+
+/* Réagit à un changement d'affichage principal de contenu. */
+static void change_bintree_panel_current_binary(GBintreePanel *, GLoadedBinary *);
+
+
+
+/* -------------------------- AFFICHAGE SOUS FORME D'ARBRE -------------------------- */
+
+
 /* Parcourt un ensemble de portions. */
-static bool populate_tree_with_portion(GBinPortion *, GBinPortion *, BinaryPortionVisit, GBintreePanel *);
+static bool populate_tree_with_portion(GBinPortion *, GBinPortion *, BinaryPortionVisit, bintree_update_data *);
 
 /* Réagit à un changement d'affichage principal de contenu. */
-static void update_panel_with_binary_portions(GBintreePanel *, GLoadedBinary *);
+static void reload_portions_for_new_tree_view(const GBintreePanel *, GtkStatusStack *, activity_id_t, bintree_update_data *);
+
+/* Met en surbrillance les éléments recherchés dans les noms. */
+static void update_bintree_column_in_tree_view(GtkTreeStore *, GtkTreeIter *, GBinPortion *, gint, const regmatch_t *);
+
+
+
+/* ------------------------- FILTRAGE DES SYMBOLES PRESENTS ------------------------- */
 
-/* Modifie la profondeur affichée des portions présentes. */
-static void on_depth_spin_value_changed(GtkSpinButton *, GtkTreeView *);
 
 /* Prend note du changement de filtre sur les portions. */
 static void on_search_entry_changed(GtkSearchEntry *, GBintreePanel *);
 
-/* Parcourt un arbre en place et retire les branches filtrées. */
-static void apply_filter_on_portions(GtkTreeStore *);
+/* Détermine si un noeud de l'arborescence doit être filtré. */
+static bool update_bintree_node(const bintree_update_data *, GtkTreeStore *, GtkTreeIter *, GBinPortion *);
+
+/* Exécute un nouveau filtrage des symboles affichés. */
+static void do_filtering_on_portions(const GBintreePanel *, GtkStatusStack *, activity_id_t, bintree_update_data *);
 
-/* Réagit au changement de sélection des portions. */
-static void on_bintree_selection_changed(GtkTreeSelection *, gpointer);
 
 
+/* ---------------------- MECANISMES DE MISE A JOUR DE PANNEAU ---------------------- */
+
+
+/* Données utiles à la mise à jour */
+struct _bintree_update_data
+{
+    size_t count;                           /* Qté d'inscriptions réalisées*/
+
+    regex_t *filter;                        /* Filtre appliqué ou NULL     */
+
+    char **expanded;                        /* Chemins des noeuds ouverts  */
+    size_t ecount;                          /* Nombre de ces chemins       */
+    size_t eallocated;                      /* Espace alloué effectivement */
+
+    const GBintreePanel *panel;             /* Transfert de panneau        */
+    GtkTreeIter *top;                       /* Transfert de racine         */
+
+};
+
+
+#define EXPAND_ALLOC_RANGE 10
+
+
+/* Détermine si une valeur de portion doit être filtrée ou non. */
+static bool is_bintree_column_matching(const bintree_update_data *, GBinPortion *, gint, regmatch_t *);
+
+/* Prépare une opération de mise à jour de panneau. */
+static const char *g_bintree_panel_setup(const GBintreePanel *, unsigned int, size_t *, bintree_update_data **);
+
+/* Bascule l'affichage d'un panneau avant mise à jour. */
+static void g_bintree_panel_introduce(const GBintreePanel *, unsigned int, bintree_update_data *);
+
+/* Réalise une opération de mise à jour de panneau. */
+static void g_bintree_panel_process(const GBintreePanel *, unsigned int, GtkStatusStack *, activity_id_t, bintree_update_data *);
+
+/* Bascule l'affichage d'un panneau après mise à jour. */
+static void g_bintree_panel_conclude(GBintreePanel *, unsigned int, bintree_update_data *);
+
+/* Supprime les données dynamiques utilisées à la mise à jour. */
+static void g_bintree_panel_clean_data(GUpdatablePanel *, unsigned int, bintree_update_data *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                            PARTIE PRINCIPALE DU PANNEAU                            */
+/* ---------------------------------------------------------------------------------- */
+
 
 /* Indique le type défini pour un panneau d'affichage des portions. */
-G_DEFINE_TYPE(GBintreePanel, g_bintree_panel, G_TYPE_PANEL_ITEM);
+G_DEFINE_TYPE_WITH_CODE(GBintreePanel, g_bintree_panel, G_TYPE_PANEL_ITEM,
+                        G_IMPLEMENT_INTERFACE(G_TYPE_UPDATABLE_PANEL, g_bintree_panel_updatable_interface_init));
 
 
 /******************************************************************************
@@ -137,6 +219,7 @@ static void g_bintree_panel_class_init(GBintreePanelClass *klass)
 {
     GObjectClass *object;                   /* Autre version de la classe  */
     GEditorItemClass *editem;               /* Encore une autre vision...  */
+    GPanelItemClass *panel;                 /* Version parente de la classe*/
 
     object = G_OBJECT_CLASS(klass);
 
@@ -145,7 +228,11 @@ static void g_bintree_panel_class_init(GBintreePanelClass *klass)
 
     editem = G_EDITOR_ITEM_CLASS(klass);
 
-    editem->update_binary = (update_item_binary_fc)update_panel_with_binary_portions;
+    editem->update_binary = (update_item_binary_fc)change_bintree_panel_current_binary;
+
+    panel = G_PANEL_ITEM_CLASS(klass);
+
+    panel->gid = setup_tiny_global_work_group(1);
 
 }
 
@@ -187,7 +274,6 @@ static void g_bintree_panel_init(GBintreePanel *panel)
     /* Compléments propres */
 
     panel->binary = NULL;
-    panel->filter = NULL;
 
     panel->last = UAT_EXPAND;
 
@@ -251,6 +337,30 @@ static void g_bintree_panel_init(GBintreePanel *panel)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : iface = interface GLib à initialiser.                        *
+*                                                                             *
+*  Description : Procède à l'initialisation de l'interface de mise à jour.    *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_bintree_panel_updatable_interface_init(GUpdatablePanelInterface *iface)
+{
+    iface->setup = (setup_updatable_cb)g_bintree_panel_setup;
+    iface->get_group = (get_updatable_group_cb)g_panel_item_get_group;
+    iface->introduce = (introduce_updatable_cb)g_bintree_panel_introduce;
+    iface->process = (process_updatable_cb)g_bintree_panel_process;
+    iface->conclude = (conclude_updatable_cb)g_bintree_panel_conclude;
+    iface->clean = (clean_updatable_data_cb)g_bintree_panel_clean_data;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : panel = instance d'objet GLib à traiter.                     *
 *                                                                             *
 *  Description : Supprime toutes les références externes.                     *
@@ -285,12 +395,6 @@ static void g_bintree_panel_dispose(GBintreePanel *panel)
 
 static void g_bintree_panel_finalize(GBintreePanel *panel)
 {
-    if (panel->filter != NULL)
-    {
-        regfree(panel->filter);
-        free(panel->filter);
-    }
-
     G_OBJECT_CLASS(g_bintree_panel_parent_class)->finalize(G_OBJECT(panel));
 
 }
@@ -321,122 +425,216 @@ GPanelItem *g_bintree_panel_new(void)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : panel  = portion de binaire à traiter.                       *
-*                parent = portion parent de la portion visitée.               *
-*                visit  = indication sur le sens de la visite.                *
-*                panel  = lien vers toutes les autres informations utiles.    *
+*  Paramètres  : button   = bouton de réglage de l'affichage.                 *
+*                treeview = arborescence dont l'affichage est à moduler.      *
 *                                                                             *
-*  Description : Parcourt un ensemble de portions.                            *
+*  Description : Modifie la profondeur affichée des portions présentes.       *
 *                                                                             *
-*  Retour      : true pour continuer la visite.                               *
+*  Retour      : -                                                            *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static bool populate_tree_with_portion(GBinPortion *portion, GBinPortion *parent, BinaryPortionVisit visit, GBintreePanel *panel)
+static void on_depth_spin_value_changed(GtkSpinButton *button, const GBintreePanel *panel)
 {
-    const char *desc;                       /* Description d'origine       */
-    bool fmatched;                          /* Correspondance rencontrée ? */
-    regmatch_t match;                       /* Position d'un filtre        */
-    char *node_caption;                     /* Etiquette de nouveau noeud  */
-    const mrange_t *range;                  /* Espace de portion à traiter */
-    VMPA_BUFFER(offset);                    /* Décalage physique           */
-    char *node_start;                       /* Position pour nouveau noeud */
-    vmpa2t end;                             /* Zone de construction temp.  */
-    char *node_end;                         /* Bordure pour nouveau noeud  */
-    PortionAccessRights rights;             /* Droits d'accès à analyser   */
-    char hrights[4];                        /* Version humainement lisible */
-    char *node_rights;                      /* Droits pour nouveau noeud   */
-    cairo_surface_t *icon;                  /* Miniature de décoration     */
+    gint max_depth;                         /* Profondeur maximale         */
     GtkBuilder *builder;                    /* Constructeur utilisé        */
+    GtkTreeView *treeview;                  /* Arborescence constituée     */
     GtkTreeStore *store;                    /* Modèle de gestion           */
-    GtkTreeIter iter;                       /* Point d'insertion           */
-    GtkTreeIter *save;                      /* Sauvegarde d'une position   */
 
-    if (parent == NULL)
-        return true;
+    max_depth = gtk_spin_button_get_value_as_int(button);
 
-    /* Insertion de la portion courante */
+    gboolean apply_max_depth(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer unused)
+    {
+        gint depth;                         /* Profondeur du point courant */
 
-    if (visit == BPV_ENTER || visit == BPV_SHOW)
+        depth = gtk_tree_store_iter_depth(GTK_TREE_STORE(model), iter);
+
+        if (depth < max_depth)
+            gtk_tree_view_expand_to_path(treeview, path);
+
+        return FALSE;
+
+    }
+
+    builder = G_PANEL_ITEM(panel)->builder;
+
+    treeview = GTK_TREE_VIEW(gtk_builder_get_object(builder, "treeview"));
+
+    gtk_tree_view_collapse_all(treeview);
+
+    store = GTK_TREE_STORE(gtk_builder_get_object(builder, "store"));
+
+    gtk_tree_model_foreach(GTK_TREE_MODEL(store), (GtkTreeModelForeachFunc)apply_max_depth, NULL);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : selection = sélection modifiée.                              *
+*                unused    = adresse non utilisée ici.                        *
+*                                                                             *
+*  Description : Réagit au changement de sélection des portions.              *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void on_bintree_selection_changed(GtkTreeSelection *selection, gpointer unused)
+{
+    GtkTreeIter iter;                       /* Point de sélection          */
+    GtkTreeModel *model;                    /* Modèle de gestion           */
+    GBinPortion *portion;                   /* Portion à traiter           */
+    const mrange_t *range;                  /* Couverture dudit symbole    */
+    GLoadedPanel *panel;                    /* Afficheur effectif de code  */
+
+    if (gtk_tree_selection_get_selected(selection, &model, &iter))
     {
-        /* Etiquette */
+        gtk_tree_model_get(model, &iter, BTC_PORTION, &portion, -1);
+
+        if (portion != NULL)
+        {
+            range = g_binary_portion_get_range(portion);
+
+            panel = get_current_view();
+
+            if (GTK_IS_DISPLAY_PANEL(panel))
+                gtk_display_panel_request_move(GTK_DISPLAY_PANEL(panel), get_mrange_addr(range));
+
+            g_object_unref(G_OBJECT(panel));
+
+            g_object_unref(G_OBJECT(portion));
+
+        }
+
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : panel  = panneau à mettre à jour.                            *
+*                binary = nouvelle instance de binaire analysé.               *
+*                                                                             *
+*  Description : Réagit à un changement d'affichage principal de contenu.     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void change_bintree_panel_current_binary(GBintreePanel *panel, GLoadedBinary *binary)
+{
+    GtkBuilder *builder;                    /* Constructeur utilisé        */
+    GtkTreeStore *store;                    /* Modèle de gestion           */
+
+    /* Basculement du binaire utilisé */
+
+    if (panel->binary != NULL)
+        g_object_unref(G_OBJECT(panel->binary));
+
+    panel->binary = binary;
+
+    if (panel->binary != NULL)
+        g_object_ref(G_OBJECT(panel->binary));
 
-        desc = g_binary_portion_get_desc(portion);
+    /* Réinitialisation */
 
-        fmatched = is_content_matching(panel->filter, desc, &match);
-        node_caption = build_highlighted_name(desc, &match, 0);
+    builder = G_PANEL_ITEM(panel)->builder;
 
-        /* Point de départ */
+    store = GTK_TREE_STORE(gtk_builder_get_object(builder, "store"));
 
-        range = g_binary_portion_get_range(portion);
+    gtk_tree_store_clear(store);
 
-        vmpa2_phys_to_string(get_mrange_addr(range), MDS_UNDEFINED, offset, NULL);
+    /* Si le panneau actif représente un binaire, actualisation de l'affichage */
 
-        fmatched |= is_content_matching(panel->filter, offset, &match);
-        node_start = build_highlighted_name(offset, &match, 0);
+    if (binary != NULL)
+        run_panel_update(G_UPDATABLE_PANEL(panel), PUI_0);
 
-        /* Point d'arrivée */
+}
 
-        compute_mrange_end_addr(range, &end);
 
-        vmpa2_phys_to_string(&end, MDS_UNDEFINED, offset, NULL);
 
-        fmatched |= is_content_matching(panel->filter, offset, &match);
-        node_end = build_highlighted_name(offset, &match, 0);
+/* ---------------------------------------------------------------------------------- */
+/*                            AFFICHAGE SOUS FORME D'ARBRE                            */
+/* ---------------------------------------------------------------------------------- */
 
-        /* Droits nominaux */
 
-        rights = g_binary_portion_get_rights(portion);
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : panel  = portion de binaire à traiter.                       *
+*                parent = portion parent de la portion visitée.               *
+*                visit  = indication sur le sens de la visite.                *
+*                panel  = lien vers toutes les autres informations utiles.    *
+*                                                                             *
+*  Description : Parcourt un ensemble de portions.                            *
+*                                                                             *
+*  Retour      : true pour continuer la visite.                               *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
 
-        hrights[0] = (rights & PAC_READ ? 'r' : '-');
-        hrights[1] = (rights & PAC_WRITE ? 'w' : '-');
-        hrights[2] = (rights & PAC_EXEC ? 'x' : '-');
-        hrights[3] = '\0';
+static bool populate_tree_with_portion(GBinPortion *portion, GBinPortion *parent, BinaryPortionVisit visit, bintree_update_data *data)
+{
+    const GBintreePanel *panel;             /* Panneau à compléter         */
+    cairo_surface_t *icon;                  /* Miniature de décoration     */
+    GtkBuilder *builder;                    /* Constructeur utilisé        */
+    GtkTreeStore *store;                    /* Modèle de gestion           */
+    GtkTreeIter iter;                       /* Point d'insertion           */
+    GtkTreeIter *save;                      /* Sauvegarde d'une position   */
 
-        fmatched |= is_content_matching(panel->filter, hrights, &match);
-        node_rights = build_highlighted_name(hrights, &match, 0);
+    if (parent == NULL)
+        return true;
+
+    panel = data->panel;
 
-        /* Intégration */
+    /* Insertion de la portion courante */
 
+    if (visit == BPV_ENTER || visit == BPV_SHOW)
+    {
         icon = NULL;
 
         builder = G_PANEL_ITEM(panel)->builder;
 
         store = GTK_TREE_STORE(gtk_builder_get_object(builder, "store"));
 
-        gtk_tree_store_append(store, &iter, panel->top);
+        gtk_tree_store_append(store, &iter, data->top);
 
         gtk_tree_store_set(store, &iter,
-                           BTC_ICON, icon,
-                           BTC_CAPTION, node_caption,
-                           BTC_START, node_start,
-                           BTC_END, node_end,
-                           BTC_RIGHTS, node_rights,
-                           BTC_MATCHED, fmatched,
                            BTC_PORTION, portion,
+                           BTC_ICON, icon,
+                           BTC_CAPTION, NULL,
+                           BTC_START, NULL,
+                           BTC_END, NULL,
+                           BTC_RIGHTS, NULL,
+                           BTC_MATCHED, false,
+                           BTC_MATCH_POINTS, 0,
                            -1);
 
-        free(node_caption);
-        free(node_start);
-        free(node_end);
-        free(node_rights);
-
         if (icon != NULL)
             cairo_surface_destroy(icon);
 
+        update_bintree_node(data, store, &iter, portion);
+
+
     }
 
     /* Définition de la hiérarchie */
 
     if (visit == BPV_ENTER)
     {
-        save = gtk_tree_iter_copy(panel->top);
+        save = gtk_tree_iter_copy(data->top);
 
         g_object_set_data_full(G_OBJECT(portion), "_save", save, (GDestroyNotify)gtk_tree_iter_free);
 
-        *panel->top = iter;
+        *data->top = iter;
 
     }
 
@@ -444,7 +642,7 @@ static bool populate_tree_with_portion(GBinPortion *portion, GBinPortion *parent
     {
         save = g_object_get_data(G_OBJECT(portion), "_save");
 
-        *panel->top = *save;
+        *data->top = *save;
 
         g_object_set_data(G_OBJECT(portion), "_save", NULL);
 
@@ -458,7 +656,9 @@ static bool populate_tree_with_portion(GBinPortion *portion, GBinPortion *parent
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : panel  = panneau à mettre à jour.                            *
-*                binary = nouvelle instance de binaire analysé.               *
+*                status = barre de statut à tenir informée.                   *
+*                id     = identifiant pour le suivi de la progression.        *
+*                data   = données complémentaire à manipuler.                 *
 *                                                                             *
 *  Description : Réagit à un changement d'affichage principal de contenu.     *
 *                                                                             *
@@ -468,7 +668,7 @@ static bool populate_tree_with_portion(GBinPortion *portion, GBinPortion *parent
 *                                                                             *
 ******************************************************************************/
 
-static void update_panel_with_binary_portions(GBintreePanel *panel, GLoadedBinary *binary)
+static void reload_portions_for_new_tree_view(const GBintreePanel *panel, GtkStatusStack *status, activity_id_t id, bintree_update_data *data)
 {
     GtkBuilder *builder;                    /* Constructeur utilisé        */
     GtkTreeStore *store;                    /* Modèle de gestion           */
@@ -479,44 +679,31 @@ static void update_panel_with_binary_portions(GBintreePanel *panel, GLoadedBinar
     GtkSpinButton *depth_spin;              /* Bouton de variation         */
     GtkTreeView *treeview;                  /* Arborescence constituée     */
 
-    /* Réinitialisation */
-
-    if (panel->binary != NULL)
-        g_object_unref(G_OBJECT(panel->binary));
-
-    panel->binary = binary;
-
     builder = G_PANEL_ITEM(panel)->builder;
 
     store = GTK_TREE_STORE(gtk_builder_get_object(builder, "store"));
 
-    gtk_tree_store_clear(store);
+    /* Constitution de l'arborescence */
 
-    /* Chargement */
+    format = g_loaded_binary_get_format(panel->binary);
 
-    if (binary != NULL)
-    {
-        g_object_ref(G_OBJECT(binary));
-
-        format = g_loaded_binary_get_format(binary);
-
-        portions = g_exe_format_get_portions(format);
+    portions = g_exe_format_get_portions(format);
 
-        gtk_tree_store_append(store, &top, NULL);
+    gtk_tree_store_append(store, &top, NULL);
 
-        gtk_tree_store_set(store, &top,
-                           BTC_ICON, NULL,
-                           BTC_CAPTION, g_loaded_binary_get_name(binary, false),
-                           -1);
+    gtk_tree_store_set(store, &top,
+                       BTC_ICON, NULL,
+                       BTC_CAPTION, g_loaded_binary_get_name(panel->binary, false),
+                       -1);
 
-        panel->top = &top;
-        g_binary_portion_visit(portions, (visit_portion_fc)populate_tree_with_portion, panel);
+    data->panel = panel;
+    data->top = &top;
 
-        g_object_unref(G_OBJECT(portions));
+    g_binary_portion_visit(portions, (visit_portion_fc)populate_tree_with_portion, data);
 
-        g_object_unref(G_OBJECT(format));
+    g_object_unref(G_OBJECT(portions));
 
-    }
+    g_object_unref(G_OBJECT(format));
 
     /* Détermination de la profondeur maximale */
 
@@ -556,23 +743,23 @@ static void update_panel_with_binary_portions(GBintreePanel *panel, GLoadedBinar
             break;
 
         case UAT_DEPTH:
-            on_depth_spin_value_changed(depth_spin, treeview);
+            on_depth_spin_value_changed(depth_spin, panel);
             break;
 
     }
 
-    if (panel->filter != NULL)
-        apply_filter_on_portions(store);
-
 }
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : button   = bouton de réglage de l'affichage.                 *
-*                treeview = arborescence dont l'affichage est à moduler.      *
+*  Paramètres  : store   = gestionnaire de l'ensemble des données.            *
+*                iter    = localisation des données à analyser.               *
+*                portion = portion de binaire concernée par l'analyse.        *
+*                column  = colonne visée par l'analyse.                       *
+*                match  = portion de texte à mettre en évidence.              *
 *                                                                             *
-*  Description : Modifie la profondeur affichée des portions présentes.       *
+*  Description : Met en surbrillance les éléments recherchés dans les noms.   *
 *                                                                             *
 *  Retour      : -                                                            *
 *                                                                             *
@@ -580,35 +767,61 @@ static void update_panel_with_binary_portions(GBintreePanel *panel, GLoadedBinar
 *                                                                             *
 ******************************************************************************/
 
-static void on_depth_spin_value_changed(GtkSpinButton *button, GtkTreeView *treeview)
+static void update_bintree_column_in_tree_view(GtkTreeStore *store, GtkTreeIter *iter, GBinPortion *portion, gint column, const regmatch_t *match)
 {
-    gint max_depth;                         /* Profondeur maximale         */
-    GtkTreeModel *model;                    /* Modèle de gestion           */
-
-    max_depth = gtk_spin_button_get_value_as_int(button);
+    const char *content;                    /* Contenu brut d'origine      */
+    const mrange_t *range;                  /* Espace de portion à traiter */
+    VMPA_BUFFER(offset);                    /* Localisation quelconque     */
+    vmpa2t end;                             /* Zone de construction temp.  */
+    PortionAccessRights rights;             /* Droits d'accès à analyser   */
+    char hrights[4];                        /* Version humainement lisible */
+    char *value;                            /* Etiquette mise en relief    */
 
-    gboolean apply_max_depth(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer unused)
+    switch (column)
     {
-        gint depth;                         /* Profondeur du point courant */
+        case BTC_CAPTION:
+            content = g_binary_portion_get_desc(portion);
+            break;
 
-        depth = gtk_tree_store_iter_depth(GTK_TREE_STORE(model), iter);
+        case BTC_START:
+            range = g_binary_portion_get_range(portion);
+            vmpa2_phys_to_string(get_mrange_addr(range), MDS_UNDEFINED, offset, NULL);
+            content = offset;
+            break;
 
-        if (depth < max_depth)
-            gtk_tree_view_expand_to_path(treeview, path);
+        case BTC_END:
+            range = g_binary_portion_get_range(portion);
+            compute_mrange_end_addr(range, &end);
+            vmpa2_phys_to_string(&end, MDS_UNDEFINED, offset, NULL);
+            content = offset;
+            break;
 
-        return FALSE;
+        case BTC_RIGHTS:
+            rights = g_binary_portion_get_rights(portion);
+            hrights[0] = (rights & PAC_READ ? 'r' : '-');
+            hrights[1] = (rights & PAC_WRITE ? 'w' : '-');
+            hrights[2] = (rights & PAC_EXEC ? 'x' : '-');
+            hrights[3] = '\0';
+            content = hrights;
+            break;
 
     }
 
-    gtk_tree_view_collapse_all(treeview);
+    value = build_highlighted_name(content, match, 0);
 
-    model = gtk_tree_view_get_model(treeview);
+    gtk_tree_store_set(store, iter, column, value, -1);
 
-    gtk_tree_model_foreach(model, (GtkTreeModelForeachFunc)apply_max_depth, NULL);
+    free(value);
 
 }
 
 
+
+/* ---------------------------------------------------------------------------------- */
+/*                           FILTRAGE DES SYMBOLES PRESENTS                           */
+/* ---------------------------------------------------------------------------------- */
+
+
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : entry = zone de texte avec un nouveau filtre d'affichage.    *
@@ -624,71 +837,74 @@ static void on_depth_spin_value_changed(GtkSpinButton *button, GtkTreeView *tree
 
 static void on_search_entry_changed(GtkSearchEntry *entry, GBintreePanel *panel)
 {
-    update_regex_on_search_entry_changed(entry, &panel->filter);
+    update_regex_on_search_entry_changed(entry, &G_PANEL_ITEM(panel)->filter);
 
-    if (panel->binary != NULL)
-    {
-        g_object_ref(G_OBJECT(panel->binary));
-        update_panel_with_binary_portions(panel, panel->binary);
-        g_object_unref(G_OBJECT(panel->binary));
-    }
+    run_panel_update(G_UPDATABLE_PANEL(panel), PUI_1);
 
 }
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : store = gestionnaire de contenu d'une arborescence donnée.   *
+*  Paramètres  : data    = données complémentaire à manipuler.                *
+*                store   = gestionnaire de l'ensemble des données.            *
+*                iter    = localisation des données à analyser.               *
+*                portion = portion binaire présente à la position courante.   *
 *                                                                             *
-*  Description : Parcourt un arbre en place et retire les branches filtrées.  *
+*  Description : Détermine si un noeud de l'arborescence doit être filtré.    *
 *                                                                             *
-*  Retour      : -                                                            *
+*  Retour      : Bilan du filtrage.                                           *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static void apply_filter_on_portions(GtkTreeStore *store)
+static bool update_bintree_node(const bintree_update_data *data, GtkTreeStore *store, GtkTreeIter *iter, GBinPortion *portion)
 {
-    GtkTreeIter root;                       /* Racine de l'arboresence     */
+    bool result;                            /* Bilan à retourner           */
+    regmatch_t match;                       /* Récupération des trouvailles*/
+    bool caption_matched;                   /* Correspondance de sélection */
+    bool start_matched;                     /* Correspondance de sélection */
+    bool end_matched;                       /* Correspondance de sélection */
+    bool rights_matched;                    /* Correspondance de sélection */
 
-    void check_portion_iter(GtkTreeIter *iter)
-    {
-        GtkTreeModel *model;                /* Version alternative         */
-        gint children_count;                /* Nombre d'enfants présents   */
-        gint i;                             /* Boucle de parcours          */
-        GtkTreeIter child;                  /* Pointeur vers la descendance*/
-        gboolean fmatched;                  /* Correspondance immédiate ?  */
+    caption_matched = is_bintree_column_matching(data, portion, BTC_CAPTION, &match);
 
-        model = GTK_TREE_MODEL(store);
+    if (caption_matched)
+        update_bintree_column_in_tree_view(store, iter, portion, BTC_CAPTION, &match);
 
-        children_count = gtk_tree_model_iter_n_children(model, iter);
+    start_matched = is_bintree_column_matching(data, portion, BTC_START, &match);
 
-        for (i = children_count; i > 0; i--)
-            if (gtk_tree_model_iter_nth_child(model, &child, iter, i - 1))
-                check_portion_iter(&child);
+    if (start_matched)
+        update_bintree_column_in_tree_view(store, iter, portion, BTC_START, &match);
 
-        children_count = gtk_tree_model_iter_n_children(model, iter);
+    end_matched = is_bintree_column_matching(data, portion, BTC_END, &match);
 
-        gtk_tree_model_get(model, iter, BTC_MATCHED, &fmatched, -1);
+    if (end_matched)
+        update_bintree_column_in_tree_view(store, iter, portion, BTC_END, &match);
 
-        if (!fmatched && children_count == 0)
-            gtk_tree_store_remove(store, iter);
+    rights_matched = is_bintree_column_matching(data, portion, BTC_RIGHTS, &match);
 
-    }
+    if (rights_matched)
+        update_bintree_column_in_tree_view(store, iter, portion, BTC_RIGHTS, &match);
 
-    if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &root))
-        check_portion_iter(&root);
+    result = (caption_matched || start_matched || end_matched || rights_matched);
+
+    gtk_tree_store_set(store, iter, BTC_MATCHED, result, -1);
+
+    return result;
 
 }
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : selection = sélection modifiée.                              *
-*                unused    = adresse non utilisée ici.                        *
+*  Paramètres  : panel  = panneau assurant l'affichage des symboles.          *
+*                status = barre de statut à tenir informée.                   *
+*                id     = identifiant pour le suivi de la progression.        *
+*                data   = données complémentaire à manipuler.                 *
 *                                                                             *
-*  Description : Réagit au changement de sélection des portions.              *
+*  Description : Exécute un nouveau filtrage des symboles affichés.           *
 *                                                                             *
 *  Retour      : -                                                            *
 *                                                                             *
@@ -696,33 +912,377 @@ static void apply_filter_on_portions(GtkTreeStore *store)
 *                                                                             *
 ******************************************************************************/
 
-static void on_bintree_selection_changed(GtkTreeSelection *selection, gpointer unused)
+static void do_filtering_on_portions(const GBintreePanel *panel, GtkStatusStack *status, activity_id_t id, bintree_update_data *data)
 {
-    GtkTreeIter iter;                       /* Point de sélection          */
-    GtkTreeModel *model;                    /* Modèle de gestion           */
-    GBinPortion *portion;                   /* Portion à traiter           */
-    const mrange_t *range;                  /* Couverture dudit symbole    */
-    GLoadedPanel *panel;                    /* Afficheur effectif de code  */
+    GtkBuilder *builder;                    /* Constructeur utilisé        */
+    GtkTreeStore *store;                    /* Modèle de gestion           */
 
-    if (gtk_tree_selection_get_selected(selection, &model, &iter))
+
+    gboolean filter_portion_panel_iter(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer unused)
     {
-        gtk_tree_model_get(model, &iter, BTC_PORTION, &portion, -1);
+        GBinPortion *portion;               /* Portion à traiter           */
+        bool matched;                       /* Correspondance de sélection */
+        gboolean shown;                     /* Visibilité actuelle         */
+
+        gtk_tree_model_get(model, iter, BTC_PORTION, &portion, -1);
 
         if (portion != NULL)
         {
-            range = g_binary_portion_get_range(portion);
+            matched = update_bintree_node(data, store, iter, portion);
 
-            panel = get_current_view();
+            gtk_tree_model_get(model, iter, BTC_MATCHED, &shown, -1);
 
-            if (GTK_IS_DISPLAY_PANEL(panel))
-                gtk_display_panel_request_move(GTK_DISPLAY_PANEL(panel), get_mrange_addr(range));
+            if (!matched)
+            {
+                if (shown)
+                    update_node_visibility(store, iter, BTC_MATCHED, false);
+            }
 
-            g_object_unref(G_OBJECT(panel));
+            else
+            {
+                if (!shown)
+                    update_node_visibility(store, iter, BTC_MATCHED, true);
+            }
 
             g_object_unref(G_OBJECT(portion));
 
+            gtk_status_stack_update_activity_value(status, id, 1);
+
+        }
+
+        return FALSE;
+
+    }
+
+
+    builder = G_PANEL_ITEM(panel)->builder;
+
+    store = GTK_TREE_STORE(gtk_builder_get_object(builder, "store"));
+
+    gtk_tree_model_foreach(GTK_TREE_MODEL(store), (GtkTreeModelForeachFunc)filter_portion_panel_iter, NULL);
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                        MECANISMES DE MISE A JOUR DE PANNEAU                        */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : data    = données complémentaire à manipuler.                *
+*                portion = portion de binaire concernée par l'analyse.        *
+*                column  = colonne visée par l'analyse.                       *
+*                match   = récupération des trouvailles. [OUT]                *
+*                                                                             *
+*  Description : Détermine si une valeur de portion doit être filtrée ou non. *
+*                                                                             *
+*  Retour      : true si le symbol ne doit pas être affiché, false sinon.     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool is_bintree_column_matching(const bintree_update_data *data, GBinPortion *portion, gint column, regmatch_t *match)
+{
+    bool result;                            /* Bilan à retourner           */
+    const char *content;                    /* Contenu à analyser          */
+    const mrange_t *range;                  /* Espace de portion à traiter */
+    VMPA_BUFFER(offset);                    /* Localisation quelconque     */
+    vmpa2t end;                             /* Zone de construction temp.  */
+    PortionAccessRights rights;             /* Droits d'accès à analyser   */
+    char hrights[4];                        /* Version humainement lisible */
+
+    switch (column)
+    {
+        case BTC_CAPTION:
+            content = g_binary_portion_get_desc(portion);
+            break;
+
+        case BTC_START:
+            range = g_binary_portion_get_range(portion);
+            vmpa2_phys_to_string(get_mrange_addr(range), MDS_UNDEFINED, offset, NULL);
+            content = offset;
+            break;
+
+        case BTC_END:
+            range = g_binary_portion_get_range(portion);
+            compute_mrange_end_addr(range, &end);
+            vmpa2_phys_to_string(&end, MDS_UNDEFINED, offset, NULL);
+            content = offset;
+            break;
+
+        case BTC_RIGHTS:
+            rights = g_binary_portion_get_rights(portion);
+            hrights[0] = (rights & PAC_READ ? 'r' : '-');
+            hrights[1] = (rights & PAC_WRITE ? 'w' : '-');
+            hrights[2] = (rights & PAC_EXEC ? 'x' : '-');
+            hrights[3] = '\0';
+            content = hrights;
+            break;
+
+    }
+
+    result = is_content_matching(data->filter, content, match);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : panel = panneau ciblé par une mise à jour.                   *
+*                uid   = identifiant de la phase de traitement.               *
+*                count = nombre d'étapes à prévoir dans le traitement. [OUT]  *
+*                data  = données sur lesquelles s'appuyer ensuite. [OUT]      *
+*                                                                             *
+*  Description : Prépare une opération de mise à jour de panneau.             *
+*                                                                             *
+*  Retour      : Description du message d'information.                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static const char *g_bintree_panel_setup(const GBintreePanel *panel, unsigned int uid, size_t *count, bintree_update_data **data)
+{
+    const char *result;                     /* Message à retourner         */
+    int ret;                                /* Bilan de mise en place      */
+    GtkBuilder *builder;                    /* Constructeur utilisé        */
+    GtkTreeView *treeview;                  /* Arborescence graphique      */
+
+    *data = malloc(sizeof(bintree_update_data));
+
+    switch (uid)
+    {
+        case PUI_0:
+
+            *count = 1;
+            (*data)->count = 0;
+
+            result = _("Loading portions contained in the binary format...");
+
+            break;
+
+        case PUI_1:
+
+            *count = panel->count;
+            (*data)->count = panel->count;
+
+            result = _("Filtering portions contained in the binary format...");
+
+            break;
+
+        default:    /* Pour GCC... */
+            assert(false);
+            result = "";
+            break;
+
+    }
+
+    if (G_PANEL_ITEM(panel)->filter != NULL)
+    {
+        (*data)->filter = (regex_t *)malloc(sizeof(regex_t));
+
+        ret = regcomp((*data)->filter, G_PANEL_ITEM(panel)->filter, REG_EXTENDED | REG_ICASE);
+        assert(ret == 0);
+
+    }
+
+    else
+        (*data)->filter = NULL;
+
+    /* Mémorisation de tous les noeuds ouverts */
+
+    builder = G_PANEL_ITEM(panel)->builder;
+
+    treeview = GTK_TREE_VIEW(gtk_builder_get_object(builder, "treeview"));
+
+    void keep_track_of_expanded(GtkTreeView *tv, GtkTreePath *path, bintree_update_data *sud)
+    {
+        if (sud->ecount == sud->eallocated)
+        {
+            sud->eallocated += EXPAND_ALLOC_RANGE;
+            sud->expanded = (char **)realloc(sud->expanded, sud->eallocated * sizeof(char *));
         }
 
+        sud->expanded[sud->ecount] = gtk_tree_path_to_string(path);
+
+        sud->ecount++;
+
+    }
+
+    (*data)->expanded = NULL;
+    (*data)->ecount = 0;
+    (*data)->eallocated = 0;
+
+    gtk_tree_view_map_expanded_rows(treeview, (GtkTreeViewMappingFunc)keep_track_of_expanded, *data);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : panel = panneau ciblé par une mise à jour.                   *
+*                uid   = identifiant de la phase de traitement.               *
+*                data  = données préparées par l'appelant.                    *
+*                                                                             *
+*  Description : Bascule l'affichage d'un panneau avant mise à jour.          *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : Cette fonction est appelée depuis le contexte principal.     *
+*                                                                             *
+******************************************************************************/
+
+static void g_bintree_panel_introduce(const GBintreePanel *panel, unsigned int uid, bintree_update_data *data)
+{
+    GtkBuilder *builder;                    /* Constructeur utilisé        */
+    GtkTreeView *treeview;                  /* Arborescence graphique      */
+    GtkTreeModel *model;                    /* Source de données associée  */
+
+    /* Basculement de l'affichage hors ligne */
+
+    g_panel_item_switch_to_updating_mask(G_PANEL_ITEM(panel));
+
+    builder = G_PANEL_ITEM(panel)->builder;
+
+    treeview = GTK_TREE_VIEW(gtk_builder_get_object(builder, "treeview"));
+
+    model = gtk_tree_view_get_model(treeview);
+
+    if (model != NULL)
+    {
+        g_object_ref(G_OBJECT(model));
+        gtk_tree_view_set_model(treeview, NULL);
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : panel  = panneau ciblé par une mise à jour.                  *
+*                uid    = identifiant de la phase de traitement.              *
+*                status = barre de statut à tenir informée.                   *
+*                id     = identifiant pour le suivi de la progression.        *
+*                data   = données préparées par l'appelant.                   *
+*                                                                             *
+*  Description : Réalise une opération de mise à jour de panneau.             *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_bintree_panel_process(const GBintreePanel *panel, unsigned int uid, GtkStatusStack *status, activity_id_t id, bintree_update_data *data)
+{
+    switch (uid)
+    {
+        case PUI_0:
+            reload_portions_for_new_tree_view(panel, status, id, data);
+            break;
+
+        case PUI_1:
+            do_filtering_on_portions(panel, status, id, data);
+            break;
+
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : panel = panneau ciblé par une mise à jour.                   *
+*                uid   = identifiant de la phase de traitement.               *
+*                data  = données préparées par l'appelant.                    *
+*                                                                             *
+*  Description : Bascule l'affichage d'un panneau après mise à jour.          *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : Cette fonction est appelée depuis le contexte principal.     *
+*                                                                             *
+******************************************************************************/
+
+static void g_bintree_panel_conclude(GBintreePanel *panel, unsigned int uid, bintree_update_data *data)
+{
+    GtkBuilder *builder;                    /* Constructeur utilisé        */
+    GtkTreeView *treeview;                  /* Arborescence graphique      */
+    GtkTreeModel *model;                    /* Source de données associée  */
+    size_t i;                               /* Boucle de parcours          */
+    GtkTreePath *path;                      /* Chemin d'accès à un noeud   */
+
+    if (g_atomic_int_get(&G_PANEL_ITEM(panel)->switched) > 1)
+        goto skip_this_step;
+
+    /* Mise à jour des compteurs */
+
+    panel->count = data->count;
+
+    /* Basculement de l'affichage en ligne */
+
+    builder = G_PANEL_ITEM(panel)->builder;
+
+    treeview = GTK_TREE_VIEW(gtk_builder_get_object(builder, "treeview"));
+
+    model = GTK_TREE_MODEL(gtk_builder_get_object(builder, "filter"));
+
+    g_object_ref(G_OBJECT(model));
+    gtk_tree_view_set_model(treeview, model);
+
+    for (i = 0; i < data->ecount; i++)
+    {
+        path = gtk_tree_path_new_from_string(data->expanded[i]);
+
+        gtk_tree_view_expand_to_path(treeview, path);
+
+        gtk_tree_path_free(path);
+
     }
 
+ skip_this_step:
+
+    g_panel_item_switch_to_updated_content(G_PANEL_ITEM(panel));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : panel = panneau ciblé par une mise à jour.                   *
+*                uid   = identifiant de la phase de traitement.               *
+*                data  = données en place à nettoyer avant suppression.       *
+*                                                                             *
+*  Description : Supprime les données dynamiques utilisées à la mise à jour.  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_bintree_panel_clean_data(GUpdatablePanel *panel, unsigned int uid, bintree_update_data *data)
+{
+    size_t i;                               /* Boucle de parcours          */
+
+    if (data->filter != NULL)
+    {
+        regfree(data->filter);
+        free(data->filter);
+    }
+
+    for (i = 0; i < data->ecount; i++)
+        g_free(data->expanded[i]);
+
+    if (data->expanded != NULL)
+        free(data->expanded);
+
 }
diff --git a/src/gui/panels/bintree.ui b/src/gui/panels/bintree.ui
index aa5a112..90aac50 100644
--- a/src/gui/panels/bintree.ui
+++ b/src/gui/panels/bintree.ui
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.20.0 -->
+<!-- Generated with glade 3.21.0 -->
 <interface>
   <requires lib="gtk+" version="3.12"/>
   <object class="GtkAdjustment" id="adjustment1">
@@ -19,9 +19,11 @@
   </object>
   <object class="GtkTreeStore" id="store">
     <columns>
+      <!-- column-name portion -->
+      <column type="GObject"/>
       <!-- column-name icon -->
       <column type="CairoSurface"/>
-      <!-- column-name name -->
+      <!-- column-name caption -->
       <column type="gchararray"/>
       <!-- column-name start -->
       <column type="gchararray"/>
@@ -31,10 +33,13 @@
       <column type="gchararray"/>
       <!-- column-name matched -->
       <column type="gboolean"/>
-      <!-- column-name portion -->
-      <column type="GObject"/>
+      <!-- column-name match_points -->
+      <column type="guint"/>
     </columns>
   </object>
+  <object class="GtkTreeModelFilter" id="filter">
+    <property name="child_model">store</property>
+  </object>
   <object class="GtkOffscreenWindow" id="offscreenwindow1">
     <property name="can_focus">False</property>
     <property name="margin_left">8</property>
@@ -120,7 +125,7 @@
                     <property name="progress_pulse_step">1</property>
                     <property name="adjustment">adjustment1</property>
                     <property name="numeric">True</property>
-                    <signal name="value-changed" handler="on_depth_spin_value_changed" object="treeview" swapped="no"/>
+                    <signal name="value-changed" handler="on_depth_spin_value_changed" swapped="no"/>
                   </object>
                 </child>
               </object>
@@ -168,22 +173,45 @@
           </packing>
         </child>
         <child>
-          <object class="GtkScrolledWindow" id="scrolledwindow1">
+          <object class="GtkStack" id="stack">
             <property name="visible">True</property>
-            <property name="can_focus">True</property>
-            <property name="shadow_type">in</property>
+            <property name="can_focus">False</property>
             <child>
-              <object class="GtkTreeView" id="treeview">
+              <object class="GtkScrolledWindow" id="content">
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
-                <property name="model">store</property>
-                <property name="headers_visible">False</property>
-                <child internal-child="selection">
-                  <object class="GtkTreeSelection" id="treeview-selection1">
-                    <signal name="changed" handler="on_bintree_selection_changed" swapped="no"/>
+                <property name="shadow_type">in</property>
+                <child>
+                  <object class="GtkTreeView" id="treeview">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="model">filter</property>
+                    <property name="headers_visible">False</property>
+                    <property name="search_column">1</property>
+                    <child internal-child="selection">
+                      <object class="GtkTreeSelection">
+                        <signal name="changed" handler="on_bintree_selection_changed" swapped="no"/>
+                      </object>
+                    </child>
                   </object>
                 </child>
               </object>
+              <packing>
+                <property name="name">page0</property>
+                <property name="title" translatable="yes">page0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkSpinner" id="mask">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="active">True</property>
+              </object>
+              <packing>
+                <property name="name">page1</property>
+                <property name="title" translatable="yes">page1</property>
+                <property name="position">1</property>
+              </packing>
             </child>
           </object>
           <packing>
@@ -194,5 +222,8 @@
         </child>
       </object>
     </child>
+    <child type="titlebar">
+      <placeholder/>
+    </child>
   </object>
 </interface>
diff --git a/src/gui/panels/bookmarks.c b/src/gui/panels/bookmarks.c
index b7d0bc3..104e519 100644
--- a/src/gui/panels/bookmarks.c
+++ b/src/gui/panels/bookmarks.c
@@ -41,6 +41,7 @@
 #include "../../common/cpp.h"
 #include "../../common/extstr.h"
 #include "../../core/params.h"
+#include "../../core/queue.h"
 #include "../../glibext/chrysamarshal.h"
 #include "../../glibext/signal.h"
 #include "../../gtkext/easygtk.h"
@@ -99,9 +100,6 @@ static void g_bookmarks_panel_class_init(GBookmarksPanelClass *);
 /* Initialise une instance de panneau de paramètres de config. */
 static void g_bookmarks_panel_init(GBookmarksPanel *);
 
-/* Procède à l'initialisation de l'interface de rassemblement. */
-static void g_bookmarks_panel_dockable_interface_init(GtkDockableInterface *);
-
 /* Supprime toutes les références externes. */
 static void g_bookmarks_panel_dispose(GBookmarksPanel *);
 
@@ -145,7 +143,7 @@ static void on_param_value_edited(GtkCellRendererText *, gchar *, gchar *, GtkTr
 
 
 /* Démarre l'actualisation du filtrage des paramètres. */
-static void update_filtered_bookmarks(GBookmarksPanel *, const regex_t *);
+static void update_filtered_bookmarks(GBookmarksPanel *);
 
 /* Détermine si un signet doit être filtré ou non. */
 static bool is_bookmark_filtered(GBookmarksPanel *, const char *, const char *, const char *);
@@ -181,8 +179,7 @@ static void mcb_bookmarks_panel_filter(GtkMenuItem *, GBookmarksPanel *);
 
 
 /* Indique le type définit pour un panneau d'affichage des signets liés à un binaire. */
-G_DEFINE_TYPE_WITH_CODE(GBookmarksPanel, g_bookmarks_panel, G_TYPE_PANEL_ITEM,
-                        G_IMPLEMENT_INTERFACE(GTK_TYPE_DOCKABLE, g_bookmarks_panel_dockable_interface_init));
+G_DEFINE_TYPE(GBookmarksPanel, g_bookmarks_panel, G_TYPE_PANEL_ITEM);
 
 
 /******************************************************************************
@@ -201,6 +198,7 @@ static void g_bookmarks_panel_class_init(GBookmarksPanelClass *klass)
 {
     GObjectClass *object;                   /* Autre version de la classe  */
     GEditorItemClass *editem;               /* Encore une autre vision...  */
+    GPanelItemClass *panel;                 /* Version parente de la classe*/
     gchar *filename;                        /* Chemin d'accès à utiliser   */
 
     object = G_OBJECT_CLASS(klass);
@@ -212,6 +210,15 @@ static void g_bookmarks_panel_class_init(GBookmarksPanelClass *klass)
 
     editem->update_binary = (update_item_binary_fc)reload_bookmarks_into_treeview;
 
+    panel = G_PANEL_ITEM_CLASS(klass);
+
+    panel->can_search = true;
+    panel->can_be_closed = true;
+
+    panel->update_filtered = (update_filtered_fc)update_filtered_bookmarks;
+
+    panel->gid = setup_tiny_global_work_group(1);
+
     filename = find_pixmap_file("bookmark.png");
     assert(filename != NULL);
 
@@ -349,35 +356,6 @@ static void g_bookmarks_panel_init(GBookmarksPanel *panel)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : iface = interface GTK à initialiser.                         *
-*                                                                             *
-*  Description : Procède à l'initialisation de l'interface de rassemblement.  *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void g_bookmarks_panel_dockable_interface_init(GtkDockableInterface *iface)
-{
-    GtkDockableInterface *parent_iface;     /* Définition précédente       */
-
-    parent_iface = (GtkDockableInterface *)g_type_interface_peek_parent(iface);
-
-    iface->can_search = true;
-    iface->can_be_closed = true;
-
-    iface->get_name = parent_iface->get_name;
-    iface->get_desc = parent_iface->get_desc;
-    iface->get_widget = parent_iface->get_widget;
-    iface->update_filtered = (update_filtered_data_fc)update_filtered_bookmarks;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
 *  Paramètres  : panel = instance d'objet GLib à traiter.                     *
 *                                                                             *
 *  Description : Supprime toutes les références externes.                     *
@@ -966,7 +944,6 @@ static void on_param_value_edited(GtkCellRendererText *renderer, gchar *path, gc
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : panel = panneau assurant l'affichage des paramètres.         *
-*                preg  = expression régulière compilée à utiliser.            *
 *                                                                             *
 *  Description : Démarre l'actualisation du filtrage des paramètres.          *
 *                                                                             *
@@ -976,11 +953,9 @@ static void on_param_value_edited(GtkCellRendererText *renderer, gchar *path, gc
 *                                                                             *
 ******************************************************************************/
 
-static void update_filtered_bookmarks(GBookmarksPanel *panel, const regex_t *preg)
+static void update_filtered_bookmarks(GBookmarksPanel *panel)
 {
-    panel->filter = preg;
-
-    reload_bookmarks_into_treeview(panel, panel->binary);
+    //reload_bookmarks_into_treeview(panel, panel->binary);
 
 }
 
diff --git a/src/gui/panels/gresource.xml b/src/gui/panels/gresource.xml
index 214e546..b6f6cf9 100644
--- a/src/gui/panels/gresource.xml
+++ b/src/gui/panels/gresource.xml
@@ -8,6 +8,7 @@
         <file compressed="true">../../../pixmaps/symbol_class_classic.png</file>
         <file compressed="true">bintree.ui</file>
         <file compressed="true">errors.ui</file>
+        <file compressed="true">strings.ui</file>
         <file compressed="true">symbols.ui</file>
         <file compressed="true">welcome.ui</file>
     </gresource>
diff --git a/src/gui/panels/panel-int.h b/src/gui/panels/panel-int.h
index 8f5f42f..3f5213d 100644
--- a/src/gui/panels/panel-int.h
+++ b/src/gui/panels/panel-int.h
@@ -41,10 +41,13 @@
 
 
 /* Place un panneau dans l'ensemble affiché. */
-typedef void (* ack_dock_process_fc) (GPanelItem *item);
+typedef void (* ack_dock_process_fc) (GPanelItem *);
 
 /* Supprime un panneau de l'ensemble affiché. */
-typedef void (* ack_undock_process_fc) (GPanelItem *item);
+typedef void (* ack_undock_process_fc) (GPanelItem *);
+
+/* Démarre l'actualisation du filtrage du contenu. */
+typedef void (* update_filtered_fc) (GPanelItem *);
 
 
 /* Elément réactif pour panneaux de l'éditeur (instance) */
@@ -63,6 +66,8 @@ struct _GPanelItem
 
     bool docked;                            /* Panneau inscrusté ?         */
 
+    char *filter;                           /* Eventuel filtre textuel     */
+
     /**
      * La gestion générique du constructeur repose sur quelques
      * prérequis quant à l'enregistrement de composants :
@@ -92,9 +97,14 @@ struct _GPanelItemClass
     bool unique;                            /* Panneau instanciable ?      */
     const char *bindings;                   /* Raccourci clavier éventuel  */
 
+    bool can_search;                        /* Contenu fouillable ?        */
+    bool can_be_closed;                     /* Fermeture possible ?        */
+
     ack_dock_process_fc ack_dock;           /* Prise en compte d'accroche  */
     ack_undock_process_fc ack_undock;       /* Prise en compte de décroche */
 
+    update_filtered_fc update_filtered;     /* Lancement du filtrage       */
+
     wgroup_id_t gid;                        /* Groupe de travail dédié     */
 
     /* Signaux */
diff --git a/src/gui/panels/panel.c b/src/gui/panels/panel.c
index 424e779..78f70f3 100644
--- a/src/gui/panels/panel.c
+++ b/src/gui/panels/panel.c
@@ -54,6 +54,12 @@ static void g_panel_item_dispose(GPanelItem *);
 /* Procède à la libération totale de la mémoire. */
 static void g_panel_item_finalize(GPanelItem *);
 
+/* Détermine si un panneau peut être filtré. */
+static bool gtk_panel_item_can_search(const GPanelItem *);
+
+/* Détermine si un panneau peut être fermé. */
+static bool gtk_panel_item_can_be_closed(const GPanelItem *);
+
 /* Fournit le nom court du composant encapsulable. */
 static const char *gtk_panel_item_get_name(const GPanelItem *);
 
@@ -63,6 +69,9 @@ static const char *gtk_panel_item_get_desc(const GPanelItem *);
 /* Fournit le composant graphique intégrable dans un ensemble. */
 static GtkWidget *gtk_panel_item_get_widget(GPanelItem *);
 
+/* Démarre l'actualisation du filtrage du contenu. */
+static void gtk_panel_item_update_filtered(GPanelItem *, char *);
+
 /* Construit la chaîne d'accès à un élément de configuration. */
 static char *gtk_panel_item_build_configuration_key(const GPanelItem *, const char *);
 
@@ -123,6 +132,9 @@ static void g_panel_item_class_init(GPanelItemClass *klass)
                  g_cclosure_marshal_VOID__VOID,
                  G_TYPE_NONE, 0);
 
+    klass->can_search = false;
+    klass->can_be_closed = false;
+
 }
 
 
@@ -144,6 +156,8 @@ static void g_panel_item_init(GPanelItem *item)
 
     item->personality = PIP_INVALID;
 
+    item->filter = NULL;
+
     g_atomic_int_set(&item->switched, 0);
 
 }
@@ -163,13 +177,12 @@ static void g_panel_item_init(GPanelItem *item)
 
 static void g_panel_item_dockable_interface_init(GtkDockableInterface *iface)
 {
-    iface->can_search = false;
-    iface->can_be_closed = true;
-
+    iface->can_search = (can_dockable_search_fc)gtk_panel_item_can_search;
+    iface->can_be_closed = (can_dockable_search_fc)gtk_panel_item_can_be_closed;
     iface->get_name = (get_dockable_name_fc)gtk_panel_item_get_name;
     iface->get_desc = (get_dockable_desc_fc)gtk_panel_item_get_desc;
     iface->get_widget = (get_dockable_widget_fc)gtk_panel_item_get_widget;
-    iface->update_filtered = (update_filtered_data_fc)NULL;
+    iface->update_filtered = (update_filtered_data_fc)gtk_panel_item_update_filtered;
 
 }
 
@@ -212,6 +225,9 @@ static void g_panel_item_finalize(GPanelItem *item)
 {
     free(item->path);
 
+    if (item->filter != NULL)
+        free(item->filter);
+
     if (item->surface != NULL)
         cairo_surface_destroy(item->surface);
 
@@ -306,6 +322,58 @@ GtkBuilder *g_panel_item_build(GPanelItem *item, const char *name)
 *                                                                             *
 *  Paramètres  : item = instance GTK dont l'interface est à consulter.        *
 *                                                                             *
+*  Description : Détermine si un panneau peut être filtré.                    *
+*                                                                             *
+*  Retour      : Bilan de la consultation.                                    *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool gtk_panel_item_can_search(const GPanelItem *item)
+{
+    bool result;                            /* Indication à retourner      */
+    GPanelItemClass *class;                 /* Classe de l'élément visé    */
+
+    class = G_PANEL_ITEM_GET_CLASS(item);
+
+    result = class->can_search;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : item = instance GTK dont l'interface est à consulter.        *
+*                                                                             *
+*  Description : Détermine si un panneau peut être fermé.                     *
+*                                                                             *
+*  Retour      : Bilan de la consultation.                                    *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool gtk_panel_item_can_be_closed(const GPanelItem *item)
+{
+    bool result;                            /* Indication à retourner      */
+    GPanelItemClass *class;                 /* Classe de l'élément visé    */
+
+    class = G_PANEL_ITEM_GET_CLASS(item);
+
+    result = class->can_be_closed;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : item = instance GTK dont l'interface est à consulter.        *
+*                                                                             *
 *  Description : Fournit le nom court du composant encapsulable.              *
 *                                                                             *
 *  Retour      : Désignation humaine pour titre d'onglet ou de fenêtre.       *
@@ -361,6 +429,32 @@ static GtkWidget *gtk_panel_item_get_widget(GPanelItem *item)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : item = instance GTK dont l'interface est à sollicitée.       *
+*                                                                             *
+*  Description : Démarre l'actualisation du filtrage du contenu.              *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void gtk_panel_item_update_filtered(GPanelItem *item, char *filter)
+{
+    assert(gtk_panel_item_can_search(item));
+
+    if (item->filter != NULL)
+        free(item->filter);
+
+    item->filter = filter;
+
+    G_PANEL_ITEM_GET_CLASS(item)->update_filtered(item);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : item   = instance GTK à consulter.                           *
 *                attrib = élément de configuration à inclure dans le résultat.*
 *                                                                             *
diff --git a/src/gui/panels/panel.h b/src/gui/panels/panel.h
index bdeffcc..4a92409 100644
--- a/src/gui/panels/panel.h
+++ b/src/gui/panels/panel.h
@@ -34,12 +34,12 @@
 
 
 
-#define G_TYPE_PANEL_ITEM               g_panel_item_get_type()
-#define G_PANEL_ITEM(obj)               (G_TYPE_CHECK_INSTANCE_CAST((obj), g_panel_item_get_type(), GPanelItem))
-#define G_IS_PANEL_ITEM(obj)            (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_panel_item_get_type()))
-#define G_PANEL_ITEM_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_PANEL_ITEM, GPanelItemClass))
-#define G_IS_PANEL_ITEM_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_PANEL_ITEM))
-#define G_PANEL_ITEM_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_PANEL_ITEM, GPanelItemClass))
+#define G_TYPE_PANEL_ITEM            g_panel_item_get_type()
+#define G_PANEL_ITEM(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_PANEL_ITEM, GPanelItem))
+#define G_IS_PANEL_ITEM(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_PANEL_ITEM))
+#define G_PANEL_ITEM_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_PANEL_ITEM, GPanelItemClass))
+#define G_IS_PANEL_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_PANEL_ITEM))
+#define G_PANEL_ITEM_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_PANEL_ITEM, GPanelItemClass))
 
 
 /* Elément réactif pour panneaux de l'éditeur (instance) */
diff --git a/src/gui/panels/strings.c b/src/gui/panels/strings.c
index 7420ffe..4828038 100644
--- a/src/gui/panels/strings.c
+++ b/src/gui/panels/strings.c
@@ -25,19 +25,23 @@
 #include "strings.h"
 
 
+#include <assert.h>
 #include <string.h>
 #include <inttypes.h>
 
 
 #include "panel-int.h"
+#include "updating-int.h"
 #include "../core/global.h"
 #include "../dialogs/gotox.h"
 #include "../../common/extstr.h"
 #include "../../core/params.h"
+#include "../../core/queue.h"
 #include "../../format/format.h"
 #include "../../format/symiter.h"
 #include "../../gtkext/easygtk.h"
 #include "../../gtkext/gtkdockable-int.h"
+#include "../../gtkext/tmgt.h"
 
 
 
@@ -49,16 +53,14 @@ struct _GStringsPanel
 {
     GPanelItem parent;                      /* A laisser en premier        */
 
-    GtkTreeView *treeview;                  /* Composant d'affichage       */
-    const regex_t *filter;                  /* Filtre appliqué ou NULL     */
+    GLoadedBinary *binary;                  /* Binaire en cours d'analyse  */
 
     GtkMenu *menu;                          /* Menu contextuel pour param. */
 
-    GLoadedBinary *binary;                  /* Binaire en cours d'analyse  */
+    size_t count;                           /* Quantité de symboles utiles */
 
 };
 
-
 /* Panneau d'aperçu de graphiques (classe) */
 struct _GStringsPanelClass
 {
@@ -70,27 +72,34 @@ struct _GStringsPanelClass
 /* Colonnes de la liste des symboles */
 typedef enum _StringsColumn
 {
-    STC_STRING,                             /* Elément GLib représenté     */
+    STC_SYMBOL,                             /* Symbole représenté          */
 
     STC_PHYSICAL,                           /* Adresse phyisque            */
     STC_VIRTUAL,                            /* Adresse virtuelle           */
     STC_AREA,                               /* Zone de localisation        */
     STC_NAME,                               /* Désignation humaine         */
     STC_VALUE,                              /* Chaîne de caractères        */
+    STC_ORIGINAL,                           /* Version brute d'origine     */
+
+    STC_MATCHED,                            /* Correspondance établie ?    */
 
     STC_COUNT                               /* Nombre de colonnes          */
 
 } StringsColumn;
 
 
+/* Données utiles à la mise à jour */
+typedef struct _strings_update_data strings_update_data;
+
+
 /* Initialise la classe des panneaux d'affichage de chaînes. */
 static void g_strings_panel_class_init(GStringsPanelClass *);
 
 /* Initialise une instance de panneau d'affichage des chaînes. */
 static void g_strings_panel_init(GStringsPanel *);
 
-/* Procède à l'initialisation de l'interface de rassemblement. */
-static void g_strings_panel_dockable_interface_init(GtkDockableInterface *);
+/* Procède à l'initialisation de l'interface de mise à jour. */
+static void g_strings_panel_updatable_interface_init(GUpdatablePanelInterface *);
 
 /* Supprime toutes les références externes. */
 static void g_strings_panel_dispose(GStringsPanel *);
@@ -98,14 +107,6 @@ static void g_strings_panel_dispose(GStringsPanel *);
 /* Procède à la libération totale de la mémoire. */
 static void g_strings_panel_finalize(GStringsPanel *);
 
-
-
-/* ------------------------- AFFICHAGE A L'AIDE D'UNE LISTE ------------------------- */
-
-
-/* Réagit à un changement d'affichage principal de contenu. */
-static void change_strings_panel_current_binary(GStringsPanel *, GLoadedBinary *);
-
 /* Réagit au changement de sélection des chaînes textuelles. */
 static void on_strings_selection_change(GtkTreeSelection *, gpointer);
 
@@ -116,18 +117,38 @@ static gint compare_strings_list_columns(GtkTreeModel *, GtkTreeIter *, GtkTreeI
 static gboolean on_key_pressed_over_strings(GtkTreeView *, GdkEventKey *, GStringsPanel *);
 
 /* Réagit à une édition de l'étiquette d'une chaîne textuelle. */
-static void on_string_value_edited(GtkCellRendererText *, gchar *, gchar *, GtkTreeStore *);
+static void on_string_name_edited(GtkCellRendererText *, gchar *, gchar *, GtkTreeModel *);
+
+/* Réagit à un changement d'affichage principal de contenu. */
+static void change_strings_panel_current_binary(GStringsPanel *, GLoadedBinary *);
+
+
+
+/* ------------------------- AFFICHAGE A L'AIDE D'UNE LISTE ------------------------- */
+
+
+/* Réagit à un changement d'affichage principal de contenu. */
+static void reload_strings_for_new_list_view(const GStringsPanel *, GtkStatusStack *, activity_id_t, strings_update_data *);
 
+/* Met en surbrillance les éléments recherchés dans les noms. */
+static void update_string_label_in_list_view(GtkListStore *, GtkTreeIter *, const regmatch_t *);
 
+/* Met en surbrillance les éléments recherchés dans les valeurs. */
+static void update_string_value_in_list_view(GtkListStore *, GtkTreeIter *, const regmatch_t *);
 
-/* ------------------------- FILTRAGE DES SYMBOLES PRESENTS ------------------------- */
+
+
+/* ------------------------- FILTRAGE DES CHAINES PRESENTES ------------------------- */
 
 
 /* Démarre l'actualisation du filtrage des chaînes. */
-static void update_filtered_strings(GStringsPanel *, const regex_t *);
+static void update_filtered_strings(GStringsPanel *);
 
-/* Détermine si une chaîne textuelle doit être filtrée ou non. */
-static bool is_string_filtered(GStringsPanel *, const char *, const char *);
+/* Détermine si un noeud de l'arborescence doit être filtré. */
+static void update_string_node(const strings_update_data *, GtkListStore *, GtkTreeIter *);
+
+/* Exécute un nouveau filtrage des chaînes affichées. */
+static void do_filtering_on_strings(const GStringsPanel *, GtkStatusStack *, activity_id_t, strings_update_data *);
 
 
 
@@ -141,7 +162,7 @@ static gboolean on_button_event_over_strings(GtkWidget *, GdkEventButton *, GStr
 static GtkMenu *build_strings_panel_menu(GStringsPanel *);
 
 /* Fournit le signet sélectionné dans la liste. */
-static GBinSymbol *get_selected_panel_symbol(GtkTreeView *, GtkTreeIter *);
+static GBinSymbol *get_selected_panel_symbol(GStringsPanel *, GtkTreeIter *);
 
 /* Réagit avec le menu "Editer le nom". */
 static void mcb_strings_panel_edit(GtkMenuItem *, GStringsPanel *);
@@ -156,6 +177,41 @@ static void mcb_strings_panel_find_refs(GtkMenuItem *, GStringsPanel *);
 static void mcb_strings_panel_filter(GtkMenuItem *, GStringsPanel *);
 
 
+/* ---------------------- MECANISMES DE MISE A JOUR DE PANNEAU ---------------------- */
+
+
+/* Données utiles à la mise à jour */
+struct _strings_update_data
+{
+    size_t count;                           /* Qté d'inscriptions réalisées*/
+
+    regex_t *filter;                        /* Filtre appliqué ou NULL     */
+
+};
+
+
+/* Détermine si un nom de symbole doit être filtré ou non. */
+static bool is_string_name_matching(const strings_update_data *, GtkTreeModel *, GtkTreeIter *, regmatch_t *);
+
+/* Détermine si une valeur de symbole doit être filtrée ou non. */
+static bool is_string_value_matching(const strings_update_data *, GtkTreeModel *, GtkTreeIter *, regmatch_t *);
+
+/* Prépare une opération de mise à jour de panneau. */
+static const char *g_strings_panel_setup(const GStringsPanel *, unsigned int, size_t *, strings_update_data **);
+
+/* Bascule l'affichage d'un panneau avant mise à jour. */
+static void g_strings_panel_introduce(const GStringsPanel *, unsigned int, strings_update_data *);
+
+/* Réalise une opération de mise à jour de panneau. */
+static void g_strings_panel_process(const GStringsPanel *, unsigned int, GtkStatusStack *, activity_id_t, strings_update_data *);
+
+/* Bascule l'affichage d'un panneau après mise à jour. */
+static void g_strings_panel_conclude(GStringsPanel *, unsigned int, strings_update_data *);
+
+/* Supprime les données dynamiques utilisées à la mise à jour. */
+static void g_strings_panel_clean_data(GUpdatablePanel *, unsigned int, strings_update_data *);
+
+
 
 /* ---------------------------------------------------------------------------------- */
 /*                            PARTIE PRINCIPALE DU PANNEAU                            */
@@ -164,7 +220,7 @@ static void mcb_strings_panel_filter(GtkMenuItem *, GStringsPanel *);
 
 /* Indique le type définit pour un panneau d'affichage des chaînes. */
 G_DEFINE_TYPE_WITH_CODE(GStringsPanel, g_strings_panel, G_TYPE_PANEL_ITEM,
-                        G_IMPLEMENT_INTERFACE(GTK_TYPE_DOCKABLE, g_strings_panel_dockable_interface_init));
+                        G_IMPLEMENT_INTERFACE(G_TYPE_UPDATABLE_PANEL, g_strings_panel_updatable_interface_init));
 
 
 /******************************************************************************
@@ -199,6 +255,13 @@ static void g_strings_panel_class_init(GStringsPanelClass *klass)
     panel->unique = true;
     panel->bindings = "<Shift>F12";
 
+    panel->can_search = true;
+    panel->can_be_closed = true;
+
+    panel->update_filtered = (update_filtered_fc)update_filtered_strings;
+
+    panel->gid = setup_tiny_global_work_group(1);
+
 }
 
 
@@ -218,14 +281,13 @@ static void g_strings_panel_init(GStringsPanel *panel)
 {
     GEditorItem *base;                      /* Version basique d'instance  */
     GPanelItem *pitem;                      /* Version parente du panneau  */
-    GObject *ref;                           /* Espace de référencement     */
-    GtkTreeStore *store;                    /* Modèle de gestion           */
-    GtkWidget *treeview;                    /* Affichage de la liste       */
+    GtkBuilder *builder;                    /* Constructeur utilisé        */
+    GtkTreeModelFilter *filter;             /* Filtre pour l'arborescence  */
+    GtkTreeView *treeview;                  /* Affichage de la liste       */
     GtkCellRenderer *renderer;              /* Moteur de rendu de colonne  */
     GtkTreeViewColumn *column;              /* Colonne de la liste         */
+    GtkTreeModel *model;                    /* Modèle de gestion de liste  */
     GtkTreeSortable *sortable;              /* Autre vision de la liste    */
-    GtkTreeSelection *select;               /* Sélection dans la liste     */
-    bool display;                           /* Affichage si sélection ?    */
 
     /* Eléments de base */
 
@@ -242,37 +304,15 @@ static void g_strings_panel_init(GStringsPanel *panel)
 
     /* Représentation graphique */
 
-    base->widget = gtk_scrolled_window_new(NULL, NULL);
-    gtk_widget_show(base->widget);
-
-    gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(base->widget), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
-    gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(base->widget), GTK_SHADOW_IN);
-
-    ref = G_OBJECT(base->widget);
-    g_object_set_data(ref, "panel", panel);
+    builder = g_panel_item_build(pitem, "strings");
 
-    /* Partie chaînes */
-
-    store = gtk_tree_store_new(STC_COUNT, G_TYPE_OBJECT,
-                               G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
-
-    treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
-    panel->treeview = GTK_TREE_VIEW(treeview);
-
-    g_signal_connect(G_OBJECT(treeview), "button-press-event",
-                     G_CALLBACK(on_button_event_over_strings), panel);
-    g_signal_connect(G_OBJECT(treeview), "button-release-event",
-                     G_CALLBACK(on_button_event_over_strings), panel);
-    g_signal_connect(G_OBJECT(treeview), "key-press-event",
-                     G_CALLBACK(on_key_pressed_over_strings), panel);
-
-    gtk_widget_show(treeview);
-    gtk_container_add(GTK_CONTAINER(base->widget), treeview);
-
-    g_object_unref(G_OBJECT(store));
+    filter = GTK_TREE_MODEL_FILTER(gtk_builder_get_object(builder, "filter"));
+    gtk_tree_model_filter_set_visible_column(filter, STC_MATCHED);
 
     /* Cellules d'affichage */
 
+    treeview = GTK_TREE_VIEW(gtk_builder_get_object(builder, "treeview"));
+
     renderer = gtk_cell_renderer_text_new();
     column = gtk_tree_view_column_new_with_attributes(_("Physical address"), renderer,
                                                       "text", STC_PHYSICAL,
@@ -295,9 +335,11 @@ static void g_strings_panel_init(GStringsPanel *panel)
     gtk_tree_view_column_set_sort_column_id(column, STC_AREA);
     gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
 
+    model = GTK_TREE_MODEL(gtk_builder_get_object(builder, "store"));
+
     renderer = gtk_cell_renderer_text_new();
     g_object_set(G_OBJECT(renderer), "editable", TRUE, NULL);
-    g_signal_connect(renderer, "edited", G_CALLBACK(on_string_value_edited), store);
+    g_signal_connect(renderer, "edited", G_CALLBACK(on_string_name_edited), model);
     column = gtk_tree_view_column_new_with_attributes(_("Name"), renderer,
                                                       "text", STC_NAME,
                                                       NULL);
@@ -313,7 +355,7 @@ static void g_strings_panel_init(GStringsPanel *panel)
 
     /* Tri de la liste */
 
-    sortable = GTK_TREE_SORTABLE(store);
+    sortable = GTK_TREE_SORTABLE(gtk_builder_get_object(builder, "store"));
 
     gtk_tree_sortable_set_sort_func(sortable, STC_PHYSICAL, compare_strings_list_columns,
                                     GINT_TO_POINTER(STC_PHYSICAL), NULL);
@@ -332,15 +374,15 @@ static void g_strings_panel_init(GStringsPanel *panel)
 
     gtk_tree_sortable_set_sort_column_id(sortable, STC_VIRTUAL, GTK_SORT_ASCENDING);
 
-    /* Prise en compte de la sélection */
-
-    select = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview));
-    gtk_tree_selection_set_mode(select, GTK_SELECTION_SINGLE);
+    /* Connexion des signaux */
 
-    g_generic_config_get_value(get_main_configuration(), MPK_DISPLAY_ON_SEL, &display);
+    gtk_builder_add_callback_symbols(builder,
+                                     "on_button_event_over_strings", G_CALLBACK(on_button_event_over_strings),
+                                     "on_key_pressed_over_strings", G_CALLBACK(on_key_pressed_over_strings),
+                                     "on_strings_selection_change", G_CALLBACK(on_strings_selection_change),
+                                     NULL);
 
-    if (display)
-        g_signal_connect(G_OBJECT(select), "changed", G_CALLBACK(on_strings_selection_change), NULL);
+    gtk_builder_connect_signals(builder, panel);
 
     /* Préparation du menu contextuel */
 
@@ -351,9 +393,9 @@ static void g_strings_panel_init(GStringsPanel *panel)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : iface = interface GTK à initialiser.                         *
+*  Paramètres  : iface = interface GLib à initialiser.                        *
 *                                                                             *
-*  Description : Procède à l'initialisation de l'interface de rassemblement.  *
+*  Description : Procède à l'initialisation de l'interface de mise à jour.    *
 *                                                                             *
 *  Retour      : -                                                            *
 *                                                                             *
@@ -361,19 +403,14 @@ static void g_strings_panel_init(GStringsPanel *panel)
 *                                                                             *
 ******************************************************************************/
 
-static void g_strings_panel_dockable_interface_init(GtkDockableInterface *iface)
+static void g_strings_panel_updatable_interface_init(GUpdatablePanelInterface *iface)
 {
-    GtkDockableInterface *parent_iface;     /* Définition précédente       */
-
-    parent_iface = (GtkDockableInterface *)g_type_interface_peek_parent(iface);
-
-    iface->can_search = true;
-    iface->can_be_closed = true;
-
-    iface->get_name = parent_iface->get_name;
-    iface->get_desc = parent_iface->get_desc;
-    iface->get_widget = parent_iface->get_widget;
-    iface->update_filtered = (update_filtered_data_fc)update_filtered_strings;
+    iface->setup = (setup_updatable_cb)g_strings_panel_setup;
+    iface->get_group = (get_updatable_group_cb)g_panel_item_get_group;
+    iface->introduce = (introduce_updatable_cb)g_strings_panel_introduce;
+    iface->process = (process_updatable_cb)g_strings_panel_process;
+    iface->conclude = (conclude_updatable_cb)g_strings_panel_conclude;
+    iface->clean = (clean_updatable_data_cb)g_strings_panel_clean_data;
 
 }
 
@@ -442,143 +479,6 @@ GPanelItem *g_strings_panel_new(void)
 }
 
 
-
-/* ---------------------------------------------------------------------------------- */
-/*                           AFFICHAGE A L'AIDE D'UNE LISTE                           */
-/* ---------------------------------------------------------------------------------- */
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : panel  = panneau à mettre à jour.                            *
-*                binary = nouvelle instance de binaire analysé.               *
-*                                                                             *
-*  Description : Réagit à un changement d'affichage principal de contenu.     *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void change_strings_panel_current_binary(GStringsPanel *panel, GLoadedBinary *binary)
-{
-    GtkTreeStore *store;                    /* Modèle de gestion           */
-    GArchProcessor *proc;                   /* Architecture du binaire     */
-    MemoryDataSize msize;                   /* Taille par défaut           */
-    GExeFormat *format;                     /* Format de travail           */
-    GBinPortion *portions;                  /* Couche première de portions */
-    GBinContent *content;                   /* Contenu binaire en mémoire  */
-    sym_iter_t *siter;                      /* Parcours des symboles       */
-    GBinSymbol *symbol;                     /* Symbole manipulé            */
-    const mrange_t *range;                  /* Couverture mémoire          */
-    const vmpa2t *addr;                     /* Adressse liée à la chaîne   */
-    VMPA_BUFFER(phys);                      /* Position physique           */
-    VMPA_BUFFER(virt);                      /* Adresse virtuelle           */
-    GBinPortion *portion;                   /* Zone mémoire d'appartenance */
-    const char *area;                       /* Description de la zone      */
-    const char *label;                      /* Etiquette liée au symbole   */
-    vmpa2t pos;                             /* Tête de lecture modifiable  */
-    char *text;                             /* Version imprimable du texte */
-    GtkTreeIter iter;                       /* Point d'insertion           */
-
-    /* Basculement du binaire utilisé */
-
-    if (panel->binary != NULL)
-        g_object_unref(G_OBJECT(panel->binary));
-
-    panel->binary = binary;
-
-    if (panel->binary != NULL)
-        g_object_ref(G_OBJECT(panel->binary));
-
-    store = GTK_TREE_STORE(gtk_tree_view_get_model(panel->treeview));
-    gtk_tree_store_clear(store);
-
-    /* Si le panneau actif ne représente pas un binaire... */
-
-    if (binary == NULL) return;
-
-    /* Actualisation de l'affichage */
-
-    proc = g_loaded_binary_get_processor(binary);
-    msize = g_arch_processor_get_memory_size(proc);
-    g_object_unref(G_OBJECT(proc));
-
-    format = g_loaded_binary_get_format(binary);
-    portions = g_exe_format_get_portions(format);
-    content = g_binary_format_get_content(G_BIN_FORMAT(format));
-
-    siter = create_symbol_iterator(G_BIN_FORMAT(format), 0);
-
-    for (symbol = get_symbol_iterator_current(siter);
-         symbol != NULL;
-         symbol = get_symbol_iterator_next(siter))
-    {
-        if (g_binary_symbol_get_target_type(symbol) != STP_RO_STRING)
-            goto cspcb_next;
-
-        range = g_binary_symbol_get_range(symbol);
-        addr = get_mrange_addr(range);
-
-        vmpa2_phys_to_string(addr, msize, phys, NULL);
-        vmpa2_virt_to_string(addr, msize, virt, NULL);
-
-        portion = g_binary_portion_find_at_addr(portions, addr, (GdkRectangle []) { });
-        area = g_binary_portion_get_desc(portion);
-        g_object_unref(G_OBJECT(portion));
-
-        label = g_binary_symbol_get_label(symbol);
-
-        text = (char *)calloc(get_mrange_length(range) + 1, sizeof(char));
-
-        copy_vmpa(&pos, addr);
-
-        if (!g_binary_content_read_raw(content, &pos, get_mrange_length(range), (uint8_t *)text))
-        {
-            free(text);
-            goto cspcb_next;
-        }
-
-        if (is_string_filtered(panel, label, text))
-        {
-            free(text);
-            goto cspcb_next;
-        }
-
-        text = strrpl(text, "&", "&amp;");
-        text = strrpl(text, "<", "&lt;");
-        text = strrpl(text, ">", "&gt;");
-        text = strrpl(text, "\r", "<b>\\r</b>");
-        text = strrpl(text, "\n", "<b>\\n</b>");
-
-        gtk_tree_store_append(store, &iter, NULL);
-        gtk_tree_store_set(store, &iter,
-                           STC_STRING, symbol,
-                           STC_PHYSICAL, phys,
-                           STC_VIRTUAL, virt,
-                           STC_AREA, area,
-                           STC_NAME, label,
-                           STC_VALUE, text,
-                           -1);
-
-        free(text);
-
- cspcb_next:
-
-        g_object_unref(G_OBJECT(symbol));
-
-    }
-
-    delete_symbol_iterator(siter);
-
-    g_object_unref(G_OBJECT(content));
-    g_object_unref(G_OBJECT(portions));
-    g_object_unref(G_OBJECT(format));
-
-}
-
-
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : selection = sélection modifiée.                              *
@@ -602,7 +502,7 @@ static void on_strings_selection_change(GtkTreeSelection *selection, gpointer un
 
     if (gtk_tree_selection_get_selected(selection, &model, &iter))
     {
-        gtk_tree_model_get(model, &iter, STC_STRING, &symbol, -1);
+        gtk_tree_model_get(model, &iter, STC_SYMBOL, &symbol, -1);
 
         addr = get_mrange_addr(g_binary_symbol_get_range(symbol));
 
@@ -703,7 +603,7 @@ static gboolean on_key_pressed_over_strings(GtkTreeView *treeview, GdkEventKey *
 *  Paramètres  : renderer = moteur de rendu pour la cellule.                  *
 *                path     = chemin d'accès vers la cellule éditée.            *
 *                new      = nouvelle valeur sous forme de texte à valider.    *
-*                store    = gestionnaire des données de la liste affichée.    *
+*                model    = gestionnaire des données de la liste affichée.    *
 *                                                                             *
 *  Description : Réagit à une édition de l'étiquette d'une chaîne textuelle.  *
 *                                                                             *
@@ -713,7 +613,7 @@ static gboolean on_key_pressed_over_strings(GtkTreeView *treeview, GdkEventKey *
 *                                                                             *
 ******************************************************************************/
 
-static void on_string_value_edited(GtkCellRendererText *renderer, gchar *path, gchar *new, GtkTreeStore *store)
+static void on_string_name_edited(GtkCellRendererText *renderer, gchar *path, gchar *new, GtkTreeModel *model)
 {
     GtkTreePath *tree_path;                 /* Chemin d'accès natif        */
     GtkTreeIter iter;                       /* Point de la modification    */
@@ -722,10 +622,10 @@ static void on_string_value_edited(GtkCellRendererText *renderer, gchar *path, g
     tree_path = gtk_tree_path_new_from_string(path);
     if (tree_path == NULL) return;
 
-    if (!gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &iter, tree_path))
+    if (!gtk_tree_model_get_iter(model, &iter, tree_path))
         goto opve_bad_iter;
 
-    gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, STC_STRING, &symbol, -1);
+    gtk_tree_model_get(model, &iter, STC_SYMBOL, &symbol, -1);
 
     g_binary_symbol_set_alt_label(symbol, new);
 
@@ -738,18 +638,12 @@ static void on_string_value_edited(GtkCellRendererText *renderer, gchar *path, g
 }
 
 
-
-/* ---------------------------------------------------------------------------------- */
-/*                           FILTRAGE DES SYMBOLES PRESENTS                           */
-/* ---------------------------------------------------------------------------------- */
-
-
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : panel = panneau assurant l'affichage des paramètres.         *
-*                preg  = expression régulière compilée à utiliser.            *
+*  Paramètres  : panel  = panneau à mettre à jour.                            *
+*                binary = nouvelle instance de binaire analysé.               *
 *                                                                             *
-*  Description : Démarre l'actualisation du filtrage des chaînes.             *
+*  Description : Réagit à un changement d'affichage principal de contenu.     *
 *                                                                             *
 *  Retour      : -                                                            *
 *                                                                             *
@@ -757,110 +651,401 @@ static void on_string_value_edited(GtkCellRendererText *renderer, gchar *path, g
 *                                                                             *
 ******************************************************************************/
 
-static void update_filtered_strings(GStringsPanel *panel, const regex_t *preg)
+static void change_strings_panel_current_binary(GStringsPanel *panel, GLoadedBinary *binary)
 {
-    panel->filter = preg;
+    GtkBuilder *builder;                    /* Constructeur utilisé        */
+    GtkListStore *store;                    /* Modèle de gestion           */
 
-    change_strings_panel_current_binary(panel, panel->binary);
+    /* Basculement du binaire utilisé */
 
-}
+    if (panel->binary != NULL)
+        g_object_unref(G_OBJECT(panel->binary));
 
+    panel->binary = binary;
 
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : panel = panneau assurant l'affichage des paramètres.         *
-*                label = étiquette liée au symbole à traiter.                 *
-*                value = chaîne de caractères représentée par le symbole.     *
-*                                                                             *
-*  Description : Détermine si une chaîne textuelle doit être filtrée ou non.  *
-*                                                                             *
-*  Retour      : true si le symbole ne doit pas être affiché, false sinon.    *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
+    if (panel->binary != NULL)
+        g_object_ref(G_OBJECT(panel->binary));
 
-static bool is_string_filtered(GStringsPanel *panel, const char *label, const char *value)
-{
-    bool result;                            /* Bilan à retourner           */
-    regmatch_t match;                       /* Récupération des trouvailles*/
-    int ret;                                /* Bilan du filtrage           */
+    /* Réinitialisation */
 
-    if (panel->filter == NULL)
-        return false;
+    builder = G_PANEL_ITEM(panel)->builder;
 
-    result = true;
+    store = GTK_LIST_STORE(gtk_builder_get_object(builder, "store"));
 
-    if (label != NULL)
-    {
-        ret = regexec(panel->filter, label, 1, &match, 0);
-        result &= (ret == REG_NOMATCH);
-    }
+    gtk_list_store_clear(store);
 
-    ret = regexec(panel->filter, value, 1, &match, 0);
-    result &= (ret == REG_NOMATCH);
+    /* Si le panneau actif représente un binaire, actualisation de l'affichage */
 
-    return result;
+    if (binary != NULL)
+        run_panel_update(G_UPDATABLE_PANEL(panel), PUI_0);
 
 }
 
 
 
 /* ---------------------------------------------------------------------------------- */
-/*                          ATTRIBUTION D'UN MENU CONTEXTUEL                          */
+/*                           AFFICHAGE A L'AIDE D'UNE LISTE                           */
 /* ---------------------------------------------------------------------------------- */
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : widget = composant GTK visé par l'opération.                 *
-*                event  = informations liées à l'événement.                   *
-*                panel  = informations liées au panneau associé.              *
+*  Paramètres  : panel = panneau à mettre à jour.                             *
+*                status = barre de statut à tenir informée.                   *
+*                id     = identifiant pour le suivi de la progression.        *
+*                data   = données complémentaire à manipuler.                 *
 *                                                                             *
-*  Description : Assure la gestion des clics de souris sur les signets.       *
+*  Description : Réagit à un changement d'affichage principal de contenu.     *
 *                                                                             *
-*  Retour      : FALSE pour poursuivre la propagation de l'événement.         *
+*  Retour      : -                                                            *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static gboolean on_button_event_over_strings(GtkWidget *widget, GdkEventButton *event, GStringsPanel *panel)
+static void reload_strings_for_new_list_view(const GStringsPanel *panel, GtkStatusStack *status, activity_id_t id, strings_update_data *data)
 {
-    GtkTreeSelection *selection;            /* Sélection courante          */
-    GtkTreeIter iter;                       /* Point de sélection          */
-    GtkTreeModel *model;                    /* Modèle de gestion           */
-    GBinSymbol *symbol;                     /* Symbole en cours d'étude    */
-    const vmpa2t *addr;                     /* Adressse associée au signet */
-    GLoadedPanel *display;                  /* Afficheur effectif de code  */
+    GtkBuilder *builder;                    /* Constructeur utilisé        */
+    GtkListStore *store;                    /* Modèle de gestion           */
+    GArchProcessor *proc;                   /* Architecture utilisée       */
+    MemoryDataSize size;                    /* Taille des localisations    */
+    GExeFormat *format;                     /* Format associé au binaire   */
+    GBinPortion *portions;                  /* Couche première de portions */
+    GBinContent *content;                   /* Contenu binaire en mémoire  */
+    sym_iter_t *siter;                      /* Parcours des symboles       */
+    GBinSymbol *symbol;                     /* Symbole manipulé            */
+    const mrange_t *range;                  /* Couverture mémoire          */
+    const vmpa2t *addr;                     /* Adressse liée à la chaîne   */
+    VMPA_BUFFER(phys);                      /* Position physique           */
+    VMPA_BUFFER(virt);                      /* Adresse virtuelle           */
+    GBinPortion *portion;                   /* Zone mémoire d'appartenance */
+    const char *area;                       /* Description de la zone      */
+    char *text;                             /* Texte original référencé    */
+    vmpa2t pos;                             /* Tête de lecture modifiable  */
+    GtkTreeIter iter;                       /* Point d'insertion           */
 
-    switch (event->button)
-    {
-        case 1:
+    builder = G_PANEL_ITEM(panel)->builder;
 
-            if (event->type != GDK_2BUTTON_PRESS)
-                break;
+    store = GTK_LIST_STORE(gtk_builder_get_object(builder, "store"));
 
-            selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget));
+    proc = g_loaded_binary_get_processor(panel->binary);
+    size = g_arch_processor_get_memory_size(proc);
+    g_object_unref(G_OBJECT(proc));
 
-            if (gtk_tree_selection_get_selected(selection, &model, &iter))
-            {
-                gtk_tree_model_get(model, &iter, STC_STRING, &symbol, -1);
+    format = g_loaded_binary_get_format(panel->binary);
+    portions = g_exe_format_get_portions(format);
+    content = g_binary_format_get_content(G_BIN_FORMAT(format));
 
-                addr = get_mrange_addr(g_binary_symbol_get_range(symbol));
+    siter = create_symbol_iterator(G_BIN_FORMAT(format), 0);
 
-                display = get_current_view();
+    for (symbol = get_symbol_iterator_current(siter);
+         symbol != NULL;
+         symbol = get_symbol_iterator_next(siter))
+    {
+        if (g_binary_symbol_get_target_type(symbol) != STP_RO_STRING)
+            goto rsfnlv_next;
 
-                if (GTK_IS_DISPLAY_PANEL(display))
-                    gtk_display_panel_request_move(GTK_DISPLAY_PANEL(display), addr);
+        range = g_binary_symbol_get_range(symbol);
+        addr = get_mrange_addr(range);
 
-                g_object_unref(G_OBJECT(display));
+        vmpa2_phys_to_string(addr, size, phys, NULL);
+        vmpa2_virt_to_string(addr, size, virt, NULL);
 
-                g_object_unref(G_OBJECT(symbol));
+        portion = g_binary_portion_find_at_addr(portions, addr, (GdkRectangle []) { });
+        area = g_binary_portion_get_desc(portion);
+        g_object_unref(G_OBJECT(portion));
 
-            }
+        text = (char *)calloc(get_mrange_length(range) + 1, sizeof(char));
 
-            break;
+        copy_vmpa(&pos, addr);
+
+        if (!g_binary_content_read_raw(content, &pos, get_mrange_length(range), (uint8_t *)text))
+        {
+            free(text);
+            goto rsfnlv_next;
+        }
+
+        addr = get_mrange_addr(g_binary_symbol_get_range(symbol));
+        vmpa2_virt_to_string(addr, size, virt, NULL);
+
+        gtk_list_store_append(store, &iter);
+        gtk_list_store_set(store, &iter,
+                           STC_SYMBOL, symbol,
+                           STC_PHYSICAL, phys,
+                           STC_VIRTUAL, virt,
+                           STC_AREA, area,
+                           STC_NAME, NULL,
+                           STC_VALUE, NULL,
+                           STC_ORIGINAL, text,
+                           STC_MATCHED, false,
+                           -1);
+
+        update_string_node(data, store, &iter);
+
+        data->count++;
+
+        free(text);
+
+ rsfnlv_next:
+
+        g_object_unref(G_OBJECT(symbol));
+
+        gtk_status_stack_update_activity_value(status, id, 1);
+
+    }
+
+    delete_symbol_iterator(siter);
+
+    g_object_unref(G_OBJECT(content));
+    g_object_unref(G_OBJECT(portions));
+    g_object_unref(G_OBJECT(format));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : store = gestionnaire de données pour une arborescence.       *
+*                iter  = position des données traitées.                       *
+*                match = correspondance avec un objet recherché.              *
+*                                                                             *
+*  Description : Met en surbrillance les éléments recherchés dans les noms.   *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void update_string_label_in_list_view(GtkListStore *store, GtkTreeIter *iter, const regmatch_t *match)
+{
+    GtkTreeModel *model;                    /* Autre vision du gestionnaire*/
+    char *original;                         /* Etiquette brute d'origine   */
+    char *value;                            /* Etiquette mise en relief    */
+
+    model = GTK_TREE_MODEL(store);
+
+    gtk_tree_model_get(model, iter, STC_ORIGINAL, &original, -1);
+
+    original = strrpl(original, "&", "&amp;");
+    original = strrpl(original, "<", "&lt;");
+    original = strrpl(original, ">", "&gt;");
+    original = strrpl(original, "\r", "<b>\\r</b>");
+    original = strrpl(original, "\n", "<b>\\n</b>");
+
+    value = build_highlighted_name(original, match, 0);
+
+    gtk_list_store_set(store, iter, STC_VALUE, value, -1);
+
+    free(original);
+    free(value);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : store = gestionnaire de données pour une arborescence.       *
+*                iter  = position des données traitées.                       *
+*                match = correspondance avec un objet recherché.              *
+*                                                                             *
+*  Description : Met en surbrillance les éléments recherchés dans les valeurs.*
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void update_string_value_in_list_view(GtkListStore *store, GtkTreeIter *iter, const regmatch_t *match)
+{
+    GtkTreeModel *model;                    /* Autre vision du gestionnaire*/
+    char *original;                         /* Etiquette brute d'origine   */
+    char *value;                            /* Etiquette mise en relief    */
+
+    model = GTK_TREE_MODEL(store);
+
+    gtk_tree_model_get(model, iter, STC_ORIGINAL, &original, -1);
+
+    original = strrpl(original, "&", "&amp;");
+    original = strrpl(original, "<", "&lt;");
+    original = strrpl(original, ">", "&gt;");
+    original = strrpl(original, "\r", "<b>\\r</b>");
+    original = strrpl(original, "\n", "<b>\\n</b>");
+
+    value = build_highlighted_name(original, match, 0);
+
+    gtk_list_store_set(store, iter, STC_VALUE, value, -1);
+
+    free(original);
+    free(value);
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                           FILTRAGE DES CHAINES PRESENTES                           */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : panel = panneau assurant l'affichage des chaînes.            *
+*                                                                             *
+*  Description : Démarre l'actualisation du filtrage des chaînes.             *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void update_filtered_strings(GStringsPanel *panel)
+{
+    run_panel_update(G_UPDATABLE_PANEL(panel), PUI_1);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : data  = données complémentaire à manipuler.                  *
+*                store = gestionnaire de l'ensemble des données.              *
+*                iter  = localisation des données à analyser.                 *
+*                                                                             *
+*  Description : Détermine si un noeud de l'arborescence doit être filtré.    *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void update_string_node(const strings_update_data *data, GtkListStore *store, GtkTreeIter *iter)
+{
+    GtkTreeModel *model;                    /* Autre vision du gestionnaire*/
+    regmatch_t match;                       /* Récupération des trouvailles*/
+    bool name_matched;                      /* Correspondance de sélection */
+    bool value_matched;                     /* Correspondance de sélection */
+
+    model = GTK_TREE_MODEL(store);
+
+    name_matched = is_string_name_matching(data, model, iter, &match);
+
+    if (name_matched)
+        update_string_label_in_list_view(store, iter, &match);
+
+    value_matched = is_string_value_matching(data, model, iter, &match);
+
+    if (value_matched)
+        update_string_value_in_list_view(store, iter, &match);
+
+    if (name_matched || value_matched)
+        gtk_list_store_set(GTK_LIST_STORE(model), iter, STC_MATCHED, true, -1);
+    else
+        gtk_list_store_set(GTK_LIST_STORE(model), iter, STC_MATCHED, false, -1);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : panel  = panneau assurant l'affichage des chaînes.           *
+*                status = barre de statut à tenir informée.                   *
+*                id     = identifiant pour le suivi de la progression.        *
+*                data   = données complémentaire à manipuler.                 *
+*                                                                             *
+*  Description : Exécute un nouveau filtrage des chaînes affichées.           *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void do_filtering_on_strings(const GStringsPanel *panel, GtkStatusStack *status, activity_id_t id, strings_update_data *data)
+{
+    GtkBuilder *builder;                    /* Constructeur utilisé        */
+    GtkListStore *store;                    /* Modèle de gestion           */
+
+
+    gboolean filter_string_panel_iter(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer unused)
+    {
+        update_string_node(data, store, iter);
+
+        gtk_status_stack_update_activity_value(status, id, 1);
+
+        return FALSE;
+
+    }
+
+
+    builder = G_PANEL_ITEM(panel)->builder;
+
+    store = GTK_LIST_STORE(gtk_builder_get_object(builder, "store"));
+
+    gtk_tree_model_foreach(GTK_TREE_MODEL(store), (GtkTreeModelForeachFunc)filter_string_panel_iter, NULL);
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                          ATTRIBUTION D'UN MENU CONTEXTUEL                          */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : widget = composant GTK visé par l'opération.                 *
+*                event  = informations liées à l'événement.                   *
+*                panel  = informations liées au panneau associé.              *
+*                                                                             *
+*  Description : Assure la gestion des clics de souris sur les signets.       *
+*                                                                             *
+*  Retour      : FALSE pour poursuivre la propagation de l'événement.         *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static gboolean on_button_event_over_strings(GtkWidget *widget, GdkEventButton *event, GStringsPanel *panel)
+{
+    GtkTreeSelection *selection;            /* Sélection courante          */
+    GtkTreeIter iter;                       /* Point de sélection          */
+    GtkTreeModel *model;                    /* Modèle de gestion           */
+    GBinSymbol *symbol;                     /* Symbole en cours d'étude    */
+    const vmpa2t *addr;                     /* Adressse associée au signet */
+    GLoadedPanel *display;                  /* Afficheur effectif de code  */
+
+    switch (event->button)
+    {
+        case 1:
+
+            if (event->type != GDK_2BUTTON_PRESS)
+                break;
+
+            selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget));
+
+            if (gtk_tree_selection_get_selected(selection, &model, &iter))
+            {
+                gtk_tree_model_get(model, &iter, STC_SYMBOL, &symbol, -1);
+
+                addr = get_mrange_addr(g_binary_symbol_get_range(symbol));
+
+                display = get_current_view();
+
+                if (GTK_IS_DISPLAY_PANEL(display))
+                    gtk_display_panel_request_move(GTK_DISPLAY_PANEL(display), addr);
+
+                g_object_unref(G_OBJECT(display));
+
+                g_object_unref(G_OBJECT(symbol));
+
+            }
+
+            break;
 
         case 3:
             if (event->type == GDK_BUTTON_RELEASE)
@@ -918,8 +1103,8 @@ static GtkMenu *build_strings_panel_menu(GStringsPanel *panel)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : treeview = liste d'affichage à consulter.                    *
-*                save     = zone de conservation du point de trouvaille. [OUT]*
+*  Paramètres  : panel = panneau concerné par l'opération.                    *
+*                save  = zone de conservation du point de trouvaille. [OUT]   *
 *                                                                             *
 *  Description : Fournit le signet sélectionné dans la liste.                 *
 *                                                                             *
@@ -929,19 +1114,25 @@ static GtkMenu *build_strings_panel_menu(GStringsPanel *panel)
 *                                                                             *
 ******************************************************************************/
 
-static GBinSymbol *get_selected_panel_symbol(GtkTreeView *treeview, GtkTreeIter *save)
+static GBinSymbol *get_selected_panel_symbol(GStringsPanel *panel, GtkTreeIter *save)
 {
     GBinSymbol *result;                     /* Chaîne textuelle à renvoyer */
+    GtkBuilder *builder;                    /* Constructeur utilisé        */
+    GtkTreeView *treeview;                  /* Arborescence graphique      */
     GtkTreeSelection *selection;            /* Représentation de sélection */
     GtkTreeModel *model;                    /* Gestionnaire des données    */
     GtkTreeIter iter;                       /* Point de la sélection       */
 
     result = NULL;
 
+    builder = G_PANEL_ITEM(panel)->builder;
+
+    treeview = GTK_TREE_VIEW(gtk_builder_get_object(builder, "treeview"));
+
     selection = gtk_tree_view_get_selection(treeview);
 
     if (gtk_tree_selection_get_selected(selection, &model, &iter))
-        gtk_tree_model_get(model, &iter, STC_STRING, &result, -1);
+        gtk_tree_model_get(model, &iter, STC_SYMBOL, &result, -1);
 
     if (save != NULL)
         *save = iter;
@@ -968,17 +1159,23 @@ static void mcb_strings_panel_edit(GtkMenuItem *menuitem, GStringsPanel *panel)
 {
     GtkTreeIter iter;                       /* Point de la sélection       */
     GBinSymbol *symbol;                     /* Symbole sélectionné         */
+    GtkBuilder *builder;                    /* Constructeur utilisé        */
+    GtkTreeView *treeview;                  /* Arborescence graphique      */
     GtkTreeModel *model;                    /* Gestionnaire de données     */
     GtkTreePath *path;                      /* Chemin d'accès à ce point   */
 
-    symbol = get_selected_panel_symbol(panel->treeview, &iter);
+    symbol = get_selected_panel_symbol(panel, &iter);
     if (symbol == NULL) return;
 
-    model = gtk_tree_view_get_model(panel->treeview);
+    builder = G_PANEL_ITEM(panel)->builder;
+
+    treeview = GTK_TREE_VIEW(gtk_builder_get_object(builder, "treeview"));
+
+    model = gtk_tree_view_get_model(treeview);
     path = gtk_tree_model_get_path(model, &iter);
 
-    gtk_tree_view_set_cursor(panel->treeview, path,
-                             gtk_tree_view_get_column(panel->treeview, STC_NAME - STC_PHYSICAL),
+    gtk_tree_view_set_cursor(treeview, path,
+                             gtk_tree_view_get_column(treeview, STC_NAME - STC_PHYSICAL),
                              TRUE);
 
     gtk_tree_path_free(path);
@@ -1003,13 +1200,19 @@ static void mcb_strings_panel_edit(GtkMenuItem *menuitem, GStringsPanel *panel)
 
 static void mcb_strings_panel_copy(GtkMenuItem *menuitem, GStringsPanel *panel)
 {
+    GtkBuilder *builder;                    /* Constructeur utilisé        */
+    GtkTreeView *treeview;                  /* Arborescence graphique      */
     GtkTreeSelection *selection;            /* Sélection de l'arbre        */
     GtkTreeIter iter;                       /* Point de sélection          */
     GtkTreeModel *model;                    /* Modèle de gestion           */
     gchar *string;                          /* Chaîne sélectionnée         */
     GtkClipboard *clipboard;                /* Presse-papiers d'arrivée    */
 
-    selection = gtk_tree_view_get_selection(panel->treeview);
+    builder = G_PANEL_ITEM(panel)->builder;
+
+    treeview = GTK_TREE_VIEW(gtk_builder_get_object(builder, "treeview"));
+
+    selection = gtk_tree_view_get_selection(treeview);
 
     if (gtk_tree_selection_get_selected(selection, &model, &iter))
     {
@@ -1055,7 +1258,7 @@ static void mcb_strings_panel_find_refs(GtkMenuItem *menuitem, GStringsPanel *pa
     vmpa2t *addr;                           /* Adresse de destination      */
     GLoadedPanel *display;                  /* Afficheur effectif de code  */
 
-    symbol = get_selected_panel_symbol(panel->treeview, NULL);
+    symbol = get_selected_panel_symbol(panel, NULL);
     if (symbol == NULL) return;
 
     range = g_binary_symbol_get_range(symbol);
@@ -1119,7 +1322,7 @@ static void mcb_strings_panel_filter(GtkMenuItem *menuitem, GStringsPanel *panel
 #if 0
     GCfgParam *param;                       /* Paramètre sélectionné       */
 
-    param = get_selected_panel_symbol(panel->treeview, NULL);
+    param = get_selected_panel_symbol(panel, NULL);
     if (param == NULL) return;
 
     g_config_param_make_empty(param);
@@ -1127,3 +1330,305 @@ static void mcb_strings_panel_filter(GtkMenuItem *menuitem, GStringsPanel *panel
     g_object_unref(G_OBJECT(param));
 #endif
 }
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                        MECANISMES DE MISE A JOUR DE PANNEAU                        */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : data  = données complémentaire à manipuler.                  *
+*                model = gestionnaire de l'ensemble des données.              *
+*                iter  = localisation des données à analyser.                 *
+*                match = récupération des trouvailles. [OUT]                  *
+*                                                                             *
+*  Description : Détermine si un nom de symbole doit être filtré ou non.      *
+*                                                                             *
+*  Retour      : true si le symbol ne doit pas être affiché, false sinon.     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool is_string_name_matching(const strings_update_data *data, GtkTreeModel *model, GtkTreeIter *iter, regmatch_t *match)
+{
+    bool result;                            /* Bilan à retourner           */
+    GBinSymbol *symbol;                     /* Symbole manipulé            */
+#ifndef NDEBUG
+    SymbolType type;                        /* Type associé au symbole     */
+#endif
+    const char *label;                      /* Etiquette à analyser        */
+
+    gtk_tree_model_get(model, iter, STC_SYMBOL, &symbol, -1);
+    assert(symbol != NULL);
+
+#ifndef NDEBUG
+
+    type = g_binary_symbol_get_target_type(symbol);
+
+    assert(type == STP_RO_STRING);
+
+#endif
+
+    label = g_binary_symbol_get_label(symbol);
+
+    if (label == NULL)
+        result = false;
+    else
+        result = is_content_matching(data->filter, label, match);
+
+    g_object_unref(G_OBJECT(symbol));
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : data  = données complémentaire à manipuler.                  *
+*                model = gestionnaire de l'ensemble des données.              *
+*                iter  = localisation des données à analyser.                 *
+*                match = récupération des trouvailles. [OUT]                  *
+*                                                                             *
+*  Description : Détermine si une valeur de symbole doit être filtrée ou non. *
+*                                                                             *
+*  Retour      : true si le symbol ne doit pas être affiché, false sinon.     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool is_string_value_matching(const strings_update_data *data, GtkTreeModel *model, GtkTreeIter *iter, regmatch_t *match)
+{
+    bool result;                            /* Bilan à retourner           */
+    char *original;                         /* Etiquette brute d'origine   */
+
+    gtk_tree_model_get(model, iter, STC_ORIGINAL, &original, -1);
+
+    result = is_content_matching(data->filter, original, match);
+
+    free(original);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : panel = panneau ciblé par une mise à jour.                   *
+*                uid   = identifiant de la phase de traitement.               *
+*                count = nombre d'étapes à prévoir dans le traitement. [OUT]  *
+*                data  = données sur lesquelles s'appuyer ensuite. [OUT]      *
+*                                                                             *
+*  Description : Prépare une opération de mise à jour de panneau.             *
+*                                                                             *
+*  Retour      : Description du message d'information.                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static const char *g_strings_panel_setup(const GStringsPanel *panel, unsigned int uid, size_t *count, strings_update_data **data)
+{
+    const char *result;                     /* Message à retourner         */
+    GBinFormat *format;                     /* Format du binaire           */
+    int ret;                                /* Bilan de mise en place      */
+
+    *data = malloc(sizeof(strings_update_data));
+
+    switch (uid)
+    {
+        case PUI_0:
+
+            format = G_BIN_FORMAT(g_loaded_binary_get_format(panel->binary));
+
+            g_binary_format_lock_symbols_rd(format);
+            *count = g_binary_format_count_symbols(format);
+            g_binary_format_unlock_symbols_rd(format);
+
+            g_object_unref(G_OBJECT(format));
+
+            (*data)->count = 0;
+
+            result = _("Loading strings available in the binary format...");
+
+            break;
+
+        case PUI_1:
+
+            *count = panel->count;
+            (*data)->count = panel->count;
+
+            result = _("Filtering strings available in the binary format...");
+
+            break;
+
+        default:    /* Pour GCC... */
+            assert(false);
+            result = "";
+            break;
+
+    }
+
+    if (G_PANEL_ITEM(panel)->filter != NULL)
+    {
+        (*data)->filter = (regex_t *)malloc(sizeof(regex_t));
+
+        ret = regcomp((*data)->filter, G_PANEL_ITEM(panel)->filter, REG_EXTENDED | REG_ICASE);
+        assert(ret == 0);
+
+    }
+
+    else
+        (*data)->filter = NULL;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : panel = panneau ciblé par une mise à jour.                   *
+*                uid   = identifiant de la phase de traitement.               *
+*                data  = données préparées par l'appelant.                    *
+*                                                                             *
+*  Description : Bascule l'affichage d'un panneau avant mise à jour.          *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : Cette fonction est appelée depuis le contexte principal.     *
+*                                                                             *
+******************************************************************************/
+
+static void g_strings_panel_introduce(const GStringsPanel *panel, unsigned int uid, strings_update_data *data)
+{
+    GtkBuilder *builder;                    /* Constructeur utilisé        */
+    GtkTreeView *treeview;                  /* Arborescence graphique      */
+    GtkTreeModel *model;                    /* Source de données associée  */
+
+    /* Basculement de l'affichage hors ligne */
+
+    g_panel_item_switch_to_updating_mask(G_PANEL_ITEM(panel));
+
+    builder = G_PANEL_ITEM(panel)->builder;
+
+    treeview = GTK_TREE_VIEW(gtk_builder_get_object(builder, "treeview"));
+
+    model = gtk_tree_view_get_model(treeview);
+
+    if (model != NULL)
+    {
+        g_object_ref(G_OBJECT(model));
+        gtk_tree_view_set_model(treeview, NULL);
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : panel  = panneau ciblé par une mise à jour.                  *
+*                uid    = identifiant de la phase de traitement.              *
+*                status = barre de statut à tenir informée.                   *
+*                id     = identifiant pour le suivi de la progression.        *
+*                data   = données préparées par l'appelant.                   *
+*                                                                             *
+*  Description : Réalise une opération de mise à jour de panneau.             *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_strings_panel_process(const GStringsPanel *panel, unsigned int uid, GtkStatusStack *status, activity_id_t id, strings_update_data *data)
+{
+    switch (uid)
+    {
+        case PUI_0:
+            reload_strings_for_new_list_view(panel, status, id, data);
+            break;
+
+        case PUI_1:
+            do_filtering_on_strings(panel, status, id, data);
+            break;
+
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : panel = panneau ciblé par une mise à jour.                   *
+*                uid   = identifiant de la phase de traitement.               *
+*                data  = données préparées par l'appelant.                    *
+*                                                                             *
+*  Description : Bascule l'affichage d'un panneau après mise à jour.          *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : Cette fonction est appelée depuis le contexte principal.     *
+*                                                                             *
+******************************************************************************/
+
+static void g_strings_panel_conclude(GStringsPanel *panel, unsigned int uid, strings_update_data *data)
+{
+    GtkBuilder *builder;                    /* Constructeur utilisé        */
+    GtkTreeView *treeview;                  /* Arborescence graphique      */
+    GtkTreeModel *model;                    /* Source de données associée  */
+
+    if (g_atomic_int_get(&G_PANEL_ITEM(panel)->switched) > 1)
+        goto skip_this_step;
+
+    /* Mise à jour des compteurs */
+
+    panel->count = data->count;
+
+    /* Basculement de l'affichage en ligne */
+
+    builder = G_PANEL_ITEM(panel)->builder;
+
+    treeview = GTK_TREE_VIEW(gtk_builder_get_object(builder, "treeview"));
+
+    model = GTK_TREE_MODEL(gtk_builder_get_object(builder, "filter"));
+
+    g_object_ref(G_OBJECT(model));
+    gtk_tree_view_set_model(treeview, model);
+
+ skip_this_step:
+
+    g_panel_item_switch_to_updated_content(G_PANEL_ITEM(panel));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : panel = panneau ciblé par une mise à jour.                   *
+*                uid   = identifiant de la phase de traitement.               *
+*                data  = données en place à nettoyer avant suppression.       *
+*                                                                             *
+*  Description : Supprime les données dynamiques utilisées à la mise à jour.  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_strings_panel_clean_data(GUpdatablePanel *panel, unsigned int uid, strings_update_data *data)
+{
+    if (data->filter != NULL)
+    {
+        regfree(data->filter);
+        free(data->filter);
+    }
+
+}
diff --git a/src/gui/panels/strings.ui b/src/gui/panels/strings.ui
new file mode 100644
index 0000000..fb8764f
--- /dev/null
+++ b/src/gui/panels/strings.ui
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.21.0 -->
+<interface>
+  <requires lib="gtk+" version="3.20"/>
+  <object class="GtkOffscreenWindow">
+    <property name="can_focus">False</property>
+    <child>
+      <object class="GtkBox" id="box">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="orientation">vertical</property>
+        <child>
+          <object class="GtkStack" id="stack">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <child>
+              <object class="GtkScrolledWindow" id="content">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="shadow_type">in</property>
+                <child>
+                  <object class="GtkTreeView" id="treeview">
+                    <property name="name">treeview</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="model">filter</property>
+                    <property name="headers_visible">False</property>
+                    <property name="search_column">2</property>
+                    <signal name="button-press-event" handler="on_button_event_over_strings" swapped="no"/>
+                    <signal name="button-release-event" handler="on_button_event_over_strings" swapped="no"/>
+                    <signal name="key-press-event" handler="on_key_pressed_over_strings" swapped="no"/>
+                    <child internal-child="selection">
+                      <object class="GtkTreeSelection">
+                        <signal name="changed" handler="on_strings_selection_change" swapped="no"/>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="name">page0</property>
+                <property name="title" translatable="yes">page0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkSpinner" id="mask">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="active">True</property>
+              </object>
+              <packing>
+                <property name="name">page1</property>
+                <property name="title" translatable="yes">page1</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">True</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <child type="titlebar">
+      <placeholder/>
+    </child>
+  </object>
+  <object class="GtkListStore" id="store">
+    <columns>
+      <!-- column-name symbol -->
+      <column type="GObject"/>
+      <!-- column-name physical -->
+      <column type="gchararray"/>
+      <!-- column-name virtual -->
+      <column type="gchararray"/>
+      <!-- column-name area -->
+      <column type="gchararray"/>
+      <!-- column-name name -->
+      <column type="gchararray"/>
+      <!-- column-name value -->
+      <column type="gchararray"/>
+      <!-- column-name original -->
+      <column type="gchararray"/>
+      <!-- column-name matched -->
+      <column type="gboolean"/>
+    </columns>
+  </object>
+  <object class="GtkTreeModelFilter" id="filter">
+    <property name="child_model">store</property>
+  </object>
+</interface>
diff --git a/src/gui/panels/symbols.c b/src/gui/panels/symbols.c
index fe295e0..fab82a9 100644
--- a/src/gui/panels/symbols.c
+++ b/src/gui/panels/symbols.c
@@ -62,8 +62,6 @@ struct _GSymbolsPanel
 
     size_t count;                           /* Quantité de symboles utiles */
 
-    regex_t *filter;                        /* Filtre appliqué ou NULL     */
-
 };
 
 /* Panneau d'affichage des symboles (classe) */
@@ -92,10 +90,11 @@ typedef enum _SymbolsColumn
 
     SBC_EXPAND,                             /* Affichage des classes       */
     SBC_MATCHED,                            /* Correspondance établie ?    */
-    SBC_MATCH_POINTS                        /* Nombre de demandeurs        */
+    SBC_MATCH_POINTS,                       /* Nombre de demandeurs        */
 
-} SymbolsColumn;
+    SBC_COUNT                               /* Nombre de colonnes          */
 
+} SymbolsColumn;
 
 
 /* Données utiles à la mise à jour */
@@ -109,7 +108,7 @@ static void g_symbols_panel_class_init(GSymbolsPanelClass *);
 static void g_symbols_panel_init(GSymbolsPanel *);
 
 /* Procède à l'initialisation de l'interface de mise à jour. */
-static void g_symbols_panel_interface_init(GUpdatablePanelInterface *);
+static void g_symbols_panel_updatable_interface_init(GUpdatablePanelInterface *);
 
 /* Supprime toutes les références externes. */
 static void g_symbols_panel_dispose(GSymbolsPanel *);
@@ -177,15 +176,9 @@ static void update_symbol_name_in_tree_view(const GSymbolsPanel *, GtkTreeStore
 /* Démarre l'actualisation du filtrage des symboles. */
 static void on_symbols_filter_changed(GtkSearchEntry *, GSymbolsPanel *);
 
-/* Met à jour l'affichage des noeuds en fonction des besoin. */
-static void update_symbol_visibility(GtkTreeStore *, GtkTreeIter *, bool);
-
 /* Exécute un nouveau filtrage des symboles affichés. */
 static void do_filtering_on_symbols(const GSymbolsPanel *, GtkStatusStack *, activity_id_t, symbols_update_data *);
 
-/* Détermine si un nom de symbole doit être filtré ou non. */
-static bool is_symbol_matching(const GSymbolsPanel *, const GBinSymbol *, regmatch_t *);
-
 
 /* ---------------------- MECANISMES DE MISE A JOUR DE PANNEAU ---------------------- */
 
@@ -195,6 +188,8 @@ struct _symbols_update_data
 {
     size_t count;                           /* Qté d'inscriptions réalisées*/
 
+    regex_t *filter;                        /* Filtre appliqué ou NULL     */
+
     char **expanded;                        /* Chemins des noeuds ouverts  */
     size_t ecount;                          /* Nombre de ces chemins       */
     size_t eallocated;                      /* Espace alloué effectivement */
@@ -205,6 +200,9 @@ struct _symbols_update_data
 #define EXPAND_ALLOC_RANGE 10
 
 
+/* Détermine si un nom de symbole doit être filtré ou non. */
+static bool is_symbol_matching(const symbols_update_data *, const GBinSymbol *, regmatch_t *);
+
 /* Prépare une opération de mise à jour de panneau. */
 static const char *g_symbols_panel_setup(const GSymbolsPanel *, unsigned int, size_t *, symbols_update_data **);
 
@@ -229,7 +227,7 @@ static void g_symbols_panel_clean_data(GUpdatablePanel *, unsigned int, symbols_
 
 /* Indique le type définit pour un panneau d'affichage des symboles. */
 G_DEFINE_TYPE_WITH_CODE(GSymbolsPanel, g_symbols_panel, G_TYPE_PANEL_ITEM,
-                        G_IMPLEMENT_INTERFACE(G_TYPE_UPDATABLE_PANEL, g_symbols_panel_interface_init));
+                        G_IMPLEMENT_INTERFACE(G_TYPE_UPDATABLE_PANEL, g_symbols_panel_updatable_interface_init));
 
 
 /******************************************************************************
@@ -248,8 +246,8 @@ static void g_symbols_panel_class_init(GSymbolsPanelClass *klass)
 {
     GObjectClass *object;                   /* Autre version de la classe  */
     GEditorItemClass *editem;               /* Encore une autre vision...  */
-    gchar *filename;                        /* Chemin d'accès à utiliser   */
     GPanelItemClass *panel;                 /* Version parente de la classe*/
+    gchar *filename;                        /* Chemin d'accès à utiliser   */
 
     object = G_OBJECT_CLASS(klass);
 
@@ -260,6 +258,13 @@ static void g_symbols_panel_class_init(GSymbolsPanelClass *klass)
 
     editem->update_binary = (update_item_binary_fc)change_symbols_panel_current_binary;
 
+    panel = G_PANEL_ITEM_CLASS(klass);
+
+    panel->unique = true;
+    panel->bindings = "<Shift>F3";
+
+    panel->gid = setup_tiny_global_work_group(1);
+
     filename = find_pixmap_file("symbol_routine_classic.png");
     assert(filename != NULL);
 
@@ -288,13 +293,6 @@ static void g_symbols_panel_class_init(GSymbolsPanelClass *klass)
 
     g_free(filename);
 
-    panel = G_PANEL_ITEM_CLASS(klass);
-
-    panel->unique = true;
-    panel->bindings = "<Shift>F3";
-
-    panel->gid = setup_tiny_global_work_group(1);
-
 }
 
 
@@ -315,8 +313,8 @@ static void g_symbols_panel_init(GSymbolsPanel *panel)
     GEditorItem *base;                      /* Version basique d'instance  */
     GPanelItem *pitem;                      /* Version parente du panneau  */
     GtkBuilder *builder;                    /* Constructeur utilisé        */
-    GtkTreeView *treeview;                  /* Affichage de la liste       */
     GtkTreeModelFilter *filter;             /* Filtre pour l'arborescence  */
+    GtkTreeView *treeview;                  /* Affichage de la liste       */
     GtkCellRenderer *renderer;              /* Moteur de rendu de colonne  */
     GtkTreeViewColumn *column;              /* Colonne de la liste         */
 
@@ -399,7 +397,7 @@ static void g_symbols_panel_init(GSymbolsPanel *panel)
 *                                                                             *
 ******************************************************************************/
 
-static void g_symbols_panel_interface_init(GUpdatablePanelInterface *iface)
+static void g_symbols_panel_updatable_interface_init(GUpdatablePanelInterface *iface)
 {
     iface->setup = (setup_updatable_cb)g_symbols_panel_setup;
     iface->get_group = (get_updatable_group_cb)g_panel_item_get_group;
@@ -447,12 +445,6 @@ static void g_symbols_panel_dispose(GSymbolsPanel *panel)
 
 static void g_symbols_panel_finalize(GSymbolsPanel *panel)
 {
-    if (panel->filter != NULL)
-    {
-        regfree(panel->filter);
-        free(panel->filter);
-    }
-
     G_OBJECT_CLASS(g_symbols_panel_parent_class)->finalize(G_OBJECT(panel));
 
 }
@@ -738,7 +730,7 @@ static void reload_symbols_for_new_list_view(const GSymbolsPanel *panel, GtkStat
     const char *original;                   /* Etiquette brute d'origine   */
     char *name;                             /* Etiquette mise en relief    */
     const vmpa2t *addr;                     /* Localisation d'un symbole   */
-    char virt[VMPA_MAX_LEN];                /* Version humainement lisible */
+    VMPA_BUFFER(virt);                      /* Version humainement lisible */
     GtkTreeIter iter;                       /* Point d'insertion           */
 
     builder = G_PANEL_ITEM(panel)->builder;
@@ -774,7 +766,7 @@ static void reload_symbols_for_new_list_view(const GSymbolsPanel *panel, GtkStat
         if (icon == NULL)
             goto rsfnlv_next;
 
-        matched = is_symbol_matching(panel, symbol, &match);
+        matched = is_symbol_matching(data, symbol, &match);
 
         original = g_binary_symbol_get_label(symbol);
 
@@ -798,7 +790,7 @@ static void reload_symbols_for_new_list_view(const GSymbolsPanel *panel, GtkStat
                            -1);
 
         if (matched)
-            update_symbol_visibility(store, &iter, true);
+            update_node_visibility(store, &iter, SBC_MATCHED, true);
 
         data->count++;
 
@@ -809,6 +801,8 @@ static void reload_symbols_for_new_list_view(const GSymbolsPanel *panel, GtkStat
 
         g_object_unref(G_OBJECT(symbol));
 
+        gtk_status_stack_update_activity_value(status, id, 1);
+
     }
 
     delete_symbol_iterator(siter);
@@ -1050,7 +1044,7 @@ static void reload_symbols_for_new_tree_view(const GSymbolsPanel *panel, GtkStat
         if (icon == NULL)
             goto rsfntv_next;
 
-        matched = is_symbol_matching(panel, symbol, &match);
+        matched = is_symbol_matching(data, symbol, &match);
 
         if (find_parent_for_symbol(panel, symbol, &parent, &match, &last))
         {
@@ -1086,7 +1080,7 @@ static void reload_symbols_for_new_tree_view(const GSymbolsPanel *panel, GtkStat
                            -1);
 
         if (matched)
-            update_symbol_visibility(store, &iter, true);
+            update_node_visibility(store, &iter, SBC_MATCHED, true);
 
         data->count++;
 
@@ -1097,6 +1091,8 @@ static void reload_symbols_for_new_tree_view(const GSymbolsPanel *panel, GtkStat
 
         g_object_unref(G_OBJECT(symbol));
 
+        gtk_status_stack_update_activity_value(status, id, 1);
+
     }
 
     delete_symbol_iterator(siter);
@@ -1310,7 +1306,7 @@ static void update_symbol_name_in_tree_view(const GSymbolsPanel *panel, GtkTreeS
 
 static void on_symbols_filter_changed(GtkSearchEntry *entry, GSymbolsPanel *panel)
 {
-    update_regex_on_search_entry_changed(entry, &panel->filter);
+    update_regex_on_search_entry_changed(entry, &G_PANEL_ITEM(panel)->filter);
 
     run_panel_update(G_UPDATABLE_PANEL(panel), PUI_1);
 
@@ -1319,68 +1315,6 @@ static void on_symbols_filter_changed(GtkSearchEntry *entry, GSymbolsPanel *pane
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : store = organisation des données sous forme arborescente.    *
-*                iter  = position du noeud courant à traiter.                 *
-*                show  = visibilité à obtenir pour le noeud final.            *
-*                                                                             *
-*  Description : Met à jour l'affichage des noeuds en fonction des besoin.    *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void update_symbol_visibility(GtkTreeStore *store, GtkTreeIter *iter, bool show)
-{
-    GtkTreeModel *model;                    /* Autre vision du gestionnaire*/
-    guint points;                           /* Compteur de besoins         */
-    GtkTreeIter parent;                     /* Position de noeuf parent    */
-    gboolean further;                       /* Poursuite de remontée       */
-
-    model = GTK_TREE_MODEL(store);
-
-    /* Enumération des besoins */
-
-    gtk_tree_model_get(model, iter, SBC_MATCH_POINTS, &points, -1);
-
-    if (show)
-        points++;
-
-    else
-    {
-        assert(points > 0);
-        points--;
-    }
-
-    gtk_tree_store_set(store, iter, SBC_MATCH_POINTS, points, -1);
-
-    /* Adaptation de l'affichage */
-
-    if (show)
-    {
-        if (points == 1)
-            gtk_tree_store_set(store, iter, SBC_MATCHED, true, -1);
-    }
-
-    else
-    {
-        if (points == 0)
-            gtk_tree_store_set(store, iter, SBC_MATCHED, false, -1);
-    }
-
-    /* Eventuel étage supérieur */
-
-    further = gtk_tree_model_iter_parent(model, &parent, iter);
-
-    if (further)
-        update_symbol_visibility(store, &parent, show);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
 *  Paramètres  : panel  = panneau assurant l'affichage des symboles.          *
 *                status = barre de statut à tenir informée.                   *
 *                id     = identifiant pour le suivi de la progression.        *
@@ -1413,30 +1347,34 @@ static void do_filtering_on_symbols(const GSymbolsPanel *panel, GtkStatusStack *
 
         if (symbol != NULL)
         {
-            matched = is_symbol_matching(panel, symbol, &match);
+            matched = is_symbol_matching(data, symbol, &match);
+
+            if (matched)
+            {
+                if (*as_list)
+                    update_symbol_name_in_list_view(store, iter, &match);
+                else
+                    update_symbol_name_in_tree_view(panel, store, symbol, &match);
+            }
 
             gtk_tree_model_get(model, iter, SBC_MATCHED, &shown, -1);
 
             if (!matched)
             {
                 if (shown)
-                    update_symbol_visibility(store, iter, false);
+                    update_node_visibility(store, iter, SBC_MATCHED, false);
             }
 
             else
             {
-                if (*as_list)
-                    update_symbol_name_in_list_view(store, iter, &match);
-                else
-                    update_symbol_name_in_tree_view(panel, store, symbol, &match);
-
                 if (!shown)
-                    update_symbol_visibility(store, iter, true);
-
+                    update_node_visibility(store, iter, SBC_MATCHED, true);
             }
 
             g_object_unref(G_OBJECT(symbol));
 
+            gtk_status_stack_update_activity_value(status, id, 1);
+
         }
 
         return FALSE;
@@ -1456,9 +1394,15 @@ static void do_filtering_on_symbols(const GSymbolsPanel *panel, GtkStatusStack *
 }
 
 
+
+/* ---------------------------------------------------------------------------------- */
+/*                        MECANISMES DE MISE A JOUR DE PANNEAU                        */
+/* ---------------------------------------------------------------------------------- */
+
+
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : panel  = panneau assurant l'affichage des symboles.          *
+*  Paramètres  : data   = données complémentaire à manipuler.                 *
 *                symbol = symbole à traiter.                                  *
 *                match  = récupération des trouvailles. [OUT]                 *
 *                                                                             *
@@ -1470,7 +1414,7 @@ static void do_filtering_on_symbols(const GSymbolsPanel *panel, GtkStatusStack *
 *                                                                             *
 ******************************************************************************/
 
-static bool is_symbol_matching(const GSymbolsPanel *panel, const GBinSymbol *symbol, regmatch_t *match)
+static bool is_symbol_matching(const symbols_update_data *data, const GBinSymbol *symbol, regmatch_t *match)
 {
     bool result;                            /* Bilan à retourner           */
 #ifndef NDEBUG
@@ -1485,19 +1429,13 @@ static bool is_symbol_matching(const GSymbolsPanel *panel, const GBinSymbol *sym
 
 #endif
 
-    result = is_content_matching(panel->filter, g_binary_symbol_get_label(symbol), match);
+    result = is_content_matching(data->filter, g_binary_symbol_get_label(symbol), match);
 
     return result;
 
 }
 
 
-
-/* ---------------------------------------------------------------------------------- */
-/*                        MECANISMES DE MISE A JOUR DE PANNEAU                        */
-/* ---------------------------------------------------------------------------------- */
-
-
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : panel = panneau ciblé par une mise à jour.                   *
@@ -1517,6 +1455,7 @@ static const char *g_symbols_panel_setup(const GSymbolsPanel *panel, unsigned in
 {
     const char *result;                     /* Message à retourner         */
     GBinFormat *format;                     /* Format du binaire           */
+    int ret;                                /* Bilan de mise en place      */
     GtkBuilder *builder;                    /* Constructeur utilisé        */
     GtkTreeView *treeview;                  /* Arborescence graphique      */
 
@@ -1556,6 +1495,18 @@ static const char *g_symbols_panel_setup(const GSymbolsPanel *panel, unsigned in
 
     }
 
+    if (G_PANEL_ITEM(panel)->filter != NULL)
+    {
+        (*data)->filter = (regex_t *)malloc(sizeof(regex_t));
+
+        ret = regcomp((*data)->filter, G_PANEL_ITEM(panel)->filter, REG_EXTENDED | REG_ICASE);
+        assert(ret == 0);
+
+    }
+
+    else
+        (*data)->filter = NULL;
+
     /* Mémorisation de tous les noeuds ouverts */
 
     builder = G_PANEL_ITEM(panel)->builder;
@@ -1742,6 +1693,12 @@ static void g_symbols_panel_clean_data(GUpdatablePanel *panel, unsigned int uid,
 {
     size_t i;                               /* Boucle de parcours          */
 
+    if (data->filter != NULL)
+    {
+        regfree(data->filter);
+        free(data->filter);
+    }
+
     for (i = 0; i < data->ecount; i++)
         g_free(data->expanded[i]);
 
-- 
cgit v0.11.2-87-g4458