summaryrefslogtreecommitdiff
path: root/src/gui/panels/bintree.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/panels/bintree.c')
-rw-r--r--src/gui/panels/bintree.c922
1 files changed, 741 insertions, 181 deletions
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);
+
}