diff options
Diffstat (limited to 'src/gui/panels')
-rw-r--r-- | src/gui/panels/Makefile.am | 2 | ||||
-rw-r--r-- | src/gui/panels/bintree.c | 724 | ||||
-rw-r--r-- | src/gui/panels/bintree.h | 62 | ||||
-rw-r--r-- | src/gui/panels/bintree.ui | 191 | ||||
-rw-r--r-- | src/gui/panels/gresource.xml | 3 | ||||
-rw-r--r-- | src/gui/panels/symbols.c | 144 |
6 files changed, 991 insertions, 135 deletions
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 = ⊤ + 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, "<", "<"); - } - - /* 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, "<", "<"); - } - else - result = NULL; - - result = stradd(result, "<b>"); - - valid = strndup(&raw[selection.rm_so], selection.rm_eo - selection.rm_so); - valid = strrpl(valid, "<", "<"); - - result = stradd(result, valid); - - free(valid); - - result = stradd(result, "</b>"); - - valid = strdup(&raw[selection.rm_eo]); - valid = strrpl(valid, "<", "<"); - - result = stradd(result, valid); - - free(valid); - - } + result = is_content_matching(panel->filter, g_binary_symbol_get_label(symbol), match); return result; |