summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog31
-rw-r--r--src/glibext/gbinportion.c55
-rw-r--r--src/glibext/gbinportion.h6
-rw-r--r--src/gtkext/Makefile.am3
-rw-r--r--src/gtkext/tmgt.c204
-rw-r--r--src/gtkext/tmgt.h45
-rw-r--r--src/gui/core/panels.c4
-rw-r--r--src/gui/panels/Makefile.am2
-rw-r--r--src/gui/panels/bintree.c724
-rw-r--r--src/gui/panels/bintree.h62
-rw-r--r--src/gui/panels/bintree.ui191
-rw-r--r--src/gui/panels/gresource.xml3
-rw-r--r--src/gui/panels/symbols.c144
13 files changed, 1338 insertions, 136 deletions
diff --git a/ChangeLog b/ChangeLog
index b141036..5e243a0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,34 @@
+17-04-09 Cyrille Bagard <nocbos@gmail.com>
+
+ * src/glibext/gbinportion.c:
+ * src/glibext/gbinportion.h:
+ Enable icon for portions.
+
+ * src/gtkext/Makefile.am:
+ Add the 'tmgt.[ch]' files to libgtkext_la_SOURCES.
+
+ * src/gtkext/tmgt.c:
+ * src/gtkext/tmgt.h:
+ New entries: provide common helpers for managing treeviews.
+
+ * src/gui/core/panels.c:
+ Register the new binary tree panel.
+
+ * src/gui/panels/Makefile.am:
+ Add the 'bintree.ui' file to UI_FILES and the 'bintree.[ch]' files
+ to libguipanels_la_SOURCES.
+
+ * src/gui/panels/bintree.c:
+ * src/gui/panels/bintree.h:
+ * src/gui/panels/bintree.ui:
+ New entries: provide a tree panel to inspect binary content.
+
+ * src/gui/panels/gresource.xml:
+ Register the new UI and its icons.
+
+ * src/gui/panels/symbols.c:
+ Update code.
+
17-03-31 Cyrille Bagard <nocbos@gmail.com>
* plugins/readelf/Makefile.am:
diff --git a/src/glibext/gbinportion.c b/src/glibext/gbinportion.c
index caaec43..b94b0f6 100644
--- a/src/glibext/gbinportion.c
+++ b/src/glibext/gbinportion.c
@@ -51,6 +51,8 @@ struct _GBinPortion
char *code; /* Code de la couleur de fond */
+ cairo_surface_t *icon; /* Image de représentation */
+
char *desc; /* Désignation humaine */
char **text; /* Lignes brutes à représenter */
size_t lcount; /* Quantité de ces lignes */
@@ -239,6 +241,9 @@ static void g_binary_portion_finalize(GBinPortion *portion)
free(portion->code);
+ if (portion->icon != NULL)
+ cairo_surface_destroy(portion->icon);
+
if (portion->desc != NULL)
free(portion->desc);
@@ -314,6 +319,56 @@ int g_binary_portion_compare(const GBinPortion **a, const GBinPortion **b)
/******************************************************************************
* *
* Paramètres : portion = description de partie à mettre à jour. *
+* icon = image miniature de représentation à associer. *
+* *
+* Description : Attribue à la portion une éventuelle image de représentation.*
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_binary_portion_set_icon(GBinPortion *portion, cairo_surface_t *icon)
+{
+ if (icon != NULL)
+ portion->icon = cairo_surface_reference(icon);
+
+ else
+ portion->icon = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : portion = description de partie à consulter. *
+* *
+* Description : Fournit une éventuelle image de représentation de portion. *
+* *
+* Retour : Image miniature de représentation associée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+cairo_surface_t *g_binary_portion_get_icon(const GBinPortion *portion)
+{
+ cairo_surface_t *result;
+
+ result = portion->icon;
+
+ if (result != NULL)
+ cairo_surface_reference(result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : portion = description de partie à mettre à jour. *
* desc = nom à donner à la partie. *
* *
* Description : Attribue une description humaine à une partie de code. *
diff --git a/src/glibext/gbinportion.h b/src/glibext/gbinportion.h
index 27e7dc5..9f22e3d 100644
--- a/src/glibext/gbinportion.h
+++ b/src/glibext/gbinportion.h
@@ -84,6 +84,12 @@ GBinPortion *g_binary_portion_new(const char *, const vmpa2t *, phys_t);
/* Etablit la comparaison ascendante entre deux portions. */
int g_binary_portion_compare(const GBinPortion **, const GBinPortion **);
+/* Attribue à la portion une éventuelle image de représentation. */
+void g_binary_portion_set_icon(GBinPortion *, cairo_surface_t *);
+
+/* Fournit une éventuelle image de représentation de portion. */
+cairo_surface_t *g_binary_portion_get_icon(const GBinPortion *);
+
/* Attribue une description humaine à une partie de code. */
void g_binary_portion_set_desc(GBinPortion *, const char *);
diff --git a/src/gtkext/Makefile.am b/src/gtkext/Makefile.am
index d874ac1..07fe3a9 100644
--- a/src/gtkext/Makefile.am
+++ b/src/gtkext/Makefile.am
@@ -15,7 +15,8 @@ libgtkext_la_SOURCES = \
gtkdockstation.h gtkdockstation.c \
gtkgraphdisplay.h gtkgraphdisplay.c \
gtkstatusstack.h gtkstatusstack.c \
- support.h support.c
+ support.h support.c \
+ tmgt.h tmgt.c
libgtkext_la_LIBADD = \
graph/libgtkextgraph.la
diff --git a/src/gtkext/tmgt.c b/src/gtkext/tmgt.c
new file mode 100644
index 0000000..ce6f9a8
--- /dev/null
+++ b/src/gtkext/tmgt.c
@@ -0,0 +1,204 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * tmgt.c - compléments utiles à la mise en place d'arborescences
+ *
+ * Copyright (C) 2017 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "tmgt.h"
+
+
+#include <malloc.h>
+#include <string.h>
+
+
+#include "../common/extstr.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : entry = zone de texte avec un nouveau filtre d'affichage. *
+* filter = expression régulière de filtrage à constituer. [OUT]*
+* *
+* Description : Met à jour un filtre selon un contenu recherché. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void update_regex_on_search_entry_changed(GtkSearchEntry *entry, regex_t **filter)
+{
+ const gchar *text; /* Texte de l'utilisateur */
+ int ret; /* Bilan de mise en place */
+ GdkRGBA error; /* Couleur d'erreur */
+
+ if (*filter != NULL)
+ {
+ regfree(*filter);
+ free(*filter);
+ *filter = NULL;
+ }
+
+ text = gtk_entry_get_text(GTK_ENTRY(entry));
+
+ if (strlen(text) > 0)
+ {
+ *filter = (regex_t *)calloc(1, sizeof(regex_t));
+ ret = regcomp(*filter, text, REG_EXTENDED | REG_ICASE);
+
+ if (ret != 0)
+ {
+ free(*filter);
+ *filter = NULL;
+
+ error.red = 1.0;
+ error.green = 0.0;
+ error.blue = 0.0;
+ error.alpha = 1.0;
+ gtk_widget_override_color(GTK_WIDGET(entry), GTK_STATE_NORMAL, &error);
+
+ return;
+
+ }
+
+ }
+
+ gtk_widget_override_color(GTK_WIDGET(entry), GTK_STATE_NORMAL, NULL);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : filter = expression régulière servant de filtre. *
+* content = contenu textuel à analyser. *
+* match = zone pointant vers une correspondance. [OUT] *
+* *
+* Description : Détermine si un contenu correspond à un filtre donné. *
+* *
+* Retour : true si le contenu est qualifié pour un affichage, ou false. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool is_content_matching(const regex_t *filter, const char *content, regmatch_t *match)
+{
+ bool result; /* Bilan à retourner */
+ int ret; /* Bilan du filtrage */
+
+ memset( match, 0, sizeof(regmatch_t));
+
+ if (filter == NULL)
+ result = true;
+
+ else
+ {
+ ret = regexec(filter, content, 1, match, 0);
+ result = (ret != REG_NOMATCH);
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : raw = bribe de texte à traiter. *
+* match = portion de texte à mettre en évidence. *
+* start = position du texte brute dans l'étiquette complète. *
+* *
+* Description : Met en évidence le texte recherché en cas de correspondance. *
+* *
+* Retour : Texte final destiné à être inséré, à libérer après usage. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+char *build_highlighted_name(const char *raw, const regmatch_t *match, size_t start)
+{
+ char *result; /* Construction à retourner */
+ size_t len; /* Taille du texte d'entrée */
+ regmatch_t selection; /* Sélection relative au texte */
+ char *valid; /* Retouche partielle */
+
+ len = strlen(raw);
+
+ /* Si aucune sélection ou texte hors champ... */
+
+ if ((match->rm_eo - match->rm_so) == 0 || (start + len) <= match->rm_so || match->rm_eo < start)
+ {
+ result = strdup(raw);
+ result = strrpl(result, "<", "&lt;");
+ }
+
+ /* Sinon, il y a forcément correspondance quelque part ! */
+
+ else
+ {
+ /* Adaptations */
+
+ if (match->rm_so < start)
+ selection.rm_so = 0;
+ else
+ selection.rm_so = match->rm_so - start;
+
+ selection.rm_eo = match->rm_eo - start;
+
+ if (selection.rm_eo > len)
+ selection.rm_eo = len;
+
+ /* Impressions */
+
+ if (selection.rm_so > 0)
+ {
+ result = strndup(raw, selection.rm_so);
+ result = strrpl(result, "<", "&lt;");
+ }
+ else
+ result = NULL;
+
+ result = stradd(result, "<b>");
+
+ valid = strndup(&raw[selection.rm_so], selection.rm_eo - selection.rm_so);
+ valid = strrpl(valid, "<", "&lt;");
+
+ result = stradd(result, valid);
+
+ free(valid);
+
+ result = stradd(result, "</b>");
+
+ valid = strdup(&raw[selection.rm_eo]);
+ valid = strrpl(valid, "<", "&lt;");
+
+ result = stradd(result, valid);
+
+ free(valid);
+
+ }
+
+ return result;
+
+}
diff --git a/src/gtkext/tmgt.h b/src/gtkext/tmgt.h
new file mode 100644
index 0000000..eeeb848
--- /dev/null
+++ b/src/gtkext/tmgt.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * tmgt.h - prototypes pour des compléments utiles à la mise en place d'arborescences
+ *
+ * Copyright (C) 2017 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _COMMON_TMGT_H
+#define _COMMON_TMGT_H
+
+
+#include <regex.h>
+#include <stdbool.h>
+#include <gtk/gtk.h>
+
+
+
+/* Met à jour un filtre selon un contenu recherché. */
+void update_regex_on_search_entry_changed(GtkSearchEntry *, regex_t **);
+
+/* Détermine si un contenu correspond à un filtre donné. */
+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);
+
+
+
+#endif /* _COMMON_TMGT_H */
diff --git a/src/gui/core/panels.c b/src/gui/core/panels.c
index bd85be9..3d1a512 100644
--- a/src/gui/core/panels.c
+++ b/src/gui/core/panels.c
@@ -25,6 +25,7 @@
#include "panels.h"
+#include "../panels/bintree.h"
#include "../panels/bookmarks.h"
#include "../panels/glance.h"
#include "../panels/history.h"
@@ -87,6 +88,9 @@ void load_main_panels(GObject *ref)
item = g_bookmarks_panel_new();
register_panel_item(item, ref, config);
+ item = g_bintree_panel_new();
+ register_panel_item(item, ref, config);
+
}
diff --git a/src/gui/panels/Makefile.am b/src/gui/panels/Makefile.am
index bd4572d..7dc1cc5 100644
--- a/src/gui/panels/Makefile.am
+++ b/src/gui/panels/Makefile.am
@@ -4,9 +4,11 @@ BUILT_SOURCES = resources.h resources.c
noinst_LTLIBRARIES = libguipanels.la
UI_FILES = \
+ bintree.ui \
welcome.ui
libguipanels_la_SOURCES = \
+ bintree.h bintree.c \
bookmarks.h bookmarks.c \
glance.h glance.c \
history.h history.c \
diff --git a/src/gui/panels/bintree.c b/src/gui/panels/bintree.c
new file mode 100644
index 0000000..9963f94
--- /dev/null
+++ b/src/gui/panels/bintree.c
@@ -0,0 +1,724 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * bintree.c - panneau d'accueil par défaut
+ *
+ * Copyright (C) 2012-2017 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "bintree.h"
+
+
+#include <malloc.h>
+#include <regex.h>
+
+
+#include <i18n.h>
+
+
+#include "panel-int.h"
+#include "../../gtkext/tmgt.h"
+
+
+
+/* Origine de la dernière ouverture/fermeture reproductible */
+typedef enum _UserActionType
+{
+ UAT_COLLAPSE, /* Fermeture totale */
+ UAT_EXPAND, /* Ouverture totale */
+ UAT_DEPTH, /* Descente contrôlée */
+
+} UserActionType;
+
+
+/* Panneau de présentation des portions (instance) */
+struct _GBintreePanel
+{
+ GPanelItem parent; /* A laisser en premier */
+
+ GtkBuilder *builder; /* Constructeur utilisé */
+
+ GLoadedBinary *binary; /* Binaire représenté */
+ regex_t *filter; /* Filtre appliqué ou NULL */
+
+ UserActionType last; /* Dernière action */
+
+ GtkTreeIter *top; /* Transfert de racine */
+
+};
+
+/* Panneau de présentation des portions (classe) */
+struct _GBintreePanelClass
+{
+ GPanelItemClass parent; /* A laisser en premier */
+
+};
+
+
+/* Colonnes de la liste des messages */
+typedef enum _BinaryTreeColumn
+{
+ BTC_ICON, /* Image de représentation */
+ BTC_CAPTION, /* Désignation de l'élément */
+ BTC_START, /* Position de départ */
+ BTC_END, /* Position d'arrivée */
+ BTC_RIGHTS, /* Droits d'accès */
+
+ BTC_MATCHED, /* Correspondance établie ? */
+ BTC_PORTION /* Elément interne représenté */
+
+} BinaryTreeColumn;
+
+
+/* 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 *);
+
+/* 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 *);
+
+/* Parcourt un ensemble de portions. */
+static bool populate_tree_with_portion(GBinPortion *, GBinPortion *, BinaryPortionVisit, GBintreePanel *);
+
+/* Réagit à un changement d'affichage principal de contenu. */
+static void update_panel_with_binary_portions(GBintreePanel *, GLoadedBinary *);
+
+/* 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 *);
+
+/* Réagit au changement de sélection des portions. */
+static void on_bintree_selection_changed(GtkTreeSelection *, GBintreePanel *);
+
+
+
+/* Indique le type défini pour un panneau d'affichage des portions. */
+G_DEFINE_TYPE(GBintreePanel, g_bintree_panel, G_TYPE_PANEL_ITEM);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des panneaux d'affichage des portions. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_bintree_panel_class_init(GBintreePanelClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GEditorItemClass *editem; /* Encore une autre vision... */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_bintree_panel_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_bintree_panel_finalize;
+
+ editem = G_EDITOR_ITEM_CLASS(klass);
+
+ editem->update_binary = (update_item_binary_fc)update_panel_with_binary_portions;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : panel = instance à initialiser. *
+* *
+* Description : Initialise une instance de panneau d'affichage des portions. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_bintree_panel_init(GBintreePanel *panel)
+{
+ GEditorItem *base; /* Version basique d'instance */
+ GPanelItem *pitem; /* Version parente du panneau */
+ GtkTreeView *treeview; /* Affichage de la liste */
+ GtkCellRenderer *renderer; /* Moteur de rendu de colonne */
+ GtkTreeViewColumn *column; /* Colonne de la liste */
+
+ /* Eléments de base */
+
+ base = G_EDITOR_ITEM(panel);
+
+ base->name = PANEL_BINTREE_ID;
+
+ pitem = G_PANEL_ITEM(panel);
+
+ pitem->personality = PIP_SINGLETON;
+ pitem->lname = _("Binary tree");
+ pitem->dock_at_startup = true;
+ pitem->path = strdup("eN");
+
+ /* Compléments propres */
+
+ panel->binary = NULL;
+ panel->filter = NULL;
+
+ panel->last = UAT_EXPAND;
+
+ /* Représentation graphique */
+
+ panel->builder = gtk_builder_new_from_resource("/org/chrysalide/gui/panels/bintree.ui");
+
+ base->widget = GTK_WIDGET(gtk_builder_get_object(panel->builder, "box"));
+ g_object_ref(G_OBJECT(base->widget));
+ gtk_widget_unparent(base->widget);
+
+ /* Liste des projets récents */
+
+ treeview = GTK_TREE_VIEW(gtk_builder_get_object(panel->builder, "treeview"));
+
+ column = gtk_tree_view_column_new();
+ gtk_tree_view_append_column(treeview, column);
+ gtk_tree_view_set_expander_column(treeview, column);
+
+ renderer = gtk_cell_renderer_pixbuf_new();
+ gtk_tree_view_column_pack_start(column, renderer, FALSE);
+ gtk_tree_view_column_add_attribute(column, renderer, "surface", BTC_ICON);
+
+ renderer = gtk_cell_renderer_text_new();
+ gtk_tree_view_column_pack_start(column, renderer, TRUE);
+ gtk_tree_view_column_add_attribute(column, renderer, "markup", BTC_CAPTION);
+
+ column = gtk_tree_view_column_new();
+ gtk_tree_view_append_column(treeview, column);
+
+ renderer = gtk_cell_renderer_text_new();
+ g_object_set(G_OBJECT(renderer), "xalign", 1.0, NULL);
+ gtk_tree_view_column_pack_start(column, renderer, TRUE);
+ gtk_tree_view_column_add_attribute(column, renderer, "markup", BTC_START);
+
+ column = gtk_tree_view_column_new();
+ gtk_tree_view_append_column(treeview, column);
+
+ renderer = gtk_cell_renderer_text_new();
+ g_object_set(G_OBJECT(renderer), "xalign", 1.0, NULL);
+ gtk_tree_view_column_pack_start(column, renderer, TRUE);
+ gtk_tree_view_column_add_attribute(column, renderer, "markup", BTC_END);
+
+ column = gtk_tree_view_column_new();
+ gtk_tree_view_append_column(treeview, column);
+
+ renderer = gtk_cell_renderer_text_new();
+ gtk_tree_view_column_pack_start(column, renderer, TRUE);
+ gtk_tree_view_column_add_attribute(column, renderer, "markup", BTC_RIGHTS);
+
+ /* Connexion des signaux */
+
+ gtk_builder_add_callback_symbols(panel->builder,
+ "gtk_tree_view_collapse_all", G_CALLBACK(gtk_tree_view_collapse_all),
+ "gtk_tree_view_expand_all", G_CALLBACK(gtk_tree_view_expand_all),
+ "on_depth_spin_value_changed", G_CALLBACK(on_depth_spin_value_changed),
+ "on_search_entry_changed", G_CALLBACK(on_search_entry_changed),
+ "on_bintree_selection_changed", G_CALLBACK(on_bintree_selection_changed),
+ NULL);
+
+ gtk_builder_connect_signals(panel->builder, panel);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : panel = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_bintree_panel_dispose(GBintreePanel *panel)
+{
+ g_object_unref(G_OBJECT(panel->builder));
+
+ if (panel->binary != NULL)
+ g_object_unref(G_OBJECT(panel->binary));
+
+ G_OBJECT_CLASS(g_bintree_panel_parent_class)->dispose(G_OBJECT(panel));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : panel = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+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));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Crée un panneau présentant l'arborescence des portions. *
+* *
+* Retour : Adresse de la structure mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GPanelItem *g_bintree_panel_new(void)
+{
+ GBintreePanel *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_BINTREE_PANEL, NULL);
+
+ return G_PANEL_ITEM(result);
+
+}
+
+
+/******************************************************************************
+* *
+* 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 : - *
+* *
+******************************************************************************/
+
+static bool populate_tree_with_portion(GBinPortion *portion, GBinPortion *parent, BinaryPortionVisit visit, 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 */
+ GtkTreeStore *store; /* Modèle de gestion */
+ GtkTreeIter iter; /* Point d'insertion */
+ GtkTreeIter *save; /* Sauvegarde d'une position */
+
+ if (parent == NULL)
+ return true;
+
+ /* Insertion de la portion courante */
+
+ if (visit == BPV_ENTER || visit == BPV_SHOW)
+ {
+ /* Etiquette */
+
+ desc = g_binary_portion_get_desc(portion);
+
+ fmatched = is_content_matching(panel->filter, desc, &match);
+ node_caption = build_highlighted_name(desc, &match, 0);
+
+ /* Point de départ */
+
+ range = g_binary_portion_get_range(portion);
+
+ vmpa2_phys_to_string(get_mrange_addr(range), MDS_UNDEFINED, offset, NULL);
+
+ fmatched |= is_content_matching(panel->filter, offset, &match);
+ node_start = build_highlighted_name(offset, &match, 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);
+
+ /* Droits nominaux */
+
+ 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';
+
+ fmatched |= is_content_matching(panel->filter, hrights, &match);
+ node_rights = build_highlighted_name(hrights, &match, 0);
+
+ /* Intégration */
+
+ icon = NULL;
+
+ store = GTK_TREE_STORE(gtk_builder_get_object(panel->builder, "store"));
+
+ gtk_tree_store_append(store, &iter, panel->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,
+ -1);
+
+ free(node_caption);
+ free(node_start);
+ free(node_end);
+ free(node_rights);
+
+ if (icon != NULL)
+ cairo_surface_destroy(icon);
+
+ }
+
+ /* Définition de la hiérarchie */
+
+ if (visit == BPV_ENTER)
+ {
+ save = gtk_tree_iter_copy(panel->top);
+
+ g_object_set_data_full(G_OBJECT(portion), "_save", save, (GDestroyNotify)gtk_tree_iter_free);
+
+ *panel->top = iter;
+
+ }
+
+ else if (visit == BPV_EXIT)
+ {
+ save = g_object_get_data(G_OBJECT(portion), "_save");
+
+ *panel->top = *save;
+
+ g_object_set_data(G_OBJECT(portion), "_save", NULL);
+
+ }
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* 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 update_panel_with_binary_portions(GBintreePanel *panel, GLoadedBinary *binary)
+{
+ GtkTreeStore *store; /* Modèle de gestion */
+ GExeFormat *format; /* Format du binaire */
+ GBinPortion *portions; /* Couche première de portions */
+ GtkTreeIter top; /* Racine de l'arborescence */
+ gint max_depth; /* Profondeur maximale */
+ 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;
+
+ store = GTK_TREE_STORE(gtk_builder_get_object(panel->builder, "store"));
+
+ gtk_tree_store_clear(store);
+
+ /* Chargement */
+
+ if (binary != NULL)
+ {
+ g_object_ref(G_OBJECT(binary));
+
+ format = g_loaded_binary_get_format(binary);
+
+ portions = g_exe_format_get_portions(format);
+
+ 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);
+
+ panel->top = &top;
+ g_binary_portion_visit(portions, (visit_portion_fc)populate_tree_with_portion, panel);
+
+ g_object_unref(G_OBJECT(portions));
+
+ g_object_unref(G_OBJECT(format));
+
+ }
+
+ /* Détermination de la profondeur maximale */
+
+ gboolean compute_max_depth(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gint *max)
+ {
+ gint depth; /* Profondeur du point courant */
+
+ depth = gtk_tree_store_iter_depth(GTK_TREE_STORE(model), iter);
+
+ if (depth > *max)
+ *max = depth;
+
+ return FALSE;
+
+ }
+
+ max_depth = 0;
+
+ gtk_tree_model_foreach(GTK_TREE_MODEL(store), (GtkTreeModelForeachFunc)compute_max_depth, &max_depth);
+
+ depth_spin = GTK_SPIN_BUTTON(gtk_builder_get_object(panel->builder, "depth_spin"));
+
+ gtk_spin_button_set_range(depth_spin, 0, max_depth);
+
+ /* Restauration au mieux de l'affichage */
+
+ treeview = GTK_TREE_VIEW(gtk_builder_get_object(panel->builder, "treeview"));
+
+ switch (panel->last)
+ {
+ case UAT_COLLAPSE:
+ gtk_tree_view_collapse_all(treeview);
+ break;
+
+ case UAT_EXPAND:
+ gtk_tree_view_expand_all(treeview);
+ break;
+
+ case UAT_DEPTH:
+ on_depth_spin_value_changed(depth_spin, treeview);
+ 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. *
+* *
+* Description : Modifie la profondeur affichée des portions présentes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void on_depth_spin_value_changed(GtkSpinButton *button, GtkTreeView *treeview)
+{
+ gint max_depth; /* Profondeur maximale */
+ GtkTreeModel *model; /* Modèle de gestion */
+
+ max_depth = gtk_spin_button_get_value_as_int(button);
+
+ gboolean apply_max_depth(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer unused)
+ {
+ gint depth; /* Profondeur du point courant */
+
+ 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;
+
+ }
+
+ gtk_tree_view_collapse_all(treeview);
+
+ model = gtk_tree_view_get_model(treeview);
+
+ gtk_tree_model_foreach(model, (GtkTreeModelForeachFunc)apply_max_depth, NULL);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : entry = zone de texte avec un nouveau filtre d'affichage. *
+* panel = panneau contenant les informations globales. *
+* *
+* Description : Prend note du changement de filtre sur les portions. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void on_search_entry_changed(GtkSearchEntry *entry, GBintreePanel *panel)
+{
+ update_regex_on_search_entry_changed(entry, &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));
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : store = gestionnaire de contenu d'une arborescence donnée. *
+* *
+* Description : Parcourt un arbre en place et retire les branches filtrées. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void apply_filter_on_portions(GtkTreeStore *store)
+{
+ GtkTreeIter root; /* Racine de l'arboresence */
+
+ 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 ? */
+
+ model = GTK_TREE_MODEL(store);
+
+ children_count = gtk_tree_model_iter_n_children(model, iter);
+
+ for (i = children_count; i > 0; i--)
+ if (gtk_tree_model_iter_nth_child(model, &child, iter, i - 1))
+ check_portion_iter(&child);
+
+ children_count = gtk_tree_model_iter_n_children(model, iter);
+
+ gtk_tree_model_get(model, iter, BTC_MATCHED, &fmatched, -1);
+
+ if (!fmatched && children_count == 0)
+ gtk_tree_store_remove(store, iter);
+
+ }
+
+ if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &root))
+ check_portion_iter(&root);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : selection = sélection modifiée. *
+* panel = structure contenant les informations maîtresses. *
+* *
+* Description : Réagit au changement de sélection des portions. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void on_bintree_selection_changed(GtkTreeSelection *selection, GBintreePanel *panel)
+{
+ GtkTreeIter iter; /* Point de sélection */
+ GtkTreeModel *model; /* Modèle de gestion */
+ GBinPortion *portion; /* Portion à traiter */
+ const mrange_t *range; /* Couverture dudit symbole */
+ GtkDisplayPanel *display; /* Afficheur effectif de code */
+
+ if (gtk_tree_selection_get_selected(selection, &model, &iter))
+ {
+ gtk_tree_model_get(model, &iter, BTC_PORTION, &portion, -1);
+
+ if (portion != NULL)
+ {
+ range = g_binary_portion_get_range(portion);
+
+ display = g_editor_item_get_current_view(G_EDITOR_ITEM(panel));
+ gtk_display_panel_request_move(display, get_mrange_addr(range));
+
+ g_object_unref(G_OBJECT(portion));
+
+ }
+
+ }
+
+}
diff --git a/src/gui/panels/bintree.h b/src/gui/panels/bintree.h
new file mode 100644
index 0000000..8168481
--- /dev/null
+++ b/src/gui/panels/bintree.h
@@ -0,0 +1,62 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * bintree.h - prototypes pour le panneau d'accueil par défaut
+ *
+ * Copyright (C) 2012-2017 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _GUI_PANELS_BINTREE_H
+#define _GUI_PANELS_BINTREE_H
+
+
+#include <i18n.h>
+
+
+#include "panel.h"
+
+
+
+#define PANEL_BINTREE_ID _("Bintree")
+
+
+#define G_TYPE_BINTREE_PANEL g_bintree_panel_get_type()
+#define G_BINTREE_PANEL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_bintree_panel_get_type(), GBintreePanel))
+#define G_IS_BINTREE_PANEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_bintree_panel_get_type()))
+#define G_BINTREE_PANEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_BINTREE_PANEL, GBintreePanelClass))
+#define G_IS_BINTREE_PANEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_BINTREE_PANEL))
+#define G_BINTREE_PANEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_BINTREE_PANEL, GBintreePanelClass))
+
+
+/* Panneau de présentation des portions (instance) */
+typedef struct _GBintreePanel GBintreePanel;
+
+/* Panneau de présentation des portions (classe) */
+typedef struct _GBintreePanelClass GBintreePanelClass;
+
+
+/* Indique le type défini pour un panneau d'affichage des portions. */
+GType g_bintree_panel_get_type(void);
+
+/* Crée un panneau présentant l'arborescence des portions. */
+GPanelItem *g_bintree_panel_new(void);
+
+
+
+#endif /* _GUI_PANELS_BINTREE_H */
diff --git a/src/gui/panels/bintree.ui b/src/gui/panels/bintree.ui
new file mode 100644
index 0000000..2348e8d
--- /dev/null
+++ b/src/gui/panels/bintree.ui
@@ -0,0 +1,191 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.18.3 -->
+<interface>
+ <requires lib="gtk+" version="3.12"/>
+ <object class="GtkAdjustment" id="adjustment1">
+ <property name="upper">100</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">2</property>
+ </object>
+ <object class="GtkImage" id="collapse_img">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="pixbuf">../../../pixmaps/tbutton_collapse.png</property>
+ </object>
+ <object class="GtkImage" id="expand_img">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="pixbuf">../../../pixmaps/tbutton_expand.png</property>
+ </object>
+ <object class="GtkTreeStore" id="store">
+ <columns>
+ <!-- column-name icon -->
+ <column type="CairoSurface"/>
+ <!-- column-name name -->
+ <column type="gchararray"/>
+ <!-- column-name start -->
+ <column type="gchararray"/>
+ <!-- column-name end -->
+ <column type="gchararray"/>
+ <!-- column-name rights -->
+ <column type="gchararray"/>
+ <!-- column-name matched -->
+ <column type="gboolean"/>
+ <!-- column-name portion -->
+ <column type="GObject"/>
+ </columns>
+ </object>
+ <object class="GtkOffscreenWindow" id="offscreenwindow1">
+ <property name="can_focus">False</property>
+ <property name="margin_left">8</property>
+ <property name="margin_right">8</property>
+ <property name="margin_top">8</property>
+ <property name="margin_bottom">8</property>
+ <child>
+ <object class="GtkBox" id="box">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">8</property>
+ <child>
+ <object class="GtkToolbar" id="toolbar1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkToolButton" id="toolbutton1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">center</property>
+ <property name="use_underline">True</property>
+ <property name="label_widget">collapse_img</property>
+ <signal name="clicked" handler="gtk_tree_view_collapse_all" object="treeview" swapped="yes"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolButton" id="toolbutton2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">center</property>
+ <property name="use_underline">True</property>
+ <property name="label_widget">expand_img</property>
+ <signal name="clicked" handler="gtk_tree_view_expand_all" object="treeview" swapped="yes"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSeparatorToolItem" id="toolbutton3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolItem" id="toolbutton4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_right">8</property>
+ <property name="label" translatable="yes">Depth:</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolItem" id="toolbutton5">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkSpinButton" id="depth_spin">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="width_chars">2</property>
+ <property name="progress_fraction">1</property>
+ <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"/>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSeparatorToolItem" id="toolbutton6">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolItem" id="toolbutton7">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkSearchEntry" id="search">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="primary_icon_name">edit-find-symbolic</property>
+ <property name="primary_icon_activatable">False</property>
+ <property name="primary_icon_sensitive">False</property>
+ <property name="placeholder_text" translatable="yes">filter...</property>
+ <signal name="search-changed" handler="on_search_entry_changed" swapped="no"/>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkTreeView" id="treeview">
+ <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"/>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/src/gui/panels/gresource.xml b/src/gui/panels/gresource.xml
index 58d47e2..a14b8ae 100644
--- a/src/gui/panels/gresource.xml
+++ b/src/gui/panels/gresource.xml
@@ -1,6 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/org/chrysalide/gui/panels">
+ <file compressed="true">../../../pixmaps/tbutton_collapse.png</file>
+ <file compressed="true">../../../pixmaps/tbutton_expand.png</file>
+ <file compressed="true">bintree.ui</file>
<file compressed="true">welcome.ui</file>
</gresource>
</gresources>
diff --git a/src/gui/panels/symbols.c b/src/gui/panels/symbols.c
index 8c95bf6..e73a847 100644
--- a/src/gui/panels/symbols.c
+++ b/src/gui/panels/symbols.c
@@ -37,10 +37,10 @@
#include "panel-int.h"
-#include "../../common/extstr.h"
#include "../../format/format.h"
#include "../../gtkext/easygtk.h"
#include "../../gtkext/support.h"
+#include "../../gtkext/tmgt.h"
@@ -153,10 +153,7 @@ static void on_symbols_filter_changed(GtkSearchEntry *, GSymbolsPanel *);
static void do_filtering_on_symbols(GSymbolsPanel *);
/* Détermine si un nom de symbole doit être filtré ou non. */
-static bool is_symbol_filtered(GSymbolsPanel *, const GBinSymbol *, regmatch_t *);
-
-/* Met en évidence le texte recherché en cas de correspondance. */
-static char *build_highlighted_name(const char *, const regmatch_t *, size_t);
+static bool is_symbol_matching(GSymbolsPanel *, const GBinSymbol *, regmatch_t *);
@@ -670,7 +667,7 @@ static void reload_symbols_for_new_list_view(GSymbolsPanel *panel)
for (i = 0; i < sym_count; i++)
{
- if (is_symbol_filtered(panel, symbols[i], &match))
+ if (!is_symbol_matching(panel, symbols[i], &match))
continue;
switch (g_binary_symbol_get_target_type(symbols[i]))
@@ -872,7 +869,7 @@ static void reload_symbols_for_new_tree_view(GSymbolsPanel *panel)
for (i = 0; i < sym_count; i++)
{
- if (is_symbol_filtered(panel, symbols[i], &match))
+ if (!is_symbol_matching(panel, symbols[i], &match))
continue;
if (find_parent_for_symbol(panel, symbols[i], &parent, &match, &last))
@@ -1017,42 +1014,7 @@ static gboolean show_all_classes_in_tree_view(GtkTreeModel *model, GtkTreePath *
static void on_symbols_filter_changed(GtkSearchEntry *entry, GSymbolsPanel *panel)
{
- const gchar *text; /* Texte de l'utilisateur */
- int ret; /* Bilan de mise en place */
- GdkRGBA error; /* Couleur d'erreur */
-
- if (panel->filter != NULL)
- {
- regfree(panel->filter);
- free(panel->filter);
- panel->filter = NULL;
- }
-
- text = gtk_entry_get_text(GTK_ENTRY(entry));
-
- if (strlen(text) > 0)
- {
- panel->filter = (regex_t *)calloc(1, sizeof(regex_t));
- ret = regcomp(panel->filter, text, REG_EXTENDED | REG_ICASE);
-
- if (ret != 0)
- {
- free(panel->filter);
- panel->filter = NULL;
-
- error.red = 1.0;
- error.green = 0.0;
- error.blue = 0.0;
- error.alpha = 1.0;
- gtk_widget_override_color(GTK_WIDGET(entry), GTK_STATE_NORMAL, &error);
-
- return;
-
- }
-
- }
-
- gtk_widget_override_color(GTK_WIDGET(entry), GTK_STATE_NORMAL, NULL);
+ update_regex_on_search_entry_changed(entry, &panel->filter);
do_filtering_on_symbols(panel);
@@ -1094,106 +1056,18 @@ static void do_filtering_on_symbols(GSymbolsPanel *panel)
* *
******************************************************************************/
-static bool is_symbol_filtered(GSymbolsPanel *panel, const GBinSymbol *symbol, regmatch_t *match)
+static bool is_symbol_matching(GSymbolsPanel *panel, const GBinSymbol *symbol, regmatch_t *match)
{
+ bool result; /* Bilan à retourner */
SymbolType type; /* Type associé au symbole */
- int ret; /* Bilan du filtrage */
type = g_binary_symbol_get_target_type(symbol);
if (type != STP_ROUTINE && type != STP_ENTRY_POINT && type != STP_OBJECT)
- return true;
-
- memset(match, 0, sizeof(regmatch_t));
-
- if (panel->filter == NULL)
- return false;
-
- ret = regexec(panel->filter, g_binary_symbol_get_label(symbol), 1, match, 0);
- if (ret == REG_NOMATCH)
- return true;
-
- return false;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : raw = bribe de texte à traiter. *
-* match = portion de texte à mettre en évidence. *
-* start = position du texte brute dans l'étiquette complète. *
-* *
-* Description : Met en évidence le texte recherché en cas de correspondance. *
-* *
-* Retour : Texte final destiné à être inséré, à libérer après usage. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static char *build_highlighted_name(const char *raw, const regmatch_t *match, size_t start)
-{
- char *result; /* Construction à retourner */
- size_t len; /* Taille du texte d'entrée */
- regmatch_t selection; /* Sélection relative au texte */
- char *valid; /* Retouche partielle */
-
- len = strlen(raw);
-
- /* Si aucune sélection ou texte hors champ... */
-
- if ((match->rm_eo - match->rm_so) == 0 || (start + len) <= match->rm_so || match->rm_eo < start)
- {
- result = strdup(raw);
- result = strrpl(result, "<", "&lt;");
- }
-
- /* Sinon, il y a forcément correspondance quelque part ! */
+ result = false;
else
- {
- /* Adaptations */
-
- if (match->rm_so < start)
- selection.rm_so = 0;
- else
- selection.rm_so = match->rm_so - start;
-
- selection.rm_eo = match->rm_eo - start;
-
- if (selection.rm_eo > len)
- selection.rm_eo = len;
-
- /* Impressions */
-
- if (selection.rm_so > 0)
- {
- result = strndup(raw, selection.rm_so);
- result = strrpl(result, "<", "&lt;");
- }
- else
- result = NULL;
-
- result = stradd(result, "<b>");
-
- valid = strndup(&raw[selection.rm_so], selection.rm_eo - selection.rm_so);
- valid = strrpl(valid, "<", "&lt;");
-
- result = stradd(result, valid);
-
- free(valid);
-
- result = stradd(result, "</b>");
-
- valid = strdup(&raw[selection.rm_eo]);
- valid = strrpl(valid, "<", "&lt;");
-
- result = stradd(result, valid);
-
- free(valid);
-
- }
+ result = is_content_matching(panel->filter, g_binary_symbol_get_label(symbol), match);
return result;