summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2013-06-09 14:01:57 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2013-06-09 14:01:57 (GMT)
commited59530ca0cc8e4cf03ea8328122bb3d279840a9 (patch)
tree198e3dc3ebdf9208c67eff6f721411459df11cb5 /src
parent122307427c5d7ab25b985b01f145dad3a848ed51 (diff)
Improved the whole symbols panel and added a filter on it.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@351 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
Diffstat (limited to 'src')
-rw-r--r--src/gtkext/easygtk.c11
-rw-r--r--src/gtkext/easygtk.h4
-rw-r--r--src/gui/panels/symbols.c327
3 files changed, 294 insertions, 48 deletions
diff --git a/src/gtkext/easygtk.c b/src/gtkext/easygtk.c
index 2d000e7..be65578 100644
--- a/src/gtkext/easygtk.c
+++ b/src/gtkext/easygtk.c
@@ -800,6 +800,7 @@ GtkWidget *qck_create_menu_separator(void)
* *
* Paramètres : object = espace dédié à l'inscription de références. *
* name = nom à donner au nouveau composant. *
+* caption = étquette pour le bouton ou NULL. *
* filename = nom du fichier d'image à charger. *
* handler = éventuelle fonction de sélection associée. *
* data = données à transmettre avec l'événement si besoin. *
@@ -812,13 +813,13 @@ GtkWidget *qck_create_menu_separator(void)
* *
******************************************************************************/
-GtkWidget *qck_create_tool_button(GObject *object, const char *name, const char *filename, GCallback handler, gpointer data)
+GtkWidget *qck_create_tool_button(GObject *object, const char *name, const char *caption, const char *filename, GCallback handler, gpointer data)
{
GtkWidget *result; /* Résultat à renvoyer */
GtkWidget *image; /* Image de représentation */
image = get_image_from_file(filename);
- result = GTK_WIDGET(gtk_tool_button_new(image, NULL));
+ result = GTK_WIDGET(gtk_tool_button_new(image, caption));
if (G_IS_OBJECT(object) && name != NULL)
{
@@ -840,6 +841,7 @@ GtkWidget *qck_create_tool_button(GObject *object, const char *name, const char
* *
* Paramètres : object = espace dédié à l'inscription de références. *
* name = nom à donner au nouveau composant. *
+* caption = étquette pour le bouton ou NULL. *
* filename = nom du fichier d'image à charger. *
* handler = éventuelle fonction de sélection associée. *
* data = données à transmettre avec l'événement si besoin. *
@@ -852,13 +854,16 @@ GtkWidget *qck_create_tool_button(GObject *object, const char *name, const char
* *
******************************************************************************/
-GtkWidget *qck_create_toggle_tool_button(GObject *object, const char *name, const char *filename, GCallback handler, gpointer data)
+GtkWidget *qck_create_toggle_tool_button(GObject *object, const char *name, const char *caption, const char *filename, GCallback handler, gpointer data)
{
GtkWidget *result; /* Résultat à renvoyer */
GtkWidget *image; /* Image de représentation */
result = GTK_WIDGET(gtk_toggle_tool_button_new());
+ if (caption != NULL)
+ gtk_tool_button_set_label(GTK_TOOL_BUTTON(result), caption);
+
image = get_image_from_file(filename);
gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(result), image);
diff --git a/src/gtkext/easygtk.h b/src/gtkext/easygtk.h
index 815e5c2..31a2b78 100644
--- a/src/gtkext/easygtk.h
+++ b/src/gtkext/easygtk.h
@@ -99,10 +99,10 @@ GtkWidget *qck_create_menu_separator(void);
/* Crée et enregistre un composant 'GtkToolButton'. */
-GtkWidget *qck_create_tool_button(GObject *, const char *, const char *, GCallback, gpointer);
+GtkWidget *qck_create_tool_button(GObject *, const char *, const char *, const char *, GCallback, gpointer);
/* Crée et enregistre un composant 'GtkToggleToolButton'. */
-GtkWidget *qck_create_toggle_tool_button(GObject *, const char *, const char *, GCallback, gpointer);
+GtkWidget *qck_create_toggle_tool_button(GObject *, const char *, const char *, const char *, GCallback, gpointer);
/* Crée et enregistre un composant 'GtkSeparatorToolItem'. */
GtkWidget *qck_create_tool_separator(GObject *, const char *);
diff --git a/src/gui/panels/symbols.c b/src/gui/panels/symbols.c
index 0073318..c04b460 100644
--- a/src/gui/panels/symbols.c
+++ b/src/gui/panels/symbols.c
@@ -25,7 +25,13 @@
#include "symbols.h"
+#include <i18n.h>
+
+
+#include <malloc.h>
+#include <regex.h>
#include <string.h>
+#include <gdk/gdkkeysyms.h>
#include "panel-int.h"
@@ -48,8 +54,9 @@ struct _GSymbolsPanel
GLoadedBinary *binary; /* Binaire à prendre en compte */
-};
+ regex_t *filter; /* Filtre appliqué ou NULL */
+};
/* Panneau d'aperçu de graphiques (classe) */
struct _GSymbolsPanelClass
@@ -80,6 +87,9 @@ static void g_symbols_panel_class_init(GSymbolsPanelClass *);
/* Initialise une instance de panneau d'aperçu de graphiques. */
static void g_symbols_panel_init(GSymbolsPanel *);
+/* Réagit au changement d'affichage des symboles. */
+static void on_symbols_display_change(GtkToggleToolButton *, GSymbolsPanel *);
+
/* Réagit au changement de sélection des symboles. */
static void on_symbols_selection_change(GtkTreeSelection *, GSymbolsPanel *);
@@ -114,8 +124,22 @@ static void reorganize_symbols_tree_view(GtkToolButton *, GObject *);
/* Fait en sorte que toutes les classes soient affichées. */
static gboolean show_all_classes_in_tree_view(GtkTreeModel *, GtkTreePath *, GtkTreeIter *, GtkTreeView *);
-/* Réagit à une demande de nouvelle forme d'affichage. */
-static void modify_types_in_symbols_tree_view(GtkToggleToolButton *, GObject *);
+
+
+/* ------------------------- FILTRAGE DES SYMBOLES PRESENTS ------------------------- */
+
+
+/* Démarre l'actualisation du filtrage des symboles. */
+static gboolean filter_symbols_from_key_press(GtkEntry *, GdkEventKey *, GSymbolsPanel *);
+
+/* Démarre l'actualisation du filtrage des symboles. */
+static void filter_symbols_from_icons(GtkEntry *, GtkEntryIconPosition, GdkEventButton *, GSymbolsPanel *);
+
+/* Exécute un nouveau filtrage des symboles affichés. */
+static void do_filtering_on_symbols(GSymbolsPanel *, GtkEntry *);
+
+/* Détermine si un nom de symbole doit être filtré ou non. */
+static bool is_symbol_filtered(GSymbolsPanel *, const char *);
@@ -162,9 +186,11 @@ static void g_symbols_panel_init(GSymbolsPanel *panel)
{
GEditorItem *base; /* Version basique d'instance */
GObject *ref; /* Espace de référencement */
+ GtkWidget *box; /* Séparation horizontale */
GtkWidget *toolbar; /* Barre d'outils */
GtkWidget *button; /* Bouton de cette même barre */
GtkWidget *separator; /* Barre de séparation vert. */
+ GtkWidget *entry; /* Zone de recherche */
GtkWidget *scrollwnd; /* Support défilant */
GtkWidget *treeview; /* Affichage de la liste */
GtkCellRenderer *renderer; /* Moteur de rendu de colonne */
@@ -181,44 +207,64 @@ static void g_symbols_panel_init(GSymbolsPanel *panel)
/* Barre d'outils supérieure */
+ box = gtk_hbox_new(FALSE, 0);
+ gtk_widget_show(box);
+ gtk_box_pack_start(GTK_BOX(base->widget), box, FALSE, FALSE, 0);
+
toolbar = gtk_toolbar_new();
gtk_widget_show(toolbar);
- gtk_box_pack_start(GTK_BOX(base->widget), toolbar, FALSE, FALSE, 0);
-
- //group = gtk_tool_item_group_new(_("View"));
- //gtk_widget_show(group);
- //gtk_container_add(GTK_CONTAINER(toolbar), group);
-
- button = qck_create_toggle_tool_button(ref, "list", "tbutton_list_view.png", G_CALLBACK(NULL), NULL);
- gtk_container_add(GTK_CONTAINER(toolbar), button);
- //gtk_tool_item_group_insert(GTK_TOOL_ITEM_GROUP(group), GTK_TOOL_ITEM(button), -1);
-
- button = qck_create_toggle_tool_button(ref, "tree", "tbutton_tree_view.png", G_CALLBACK(NULL), NULL);
- gtk_container_add(GTK_CONTAINER(toolbar), button);
+ gtk_box_pack_start(GTK_BOX(box), toolbar, TRUE, TRUE, 0);
+
+ button = qck_create_toggle_tool_button(ref, "list", _("List"), "tbutton_list_view.png",
+ G_CALLBACK(on_symbols_display_change), panel);
+ gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(button),
+ _("Show symbols using a list view"));
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar), GTK_TOOL_ITEM(button), -1);
+
+ button = qck_create_toggle_tool_button(ref, "tree", _("Tree"), "tbutton_tree_view.png",
+ G_CALLBACK(on_symbols_display_change), panel);
+ gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(button),
+ _("Show symbols using a tree view"));
gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(button), TRUE);
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar), GTK_TOOL_ITEM(button), -1);
+ separator = qck_create_tool_separator(NULL, NULL);
+ gtk_container_add(GTK_CONTAINER(toolbar), separator);
- //gtk_tool_item_group_insert(GTK_TOOL_ITEM_GROUP(group), GTK_TOOL_ITEM(button), -1);
+ button = qck_create_tool_button(ref, "collapse", _("Collapse"), "tbutton_collapse.png",
+ G_CALLBACK(reorganize_symbols_tree_view), ref);
+ gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(button),
+ _("Collapse all symbol nodes in the tree view"));
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar), GTK_TOOL_ITEM(button), -1);
+ button = qck_create_tool_button(ref, "expand", _("Expand"), "tbutton_expand.png",
+ G_CALLBACK(reorganize_symbols_tree_view), ref);
+ gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(button),
+ _("Expand all symbol nodes in the tree view"));
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar), GTK_TOOL_ITEM(button), -1);
+ button = qck_create_tool_button(ref, "classes", _("Classes"), "symbol_class_classic.png",
+ G_CALLBACK(reorganize_symbols_tree_view), ref);
+ gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(button),
+ _("Show all classes in the tree view"));
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar), GTK_TOOL_ITEM(button), -1);
separator = qck_create_tool_separator(NULL, NULL);
gtk_container_add(GTK_CONTAINER(toolbar), separator);
- button = qck_create_tool_button(ref, "collapse", "tbutton_collapse.png", G_CALLBACK(reorganize_symbols_tree_view), ref);
- gtk_container_add(GTK_CONTAINER(toolbar), button);
+ /* Espace de recherche */
- button = qck_create_tool_button(ref, "expand", "tbutton_expand.png", G_CALLBACK(reorganize_symbols_tree_view), ref);
- gtk_container_add(GTK_CONTAINER(toolbar), button);
+ entry = qck_create_entry(ref, "search", "");
+ gtk_widget_set_tooltip_text(entry, _("Filter symbols using POSIX extended regular expressions"));
- button = qck_create_tool_button(ref, "classes", "symbol_class_classic.png", G_CALLBACK(reorganize_symbols_tree_view), ref);
- gtk_container_add(GTK_CONTAINER(toolbar), button);
+ gtk_entry_set_icon_from_stock(GTK_ENTRY(entry), GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_FIND);
- separator = qck_create_tool_separator(NULL, NULL);
- gtk_container_add(GTK_CONTAINER(toolbar), separator);
+ g_signal_connect(G_OBJECT(entry), "key-press-event",
+ G_CALLBACK(filter_symbols_from_key_press), panel);
+ g_signal_connect(G_OBJECT(entry), "icon-press",
+ G_CALLBACK(filter_symbols_from_icons), panel);
- button = qck_create_toggle_tool_button(ref, "namespace", "tbutton_namespace.png", G_CALLBACK(modify_types_in_symbols_tree_view), ref);
- gtk_container_add(GTK_CONTAINER(toolbar), button);
+ gtk_box_pack_start(GTK_BOX(box), entry, TRUE, TRUE, 0);
/* Liste arborescente ou linéaire */
@@ -333,6 +379,72 @@ GPanelItem *create_symbols_panel(GObject *ref)
/******************************************************************************
* *
+* Paramètres : button = bouton de la barre activé. *
+* panel = structure contenant les informations maîtresses. *
+* *
+* Description : Réagit au changement d'affichage des symboles. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void on_symbols_display_change(GtkToggleToolButton *button, GSymbolsPanel *panel)
+{
+ GObject *ref; /* Espace de référencement */
+ GtkToggleToolButton *list; /* Bouton pour les listes */
+ GtkToggleToolButton *tree; /* Bouton pour l'arborescence */
+ gboolean state; /* Etat du bouton courant */
+ GtkToggleToolButton *other; /* Bouton à traiter */
+ GtkWidget *option; /* Bouton dont l'accès change */
+
+ ref = G_OBJECT(G_EDITOR_ITEM(panel)->widget);
+
+ list = GTK_TOGGLE_TOOL_BUTTON(g_object_get_data(ref, "list"));
+ tree = GTK_TOGGLE_TOOL_BUTTON(g_object_get_data(ref, "tree"));
+
+ /* Désactivation de l'autre bouton */
+
+ state = gtk_toggle_tool_button_get_active(button);
+
+ if (button == list) other = tree;
+ else other = list;
+
+ g_signal_handlers_disconnect_by_func(other, G_CALLBACK(on_symbols_display_change), panel);
+ gtk_toggle_tool_button_set_active(other, !state);
+ g_signal_connect(other, "toggled", G_CALLBACK(on_symbols_display_change), panel);
+
+ /* Définition des accès sur le reste de la barre */
+
+ state = gtk_toggle_tool_button_get_active(tree);
+
+ option = GTK_WIDGET(g_object_get_data(ref, "collapse"));
+ if (option != NULL)
+ gtk_widget_set_sensitive(option, state);
+
+ option = GTK_WIDGET(g_object_get_data(ref, "expand"));
+ if (option != NULL)
+ gtk_widget_set_sensitive(option, state);
+
+ option = GTK_WIDGET(g_object_get_data(ref, "classes"));
+ if (option != NULL)
+ gtk_widget_set_sensitive(option, state);
+
+ /* Actualisation */
+
+ if (panel->binary != NULL)
+ {
+ g_object_ref(G_OBJECT(panel->binary));
+ change_symbols_panel_current_binary(panel, panel->binary);
+ g_object_unref(G_OBJECT(panel->binary));
+ }
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : selection = sélection modifiée. *
* panel = structure contenant les informations maîtresses. *
* *
@@ -437,8 +549,10 @@ static void reload_symbols_for_new_list_view(GSymbolsPanel *panel)
size_t routines_count; /* Nombre de ces routines */
GArchProcessor *proc; /* Architecture utilisée */
size_t i; /* Boucle de parcours */
+ const char *name; /* Désignation du symbole */
vmpa_t address; /* Adresse associée au symbole */
char tmp[VMPA_MAX_SIZE]; /* Version humainement lisible */
+ GdkPixbuf *pixbuf; /* Icone pour l'élément inséré */
GtkTreeIter iter; /* Point d'insertion */
format = g_loaded_binary_get_format(panel->binary);
@@ -452,13 +566,21 @@ static void reload_symbols_for_new_list_view(GSymbolsPanel *panel)
for (i = 0; i < routines_count; i++)
{
+ name = g_binary_routine_to_string(routines[i]);
+
+ if (is_symbol_filtered(panel, name))
+ continue;
+
address = g_binary_routine_get_address(routines[i]);
vmpa_to_string(address, g_arch_processor_get_memory_size(proc), tmp);
+ pixbuf = get_pixbuf_from_file("symbol_routine_classic.png");
+
gtk_tree_store_append(panel->store, &iter, NULL);
gtk_tree_store_set(panel->store, &iter,
+ SBC_ICON, pixbuf,
SBC_ADDRESS, tmp,
- SBC_NAME, g_binary_routine_to_string(routines[i]),
+ SBC_NAME, name,
-1);
}
@@ -585,9 +707,8 @@ static void reload_symbols_for_new_tree_view(GSymbolsPanel *panel)
GBinRoutine **routines; /* Liste des routines trouvées */
size_t routines_count; /* Nombre de ces routines */
GArchProcessor *proc; /* Architecture utilisée */
- Routine2StringOptions options; /* Options de rendu */
- GtkToggleToolButton *button; /* Mode de représentation */
size_t i; /* Boucle de parcours */
+ const char *name; /* Désignation du symbole */
vmpa_t address; /* Adresse associée au symbole */
char tmp[VMPA_MAX_SIZE]; /* Version humainement lisible */
GtkTreeIter parent; /* Point d'insertion parent */
@@ -603,15 +724,13 @@ static void reload_symbols_for_new_tree_view(GSymbolsPanel *panel)
{
proc = get_arch_processor_from_format(format);
- options = 0;
-
- button = g_object_get_data(G_OBJECT(G_EDITOR_ITEM(panel)->widget), "namespace");
-
- if (gtk_toggle_tool_button_get_active(button))
- options |= RSO_LONG_TYPE;
-
for (i = 0; i < routines_count; i++)
{
+ name = g_binary_routine_to_string(routines[i]);
+
+ if (is_symbol_filtered(panel, name))
+ continue;
+
address = g_binary_routine_get_address(routines[i]);
vmpa_to_string(address, g_arch_processor_get_memory_size(proc), tmp);
@@ -635,7 +754,7 @@ static void reload_symbols_for_new_tree_view(GSymbolsPanel *panel)
gtk_tree_store_set(panel->store, &iter,
SBC_ICON, pixbuf,
SBC_ADDRESS, tmp,
- SBC_NAME, _g_binary_routine_to_string(routines[i], options),
+ SBC_NAME, name,
-1);
if (pixbuf != NULL)
@@ -720,12 +839,50 @@ static gboolean show_all_classes_in_tree_view(GtkTreeModel *model, GtkTreePath *
}
+
+/* ---------------------------------------------------------------------------------- */
+/* FILTRAGE DES SYMBOLES PRESENTS */
+/* ---------------------------------------------------------------------------------- */
+
+
/******************************************************************************
* *
-* Paramètres : button = bouton concerné par l'action. *
-* ref = espace de référencement des composants. *
+* Paramètres : entry = entrée de texte contenant le filtre brut. *
+* event = informations liées à l'événement. *
+* panel = panneau assurant l'affichage des symboles. *
+* *
+* Description : Démarre l'actualisation du filtrage des symboles. *
* *
-* Description : Réagit à une demande de nouvelle forme d'affichage. *
+* Retour : FALSE pour poursuivre la propagation de l'événement. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static gboolean filter_symbols_from_key_press(GtkEntry *entry, GdkEventKey *event, GSymbolsPanel *panel)
+{
+ switch (event->keyval)
+ {
+ case GDK_KEY_Return:
+ case GDK_KEY_KP_Enter:
+ do_filtering_on_symbols(panel, entry);
+ break;
+
+ }
+
+ return FALSE;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : entry = entrée de texte contenant le filtre brut. *
+* icon_pos = position de l'image de fond. *
+* event = informations liées à l'événement. *
+* panel = panneau assurant l'affichage des symboles. *
+* *
+* Description : Démarre l'actualisation du filtrage des symboles. *
* *
* Retour : - *
* *
@@ -733,12 +890,96 @@ static gboolean show_all_classes_in_tree_view(GtkTreeModel *model, GtkTreePath *
* *
******************************************************************************/
-static void modify_types_in_symbols_tree_view(GtkToggleToolButton *button, GObject *ref)
+static void filter_symbols_from_icons(GtkEntry *entry, GtkEntryIconPosition icon_pos, GdkEventButton *event, GSymbolsPanel *panel)
{
- GSymbolsPanel *panel; /* Données du panneau */
+ do_filtering_on_symbols(panel, entry);
- panel = (GSymbolsPanel *)g_object_get_data(ref, "panel");
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : panel = panneau assurant l'affichage des symboles. *
+* entry = entrée de texte contenant le filtre brut. *
+* *
+* Description : Exécute un nouveau filtrage des symboles affichés. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+static void do_filtering_on_symbols(GSymbolsPanel *panel, GtkEntry *entry)
+{
+ const gchar *text; /* Texte de l'utilisateur */
+ int ret; /* Bilan de mise en place */
+ GdkColor error; /* Couleur d'erreur */
+
+ if (panel->filter != NULL)
+ {
+ regfree(panel->filter);
+ free(panel->filter);
+ panel->filter = NULL;
+ }
+
+ text = gtk_entry_get_text(entry);
+
+ if (strlen(text) > 0)
+ {
+ panel->filter = (regex_t *)calloc(1, sizeof(regex_t));
+ ret = regcomp(panel->filter, text, REG_EXTENDED);
+
+ if (ret != 0)
+ {
+ free(panel->filter);
+ panel->filter = NULL;
+
+ error.red = 65535;
+ error.green = 0;
+ error.blue = 0;
+ gtk_widget_modify_text(GTK_WIDGET(entry), GTK_STATE_NORMAL, &error);
+
+ return;
+
+ }
+
+ }
+
+ gtk_widget_modify_text(GTK_WIDGET(entry), GTK_STATE_NORMAL, NULL);
+
+ g_object_ref(G_OBJECT(panel->binary));
change_symbols_panel_current_binary(panel, panel->binary);
+ g_object_unref(G_OBJECT(panel->binary));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : panel = panneau assurant l'affichage des symboles. *
+* name = désignation du symbole à traiter. *
+* *
+* 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_symbol_filtered(GSymbolsPanel *panel, const char *name)
+{
+ regmatch_t match; /* Récupération des trouvailles*/
+ int ret; /* Bilan du filtrage */
+
+ if (panel->filter == NULL)
+ return false;
+
+ ret = regexec(panel->filter, name, 1, &match, 0);
+ if (ret == REG_NOMATCH)
+ return true;
+
+ return false;
}