From 43d57853c6f2c59197c7dc20ff61f3f2eacc2445 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Mon, 18 Mar 2019 10:00:20 +0100 Subject: Exported graph views using Cairo. --- src/glibext/gbufferview.c | 14 +- src/glibext/gbufferview.h | 2 +- src/gtkext/gtkbufferdisplay.c | 25 +- src/gtkext/gtkdisplaypanel-int.h | 7 + src/gtkext/gtkdisplaypanel.c | 29 ++ src/gtkext/gtkdisplaypanel.h | 7 +- src/gtkext/gtkgraphdisplay.c | 63 ++- src/gtkext/gtkgraphdisplay.h | 15 +- src/gui/dialogs/Makefile.am | 4 +- src/gui/dialogs/export.c | 880 --------------------------------------- src/gui/dialogs/export.h | 40 -- src/gui/dialogs/export_disass.c | 880 +++++++++++++++++++++++++++++++++++++++ src/gui/dialogs/export_disass.h | 40 ++ src/gui/dialogs/export_graph.c | 459 ++++++++++++++++++++ src/gui/dialogs/export_graph.h | 41 ++ src/gui/dialogs/export_graph.ui | 196 +++++++++ src/gui/dialogs/gresource.xml | 1 + src/gui/menus/binary.c | 104 ++++- src/gui/menus/binary.h | 3 + src/gui/menus/menubar.c | 2 + 20 files changed, 1860 insertions(+), 952 deletions(-) delete mode 100644 src/gui/dialogs/export.c delete mode 100644 src/gui/dialogs/export.h create mode 100644 src/gui/dialogs/export_disass.c create mode 100644 src/gui/dialogs/export_disass.h create mode 100644 src/gui/dialogs/export_graph.c create mode 100644 src/gui/dialogs/export_graph.h create mode 100644 src/gui/dialogs/export_graph.ui diff --git a/src/glibext/gbufferview.c b/src/glibext/gbufferview.c index 2239d23..c5021f2 100644 --- a/src/glibext/gbufferview.c +++ b/src/glibext/gbufferview.c @@ -1100,6 +1100,7 @@ bool g_buffer_view_highlight_segments(GBufferView *view, gint x, gint y, const G * options = règles d'affichage des colonnes modulables. * * offsets = décalages supplémentaires à appliquer. * * selected = ordonnée d'une ligne sélectionnée ou NULL. * +* export = indique si la vue est en cours d'exportation. * * * * Description : Imprime la visualisation du tampon de lignes quelconques. * * * @@ -1109,12 +1110,13 @@ bool g_buffer_view_highlight_segments(GBufferView *view, gint x, gint y, const G * * ******************************************************************************/ -void g_buffer_view_draw(const GBufferView *view, cairo_t *cr, gint virt_y, const cairo_rectangle_int_t *area, const GDisplayOptions *options, const line_width_summary *offsets, gint *selected) +void g_buffer_view_draw(const GBufferView *view, cairo_t *cr, gint virt_y, const cairo_rectangle_int_t *area, const GDisplayOptions *options, const line_width_summary *offsets, gint *selected, bool export) { gint line_height; /* Hauteur d'une ligne */ gint cr_y; /* Ordonnée pour le dessin */ size_t first; /* Première ligne visée */ size_t last; /* Dernière ligne visée */ + segcnt_list *highlighted; /* Segments mis en évidence */ line_height = g_buffer_cache_get_line_height(view->cache); @@ -1144,7 +1146,15 @@ void g_buffer_view_draw(const GBufferView *view, cairo_t *cr, gint virt_y, const if (selected != NULL) *selected -= cr_y; - g_buffer_cache_draw(view->cache, cr, first, last, area, options, offsets, selected, view->highlighted); + if (export) + highlighted = init_segment_content_list(); + else + highlighted = view->highlighted; + + g_buffer_cache_draw(view->cache, cr, first, last, area, options, offsets, selected, highlighted); + + if (export) + unref_segment_content_list(highlighted); } diff --git a/src/glibext/gbufferview.h b/src/glibext/gbufferview.h index 7e29cfd..9d40cbd 100644 --- a/src/glibext/gbufferview.h +++ b/src/glibext/gbufferview.h @@ -98,7 +98,7 @@ bool g_buffer_view_unhighlight_segments(GBufferView *); bool g_buffer_view_highlight_segments(GBufferView *, gint, gint, const GDisplayOptions *, const line_width_summary *); /* Imprime la visualisation du tampon de lignes quelconques. */ -void g_buffer_view_draw(const GBufferView *, cairo_t *, gint, const cairo_rectangle_int_t *, const GDisplayOptions *, const line_width_summary *, gint *); +void g_buffer_view_draw(const GBufferView *, cairo_t *, gint, const cairo_rectangle_int_t *, const GDisplayOptions *, const line_width_summary *, gint *, bool); diff --git a/src/gtkext/gtkbufferdisplay.c b/src/gtkext/gtkbufferdisplay.c index 0794dd4..01df570 100644 --- a/src/gtkext/gtkbufferdisplay.c +++ b/src/gtkext/gtkbufferdisplay.c @@ -382,6 +382,7 @@ static gboolean gtk_buffer_display_draw(GtkWidget *widget, cairo_t *cr) GtkBufferDisplay *display; /* Autre version du composant */ GtkDisplayPanel *parent; /* Autre version du composant */ GdkWindow *window; /* Fenêtre à redessiner */ + GtkAllocation allocation; /* Aire complète du composant */ cairo_region_t *region; /* Région visible à redessiner */ cairo_rectangle_int_t area; /* Surface correspondante */ GtkStyleContext *context; /* Contexte du thème actuel */ @@ -401,9 +402,22 @@ static gboolean gtk_buffer_display_draw(GtkWidget *widget, cairo_t *cr) gtk_cairo_transform_to_window(cr, widget, window); - region = gdk_window_get_clip_region(window); - cairo_region_get_extents(region, &area); - cairo_region_destroy(region); + if (parent->export) + { + gtk_widget_get_allocation(widget, &allocation); + + area.x = 0; + area.y = 0; + area.width = allocation.width; + area.height = allocation.height; + + } + else + { + region = gdk_window_get_clip_region(window); + cairo_region_get_extents(region, &area); + cairo_region_destroy(region); + } context = gtk_widget_get_style_context(widget); @@ -473,7 +487,7 @@ static gboolean gtk_buffer_display_draw(GtkWidget *widget, cairo_t *cr) g_generic_config_get_value(get_main_configuration(), MPK_SELECTION_LINE, &sel_line); sel_line &= gtk_widget_has_focus(widget); - if (!sel_line || display->cursor == NULL || !g_line_cursor_is_valid(display->cursor)) + if (!sel_line || display->cursor == NULL || !g_line_cursor_is_valid(display->cursor) || parent->export) selected = NULL; else { @@ -484,7 +498,8 @@ static gboolean gtk_buffer_display_draw(GtkWidget *widget, cairo_t *cr) area.x -= virt_x; virt_y += area.y; - g_buffer_view_draw(display->view, cr, virt_y, &area, parent->options, &display->offsets, selected); + g_buffer_view_draw(display->view, cr, virt_y, &area, parent->options, &display->offsets, + selected, parent->export); } diff --git a/src/gtkext/gtkdisplaypanel-int.h b/src/gtkext/gtkdisplaypanel-int.h index 62c990e..7be5616 100644 --- a/src/gtkext/gtkdisplaypanel-int.h +++ b/src/gtkext/gtkdisplaypanel-int.h @@ -71,6 +71,9 @@ typedef GLineCursor * (* get_cursor_fc) (const GtkDisplayPanel *); /* Place en cache un rendu destiné à l'aperçu graphique rapide. */ typedef void (* cache_glance_fc) (GtkDisplayPanel *, cairo_t *, const GtkAllocation *, double); +/* Marque ou non le composant pour une exportation prochaine. */ +typedef void (* prepare_export_fc) (GtkDisplayPanel *, bool); + /* Composant d'affichage générique (instance) */ @@ -89,6 +92,8 @@ struct _GtkDisplayPanel GLoadedBinary *binary; /* Binaire à visualiser */ + bool export; /* Exportation du rendu ? */ + }; /* Composant d'affichage générique (classe) */ @@ -107,6 +112,8 @@ struct _GtkDisplayPanelClass get_cursor_fc get_cursor; /* Fourniture d'une position */ cache_glance_fc cache_glance; /* Cache de la mignature */ + prepare_export_fc prepare_export; /* Préparation d'exportation */ + }; /* Propriétés propres au composant d'affichage */ diff --git a/src/gtkext/gtkdisplaypanel.c b/src/gtkext/gtkdisplaypanel.c index 010d648..b32adfa 100644 --- a/src/gtkext/gtkdisplaypanel.c +++ b/src/gtkext/gtkdisplaypanel.c @@ -181,6 +181,8 @@ static void gtk_display_panel_init(GtkDisplayPanel *panel) gtk_widget_set_has_window(GTK_WIDGET(panel), TRUE); gtk_widget_set_can_focus(GTK_WIDGET(panel), TRUE); + panel->export = false; + } @@ -756,6 +758,33 @@ void gtk_display_panel_show_border(GtkDisplayPanel *panel, bool show) /****************************************************************************** * * +* Paramètres : panel = composant GTK à mettre à jour. * +* export = préparation d'une exportation complète du rendu ? * +* * +* Description : Marque ou non le composant pour une exportation prochaine. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void gtk_display_panel_prepare_export(GtkDisplayPanel *panel, bool export) +{ + GtkDisplayPanelClass *class; /* Classe associée au composant*/ + + panel->export = export; + + class = GTK_DISPLAY_PANEL_GET_CLASS(panel); + + if (class->prepare_export != NULL) + class->prepare_export(panel, export); + +} + + +/****************************************************************************** +* * * Paramètres : panel = composant GTK à venir consulter. * * cr = contexte graphique associé à l'événement. * * offset = décalage éventuel à appliquer. * diff --git a/src/gtkext/gtkdisplaypanel.h b/src/gtkext/gtkdisplaypanel.h index 954991c..937d41d 100644 --- a/src/gtkext/gtkdisplaypanel.h +++ b/src/gtkext/gtkdisplaypanel.h @@ -55,11 +55,8 @@ GType gtk_display_panel_get_type(void); /* Définit si une bordure est à afficher. */ void gtk_display_panel_show_border(GtkDisplayPanel *, bool); -/* Définit si les adresses doivent apparaître dans le rendu. */ -void gtk_display_panel_set_addresses_display(GtkDisplayPanel *, bool); - -/* Définit si le code doit apparaître dans le rendu. */ -void gtk_display_panel_set_code_display(GtkDisplayPanel *, bool); +/* Marque ou non le composant pour une exportation prochaine. */ +void gtk_display_panel_prepare_export(GtkDisplayPanel *, bool); /* Indique la position d'affichage d'un emplacement donné. */ bool gtk_display_panel_get_cursor_coordinates(const GtkDisplayPanel *, const GLineCursor *, gint *, gint *, ScrollPositionTweak); diff --git a/src/gtkext/gtkgraphdisplay.c b/src/gtkext/gtkgraphdisplay.c index fb89b2e..97bb4d3 100644 --- a/src/gtkext/gtkgraphdisplay.c +++ b/src/gtkext/gtkgraphdisplay.c @@ -146,6 +146,9 @@ static GLineCursor *gtk_graph_display_get_cursor(const GtkGraphDisplay *); /* Place en cache un rendu destiné à l'aperçu graphique rapide. */ static void gtk_graph_display_cache_glance(GtkGraphDisplay *, cairo_t *, const GtkAllocation *, double); +/* Marque ou non le composant pour une exportation prochaine. */ +static void gtk_graph_display_prepare_export(GtkGraphDisplay *, bool); + /* Supprime tout contenu de l'afficheur de code en graphique. */ static void gtk_graph_display_reset(GtkGraphDisplay *, bool); @@ -202,6 +205,8 @@ static void gtk_graph_display_class_init(GtkGraphDisplayClass *class) panel_class->get_cursor = (get_cursor_fc)gtk_graph_display_get_cursor; panel_class->cache_glance = (cache_glance_fc)gtk_graph_display_cache_glance; + panel_class->prepare_export = (prepare_export_fc)gtk_graph_display_prepare_export; + } @@ -465,15 +470,15 @@ static void gtk_graph_display_adjust_scroll_value(GtkGraphDisplay *display, GtkA static gboolean gtk_graph_display_draw(GtkWidget *widget, cairo_t *cr, GtkGraphDisplay *display) { - size_t i; /* Boucle de parcours */ cairo_surface_t *pat_image; /* Fond du futur pinceau */ cairo_t *pat_cr; /* Pinceau pour le pinceau */ cairo_pattern_t *pattern; /* Patron de remplissage */ double degrees; /* Conversion en degrés */ + size_t i; /* Boucle de parcours */ /* Eventuel fond pour la zone de compression */ - if (display->may_collapsing) + if (display->may_collapsing && !GTK_DISPLAY_PANEL(display)->export) { /* Préparation du pinceau */ @@ -1158,6 +1163,35 @@ static void gtk_graph_display_cache_glance(GtkGraphDisplay *display, cairo_t *cr /****************************************************************************** * * +* Paramètres : display = composant GTK à mettre à jour. * +* export = préparation d'une exportation complète du rendu ? * +* * +* Description : Marque ou non le composant pour une exportation prochaine. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_graph_display_prepare_export(GtkGraphDisplay *display, bool export) +{ + void prepare_child_export(GtkWidget *child, gpointer unused) + { + if (!GTK_IS_BUFFER_DISPLAY(child)) + return; + + gtk_display_panel_prepare_export(GTK_DISPLAY_PANEL(child), export); + + } + + gtk_container_foreach(GTK_CONTAINER(display->support), (GtkCallback)prepare_child_export, NULL); + +} + + +/****************************************************************************** +* * * Paramètres : - * * * * Description : Crée un nouveau composant pour l'affichage en graphique. * @@ -1177,6 +1211,31 @@ GtkWidget *gtk_graph_display_new(void) /****************************************************************************** * * +* Paramètres : display = composant GTK à consulter. * +* * +* Description : Fournit le support utilisé pour le rendu graphique. * +* * +* Retour : Composant GTK de support. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GtkWidget *gtk_graph_display_get_support(GtkGraphDisplay *display) +{ + GtkWidget *result; /* Instance à retourner */ + + result = display->support; + + g_object_ref(G_OBJECT(result)); + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : display = composant GTK à mettre à jour. * * widget = composant GTK à insérer. * * x = abscisse du point d'insertion. * diff --git a/src/gtkext/gtkgraphdisplay.h b/src/gtkext/gtkgraphdisplay.h index e1ff00b..78008a1 100644 --- a/src/gtkext/gtkgraphdisplay.h +++ b/src/gtkext/gtkgraphdisplay.h @@ -32,12 +32,12 @@ -#define GTK_TYPE_GRAPH_DISPLAY (gtk_graph_display_get_type()) -#define GTK_GRAPH_DISPLAY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_GRAPH_DISPLAY, GtkGraphDisplay)) -#define GTK_GRAPH_DISPLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GTK_TYPE_GRAPH_DISPLAY, GtkGraphDisplayClass)) -#define GTK_IS_GRAPH_DISPLAY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_GRAPH_DISPLAY)) -#define GTK_IS_GRAPH_DISPLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GTK_TYPE_GRAPH_DISPLAY)) -#define GTK_GRAPH_DISPLAY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_GRAPH_DISPLAY, GtkGraphDisplayClass)) +#define GTK_TYPE_GRAPH_DISPLAY (gtk_graph_display_get_type()) +#define GTK_GRAPH_DISPLAY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_GRAPH_DISPLAY, GtkGraphDisplay)) +#define GTK_GRAPH_DISPLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GTK_TYPE_GRAPH_DISPLAY, GtkGraphDisplayClass)) +#define GTK_IS_GRAPH_DISPLAY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_GRAPH_DISPLAY)) +#define GTK_IS_GRAPH_DISPLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GTK_TYPE_GRAPH_DISPLAY)) +#define GTK_GRAPH_DISPLAY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_GRAPH_DISPLAY, GtkGraphDisplayClass)) /* Composant d'affichage sous forme graphique (instance) */ @@ -53,6 +53,9 @@ GType gtk_graph_display_get_type(void); /* Crée un nouveau composant pour l'affichage en graphique. */ GtkWidget *gtk_graph_display_new(void); +/* Fournit le support utilisé pour le rendu graphique. */ +GtkWidget *gtk_graph_display_get_support(GtkGraphDisplay *); + /* Place une vue sous forme de bloc dans le graphique. */ void gtk_graph_display_put(GtkGraphDisplay *, GtkWidget *, const GtkAllocation *); diff --git a/src/gui/dialogs/Makefile.am b/src/gui/dialogs/Makefile.am index 869fa7a..ae5180b 100644 --- a/src/gui/dialogs/Makefile.am +++ b/src/gui/dialogs/Makefile.am @@ -5,6 +5,7 @@ noinst_LTLIBRARIES = libguidialogs.la UI_FILES = \ bookmark.ui \ + export_graph.ui \ identity.ui \ preferences.ui \ prefs_fgraph.ui \ @@ -14,7 +15,8 @@ UI_FILES = \ libguidialogs_la_SOURCES = \ about.h about.c \ bookmark.h bookmark.c \ - export.h export.c \ + export_disass.h export_disass.c \ + export_graph.h export_graph.c \ goto.h goto.c \ gotox.h gotox.c \ identity.h identity.c \ diff --git a/src/gui/dialogs/export.c b/src/gui/dialogs/export.c deleted file mode 100644 index 5a66d02..0000000 --- a/src/gui/dialogs/export.c +++ /dev/null @@ -1,880 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * export.c - assistant d'exportation de contenu binaire - * - * Copyright (C) 2015-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 Chrysalide. If not, see . - */ - - -#include "export.h" - - -#include -#include -#include -#include -#include - - -#include - - -#include "../../common/extstr.h" -#include "../../gtkext/easygtk.h" - - - -/* ------------------------ PARTIE PRINCIPALE DE L'ASSISTANT ------------------------ */ - - -/* Ferme l'assistant sans dérouler la procédure. */ -static void export_assistant_cancel(GtkAssistant *, gpointer); - -/* Ferme l'assistant et déroule la procédure. */ -static void export_assistant_close(GtkAssistant *, GObject *); - -/* Réalise l'exportation d'un contenu binaire comme demandé. */ -static void do_binary_export(void/*GCodeBuffer*/ *, const vmpa2t *, const vmpa2t *, buffer_export_context *, BufferExportType, const bool *); - - - -/* ----------------------- DEFINITION DU FORMAT D'EXPORTATION ----------------------- */ - - -/* Ajoute le panneau de choix du format d'exportation. */ -static void register_format_panel(GtkAssistant *); - -/* Réagit un changement du format pour l'exportation. */ -static void on_export_format_changed(GtkComboBox *, GtkAssistant *); - -/* Interdit un champ de texte vide pour les options de texte. */ -static void forbid_text_empty_entry(GtkEntry *, GtkAssistant *); - -/* Interdit un champ de texte vide pour les options HTML. */ -static void forbid_html_empty_entry(GtkEntry *, GtkAssistant *); - - - -/* ------------------------- SELECTION DU CONTENU A TRAITER ------------------------- */ - - -/* Ajoute le panneau de sélection du contenu à exporter. */ -static void register_content_panel(GtkAssistant *); - - - -/* ------------------------ DEFINITION DE LA SORTIE ATTENDUE ------------------------ */ - - -/* Ajoute le panneau de choix du type de sortie. */ -static void register_output_panel(GtkAssistant *); - -/* Réagit un changement du nom de fichier pour l'exportation. */ -static void on_export_filename_changed(GtkEntry *, GtkAssistant *); - -/* Sélectionne ou non un nouveau fichier de sortie. */ -static void on_filename_browsing_clicked(GtkButton *, GObject *); - - - -/* ---------------------------------------------------------------------------------- */ -/* PARTIE PRINCIPALE DE L'ASSISTANT */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* Paramètres : binary = binaire chargé en mémoire à traiter. * -* parent = fenêtre principale de l'éditeur. * -* * -* Description : Crée et affiche un assistant d'aide à l'exportation. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void run_export_assistant(GLoadedBinary *binary, GtkWindow *parent) -{ - GtkWidget *assistant; /* Fenêtre à afficher */ - GObject *ref; /* Espace de référencement */ - - assistant = gtk_assistant_new(); - gtk_window_set_title(GTK_WINDOW(assistant), _("Export assistant")); - gtk_widget_set_size_request(assistant, 500, 350); - gtk_window_set_position(GTK_WINDOW(assistant), GTK_WIN_POS_CENTER); - - gtk_window_set_modal(GTK_WINDOW(assistant), TRUE); - gtk_window_set_transient_for(GTK_WINDOW(assistant), parent); - - ref = G_OBJECT(assistant); - g_object_set_data(ref, "binary", binary); - - register_format_panel(GTK_ASSISTANT(assistant)); - register_content_panel(GTK_ASSISTANT(assistant)); - register_output_panel(GTK_ASSISTANT(assistant)); - - g_signal_connect(G_OBJECT(assistant), "cancel", G_CALLBACK(export_assistant_cancel), NULL); - g_signal_connect(G_OBJECT(assistant), "close", G_CALLBACK(export_assistant_close), ref); - - gtk_widget_show_all(assistant); - -} - - -/****************************************************************************** -* * -* Paramètres : assistant = fenêtre à compléter et référencement global. * -* data = adresse non utilisée ici. * -* * -* Description : Ferme l'assistant sans dérouler la procédure. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void export_assistant_cancel(GtkAssistant *assistant, gpointer data) -{ - GObject *support; /* Support interne à supprimer */ - - support = G_OBJECT(g_object_get_data(G_OBJECT(assistant), "text_options")); - if (support != NULL) g_object_unref(support); - - support = G_OBJECT(g_object_get_data(G_OBJECT(assistant), "html_options")); - if (support != NULL) g_object_unref(support); - - gtk_widget_destroy(GTK_WIDGET(assistant)); - -} - - -/****************************************************************************** -* * -* Paramètres : assistant = fenêtre à compléter et référencement global. * -* ref = adresse de l'espace de référencement global. * -* * -* Description : Ferme l'assistant et déroule la procédure. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void export_assistant_close(GtkAssistant *assistant, GObject *ref) -{ -#if 0 - - GtkComboBox *combo; /* Selection du format */ - BufferExportType type; /* Type d'exportation requise */ - buffer_export_context ctx; /* Contexte à constituer */ - GtkEntry *entry; /* Zone de saisie */ - const gchar *filename; /* Chemin d'accès du fichier */ - GtkToggleButton *checkbutton; /* Coche à retrouver */ - bool display[BLC_DISPLAY]; /* Affichage à garantir */ - GLoadedBinary *binary; /* Binaire chargé à parcourir */ - GCodeBuffer *buffer; /* Tampon de code à traiter */ - GObject *support; /* Support interne à supprimer */ - - /* Type d'exportation */ - - combo = GTK_COMBO_BOX(g_object_get_data(ref, "format")); - - type = (BufferExportType)gtk_combo_box_get_active(combo); - - /* Fichier de sortie */ - - entry = GTK_ENTRY(g_object_get_data(ref, "filename")); - filename = gtk_entry_get_text(entry); - - switch (type) - { - case BET_TEXT: - case BET_HTML: - ctx.fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR); - if (ctx.fd == -1) - { - perror("open"); - return; - } - break; - - default: - assert(false); - break; - - } - - /* Eléments à afficher */ - - checkbutton = GTK_TOGGLE_BUTTON(g_object_get_data(ref, "physical_off")); - display[BLC_PHYSICAL] = gtk_toggle_button_get_active(checkbutton); - - checkbutton = GTK_TOGGLE_BUTTON(g_object_get_data(ref, "virtual_addr")); - display[BLC_VIRTUAL] = gtk_toggle_button_get_active(checkbutton); - - checkbutton = GTK_TOGGLE_BUTTON(g_object_get_data(ref, "binary_code")); - display[BLC_BINARY] = gtk_toggle_button_get_active(checkbutton); - - /* Options éventuelles */ - - switch (type) - { - case BET_TEXT: - entry = GTK_ENTRY(g_object_get_data(ref, "text_separator")); - ctx.sep = gtk_entry_get_text(entry); - if (strcmp(ctx.sep, "\\t") == 0) ctx.sep = "\t"; - break; - - case BET_HTML: - entry = GTK_ENTRY(g_object_get_data(ref, "html_font_name")); - ctx.font_name = gtk_entry_get_text(entry); - - entry = GTK_ENTRY(g_object_get_data(ref, "html_bg_color")); - ctx.bg_color = gtk_entry_get_text(entry); - - break; - - default: - break; - - } - - /* Programmation de la tâche */ - - binary = G_LOADED_BINARY(g_object_get_data(ref, "binary")); - - buffer = g_loaded_binary_get_disassembled_buffer(binary); - - do_binary_export(buffer, NULL, NULL, &ctx, type, display); - - /* Conclusion */ - - switch (type) - { - case BET_TEXT: - case BET_HTML: - close(ctx.fd); - break; - - default: - break; - - } - - support = G_OBJECT(g_object_get_data(G_OBJECT(assistant), "text_options")); - if (support != NULL) g_object_unref(support); - - support = G_OBJECT(g_object_get_data(G_OBJECT(assistant), "html_options")); - if (support != NULL) g_object_unref(support); -#endif - gtk_widget_destroy(GTK_WIDGET(assistant)); - -} - - -/****************************************************************************** -* * -* Paramètres : buffer = tampon de données à utiliser. * -* start = première adresse visée ou 0. * -* end = dernière adresse visée ou VMPA_MAX. * -* ctx = éléments à disposition pour l'exportation. * -* type = type d'exportation attendue. * -* display = règles d'affichage des colonnes modulables. * -* * -* Description : Réalise l'exportation d'un contenu binaire comme demandé. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void do_binary_export(void/*GCodeBuffer*/ *buffer, const vmpa2t *start, const vmpa2t *end, buffer_export_context *ctx, BufferExportType type, const bool *display) -{ -#if 0 - typedef struct _export_data - { - buffer_export_context *ctx; /* Contexte d'exportation */ - BufferExportType type; /* Type d'exportation menée */ - const bool *display; /* Paramètres d'affichage */ - - } export_data; - - export_data data; /* Données à faire suivre */ - GDelayedWork *work; /* Tâche laborieuse à attendre */ - - switch (type) - { - case BET_HTML: - dprintf(ctx->fd, "\n"); - dprintf(ctx->fd, "\n"); - dprintf(ctx->fd, "\t\n"); - dprintf(ctx->fd, "\n"); - dprintf(ctx->fd, "\n"); - dprintf(ctx->fd, "\n"); - dprintf(ctx->fd, "\n"); - break; - default: - break; - } - - data.ctx = ctx; - data.type = type; - data.display = display; - - bool export_line(GCodeBuffer *buf, GBufferLine *ln, export_data *d) - { - g_buffer_line_export(ln, d->ctx, d->type, d->display); - - return true; - - } - - work = g_buffer_code_scan(buffer, start, end, _("Exporting binary content"), - (process_line_fc)export_line, &data); - - g_delayed_work_wait_for_completion(work); - - switch (type) - { - case BET_HTML: - dprintf(ctx->fd, "
\n"); - dprintf(ctx->fd, "\n"); - dprintf(ctx->fd, "\n"); - break; - default: - break; - } -#endif -} - - - -/* ---------------------------------------------------------------------------------- */ -/* DEFINITION DU FORMAT D'EXPORTATION */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* Paramètres : assistant = fenêtre à compléter et référencement global. * -* * -* Description : Ajoute le panneau de choix du format d'exportation. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void register_format_panel(GtkAssistant *assistant) -{ - GtkWidget *vbox; /* Support principal #1 */ - GtkWidget *hbox; /* Support principal #2 */ - GtkWidget *label; /* Etiquette d'indication */ - GtkWidget *combobox; /* Sélection du format */ - GtkWidget *options; /* Zone d'options */ - GtkWidget *content; /* Accueil desdites options */ - - vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 8); - qck_set_margins(vbox, 8, 8, 8, 8); - gtk_widget_show(vbox); - - /* Format de sortie */ - - hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8); - gtk_widget_show(hbox); - gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); - - label = qck_create_label(NULL, NULL, _("Format: ")); - gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); - - combobox = qck_create_combobox(G_OBJECT(assistant), "format", G_CALLBACK(on_export_format_changed), assistant); - gtk_box_pack_start(GTK_BOX(hbox), combobox, TRUE, TRUE, 0); - - gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combobox), _("Simple text")); - gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combobox), _("HTML")); - - /* Eventuelles options */ - - content = gtk_event_box_new(); - gtk_widget_show(content); - - options = qck_create_frame(_("Options"), content, 0, 12, 12, 0); - gtk_box_pack_start(GTK_BOX(vbox), options, FALSE, FALSE, 0); - - g_object_set_data(G_OBJECT(assistant), "options", content); - - /* Intégration */ - - gtk_combo_box_set_active(GTK_COMBO_BOX(combobox), 1); - - gtk_assistant_append_page(assistant, vbox); - gtk_assistant_set_page_title(assistant, vbox, _("Format")); - gtk_assistant_set_page_type(assistant, vbox, GTK_ASSISTANT_PAGE_INTRO); - - gtk_assistant_set_page_complete(assistant, vbox, TRUE); - -} - - -/****************************************************************************** -* * -* Paramètres : combo = liste dont la sélection vient de changer. * -* assistant = fenêtre affichée et référencement global. * -* * -* Description : Réagit un changement du format pour l'exportation. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void on_export_format_changed(GtkComboBox *combo, GtkAssistant *assistant) -{ - BufferExportType selected; /* Format attendu */ - GtkContainer *content; /* Accueil des options */ - GtkWidget *old; /* Ancien support à remplacer */ - GtkWidget *vbox; /* Support principal #1 */ - GtkWidget *hbox; /* Support principal #2 */ - GtkWidget *label; /* Etiquette d'indication */ - GtkWidget *entry; /* Zone de saisie de valeur */ - char *filename; /* Chemin à venir modifier */ - char *dot; /* Dernière occurence de point */ - - selected = (BufferExportType)gtk_combo_box_get_active(combo); - - content = GTK_CONTAINER(g_object_get_data(G_OBJECT(assistant), "options")); - - old = gtk_bin_get_child(GTK_BIN(content)); - if (old != NULL) - { - g_object_ref(G_OBJECT(old)); - gtk_container_remove(content, old); - } - - switch (selected) - { - case BET_TEXT: - - hbox = GTK_WIDGET(g_object_get_data(G_OBJECT(assistant), "text_options")); - - if (hbox == NULL) - { - hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8); - g_object_ref(G_OBJECT(hbox)); - gtk_widget_show(hbox); - g_object_set_data(G_OBJECT(assistant), "text_options", hbox); - - label = qck_create_label(NULL, NULL, _("String between columns: ")); - gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); - - entry = qck_create_entry(G_OBJECT(assistant), "text_separator", NULL); - g_signal_connect(G_OBJECT(entry), "changed", G_CALLBACK(forbid_text_empty_entry), assistant); - gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0); - gtk_entry_set_text(GTK_ENTRY(entry), "\\t"); - - } - - gtk_container_add(content, hbox); - - break; - - case BET_HTML: - - vbox = GTK_WIDGET(g_object_get_data(G_OBJECT(assistant), "html_options")); - - if (vbox == NULL) - { - vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 8); - g_object_ref(G_OBJECT(vbox)); - gtk_widget_show(vbox); - g_object_set_data(G_OBJECT(assistant), "html_options", vbox); - - hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8); - gtk_widget_show(hbox); - gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); - - label = qck_create_label(NULL, NULL, _("HTML table font name: ")); - gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); - - entry = qck_create_entry(G_OBJECT(assistant), "html_font_name", NULL); - g_signal_connect(G_OBJECT(entry), "changed", G_CALLBACK(forbid_html_empty_entry), assistant); - gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0); - gtk_entry_set_text(GTK_ENTRY(entry), "monospace"); - - hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8); - gtk_widget_show(hbox); - gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); - - label = qck_create_label(NULL, NULL, _("HTML table background color: ")); - gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); - - entry = qck_create_entry(G_OBJECT(assistant), "html_bg_color", NULL); - g_signal_connect(G_OBJECT(entry), "changed", G_CALLBACK(forbid_html_empty_entry), assistant); - gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0); - gtk_entry_set_text(GTK_ENTRY(entry), "#2c2c2c"); - - } - - gtk_container_add(content, vbox); - - break; - - default: - break; - - } - - /* Mise à jour de l'extension du fichier de sortie, si possible */ - - entry = GTK_WIDGET(g_object_get_data(G_OBJECT(assistant), "filename")); - - if (entry != NULL) - { - filename = strdup(gtk_entry_get_text(GTK_ENTRY(entry))); - - dot = strrchr(filename, '.'); - if (dot == NULL) goto oefc_no_dot; - - *dot = '\0'; - - switch (selected) - { - case BET_TEXT: - filename = stradd(filename, ".txt"); - break; - case BET_HTML: - filename = stradd(filename, ".html"); - break; - default: - break; - } - - gtk_entry_set_text(GTK_ENTRY(entry), filename); - - oefc_no_dot: - - free(filename); - - } - -} - - -/****************************************************************************** -* * -* Paramètres : entry = zone de texte dont le contenu vient de changer. * -* assistant = fenêtre affichée et référencement global. * -* * -* Description : Interdit un champ de texte vide pour les options HTML. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void forbid_text_empty_entry(GtkEntry *entry, GtkAssistant *assistant) -{ - const gchar *text; /* Texte saisi dans la zone */ - gint num; /* Etape courante */ - GtkWidget *page; /* Support de cette étape */ - - text = gtk_entry_get_text(entry); - - num = gtk_assistant_get_current_page(assistant); - page = gtk_assistant_get_nth_page(assistant, num); - - gtk_assistant_set_page_complete(assistant, page, (strlen(text) > 0)); - -} - - -/****************************************************************************** -* * -* Paramètres : _entry = zone de texte dont le contenu vient de changer. * -* assistant = fenêtre affichée et référencement global. * -* * -* Description : Interdit un champ de texte vide pour les options de texte. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void forbid_html_empty_entry(GtkEntry *_entry, GtkAssistant *assistant) -{ - bool status; /* Etat final à remonter */ - GtkEntry *entry; /* Zone de texte générique */ - const gchar *text; /* Texte saisi dans la zone */ - gint num; /* Etape courante */ - GtkWidget *page; /* Support de cette étape */ - - status = true; - - /* Police de caractère */ - - entry = GTK_ENTRY(g_object_get_data(G_OBJECT(assistant), "html_font_name")); - text = gtk_entry_get_text(entry); - - status &= (strlen(text) > 0); - - /* Couleur de fond */ - - entry = GTK_ENTRY(g_object_get_data(G_OBJECT(assistant), "html_bg_color")); - - if (entry != NULL) - { - text = gtk_entry_get_text(entry); - - status &= (strlen(text) > 0); - - } - - /* Mise à jour graphique */ - - num = gtk_assistant_get_current_page(assistant); - - if (num != -1) - { - page = gtk_assistant_get_nth_page(assistant, num); - - gtk_assistant_set_page_complete(assistant, page, status); - - } - -} - - - -/* ---------------------------------------------------------------------------------- */ -/* SELECTION DU CONTENU A TRAITER */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* Paramètres : assistant = fenêtre à compléter et référencement global. * -* * -* Description : Ajoute le panneau de sélection du contenu à exporter. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void register_content_panel(GtkAssistant *assistant) -{ - GtkWidget *vbox; /* Support principal */ - GtkWidget *frame; /* Support avec encadrement */ - GtkWidget *sub_vbox; /* Division verticale */ - GtkWidget *checkbutton; /* Coche pour une option */ - - vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 8); - qck_set_margins(vbox, 8, 8, 8, 8); - gtk_widget_show(vbox); - - /* Eléments à afficher */ - - sub_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 8); - gtk_widget_show(sub_vbox); - - frame = qck_create_frame(_("Items to display"), sub_vbox, 0, 12, 12, 0); - gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 0); - - checkbutton = qck_create_check_button(G_OBJECT(assistant), "physical_off", _("Physical offset"), NULL, NULL); - gtk_box_pack_start(GTK_BOX(sub_vbox), checkbutton, FALSE, FALSE, 0); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbutton), TRUE); - - checkbutton = qck_create_check_button(G_OBJECT(assistant), "virtual_addr", _("Virtual address"), NULL, NULL); - gtk_box_pack_start(GTK_BOX(sub_vbox), checkbutton, FALSE, FALSE, 0); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbutton), TRUE); - - checkbutton = qck_create_check_button(G_OBJECT(assistant), "binary_code", _("Binary code"), NULL, NULL); - gtk_box_pack_start(GTK_BOX(sub_vbox), checkbutton, FALSE, FALSE, 0); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbutton), TRUE); - - /* Intégration */ - - gtk_assistant_append_page(assistant, vbox); - gtk_assistant_set_page_title(assistant, vbox, _("Exported content")); - gtk_assistant_set_page_type(assistant, vbox, GTK_ASSISTANT_PAGE_CONTENT); - - gtk_assistant_set_page_complete(assistant, vbox, TRUE); - -} - - - -/* ---------------------------------------------------------------------------------- */ -/* DEFINITION DE LA SORTIE ATTENDUE */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* Paramètres : assistant = fenêtre à compléter et référencement global. * -* * -* Description : Ajoute le panneau de choix du type de sortie. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void register_output_panel(GtkAssistant *assistant) -{ - GtkWidget *vbox; /* Support principal #1 */ - GtkWidget *label; /* Etiquette d'indication */ - GtkWidget *hbox; /* Support principal #2 */ - GtkWidget *entry; /* Zone de saisie de texte */ - GtkWidget *button; /* Sélection de fichier */ - GLoadedBinary *binary; /* Binaire chargé à parcourir */ - const char *filename; /* Chemin d'accès par défaut */ - - vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 8); - qck_set_margins(vbox, 8, 8, 8, 8); - gtk_widget_show(vbox); - - /* Fichier de sortie */ - - label = qck_create_label(NULL, NULL, _("File: ")); - gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0); - - hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8); - gtk_widget_show(hbox); - gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); - - entry = qck_create_entry(G_OBJECT(assistant), "filename", NULL); - gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0); - - button = qck_create_button(NULL, NULL, "...", G_CALLBACK(on_filename_browsing_clicked), assistant); - gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0); - - /* Intégration */ - - gtk_assistant_append_page(assistant, vbox); - gtk_assistant_set_page_title(assistant, vbox, _("Output")); - gtk_assistant_set_page_type(assistant, vbox, GTK_ASSISTANT_PAGE_CONFIRM); - - gtk_assistant_set_page_complete(assistant, vbox, TRUE); - - /* Choix par défaut */ - - binary = G_LOADED_BINARY(g_object_get_data(G_OBJECT(assistant), "binary")); - filename = g_loaded_binary_get_name(binary, true); - - gtk_entry_set_text(GTK_ENTRY(entry), filename); - gtk_editable_insert_text(GTK_EDITABLE(entry), ".html", -1, (gint []) { strlen(filename) }); - - g_signal_connect(G_OBJECT(entry), "changed", G_CALLBACK(on_export_filename_changed), assistant); - -} - - -/****************************************************************************** -* * -* Paramètres : entry = zone de texte dont le contenu vient de changer. * -* assistant = fenêtre affichée et référencement global. * -* * -* Description : Réagit un changement du nom de fichier pour l'exportation. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void on_export_filename_changed(GtkEntry *entry, GtkAssistant *assistant) -{ - const gchar *text; /* Texte saisi dans la zone */ - gint num; /* Etape courante */ - GtkWidget *page; /* Support de cette étape */ - - text = gtk_entry_get_text(entry); - - num = gtk_assistant_get_current_page(assistant); - page = gtk_assistant_get_nth_page(assistant, num); - - gtk_assistant_set_page_complete(assistant, page, (strlen(text) > 0)); - -} - - -/****************************************************************************** -* * -* Paramètres : button = bouton d'édition de la sélection. * -* ref = espace de référencement principal. * -* * -* Description : Sélectionne ou non un nouveau fichier de sortie. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void on_filename_browsing_clicked(GtkButton *button, GObject *ref) -{ - GtkWidget *dialog; /* Boîte à afficher */ - gchar *filename; /* Nom du fichier à intégrer */ - GtkEntry *entry; /* Zone de saisie à maj. */ - - dialog = gtk_file_chooser_dialog_new(_("Choose an output filename"), GTK_WINDOW(ref), - GTK_FILE_CHOOSER_ACTION_SAVE, - _("_Cancel"), GTK_RESPONSE_CANCEL, - _("_Save"), GTK_RESPONSE_ACCEPT, - NULL); - - entry = GTK_ENTRY(g_object_get_data(ref, "filename")); - gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog), gtk_entry_get_text(entry)); - - if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) - { - filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); - - gtk_entry_set_text(GTK_ENTRY(entry), filename); - - g_free(filename); - - } - - gtk_widget_destroy(dialog); - -} diff --git a/src/gui/dialogs/export.h b/src/gui/dialogs/export.h deleted file mode 100644 index 209dea8..0000000 --- a/src/gui/dialogs/export.h +++ /dev/null @@ -1,40 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * export.h - prototypes pour l'assistant d'exportation de contenu binaire - * - * Copyright (C) 2015-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 Chrysalide. If not, see . - */ - - -#ifndef _GUI_DIALOGS_EXPORT_H -#define _GUI_DIALOGS_EXPORT_H - - -#include - - -#include "../../analysis/binary.h" - - - -/* Crée et affiche un assistant d'aide à l'exportation. */ -void run_export_assistant(GLoadedBinary *, GtkWindow *); - - - -#endif /* _GUI_DIALOGS_EXPORT_H */ diff --git a/src/gui/dialogs/export_disass.c b/src/gui/dialogs/export_disass.c new file mode 100644 index 0000000..be7d2a9 --- /dev/null +++ b/src/gui/dialogs/export_disass.c @@ -0,0 +1,880 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * export_disass.c - assistant d'exportation de contenu binaire + * + * Copyright (C) 2015-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 Chrysalide. If not, see . + */ + + +#include "export_disass.h" + + +#include +#include +#include +#include +#include + + +#include + + +#include "../../common/extstr.h" +#include "../../gtkext/easygtk.h" + + + +/* ------------------------ PARTIE PRINCIPALE DE L'ASSISTANT ------------------------ */ + + +/* Ferme l'assistant sans dérouler la procédure. */ +static void export_assistant_cancel(GtkAssistant *, gpointer); + +/* Ferme l'assistant et déroule la procédure. */ +static void export_assistant_close(GtkAssistant *, GObject *); + +/* Réalise l'exportation d'un contenu binaire comme demandé. */ +static void do_binary_export(void/*GCodeBuffer*/ *, const vmpa2t *, const vmpa2t *, buffer_export_context *, BufferExportType, const bool *); + + + +/* ----------------------- DEFINITION DU FORMAT D'EXPORTATION ----------------------- */ + + +/* Ajoute le panneau de choix du format d'exportation. */ +static void register_format_panel(GtkAssistant *); + +/* Réagit un changement du format pour l'exportation. */ +static void on_export_format_changed(GtkComboBox *, GtkAssistant *); + +/* Interdit un champ de texte vide pour les options de texte. */ +static void forbid_text_empty_entry(GtkEntry *, GtkAssistant *); + +/* Interdit un champ de texte vide pour les options HTML. */ +static void forbid_html_empty_entry(GtkEntry *, GtkAssistant *); + + + +/* ------------------------- SELECTION DU CONTENU A TRAITER ------------------------- */ + + +/* Ajoute le panneau de sélection du contenu à exporter. */ +static void register_content_panel(GtkAssistant *); + + + +/* ------------------------ DEFINITION DE LA SORTIE ATTENDUE ------------------------ */ + + +/* Ajoute le panneau de choix du type de sortie. */ +static void register_output_panel(GtkAssistant *); + +/* Réagit un changement du nom de fichier pour l'exportation. */ +static void on_export_filename_changed(GtkEntry *, GtkAssistant *); + +/* Sélectionne ou non un nouveau fichier de sortie. */ +static void on_filename_browsing_clicked(GtkButton *, GObject *); + + + +/* ---------------------------------------------------------------------------------- */ +/* PARTIE PRINCIPALE DE L'ASSISTANT */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : binary = binaire chargé en mémoire à traiter. * +* parent = fenêtre principale de l'éditeur. * +* * +* Description : Crée et affiche un assistant d'aide à l'exportation. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void run_export_assistant(GLoadedBinary *binary, GtkWindow *parent) +{ + GtkWidget *assistant; /* Fenêtre à afficher */ + GObject *ref; /* Espace de référencement */ + + assistant = gtk_assistant_new(); + gtk_window_set_title(GTK_WINDOW(assistant), _("Export assistant")); + gtk_widget_set_size_request(assistant, 500, 350); + gtk_window_set_position(GTK_WINDOW(assistant), GTK_WIN_POS_CENTER); + + gtk_window_set_modal(GTK_WINDOW(assistant), TRUE); + gtk_window_set_transient_for(GTK_WINDOW(assistant), parent); + + ref = G_OBJECT(assistant); + g_object_set_data(ref, "binary", binary); + + register_format_panel(GTK_ASSISTANT(assistant)); + register_content_panel(GTK_ASSISTANT(assistant)); + register_output_panel(GTK_ASSISTANT(assistant)); + + g_signal_connect(G_OBJECT(assistant), "cancel", G_CALLBACK(export_assistant_cancel), NULL); + g_signal_connect(G_OBJECT(assistant), "close", G_CALLBACK(export_assistant_close), ref); + + gtk_widget_show_all(assistant); + +} + + +/****************************************************************************** +* * +* Paramètres : assistant = fenêtre à compléter et référencement global. * +* data = adresse non utilisée ici. * +* * +* Description : Ferme l'assistant sans dérouler la procédure. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void export_assistant_cancel(GtkAssistant *assistant, gpointer data) +{ + GObject *support; /* Support interne à supprimer */ + + support = G_OBJECT(g_object_get_data(G_OBJECT(assistant), "text_options")); + if (support != NULL) g_object_unref(support); + + support = G_OBJECT(g_object_get_data(G_OBJECT(assistant), "html_options")); + if (support != NULL) g_object_unref(support); + + gtk_widget_destroy(GTK_WIDGET(assistant)); + +} + + +/****************************************************************************** +* * +* Paramètres : assistant = fenêtre à compléter et référencement global. * +* ref = adresse de l'espace de référencement global. * +* * +* Description : Ferme l'assistant et déroule la procédure. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void export_assistant_close(GtkAssistant *assistant, GObject *ref) +{ +#if 0 + + GtkComboBox *combo; /* Selection du format */ + BufferExportType type; /* Type d'exportation requise */ + buffer_export_context ctx; /* Contexte à constituer */ + GtkEntry *entry; /* Zone de saisie */ + const gchar *filename; /* Chemin d'accès du fichier */ + GtkToggleButton *checkbutton; /* Coche à retrouver */ + bool display[BLC_DISPLAY]; /* Affichage à garantir */ + GLoadedBinary *binary; /* Binaire chargé à parcourir */ + GCodeBuffer *buffer; /* Tampon de code à traiter */ + GObject *support; /* Support interne à supprimer */ + + /* Type d'exportation */ + + combo = GTK_COMBO_BOX(g_object_get_data(ref, "format")); + + type = (BufferExportType)gtk_combo_box_get_active(combo); + + /* Fichier de sortie */ + + entry = GTK_ENTRY(g_object_get_data(ref, "filename")); + filename = gtk_entry_get_text(entry); + + switch (type) + { + case BET_TEXT: + case BET_HTML: + ctx.fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR); + if (ctx.fd == -1) + { + perror("open"); + return; + } + break; + + default: + assert(false); + break; + + } + + /* Eléments à afficher */ + + checkbutton = GTK_TOGGLE_BUTTON(g_object_get_data(ref, "physical_off")); + display[BLC_PHYSICAL] = gtk_toggle_button_get_active(checkbutton); + + checkbutton = GTK_TOGGLE_BUTTON(g_object_get_data(ref, "virtual_addr")); + display[BLC_VIRTUAL] = gtk_toggle_button_get_active(checkbutton); + + checkbutton = GTK_TOGGLE_BUTTON(g_object_get_data(ref, "binary_code")); + display[BLC_BINARY] = gtk_toggle_button_get_active(checkbutton); + + /* Options éventuelles */ + + switch (type) + { + case BET_TEXT: + entry = GTK_ENTRY(g_object_get_data(ref, "text_separator")); + ctx.sep = gtk_entry_get_text(entry); + if (strcmp(ctx.sep, "\\t") == 0) ctx.sep = "\t"; + break; + + case BET_HTML: + entry = GTK_ENTRY(g_object_get_data(ref, "html_font_name")); + ctx.font_name = gtk_entry_get_text(entry); + + entry = GTK_ENTRY(g_object_get_data(ref, "html_bg_color")); + ctx.bg_color = gtk_entry_get_text(entry); + + break; + + default: + break; + + } + + /* Programmation de la tâche */ + + binary = G_LOADED_BINARY(g_object_get_data(ref, "binary")); + + buffer = g_loaded_binary_get_disassembled_buffer(binary); + + do_binary_export(buffer, NULL, NULL, &ctx, type, display); + + /* Conclusion */ + + switch (type) + { + case BET_TEXT: + case BET_HTML: + close(ctx.fd); + break; + + default: + break; + + } + + support = G_OBJECT(g_object_get_data(G_OBJECT(assistant), "text_options")); + if (support != NULL) g_object_unref(support); + + support = G_OBJECT(g_object_get_data(G_OBJECT(assistant), "html_options")); + if (support != NULL) g_object_unref(support); +#endif + gtk_widget_destroy(GTK_WIDGET(assistant)); + +} + + +/****************************************************************************** +* * +* Paramètres : buffer = tampon de données à utiliser. * +* start = première adresse visée ou 0. * +* end = dernière adresse visée ou VMPA_MAX. * +* ctx = éléments à disposition pour l'exportation. * +* type = type d'exportation attendue. * +* display = règles d'affichage des colonnes modulables. * +* * +* Description : Réalise l'exportation d'un contenu binaire comme demandé. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void do_binary_export(void/*GCodeBuffer*/ *buffer, const vmpa2t *start, const vmpa2t *end, buffer_export_context *ctx, BufferExportType type, const bool *display) +{ +#if 0 + typedef struct _export_data + { + buffer_export_context *ctx; /* Contexte d'exportation */ + BufferExportType type; /* Type d'exportation menée */ + const bool *display; /* Paramètres d'affichage */ + + } export_data; + + export_data data; /* Données à faire suivre */ + GDelayedWork *work; /* Tâche laborieuse à attendre */ + + switch (type) + { + case BET_HTML: + dprintf(ctx->fd, "\n"); + dprintf(ctx->fd, "\n"); + dprintf(ctx->fd, "\t\n"); + dprintf(ctx->fd, "\n"); + dprintf(ctx->fd, "\n"); + dprintf(ctx->fd, "\n"); + dprintf(ctx->fd, "\n"); + break; + default: + break; + } + + data.ctx = ctx; + data.type = type; + data.display = display; + + bool export_line(GCodeBuffer *buf, GBufferLine *ln, export_data *d) + { + g_buffer_line_export(ln, d->ctx, d->type, d->display); + + return true; + + } + + work = g_buffer_code_scan(buffer, start, end, _("Exporting binary content"), + (process_line_fc)export_line, &data); + + g_delayed_work_wait_for_completion(work); + + switch (type) + { + case BET_HTML: + dprintf(ctx->fd, "
\n"); + dprintf(ctx->fd, "\n"); + dprintf(ctx->fd, "\n"); + break; + default: + break; + } +#endif +} + + + +/* ---------------------------------------------------------------------------------- */ +/* DEFINITION DU FORMAT D'EXPORTATION */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : assistant = fenêtre à compléter et référencement global. * +* * +* Description : Ajoute le panneau de choix du format d'exportation. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void register_format_panel(GtkAssistant *assistant) +{ + GtkWidget *vbox; /* Support principal #1 */ + GtkWidget *hbox; /* Support principal #2 */ + GtkWidget *label; /* Etiquette d'indication */ + GtkWidget *combobox; /* Sélection du format */ + GtkWidget *options; /* Zone d'options */ + GtkWidget *content; /* Accueil desdites options */ + + vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 8); + qck_set_margins(vbox, 8, 8, 8, 8); + gtk_widget_show(vbox); + + /* Format de sortie */ + + hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8); + gtk_widget_show(hbox); + gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); + + label = qck_create_label(NULL, NULL, _("Format: ")); + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); + + combobox = qck_create_combobox(G_OBJECT(assistant), "format", G_CALLBACK(on_export_format_changed), assistant); + gtk_box_pack_start(GTK_BOX(hbox), combobox, TRUE, TRUE, 0); + + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combobox), _("Simple text")); + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combobox), _("HTML")); + + /* Eventuelles options */ + + content = gtk_event_box_new(); + gtk_widget_show(content); + + options = qck_create_frame(_("Options"), content, 0, 12, 12, 0); + gtk_box_pack_start(GTK_BOX(vbox), options, FALSE, FALSE, 0); + + g_object_set_data(G_OBJECT(assistant), "options", content); + + /* Intégration */ + + gtk_combo_box_set_active(GTK_COMBO_BOX(combobox), 1); + + gtk_assistant_append_page(assistant, vbox); + gtk_assistant_set_page_title(assistant, vbox, _("Format")); + gtk_assistant_set_page_type(assistant, vbox, GTK_ASSISTANT_PAGE_INTRO); + + gtk_assistant_set_page_complete(assistant, vbox, TRUE); + +} + + +/****************************************************************************** +* * +* Paramètres : combo = liste dont la sélection vient de changer. * +* assistant = fenêtre affichée et référencement global. * +* * +* Description : Réagit un changement du format pour l'exportation. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void on_export_format_changed(GtkComboBox *combo, GtkAssistant *assistant) +{ + BufferExportType selected; /* Format attendu */ + GtkContainer *content; /* Accueil des options */ + GtkWidget *old; /* Ancien support à remplacer */ + GtkWidget *vbox; /* Support principal #1 */ + GtkWidget *hbox; /* Support principal #2 */ + GtkWidget *label; /* Etiquette d'indication */ + GtkWidget *entry; /* Zone de saisie de valeur */ + char *filename; /* Chemin à venir modifier */ + char *dot; /* Dernière occurence de point */ + + selected = (BufferExportType)gtk_combo_box_get_active(combo); + + content = GTK_CONTAINER(g_object_get_data(G_OBJECT(assistant), "options")); + + old = gtk_bin_get_child(GTK_BIN(content)); + if (old != NULL) + { + g_object_ref(G_OBJECT(old)); + gtk_container_remove(content, old); + } + + switch (selected) + { + case BET_TEXT: + + hbox = GTK_WIDGET(g_object_get_data(G_OBJECT(assistant), "text_options")); + + if (hbox == NULL) + { + hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8); + g_object_ref(G_OBJECT(hbox)); + gtk_widget_show(hbox); + g_object_set_data(G_OBJECT(assistant), "text_options", hbox); + + label = qck_create_label(NULL, NULL, _("String between columns: ")); + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); + + entry = qck_create_entry(G_OBJECT(assistant), "text_separator", NULL); + g_signal_connect(G_OBJECT(entry), "changed", G_CALLBACK(forbid_text_empty_entry), assistant); + gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0); + gtk_entry_set_text(GTK_ENTRY(entry), "\\t"); + + } + + gtk_container_add(content, hbox); + + break; + + case BET_HTML: + + vbox = GTK_WIDGET(g_object_get_data(G_OBJECT(assistant), "html_options")); + + if (vbox == NULL) + { + vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 8); + g_object_ref(G_OBJECT(vbox)); + gtk_widget_show(vbox); + g_object_set_data(G_OBJECT(assistant), "html_options", vbox); + + hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8); + gtk_widget_show(hbox); + gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); + + label = qck_create_label(NULL, NULL, _("HTML table font name: ")); + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); + + entry = qck_create_entry(G_OBJECT(assistant), "html_font_name", NULL); + g_signal_connect(G_OBJECT(entry), "changed", G_CALLBACK(forbid_html_empty_entry), assistant); + gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0); + gtk_entry_set_text(GTK_ENTRY(entry), "monospace"); + + hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8); + gtk_widget_show(hbox); + gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); + + label = qck_create_label(NULL, NULL, _("HTML table background color: ")); + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); + + entry = qck_create_entry(G_OBJECT(assistant), "html_bg_color", NULL); + g_signal_connect(G_OBJECT(entry), "changed", G_CALLBACK(forbid_html_empty_entry), assistant); + gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0); + gtk_entry_set_text(GTK_ENTRY(entry), "#2c2c2c"); + + } + + gtk_container_add(content, vbox); + + break; + + default: + break; + + } + + /* Mise à jour de l'extension du fichier de sortie, si possible */ + + entry = GTK_WIDGET(g_object_get_data(G_OBJECT(assistant), "filename")); + + if (entry != NULL) + { + filename = strdup(gtk_entry_get_text(GTK_ENTRY(entry))); + + dot = strrchr(filename, '.'); + if (dot == NULL) goto oefc_no_dot; + + *dot = '\0'; + + switch (selected) + { + case BET_TEXT: + filename = stradd(filename, ".txt"); + break; + case BET_HTML: + filename = stradd(filename, ".html"); + break; + default: + break; + } + + gtk_entry_set_text(GTK_ENTRY(entry), filename); + + oefc_no_dot: + + free(filename); + + } + +} + + +/****************************************************************************** +* * +* Paramètres : entry = zone de texte dont le contenu vient de changer. * +* assistant = fenêtre affichée et référencement global. * +* * +* Description : Interdit un champ de texte vide pour les options HTML. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void forbid_text_empty_entry(GtkEntry *entry, GtkAssistant *assistant) +{ + const gchar *text; /* Texte saisi dans la zone */ + gint num; /* Etape courante */ + GtkWidget *page; /* Support de cette étape */ + + text = gtk_entry_get_text(entry); + + num = gtk_assistant_get_current_page(assistant); + page = gtk_assistant_get_nth_page(assistant, num); + + gtk_assistant_set_page_complete(assistant, page, (strlen(text) > 0)); + +} + + +/****************************************************************************** +* * +* Paramètres : _entry = zone de texte dont le contenu vient de changer. * +* assistant = fenêtre affichée et référencement global. * +* * +* Description : Interdit un champ de texte vide pour les options de texte. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void forbid_html_empty_entry(GtkEntry *_entry, GtkAssistant *assistant) +{ + bool status; /* Etat final à remonter */ + GtkEntry *entry; /* Zone de texte générique */ + const gchar *text; /* Texte saisi dans la zone */ + gint num; /* Etape courante */ + GtkWidget *page; /* Support de cette étape */ + + status = true; + + /* Police de caractère */ + + entry = GTK_ENTRY(g_object_get_data(G_OBJECT(assistant), "html_font_name")); + text = gtk_entry_get_text(entry); + + status &= (strlen(text) > 0); + + /* Couleur de fond */ + + entry = GTK_ENTRY(g_object_get_data(G_OBJECT(assistant), "html_bg_color")); + + if (entry != NULL) + { + text = gtk_entry_get_text(entry); + + status &= (strlen(text) > 0); + + } + + /* Mise à jour graphique */ + + num = gtk_assistant_get_current_page(assistant); + + if (num != -1) + { + page = gtk_assistant_get_nth_page(assistant, num); + + gtk_assistant_set_page_complete(assistant, page, status); + + } + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* SELECTION DU CONTENU A TRAITER */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : assistant = fenêtre à compléter et référencement global. * +* * +* Description : Ajoute le panneau de sélection du contenu à exporter. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void register_content_panel(GtkAssistant *assistant) +{ + GtkWidget *vbox; /* Support principal */ + GtkWidget *frame; /* Support avec encadrement */ + GtkWidget *sub_vbox; /* Division verticale */ + GtkWidget *checkbutton; /* Coche pour une option */ + + vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 8); + qck_set_margins(vbox, 8, 8, 8, 8); + gtk_widget_show(vbox); + + /* Eléments à afficher */ + + sub_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 8); + gtk_widget_show(sub_vbox); + + frame = qck_create_frame(_("Items to display"), sub_vbox, 0, 12, 12, 0); + gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 0); + + checkbutton = qck_create_check_button(G_OBJECT(assistant), "physical_off", _("Physical offset"), NULL, NULL); + gtk_box_pack_start(GTK_BOX(sub_vbox), checkbutton, FALSE, FALSE, 0); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbutton), TRUE); + + checkbutton = qck_create_check_button(G_OBJECT(assistant), "virtual_addr", _("Virtual address"), NULL, NULL); + gtk_box_pack_start(GTK_BOX(sub_vbox), checkbutton, FALSE, FALSE, 0); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbutton), TRUE); + + checkbutton = qck_create_check_button(G_OBJECT(assistant), "binary_code", _("Binary code"), NULL, NULL); + gtk_box_pack_start(GTK_BOX(sub_vbox), checkbutton, FALSE, FALSE, 0); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbutton), TRUE); + + /* Intégration */ + + gtk_assistant_append_page(assistant, vbox); + gtk_assistant_set_page_title(assistant, vbox, _("Exported content")); + gtk_assistant_set_page_type(assistant, vbox, GTK_ASSISTANT_PAGE_CONTENT); + + gtk_assistant_set_page_complete(assistant, vbox, TRUE); + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* DEFINITION DE LA SORTIE ATTENDUE */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : assistant = fenêtre à compléter et référencement global. * +* * +* Description : Ajoute le panneau de choix du type de sortie. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void register_output_panel(GtkAssistant *assistant) +{ + GtkWidget *vbox; /* Support principal #1 */ + GtkWidget *label; /* Etiquette d'indication */ + GtkWidget *hbox; /* Support principal #2 */ + GtkWidget *entry; /* Zone de saisie de texte */ + GtkWidget *button; /* Sélection de fichier */ + GLoadedBinary *binary; /* Binaire chargé à parcourir */ + const char *filename; /* Chemin d'accès par défaut */ + + vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 8); + qck_set_margins(vbox, 8, 8, 8, 8); + gtk_widget_show(vbox); + + /* Fichier de sortie */ + + label = qck_create_label(NULL, NULL, _("File: ")); + gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0); + + hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8); + gtk_widget_show(hbox); + gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); + + entry = qck_create_entry(G_OBJECT(assistant), "filename", NULL); + gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0); + + button = qck_create_button(NULL, NULL, "...", G_CALLBACK(on_filename_browsing_clicked), assistant); + gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0); + + /* Intégration */ + + gtk_assistant_append_page(assistant, vbox); + gtk_assistant_set_page_title(assistant, vbox, _("Output")); + gtk_assistant_set_page_type(assistant, vbox, GTK_ASSISTANT_PAGE_CONFIRM); + + gtk_assistant_set_page_complete(assistant, vbox, TRUE); + + /* Choix par défaut */ + + binary = G_LOADED_BINARY(g_object_get_data(G_OBJECT(assistant), "binary")); + filename = g_loaded_binary_get_name(binary, true); + + gtk_entry_set_text(GTK_ENTRY(entry), filename); + gtk_editable_insert_text(GTK_EDITABLE(entry), ".html", -1, (gint []) { strlen(filename) }); + + g_signal_connect(G_OBJECT(entry), "changed", G_CALLBACK(on_export_filename_changed), assistant); + +} + + +/****************************************************************************** +* * +* Paramètres : entry = zone de texte dont le contenu vient de changer. * +* assistant = fenêtre affichée et référencement global. * +* * +* Description : Réagit un changement du nom de fichier pour l'exportation. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void on_export_filename_changed(GtkEntry *entry, GtkAssistant *assistant) +{ + const gchar *text; /* Texte saisi dans la zone */ + gint num; /* Etape courante */ + GtkWidget *page; /* Support de cette étape */ + + text = gtk_entry_get_text(entry); + + num = gtk_assistant_get_current_page(assistant); + page = gtk_assistant_get_nth_page(assistant, num); + + gtk_assistant_set_page_complete(assistant, page, (strlen(text) > 0)); + +} + + +/****************************************************************************** +* * +* Paramètres : button = bouton d'édition de la sélection. * +* ref = espace de référencement principal. * +* * +* Description : Sélectionne ou non un nouveau fichier de sortie. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void on_filename_browsing_clicked(GtkButton *button, GObject *ref) +{ + GtkWidget *dialog; /* Boîte à afficher */ + gchar *filename; /* Nom du fichier à intégrer */ + GtkEntry *entry; /* Zone de saisie à maj. */ + + dialog = gtk_file_chooser_dialog_new(_("Choose an output filename"), GTK_WINDOW(ref), + GTK_FILE_CHOOSER_ACTION_SAVE, + _("_Cancel"), GTK_RESPONSE_CANCEL, + _("_Save"), GTK_RESPONSE_ACCEPT, + NULL); + + entry = GTK_ENTRY(g_object_get_data(ref, "filename")); + gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog), gtk_entry_get_text(entry)); + + if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) + { + filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); + + gtk_entry_set_text(GTK_ENTRY(entry), filename); + + g_free(filename); + + } + + gtk_widget_destroy(dialog); + +} diff --git a/src/gui/dialogs/export_disass.h b/src/gui/dialogs/export_disass.h new file mode 100644 index 0000000..86fe4a7 --- /dev/null +++ b/src/gui/dialogs/export_disass.h @@ -0,0 +1,40 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * export_disass.h - prototypes pour l'assistant d'exportation de contenu binaire + * + * Copyright (C) 2015-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 Chrysalide. If not, see . + */ + + +#ifndef _GUI_DIALOGS_EXPORT_DISASS_H +#define _GUI_DIALOGS_EXPORT_DISASS_H + + +#include + + +#include "../../analysis/binary.h" + + + +/* Crée et affiche un assistant d'aide à l'exportation. */ +void run_export_assistant(GLoadedBinary *, GtkWindow *); + + + +#endif /* _GUI_DIALOGS_EXPORT_DISASS_H */ diff --git a/src/gui/dialogs/export_graph.c b/src/gui/dialogs/export_graph.c new file mode 100644 index 0000000..55556b6 --- /dev/null +++ b/src/gui/dialogs/export_graph.c @@ -0,0 +1,459 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * export_graph.c - assistant d'exportation de vues graphiques + * + * Copyright (C) 2019 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 Chrysalide. If not, see . + */ + + +#include "export_graph.h" + + +#include +#include +#include +#include +#include +#include +#include +#include + + +#include "../../common/extstr.h" +#include "../../core/logs.h" +#include "../../glibext/gbinarycursor.h" +#include "../../glibext/gloadedpanel.h" +#include "../../gtkext/gtkdisplaypanel.h" + + + +/* Ferme l'assistant sans dérouler la procédure. */ +static void graph_export_assistant_cancel(GtkAssistant *, GtkBuilder *); + +/* Réalise l'exportation du contenu sous la forme choisie. */ +static void graph_export_assistant_close(GtkAssistant *, GtkBuilder *); + +/* Actualise l'extension du fichier de sortie. */ +static void on_output_format_toggled(GtkToggleButton *, GtkBuilder *); + +/* Prend note d'un changement dans la saisie du fichier final. */ +static void on_output_filename_changed(GtkEditable *, GtkBuilder *); + +/* Réagit à la demande de sélection d'un nouveau fichier final. */ +static void on_output_filename_selection(GtkButton *, GtkBuilder *); + + + +/****************************************************************************** +* * +* Paramètres : binary = contenu bnaire chargé en mémoire. * +* display = vue graphique à traiter. * +* parent = fenêtre principale de l'éditeur. * +* * +* Description : Crée et affiche un assistant d'aide à l'exportation. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void run_graph_export_assistant(GLoadedBinary *binary, GtkGraphDisplay *display, GtkWindow *parent) +{ + GtkBuilder *builder; /* Constructeur utilisé */ + GtkWidget *assistant; /* Fenêtre à afficher */ +#if !defined CAIRO_HAS_PDF_SURFACE || !defined CAIRO_HAS_PS_SURFACE || !defined CAIRO_HAS_SVG_SURFACE + GtkWIdget *button; /* Bouton de sélection */ +#endif + GLineCursor *cursor; /* Position dans la vue */ + vmpa2t target; /* Localisation ciblée */ + GBinFormat *format; /* Format de fichier reconnu */ + bool status; /* Bilan d'un appel */ + GBinSymbol *symbol; /* Symbole affiché */ + char *label; /* Etiquette humaine associée */ + GtkEntry *entry; /* Zone de texte */ + + builder = gtk_builder_new_from_resource("/org/chrysalide/gui/dialogs/export_graph.ui"); + + assistant = GTK_WIDGET(gtk_builder_get_object(builder, "window")); + + gtk_window_set_transient_for(GTK_WINDOW(assistant), parent); + + /* Validation des formats de sortie */ + +#ifndef CAIRO_HAS_PDF_SURFACE + button = GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "as_pdf")); + gtk_widget_set_sensitive(button, FALSE); +#endif + +#ifndef CAIRO_HAS_PS_SURFACE + button = GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "as_ps")); + gtk_widget_set_sensitive(button, FALSE); +#endif + +#ifndef CAIRO_HAS_SVG_SURFACE + button = GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "as_svg")); + gtk_widget_set_sensitive(button, FALSE); +#endif + + /* Choix du fichier d'exportation par défaut */ + + cursor = g_loaded_panel_get_cursor(G_LOADED_PANEL(display)); + + if (cursor != NULL) + { + g_binary_cursor_get_info(G_BINARY_CURSOR(cursor), &target); + + g_object_unref(G_OBJECT(cursor)); + + format = G_BIN_FORMAT(g_loaded_binary_get_format(binary)); + + status = g_binary_format_find_symbol_for(format, &target, &symbol); + + g_object_unref(G_OBJECT(format)); + + if (status) + { + label = g_binary_symbol_get_label(symbol); + + entry = GTK_ENTRY(gtk_builder_get_object(builder, "output")); + + gtk_entry_set_text(entry, label); + + free(label); + + g_object_unref(G_OBJECT(symbol)); + + } + + } + + on_output_format_toggled(NULL, builder); + + /* Mémorisation pour les traitement */ + + g_object_ref(G_OBJECT(display)); + g_object_set_data_full(G_OBJECT(assistant), "display", display, g_object_unref); + + /* Connexion des signaux */ + + gtk_builder_add_callback_symbols(builder, + "graph_export_assistant_cancel", G_CALLBACK(graph_export_assistant_cancel), + "graph_export_assistant_close", G_CALLBACK(graph_export_assistant_close), + "on_output_format_toggled", G_CALLBACK(on_output_format_toggled), + "on_output_filename_changed", G_CALLBACK(on_output_filename_changed), + "on_output_filename_selection", G_CALLBACK(on_output_filename_selection), + NULL); + + gtk_builder_connect_signals(builder, builder); + + gtk_widget_show_all(assistant); + +} + + +/****************************************************************************** +* * +* Paramètres : assistant = fenêtre à compléter et référencement global. * +* builder = espace de référencement global. * +* * +* Description : Ferme l'assistant sans dérouler la procédure. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void graph_export_assistant_cancel(GtkAssistant *assistant, GtkBuilder *builder) +{ + g_object_set_data(G_OBJECT(assistant), "binary", NULL); + g_object_set_data(G_OBJECT(assistant), "display", NULL); + + g_object_ref(G_OBJECT(assistant)); + gtk_widget_destroy(GTK_WIDGET(assistant)); + + g_object_unref(G_OBJECT(builder)); + +} + + +/****************************************************************************** +* * +* Paramètres : button = bouton à l'origine de la procédure. * +* builder = espace de référencement global. * +* * +* Description : Réalise l'exportation du contenu sous la forme choisie. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void graph_export_assistant_close(GtkAssistant *assistant, GtkBuilder *builder) +{ + GtkEntry *entry; /* Zone de texte */ + const gchar *cur_filename; /* Fichier de sortie courant */ + GtkGraphDisplay *display; /* Vue grahique associée */ + GtkRequisition size; /* Taille idéale associée */ + bool as_png; /* Exportation en PNG ? */ + GtkToggleButton *button; /* Bouton de sélection */ + gboolean state; /* Etat de la sélection */ + cairo_surface_t *surface; /* Zone de dessin nouvelle */ + cairo_t *cr; /* Contexte de rendu */ + GtkWidget *widget; /* Composant GTK à dessiner */ + cairo_status_t status; /* Bilan de l'écriture */ + + /* Collecte des informations de base */ + + entry = GTK_ENTRY(gtk_builder_get_object(builder, "output")); + + cur_filename = gtk_entry_get_text(entry); + + display = GTK_GRAPH_DISPLAY(g_object_get_data(G_OBJECT(assistant), "display")); + + gtk_widget_get_preferred_size(GTK_WIDGET(display), &size, NULL); + + /* Préparation du fichier de sortie */ + + as_png = false; + + button = GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "as_pdf")); + state = gtk_toggle_button_get_active(button); + + if (state) + { + surface = cairo_pdf_surface_create(cur_filename, size.width, size.height); + goto do_export; + } + + button = GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "as_ps")); + state = gtk_toggle_button_get_active(button); + + if (state) + { + surface = cairo_ps_surface_create(cur_filename, size.width, size.height); + goto do_export; + } + + button = GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "as_svg")); + state = gtk_toggle_button_get_active(button); + + if (state) + { + surface = cairo_svg_surface_create(cur_filename, size.width, size.height); + goto do_export; + } + + surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, size.width, size.height); + as_png = true; + + /* Exportation du rendu */ + + do_export: + + cr = cairo_create(surface); + + gtk_display_panel_prepare_export(GTK_DISPLAY_PANEL(display), true); + + widget = gtk_graph_display_get_support(display); + + gtk_widget_draw(widget, cr); + + g_object_unref(G_OBJECT(widget)); + + gtk_display_panel_prepare_export(GTK_DISPLAY_PANEL(display), false); + + if (as_png) + { + status = cairo_surface_write_to_png(surface, cur_filename); + + if (status != CAIRO_STATUS_SUCCESS) + log_variadic_message(LMT_ERROR, "Export error: %s (%u)", cairo_status_to_string(status), status); + + } + else + cairo_show_page(cr); + + cairo_destroy(cr); + + cairo_surface_destroy(surface); + + graph_export_assistant_cancel(assistant, builder); + +} + + +/****************************************************************************** +* * +* Paramètres : tbutton = bouton à l'origine de la procédure. * +* builder = espace de référencement global. * +* * +* Description : Actualise l'extension du fichier de sortie. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void on_output_format_toggled(GtkToggleButton *tbutton, GtkBuilder *builder) +{ + GtkToggleButton *button; /* Bouton de sélection */ + gboolean state; /* Etat de la sélection */ + const char *ext; /* Extension attendue */ + GtkEntry *entry; /* Zone de texte */ + const gchar *cur_filename; /* Fichier de sortie courant */ + char *found; /* Point final trouvé */ + char *new_filename; /* Nouveau fichier de sortie */ + + button = GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "as_pdf")); + state = gtk_toggle_button_get_active(button); + + if (state) + { + ext = "pdf"; + goto do_update; + } + + button = GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "as_ps")); + state = gtk_toggle_button_get_active(button); + + if (state) + { + ext = "ps"; + goto do_update; + } + + button = GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "as_svg")); + state = gtk_toggle_button_get_active(button); + + if (state) + { + ext = "svg"; + goto do_update; + } + + ext = "png"; + + do_update: + + entry = GTK_ENTRY(gtk_builder_get_object(builder, "output")); + + cur_filename = gtk_entry_get_text(entry); + + found = rindex(cur_filename, '.'); + + if (found == NULL) + asprintf(&new_filename, "%s.%s", cur_filename, ext); + + else + { + new_filename = strndup(cur_filename, found - cur_filename); + + new_filename = stradd(new_filename, "."); + new_filename = stradd(new_filename, ext); + + } + + gtk_entry_set_text(entry, new_filename); + + free(new_filename); + +} + + +/****************************************************************************** +* * +* Paramètres : editable = zone de texte à l'origine de la procédure. * +* builder = espace de référencement global. * +* * +* Description : Prend note d'un changement dans la saisie du fichier final. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void on_output_filename_changed(GtkEditable *editable, GtkBuilder *builder) +{ + const gchar *cur_filename; /* Fichier de sortie courant */ + GtkAssistant *assistant; /* Fenêtre affichée */ + GtkWidget *page; /* Composant associé à une page*/ + + cur_filename = gtk_entry_get_text(GTK_ENTRY(editable)); + + assistant = GTK_ASSISTANT(gtk_builder_get_object(builder, "window")); + + page = gtk_assistant_get_nth_page(assistant, 1); + + gtk_assistant_set_page_complete(assistant, page, strlen(cur_filename) > 0); + +} + + +/****************************************************************************** +* * +* Paramètres : button = bouton à l'origine de la procédure. * +* builder = espace de référencement global. * +* * +* Description : Réagit à la demande de sélection d'un nouveau fichier final. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void on_output_filename_selection(GtkButton *button, GtkBuilder *builder) +{ + GtkWindow *assistant; /* Fenêtre affichée */ + GtkEntry *entry; /* Zone de texte */ + const gchar *cur_filename; /* Fichier de sortie courant */ + GtkWidget *dialog; /* Boîte à afficher */ + gchar *new_filename; /* Nouveau fichier de sortie */ + + assistant = GTK_WINDOW(gtk_builder_get_object(builder, "window")); + + entry = GTK_ENTRY(gtk_builder_get_object(builder, "output")); + + cur_filename = gtk_entry_get_text(entry); + + dialog = gtk_file_chooser_dialog_new(_("Save the output as..."), assistant, + GTK_FILE_CHOOSER_ACTION_SAVE, + _("_Cancel"), GTK_RESPONSE_CANCEL, + _("_Save"), GTK_RESPONSE_ACCEPT, + NULL); + + gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog), cur_filename); + + if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) + { + new_filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); + + gtk_entry_set_text(entry, new_filename); + + g_free(new_filename); + + } + + gtk_widget_destroy(dialog); + +} diff --git a/src/gui/dialogs/export_graph.h b/src/gui/dialogs/export_graph.h new file mode 100644 index 0000000..a88db3e --- /dev/null +++ b/src/gui/dialogs/export_graph.h @@ -0,0 +1,41 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * export_graph.h - prototypes pour l'assistant d'exportation de vues graphiques + * + * Copyright (C) 2019 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 Chrysalide. If not, see . + */ + + +#ifndef _GUI_DIALOGS_EXPORT_GRAPH_H +#define _GUI_DIALOGS_EXPORT_GRAPH_H + + +#include + + +#include "../../analysis/binary.h" +#include "../../gtkext/gtkgraphdisplay.h" + + + +/* Crée et affiche un assistant d'aide à l'exportation. */ +void run_graph_export_assistant(GLoadedBinary *, GtkGraphDisplay *, GtkWindow *); + + + +#endif /* _GUI_DIALOGS_EXPORT_GRAPH_H */ diff --git a/src/gui/dialogs/export_graph.ui b/src/gui/dialogs/export_graph.ui new file mode 100644 index 0000000..1c34bd3 --- /dev/null +++ b/src/gui/dialogs/export_graph.ui @@ -0,0 +1,196 @@ + + + + + + False + True + center + 440 + 250 + dialog + 1 + + + + + True + False + center + center + 8 + 8 + 8 + 8 + vertical + 8 + + + PNG image + True + True + False + True + True + + + + False + True + 0 + + + + + PDF document + True + True + False + True + as_png + + + + False + True + 1 + + + + + PostScript document + True + True + False + True + as_png + + + + False + True + 2 + + + + + SVG image + True + True + False + True + as_png + + + + False + True + 3 + + + + + Export format + True + False + + + + + True + False + center + 8 + 8 + 8 + 8 + vertical + 8 + + + True + False + + + True + True + True + + + False + True + 0 + + + + + Parcourir... + True + True + True + + + + False + True + 1 + + + + + False + True + 0 + + + + + True + False + Warning: the output file will be overwritten if it exists. + 0 + + + False + True + 1 + + + + + confirm + Output file + True + False + + + + + + + + + + + False + end + 6 + 6 + 6 + 6 + 6 + 6 + 6 + + + + + + + + + + + + + diff --git a/src/gui/dialogs/gresource.xml b/src/gui/dialogs/gresource.xml index ff606ba..1d18e39 100644 --- a/src/gui/dialogs/gresource.xml +++ b/src/gui/dialogs/gresource.xml @@ -2,6 +2,7 @@ bookmark.ui + export_graph.ui identity.ui preferences.ui prefs_fgraph.ui diff --git a/src/gui/menus/binary.c b/src/gui/menus/binary.c index c4c4e22..3a143da 100644 --- a/src/gui/menus/binary.c +++ b/src/gui/menus/binary.c @@ -31,11 +31,13 @@ #include "../agroup.h" #include "../editem-int.h" #include "../core/global.h" -#include "../dialogs/export.h" +#include "../dialogs/export_disass.h" +#include "../dialogs/export_graph.h" #include "../dialogs/gotox.h" #include "../dialogs/storage.h" #include "../../gtkext/easygtk.h" #include "../../gtkext/gtkdisplaypanel.h" +#include "../../gtkext/gtkgraphdisplay.h" @@ -48,8 +50,11 @@ static void mcb_binary_attach_debugger(GtkMenuItem *, GMenuBar *); /* Réagit au menu "Binaire -> Enregistrements...". */ static void mcb_binary_storage(GtkMenuItem *, GMenuBar *); -/* Réagit au menu "Binaire -> Exporter...". */ -static void mcb_binary_export(GtkMenuItem *, GMenuBar *); +/* Réagit au menu "Binaire -> Exporter -> Désassemblage". */ +static void mcb_binary_export_disass(GtkMenuItem *, gpointer); + +/* Réagit au menu "Binaire -> Exporter -> Vue graphique". */ +static void mcb_binary_export_graph(GtkMenuItem *, gpointer); @@ -70,7 +75,9 @@ GtkWidget *build_menu_binary(GObject *ref, GMenuBar *bar) { GtkWidget *result; /* Support à retourner */ GtkWidget *menubar; /* Support pour éléments */ - GtkWidget *submenuitem; /* Sous-élément de menu */ + GtkWidget *submenuitem; /* Sous-élément de menu #1 */ + GtkWidget *deepmenubar; /* Support pour éléments #2 */ + GtkWidget *deepmenuitem; /* Sous-élément de menu #2 */ result = gtk_menu_item_new_with_mnemonic(_("_Binary")); gtk_widget_show(result); @@ -96,10 +103,26 @@ GtkWidget *build_menu_binary(GObject *ref, GMenuBar *bar) G_CALLBACK(mcb_binary_storage), bar); gtk_container_add(GTK_CONTAINER(menubar), submenuitem); - submenuitem = qck_create_menu_item(ref, "mnu_binary_export", _("Export..."), - G_CALLBACK(mcb_binary_export), bar); + /* Séparation */ + + submenuitem = qck_create_menu_separator(); + gtk_container_add(GTK_CONTAINER(menubar), submenuitem); + + /* Exportations */ + + submenuitem = qck_create_menu_item(NULL, NULL, _("Export"), NULL, NULL); gtk_container_add(GTK_CONTAINER(menubar), submenuitem); + deepmenubar = qck_create_menu(GTK_MENU_ITEM(submenuitem)); + + deepmenuitem = qck_create_menu_item(ref, "mnu_binary_export_disass", _("Disassembly"), + G_CALLBACK(mcb_binary_export_disass), bar); + gtk_container_add(GTK_CONTAINER(deepmenubar), deepmenuitem); + + deepmenuitem = qck_create_menu_item(ref, "mnu_binary_export_graph", _("Graph view"), + G_CALLBACK(mcb_binary_export_graph), NULL); + gtk_container_add(GTK_CONTAINER(deepmenubar), deepmenuitem); + return result; } @@ -137,7 +160,37 @@ void update_access_for_content_in_menu_binary(GLoadedContent *new) item = GTK_WIDGET(g_object_get_data(ref, "mnu_binary_storage")); gtk_widget_set_sensitive(item, access); - item = GTK_WIDGET(g_object_get_data(ref, "mnu_binary_export")); + item = GTK_WIDGET(g_object_get_data(ref, "mnu_binary_export_disass")); + gtk_widget_set_sensitive(item, access); + +} + + +/****************************************************************************** +* * +* Paramètres : new = nouvelle vue du contenu chargé analysé. * +* * +* Description : Lance une actualisation du fait d'un changement de support. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void update_access_for_view_in_menu_binary(GLoadedPanel *new) +{ + GObject *ref; /* Espace de référencements */ + gboolean access; /* Accès à déterminer */ + GtkWidget *item; /* Elément de menu à traiter */ + + ref = get_global_ref(); + + /* Exportation de graphiques */ + + access = GTK_IS_GRAPH_DISPLAY(new); + + item = GTK_WIDGET(g_object_get_data(ref, "mnu_binary_export_graph")); gtk_widget_set_sensitive(item, access); } @@ -249,9 +302,9 @@ static void mcb_binary_storage(GtkMenuItem *menuitem, GMenuBar *bar) /****************************************************************************** * * * Paramètres : menuitem = élément de menu sélectionné. * -* bar = barre de menu parente. * +* unused = adresse non utilisée ici. * * * -* Description : Réagit au menu "Binaire -> Exporter...". * +* Description : Réagit au menu "Binaire -> Exporter -> Désassemblage". * * * * Retour : - * * * @@ -259,7 +312,7 @@ static void mcb_binary_storage(GtkMenuItem *menuitem, GMenuBar *bar) * * ******************************************************************************/ -static void mcb_binary_export(GtkMenuItem *menuitem, GMenuBar *bar) +static void mcb_binary_export_disass(GtkMenuItem *menuitem, gpointer unused) { GLoadedBinary *binary; /* Edition courante */ @@ -270,3 +323,34 @@ static void mcb_binary_export(GtkMenuItem *menuitem, GMenuBar *bar) g_object_unref(G_OBJECT(binary)); } + + +/****************************************************************************** +* * +* Paramètres : menuitem = élément de menu sélectionné. * +* unused = adresse non utilisée ici. * +* * +* Description : Réagit au menu "Binaire -> Exporter -> Vue graphique". * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void mcb_binary_export_graph(GtkMenuItem *menuitem, gpointer unused) +{ + GtkGraphDisplay *panel; /* Panneau de code courant */ + GLoadedBinary *binary; /* Edition courante */ + + binary = G_LOADED_BINARY(get_current_content()); + + panel = GTK_GRAPH_DISPLAY(get_current_view()); + + run_graph_export_assistant(binary, panel, get_editor_window()); + + g_object_unref(G_OBJECT(panel)); + + g_object_unref(G_OBJECT(binary)); + +} diff --git a/src/gui/menus/binary.h b/src/gui/menus/binary.h index c68b67c..a752626 100644 --- a/src/gui/menus/binary.h +++ b/src/gui/menus/binary.h @@ -40,6 +40,9 @@ GtkWidget *build_menu_binary(GObject *, GMenuBar *); /* Réagit à un changement d'affichage principal de contenu. */ void update_access_for_content_in_menu_binary(GLoadedContent *); +/* Lance une actualisation du fait d'un changement de support. */ +void update_access_for_view_in_menu_binary(GLoadedPanel *); + #endif /* _GUI_MENUS_BINARY_H */ diff --git a/src/gui/menus/menubar.c b/src/gui/menus/menubar.c index 886387c..aa89a13 100644 --- a/src/gui/menus/menubar.c +++ b/src/gui/menus/menubar.c @@ -311,6 +311,8 @@ static void change_menubar_current_view(GMenuBar *bar, GLoadedPanel *old, GLoade update_access_for_view_in_menu_view(G_EDITOR_ITEM(bar)->ref, new); + update_access_for_view_in_menu_binary(new); + } -- cgit v0.11.2-87-g4458