summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/params.c3
-rw-r--r--src/core/params.h1
-rw-r--r--src/gtkext/gtkdockable-int.h12
-rw-r--r--src/gtkext/gtkdockable.c65
-rw-r--r--src/gtkext/tmgt.c118
-rw-r--r--src/gtkext/tmgt.h5
-rw-r--r--src/gui/panels/Makefile.am1
-rw-r--r--src/gui/panels/bintree.c922
-rw-r--r--src/gui/panels/bintree.ui59
-rw-r--r--src/gui/panels/bookmarks.c55
-rw-r--r--src/gui/panels/gresource.xml1
-rw-r--r--src/gui/panels/panel-int.h14
-rw-r--r--src/gui/panels/panel.c102
-rw-r--r--src/gui/panels/panel.h12
-rw-r--r--src/gui/panels/strings.c1015
-rw-r--r--src/gui/panels/strings.ui93
-rw-r--r--src/gui/panels/symbols.c185
17 files changed, 1969 insertions, 694 deletions
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 *);
-/* ------------------------- FILTRAGE DES SYMBOLES PRESENTS ------------------------- */
+
+/* ------------------------- 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 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 un noeud de l'arborescence doit être filtré. */
+static void update_string_node(const strings_update_data *, GtkListStore *, GtkTreeIter *);
-/* Détermine si une chaîne textuelle doit être filtrée ou non. */
-static bool is_string_filtered(GStringsPanel *, const char *, const char *);
+/* 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);
-
- /* 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);
+ builder = g_panel_item_build(pitem, "strings");
- 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 */
+ /* Connexion des signaux */
- select = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview));
- gtk_tree_selection_set_mode(select, GTK_SELECTION_SINGLE);
+ 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);
- g_generic_config_get_value(get_main_configuration(), MPK_DISPLAY_ON_SEL, &display);
-
- 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,64 @@ static void on_string_value_edited(GtkCellRendererText *renderer, gchar *path, g
}
+/******************************************************************************
+* *
+* 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)
+{
+ GtkBuilder *builder; /* Constructeur utilisé */
+ GtkListStore *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));
+
+ /* Réinitialisation */
+
+ builder = G_PANEL_ITEM(panel)->builder;
+
+ store = GTK_LIST_STORE(gtk_builder_get_object(builder, "store"));
+
+ gtk_list_store_clear(store);
+
+ /* Si le panneau actif représente un binaire, actualisation de l'affichage */
+
+ if (binary != NULL)
+ run_panel_update(G_UPDATABLE_PANEL(panel), PUI_0);
+
+}
+
+
/* ---------------------------------------------------------------------------------- */
-/* FILTRAGE DES SYMBOLES PRESENTS */
+/* AFFICHAGE A L'AIDE D'UNE LISTE */
/* ---------------------------------------------------------------------------------- */
/******************************************************************************
* *
-* Paramètres : panel = panneau assurant l'affichage des paramètres. *
-* preg = expression régulière compilée à utiliser. *
+* 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 : Démarre l'actualisation du filtrage des chaînes. *
+* Description : Réagit à un changement d'affichage principal de contenu. *
* *
* Retour : - *
* *
@@ -757,50 +703,289 @@ static void on_string_value_edited(GtkCellRendererText *renderer, gchar *path, g
* *
******************************************************************************/
-static void update_filtered_strings(GStringsPanel *panel, const regex_t *preg)
+static void reload_strings_for_new_list_view(const GStringsPanel *panel, GtkStatusStack *status, activity_id_t id, strings_update_data *data)
{
- panel->filter = preg;
+ 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 */
+
+ builder = G_PANEL_ITEM(panel)->builder;
+
+ store = GTK_LIST_STORE(gtk_builder_get_object(builder, "store"));
+
+ proc = g_loaded_binary_get_processor(panel->binary);
+ size = g_arch_processor_get_memory_size(proc);
+ g_object_unref(G_OBJECT(proc));
+
+ 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));
+
+ 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 rsfnlv_next;
+
+ range = g_binary_symbol_get_range(symbol);
+ addr = get_mrange_addr(range);
+
+ vmpa2_phys_to_string(addr, size, phys, NULL);
+ vmpa2_virt_to_string(addr, size, 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));
+
+ 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 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);
- change_strings_panel_current_binary(panel, panel->binary);
+ 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 : 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. *
+* Paramètres : store = gestionnaire de données pour une arborescence. *
+* iter = position des données traitées. *
+* match = correspondance avec un objet recherché. *
* *
-* Description : Détermine si une chaîne textuelle doit être filtrée ou non. *
+* Description : Met en surbrillance les éléments recherchés dans les noms. *
* *
-* Retour : true si le symbole ne doit pas être affiché, false sinon. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-static bool is_string_filtered(GStringsPanel *panel, const char *label, const char *value)
+static void update_string_label_in_list_view(GtkListStore *store, GtkTreeIter *iter, const regmatch_t *match)
{
- bool result; /* Bilan à retourner */
+ 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*/
- int ret; /* Bilan du filtrage */
+ 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);
+
+}
+
- if (panel->filter == NULL)
- return false;
+/******************************************************************************
+* *
+* 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 */
- result = true;
- if (label != NULL)
+ gboolean filter_string_panel_iter(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer unused)
{
- ret = regexec(panel->filter, label, 1, &match, 0);
- result &= (ret == REG_NOMATCH);
+ update_string_node(data, store, iter);
+
+ gtk_status_stack_update_activity_value(status, id, 1);
+
+ return FALSE;
+
}
- ret = regexec(panel->filter, value, 1, &match, 0);
- result &= (ret == REG_NOMATCH);
- return result;
+ 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);
}
@@ -845,7 +1030,7 @@ static gboolean on_button_event_over_strings(GtkWidget *widget, GdkEventButton *
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));
@@ -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]);