summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2019-03-18 09:00:20 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2019-03-18 09:00:55 (GMT)
commit43d57853c6f2c59197c7dc20ff61f3f2eacc2445 (patch)
tree3dcb5ad426c7e5d4159d95f7e9e5e80eef45bfe0
parentf65f83fd222d14934b527152899359327813128e (diff)
Exported graph views using Cairo.
-rw-r--r--src/glibext/gbufferview.c14
-rw-r--r--src/glibext/gbufferview.h2
-rw-r--r--src/gtkext/gtkbufferdisplay.c25
-rw-r--r--src/gtkext/gtkdisplaypanel-int.h7
-rw-r--r--src/gtkext/gtkdisplaypanel.c29
-rw-r--r--src/gtkext/gtkdisplaypanel.h7
-rw-r--r--src/gtkext/gtkgraphdisplay.c63
-rw-r--r--src/gtkext/gtkgraphdisplay.h15
-rw-r--r--src/gui/dialogs/Makefile.am4
-rw-r--r--src/gui/dialogs/export_disass.c (renamed from src/gui/dialogs/export.c)4
-rw-r--r--src/gui/dialogs/export_disass.h (renamed from src/gui/dialogs/export.h)8
-rw-r--r--src/gui/dialogs/export_graph.c459
-rw-r--r--src/gui/dialogs/export_graph.h41
-rw-r--r--src/gui/dialogs/export_graph.ui196
-rw-r--r--src/gui/dialogs/gresource.xml1
-rw-r--r--src/gui/menus/binary.c104
-rw-r--r--src/gui/menus/binary.h3
-rw-r--r--src/gui/menus/menubar.c2
18 files changed, 946 insertions, 38 deletions
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_disass.c
index 5a66d02..be7d2a9 100644
--- a/src/gui/dialogs/export.c
+++ b/src/gui/dialogs/export_disass.c
@@ -1,6 +1,6 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * export.c - assistant d'exportation de contenu binaire
+ * export_disass.c - assistant d'exportation de contenu binaire
*
* Copyright (C) 2015-2017 Cyrille Bagard
*
@@ -21,7 +21,7 @@
*/
-#include "export.h"
+#include "export_disass.h"
#include <assert.h>
diff --git a/src/gui/dialogs/export.h b/src/gui/dialogs/export_disass.h
index 209dea8..86fe4a7 100644
--- a/src/gui/dialogs/export.h
+++ b/src/gui/dialogs/export_disass.h
@@ -1,6 +1,6 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * export.h - prototypes pour l'assistant d'exportation de contenu binaire
+ * export_disass.h - prototypes pour l'assistant d'exportation de contenu binaire
*
* Copyright (C) 2015-2017 Cyrille Bagard
*
@@ -21,8 +21,8 @@
*/
-#ifndef _GUI_DIALOGS_EXPORT_H
-#define _GUI_DIALOGS_EXPORT_H
+#ifndef _GUI_DIALOGS_EXPORT_DISASS_H
+#define _GUI_DIALOGS_EXPORT_DISASS_H
#include <gtk/gtk.h>
@@ -37,4 +37,4 @@ void run_export_assistant(GLoadedBinary *, GtkWindow *);
-#endif /* _GUI_DIALOGS_EXPORT_H */
+#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 <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "export_graph.h"
+
+
+#include <assert.h>
+#include <cairo-pdf.h>
+#include <cairo-svg.h>
+#include <cairo-ps.h>
+#include <malloc.h>
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+
+
+#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 <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GUI_DIALOGS_EXPORT_GRAPH_H
+#define _GUI_DIALOGS_EXPORT_GRAPH_H
+
+
+#include <gtk/gtk.h>
+
+
+#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 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.21.0 -->
+<interface>
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkAssistant" id="window">
+ <property name="can_focus">False</property>
+ <property name="modal">True</property>
+ <property name="window_position">center</property>
+ <property name="default_width">440</property>
+ <property name="default_height">250</property>
+ <property name="type_hint">dialog</property>
+ <property name="use_header_bar">1</property>
+ <signal name="cancel" handler="graph_export_assistant_cancel" swapped="no"/>
+ <signal name="close" handler="graph_export_assistant_close" swapped="no"/>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <property name="margin_left">8</property>
+ <property name="margin_right">8</property>
+ <property name="margin_top">8</property>
+ <property name="margin_bottom">8</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">8</property>
+ <child>
+ <object class="GtkRadioButton" id="as_png">
+ <property name="label" translatable="yes">PNG image</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ <signal name="toggled" handler="on_output_format_toggled" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="as_pdf">
+ <property name="label" translatable="yes">PDF document</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">as_png</property>
+ <signal name="toggled" handler="on_output_format_toggled" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="as_ps">
+ <property name="label" translatable="yes">PostScript document</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">as_png</property>
+ <signal name="toggled" handler="on_output_format_toggled" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="as_svg">
+ <property name="label" translatable="yes">SVG image</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">as_png</property>
+ <signal name="toggled" handler="on_output_format_toggled" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="title" translatable="yes">Export format</property>
+ <property name="complete">True</property>
+ <property name="has_padding">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="valign">center</property>
+ <property name="margin_left">8</property>
+ <property name="margin_right">8</property>
+ <property name="margin_top">8</property>
+ <property name="margin_bottom">8</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">8</property>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkEntry" id="output">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton">
+ <property name="label" translatable="yes">Parcourir...</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <signal name="clicked" handler="on_output_filename_selection" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Warning: the output file will be overwritten if it exists. </property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="page_type">confirm</property>
+ <property name="title" translatable="yes">Output file</property>
+ <property name="complete">True</property>
+ <property name="has_padding">False</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child internal-child="action_area">
+ <object class="GtkBox">
+ <property name="can_focus">False</property>
+ <property name="halign">end</property>
+ <property name="margin_left">6</property>
+ <property name="margin_right">6</property>
+ <property name="margin_start">6</property>
+ <property name="margin_end">6</property>
+ <property name="margin_top">6</property>
+ <property name="margin_bottom">6</property>
+ <property name="spacing">6</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ </object>
+</interface>
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 @@
<gresources>
<gresource prefix="/org/chrysalide/gui/dialogs">
<file compressed="true">bookmark.ui</file>
+ <file compressed="true">export_graph.ui</file>
<file compressed="true">identity.ui</file>
<file compressed="true">preferences.ui</file>
<file compressed="true">prefs_fgraph.ui</file>
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);
+
}