summaryrefslogtreecommitdiff
path: root/src/gtkext/gtkgraphview.c
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2016-12-30 10:38:52 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2016-12-30 10:38:52 (GMT)
commit932ea7c83c07d3982fee605c6dd9895fd2753874 (patch)
tree766ad53bab9e3e3005334c30e823493de8e84168 /src/gtkext/gtkgraphview.c
parent1b5d39bfbc48c33a0ea0924b60e48448c8b45dd4 (diff)
Rewritten the line buffers using generators and on-demand building to save memory.
Diffstat (limited to 'src/gtkext/gtkgraphview.c')
-rw-r--r--src/gtkext/gtkgraphview.c1371
1 files changed, 0 insertions, 1371 deletions
diff --git a/src/gtkext/gtkgraphview.c b/src/gtkext/gtkgraphview.c
deleted file mode 100644
index 57bbec0..0000000
--- a/src/gtkext/gtkgraphview.c
+++ /dev/null
@@ -1,1371 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * gtkgraphview.c - affichage de morceaux de code sous forme graphique
- *
- * Copyright (C) 2009-2014 Cyrille Bagard
- *
- * This file is part of Chrysalide.
- *
- * Chrysalide is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * Chrysalide is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#include "gtkgraphview.h"
-
-
-#include <assert.h>
-
-
-#include "gtkblockview.h"
-#include "gtkbufferview.h"
-#include "gtkdisplaypanel-int.h"
-#include "graph/cluster.h"
-#include "../analysis/blocks/flow.h"
-#include "../format/format.h"
-#include "../gui/editem.h"
-
-
-
-/* Composant d'affichage sous forme graphique (instance) */
-struct _GtkGraphView
-{
- GtkDisplayPanel parent; /* A laisser en premier */
- GtkWidget *support; /* Support des vues en bloc */
- GtkWidget *extender; /* Force la taille du support */
-
- GBinRoutine *routine; /* Routine en cours d'affichage*/
-
- segcnt_list *highlighted; /* Segments mis en évidence */
- GtkBufferView **children; /* Liste des sous-blocs */
- GtkAllocation *allocs; /* Emplacements prévisibles */
- size_t children_count; /* Taille de cette liste */
-
- //GGraphLayout *layout; /* Disposition en graphique */
- GGraphCluster *cluster; /* Disposition en graphique */
-
- GGraphEdge **edges; /* Liens entre les noeuds */
- size_t edges_count; /* Quantité de ces liens */
-
- gdouble start_x; /* Abscisse du point de souris */
- gdouble start_y; /* Ordonnée du point de souris */
- bool big_enough; /* Capacités de déplacement ? */
- gdouble ref_h; /* Position horizontale de ref.*/
- gdouble ref_v; /* Position verticale de ref. */
-
-};
-
-/* Composant d'affichage sous forme graphique (classe) */
-struct _GtkGraphViewClass
-{
- GtkDisplayPanelClass parent; /* A laisser en premier */
-
-};
-
-
-/* Profondeur de l'ombre */
-#define SHADOW_SIZE 4
-
-
-/* Initialise la classe générique des graphiques de code. */
-static void gtk_graph_view_class_init(GtkGraphViewClass *);
-
-/* Initialise une instance d'afficheur de code en graphique. */
-static void gtk_graph_view_init(GtkGraphView *);
-
-/* Supprime toutes les références externes. */
-static void gtk_graph_view_dispose(GtkGraphView *);
-
-/* Procède à la libération totale de la mémoire. */
-static void gtk_graph_view_finalize(GtkGraphView *);
-
-/* S'adapte à la surface concédée par le composant parent. */
-static void gtk_graph_view_size_allocate(GtkWidget *, GtkAllocation *);
-
-/* Centre si possible le contenu du panneau d'affichage. */
-static void gtk_graph_view_update_support_margins(GtkGraphView *, const GtkAllocation *);
-
-/* Indique les dimensions de travail du composant d'affichage. */
-static void gtk_graph_view_compute_requested_size(GtkGraphView *, gint *, gint *);
-
-/* Réagit à un défilement chez une barre associée au composant. */
-static void gtk_graph_view_adjust_scroll_value(GtkGraphView *, GtkAdjustment *, GtkOrientation);
-
-/* Met à jour l'affichage de la vue sous forme graphique. */
-static gboolean gtk_graph_view_draw(GtkWidget *, cairo_t *, GtkGraphView *);
-
-/* Assure la gestion des clics de souris sur le composant. */
-static gboolean gtk_graph_view_button_press(GtkWidget *, GdkEventButton *, GtkGraphView *);
-
-/* Assure la gestion des clics de souris sur le composant. */
-static gboolean gtk_graph_view_button_release(GtkWidget *, GdkEventButton *, GtkGraphView *);
-
-/* Assure la suivi des déplacements de souris sur le composant. */
-static gboolean gtk_graph_view_motion_notify(GtkWidget *, GdkEventMotion *, GtkGraphView *);
-
-/* Actualise les besoins internes avant un redimensionnement. */
-static void gtk_graph_view_prepare_resize(GtkGraphView *);
-
-/* Réagit à la sélection externe d'une adresse. */
-static void gtk_graph_view_define_main_address(GtkGraphView *, const vmpa2t *);
-
-/* Indique la position courante du curseur. */
-static const vmpa2t *gtk_graph_view_get_caret_location(const GtkGraphView *);
-
-/* Indique la position d'affichage d'une adresse donnée. */
-static bool gtk_graph_view_get_address_coordinates(const GtkGraphView *, const vmpa2t *addr, gint *x, gint *y, ScrollPositionTweak tweak);
-
-/* Déplace le curseur à un emplacement défini. */
-static bool gtk_graph_view_move_caret_to(GtkGraphView *, gint, gint);
-
-/* Place en cache un rendu destiné à l'aperçu graphique rapide. */
-static void gtk_graph_view_cache_glance(GtkGraphView *, cairo_t *, const GtkAllocation *, double);
-
-/* Supprime tout contenu de l'afficheur de code en graphique. */
-static void gtk_graph_view_reset(GtkGraphView *);
-
-/* Définit la liste complète des éléments du futur graphique. */
-static GtkBufferView **gtk_graph_view_load_nodes(GtkGraphView *, GLoadedBinary *, const GBinRoutine *);
-
-/* Notifie un changement de surbrillance au sein d'un noeud. */
-static void gtk_graph_view_changed_highlights(GtkBlockView *, GtkGraphView *);
-
-/* Notifie une incapacité de déplacement au sein d'un noeud. */
-static void gtk_graph_view_reach_caret_limit(GtkBufferView *, GdkScrollDirection, GtkGraphView *);
-
-
-
-/* Détermine le type du composant d'affichage en graphique. */
-G_DEFINE_TYPE(GtkGraphView, gtk_graph_view, GTK_TYPE_DISPLAY_PANEL)
-
-
-/******************************************************************************
-* *
-* Paramètres : class = classe GTK à initialiser. *
-* *
-* Description : Initialise la classe générique des graphiques de code. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void gtk_graph_view_class_init(GtkGraphViewClass *class)
-{
- GObjectClass *object; /* Autre version de la classe */
- GtkWidgetClass *widget_class; /* Classe de haut niveau */
- GtkDisplayPanelClass *panel_class; /* Classe parente */
-
- object = G_OBJECT_CLASS(class);
-
- object->dispose = (GObjectFinalizeFunc/* ! */)gtk_graph_view_dispose;
- object->finalize = (GObjectFinalizeFunc)gtk_graph_view_finalize;
-
- widget_class = GTK_WIDGET_CLASS(class);
-
- widget_class->size_allocate = gtk_graph_view_size_allocate;
-
- panel_class = GTK_DISPLAY_PANEL_CLASS(class);
-
- panel_class->compute_size = (compute_requested_size_fc)gtk_graph_view_compute_requested_size;
- panel_class->adjust = (adjust_scroll_value_fc)gtk_graph_view_adjust_scroll_value;
- panel_class->define = (define_address_fc)gtk_graph_view_define_main_address;
-
- panel_class->get_caret_loc = (get_caret_location_fc)gtk_graph_view_get_caret_location;
- panel_class->get_coordinates = (get_addr_coordinates_fc)gtk_graph_view_get_address_coordinates;
- panel_class->move_caret_to = (move_caret_to_fc)gtk_graph_view_move_caret_to;
- panel_class->cache_glance = (cache_glance_fc)gtk_graph_view_cache_glance;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : view = instance GTK à initialiser. *
-* *
-* Description : Initialise une instance d'afficheur de code en graphique. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void gtk_graph_view_init(GtkGraphView *view)
-{
- GtkDisplayPanel *panel; /* Instance parente #1 */
- //GtkBinView *binview; /* Instance parente #2 */
-
- panel = GTK_DISPLAY_PANEL(view);
-
- panel->resize = (prepare_resize_fc)gtk_graph_view_prepare_resize;
- ////////viewpanel->get_coordinates = (get_addr_coordinates_fc)gtk_graph_view_get_address_coordinates;
-
- //binview = GTK_BIN_VIEW(view);
-
- //binview->set_lines = (set_rendering_lines_fc)gtk_graph_view_set_rendering_lines;
- //binview->define_address = (define_main_address_fc)gtk_graph_view_define_main_address;
- //binview->get_coordinates = (get_addr_coordinates_fc)gtk_graph_view_get_address_coordinates;
-
- view->support = gtk_fixed_new();
- gtk_widget_set_has_window(view->support, TRUE);
- gtk_widget_set_can_focus(view->support, TRUE);
-
- g_signal_connect(G_OBJECT(view->support), "draw",
- G_CALLBACK(gtk_graph_view_draw), view);
-
- g_signal_connect(G_OBJECT(view->support), "button-press-event",
- G_CALLBACK(gtk_graph_view_button_press), view);
- g_signal_connect(G_OBJECT(view->support), "button-release-event",
- G_CALLBACK(gtk_graph_view_button_release), view);
- g_signal_connect(G_OBJECT(view->support), "motion-notify-event",
- G_CALLBACK(gtk_graph_view_motion_notify), view);
-
- gtk_widget_add_events(view->support,
- GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
-
- gtk_widget_show(view->support);
-
- gtk_fixed_put(GTK_FIXED(view), view->support, 0, 0);
-
- //view->mutex = g_mutex_new();
- //view->cond = g_cond_new();
-
-
- view->extender = gtk_fixed_new();
-
- gtk_widget_set_margin_end(view->extender, 1);
- gtk_widget_set_margin_top(view->extender, 1);
-
- gtk_widget_show(view->extender);
-
-
- view->cluster = NULL;
-
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : view = instance d'objet GLib à traiter. *
-* *
-* Description : Supprime toutes les références externes. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void gtk_graph_view_dispose(GtkGraphView *view)
-{
- g_object_unref(G_OBJECT(view->extender));
-
- if (view->cluster != NULL)
- {
- g_object_unref(G_OBJECT(view->cluster));
- view->cluster = NULL;
- }
-
- G_OBJECT_CLASS(gtk_graph_view_parent_class)->dispose(G_OBJECT(view));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : view = instance d'objet GLib à traiter. *
-* *
-* Description : Procède à la libération totale de la mémoire. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void gtk_graph_view_finalize(GtkGraphView *view)
-{
- G_OBJECT_CLASS(gtk_graph_view_parent_class)->finalize(G_OBJECT(view));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : widget = composant GTK à mettre à jour. *
-* allocation = étendue accordée à la vue. *
-* *
-* Description : S'adapte à la surface concédée par le composant parent. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void gtk_graph_view_size_allocate(GtkWidget *widget, GtkAllocation *allocation)
-{
- GtkGraphView *view; /* Autre version du composant */
-
- GTK_WIDGET_CLASS(gtk_graph_view_parent_class)->size_allocate(widget, allocation);
-
- view = GTK_GRAPH_VIEW(widget);
-
- gtk_graph_view_update_support_margins(view, allocation);
-
-}
-
-/******************************************************************************
-* *
-* Paramètres : view = panneau dont le contenu est à déplacer. *
-* allocation = étendue accordée à la vue. *
-* *
-* Description : Centre si possible le contenu du panneau d'affichage. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void gtk_graph_view_update_support_margins(GtkGraphView *view, const GtkAllocation *allocation)
-{
- gint width; /* Largeur totale du support */
- gint height; /* Hauteur totale du support */
- gint start; /* Bordure horizontale */
- gint top; /* Bordure verticale */
-
- gtk_graph_view_compute_requested_size(view, &width, &height);
-
- if (width > allocation->width)
- start = 0;
- else
- start = (allocation->width - width) / 2;
-
- if (height > allocation->height)
- top = 0;
- else
- top = (allocation->height - height) / 2;
-
- gtk_widget_set_margin_start(view->support, start);
- gtk_widget_set_margin_top(view->support, top);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : view = composant GTK à consulter. *
-* width = largeur requise à renseigner ou NULL. [OUT] *
-* height = hauteur requise à renseigner ou NULL. [OUT] *
-* *
-* Description : Indique les dimensions de travail du composant d'affichage. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void gtk_graph_view_compute_requested_size(GtkGraphView *view, gint *width, gint *height)
-{
- GtkAllocation needed; /* Taille requise */
- gint rwidth; /* Largeur demandée */
- gint rheight; /* Hauteur demandée */
-
- if (view->cluster != NULL)
- {
- g_graph_cluster_compute_needed_alloc(view->cluster, &needed);
- assert(needed.x == 0 && needed.y == 0);
-
- /* TODO : marges ou centrage */
-
- }
- else
- {
- needed.width = 0;
- needed.height = 0;
- }
-
- if (width != NULL) *width = needed.width + SHADOW_SIZE;
- if (height != NULL) *height = needed.height + SHADOW_SIZE;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : view = panneau d'affichage concerné. *
-* adj = défilement dont une valeur a changé. *
-* orientation = indication sur le défilement à traiter. *
-* *
-* Description : Réagit à un défilement chez une barre associée au composant. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void gtk_graph_view_adjust_scroll_value(GtkGraphView *view, GtkAdjustment *adj, GtkOrientation orientation)
-{
- gint fake_x; /* Abscisse virtuelle */
- gint fake_y; /* Ordonnée virtuelle */
-
- fake_x = 0;
- fake_y = 0;
- gtk_display_panel_compute_fake_coord(GTK_DISPLAY_PANEL(view), &fake_x, &fake_y);
-
- gtk_fixed_move(GTK_FIXED(view), view->support, fake_x, -fake_y);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : widget = composant GTK à redessiner. *
-* cr = contexte graphique associé à l'événement. *
-* view = support maître à consulter. *
-* *
-* Description : Met à jour l'affichage de la vue sous forme graphique. *
-* *
-* Retour : FALSE pour poursuivre la propagation de l'événement. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static gboolean gtk_graph_view_draw(GtkWidget *widget, cairo_t *cr, GtkGraphView *view)
-{
- size_t i; /* Boucle de parcours */
-
- void draw_shadow(GtkWidget *child, gpointer unused)
- {
- GtkAllocation alloc; /* Emplacement de l'enfant */
- gint j; /* Boucle de parcours */
- cairo_pattern_t *pattern; /* Zones d'application */
-
- gtk_widget_get_allocation(child, &alloc);
-
- for (j = 1; j < SHADOW_SIZE; j++)
- {
- cairo_push_group(cr);
-
- gtk_display_panel_define_border_path(GTK_DISPLAY_PANEL(child), cr, alloc.x + j, alloc.y + j);
- cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0);
- cairo_fill(cr);
-
- cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
-
- gtk_display_panel_define_border_path(GTK_DISPLAY_PANEL(child), cr, alloc.x, alloc.y);
- cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 0.0);
- cairo_fill(cr);
-
- pattern = cairo_pop_group(cr);
-
- cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 0.3);
- cairo_mask(cr, pattern);
- cairo_fill(cr);
-
- cairo_pattern_destroy(pattern);
-
- }
-
- }
-
- gtk_container_foreach(GTK_CONTAINER(view->support), (GtkCallback)draw_shadow, NULL);
-
-
- for (i = 0; i < view->edges_count; i++)
- g_graph_edge_draw(view->edges[i], cr, true);
-
-
- /*
- if (view->layout != NULL)
- g_graph_layout_draw(view->layout, cr, true);
- */
-
- return FALSE;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : widget = composant GTK visé par l'opération. *
-* event = informations liées à l'événement. *
-* view = support maître à consulter. *
-* *
-* Description : Assure la gestion des clics de souris sur le composant. *
-* *
-* Retour : FALSE pour poursuivre la propagation de l'événement. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static gboolean gtk_graph_view_button_press(GtkWidget *widget, GdkEventButton *event, GtkGraphView *view)
-{
- gboolean result; /* Poursuite à faire suivre */
- GtkScrolledWindow *support; /* Support défilant associé */
- GtkAdjustment *hadj; /* Gestionnaire du défilement */
- GtkAdjustment *vadj; /* Gestionnaire du défilement */
- GdkCursor *cursor; /* Pointeur pour la surface */
-
- result = FALSE;
-
- if (event->button == 1)
- {
- support = GTK_SCROLLED_WINDOW(gtk_widget_get_parent(GTK_WIDGET(view)));
-
- hadj = gtk_scrolled_window_get_hadjustment(support);
- vadj = gtk_scrolled_window_get_vadjustment(support);
-
- view->big_enough = (gtk_adjustment_get_upper(hadj) > gtk_adjustment_get_page_size(hadj)
- || gtk_adjustment_get_upper(vadj) > gtk_adjustment_get_page_size(vadj));
-
- if (view->big_enough)
- {
- view->start_x = event->x_root;
- view->start_y = event->y_root;
-
- view->ref_h = gtk_adjustment_get_value(hadj);
- view->ref_v = gtk_adjustment_get_value(vadj);
-
- cursor = gdk_cursor_new(GDK_FLEUR);
- gdk_window_set_cursor(gtk_widget_get_window(widget), cursor);
- g_object_unref(G_OBJECT(cursor));
-
- result = TRUE;
-
- }
-
- }
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : widget = composant GTK visé par l'opération. *
-* event = informations liées à l'événement. *
-* view = support maître à consulter. *
-* *
-* Description : Assure la gestion des clics de souris sur le composant. *
-* *
-* Retour : FALSE pour poursuivre la propagation de l'événement. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static gboolean gtk_graph_view_button_release(GtkWidget *widget, GdkEventButton *event, GtkGraphView *view)
-{
- if (event->button == 1 && view->big_enough)
- gdk_window_set_cursor(gtk_widget_get_window(widget), NULL);
-
- return FALSE;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : widget = composant GTK visé par l'opération. *
-* event = informations liées à l'événement. *
-* view = support maître à consulter. *
-* *
-* Description : Assure la suivi des déplacements de souris sur le composant. *
-* *
-* Retour : FALSE pour poursuivre la propagation de l'événement. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static gboolean gtk_graph_view_motion_notify(GtkWidget *widget, GdkEventMotion *event, GtkGraphView *view)
-{
- gdouble diff_x; /* Evolution sur les abscisses */
- gdouble diff_y; /* Evolution sur les ordonnées */
- GtkScrolledWindow *support; /* Support défilant associé */
- GtkAdjustment *hadj; /* Gestionnaire du défilement */
- GtkAdjustment *vadj; /* Gestionnaire du défilement */
- gdouble value; /* Nouvelle valeur bornée */
-
- if (event->state & GDK_BUTTON1_MASK && view->big_enough)
- {
- diff_x = view->start_x - event->x_root;
- diff_y = view->start_y - event->y_root;
-
- support = GTK_SCROLLED_WINDOW(gtk_widget_get_parent(GTK_WIDGET(view)));
-
- hadj = gtk_scrolled_window_get_hadjustment(support);
- vadj = gtk_scrolled_window_get_vadjustment(support);
-
- value = CLAMP(view->ref_h + diff_x, gtk_adjustment_get_lower(hadj),
- gtk_adjustment_get_upper(hadj) - gtk_adjustment_get_page_size(hadj));
- gtk_adjustment_set_value(hadj, value);
-
- value = CLAMP(view->ref_v + diff_y, gtk_adjustment_get_lower(vadj),
- gtk_adjustment_get_upper(vadj) - gtk_adjustment_get_page_size(vadj));
- gtk_adjustment_set_value(vadj, value);
-
- }
-
- return FALSE;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : view = composant GTK à mettre à jour. *
-* *
-* Description : Actualise les besoins internes avant un redimensionnement. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void gtk_graph_view_prepare_resize(GtkGraphView *view)
-{
- size_t i; /* Boucle de parcours */
-
- if (view->children_count > 0)
- {
- for (i = 0; i < view->children_count; i++)
- gtk_widget_queue_resize(GTK_WIDGET(view->children[i]));
-
- /*
- g_graph_layout_refresh(view->layout);
- g_graph_layout_place(view->layout, view);
- */
-
- change_editor_items_current_view_content(GTK_DISPLAY_PANEL(view));
-
- }
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : view = composant GTK à mettre à jour. *
-* addr = adresse sélectionnée de manière externe. *
-* *
-* Description : Réagit à la sélection externe d'une adresse. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void gtk_graph_view_define_main_address(GtkGraphView *view, const vmpa2t *addr)
-{
- bool need_update; /* Mise à jour du contenu ? */
- const mrange_t *range; /* Couverture courante */
- GExeFormat *format; /* Type de fichier chargé */
- GBinRoutine **routines; /* Liste des routines trouvées */
- size_t routines_count; /* Nombre de ces routines */
- size_t i; /* Boucle de parcours */
- gint right; /* Abscisse du coin droit */
- gint bottom; /* Ordonnée du coin inférieur */
- GtkAllocation allocation; /* Espace alloué au panneau */
-
- if (view->routine == NULL)
- need_update = true;
- else
- {
- range = g_binary_routine_get_range(view->routine);
- need_update = !mrange_contains_addr(range, addr);
- }
-
- if (need_update)
- {
- gtk_graph_view_reset(view);
-
- format = g_loaded_binary_get_format(GTK_DISPLAY_PANEL(view)->binary);
- routines = g_binary_format_get_routines(G_BIN_FORMAT(format), &routines_count);
-
- for (i = 0; i < routines_count; i++)
- {
- range = g_binary_routine_get_range(routines[i]);
-
- if (mrange_contains_addr(range, addr))
- {
- view->routine = routines[i];
- g_object_ref(G_OBJECT(view->routine));
-
- view->highlighted = init_segment_content_list();
-
- /*
- view->children = gtk_graph_view_load_nodes(view, GTK_DISPLAY_PANEL(view)->binary,
- routines[i]);
-
- view->allocs = (GtkAllocation *)calloc(view->children_count,
- sizeof(GtkAllocation));
-
- view->layout = g_graph_layout_new(g_binary_routine_get_basic_blocks(view->routine),
- view->children, view->children_count);
-
- g_graph_layout_place(view->layout, view);
- */
-
- do
- {
-
- GBlockList *list;
-
- list = g_binary_routine_get_basic_blocks(routines[i]);
-
-#if 0
- view->cluster = g_graph_cluster_new(GTK_DISPLAY_PANEL(view)->binary,
- list, 0/* FIXME */, view->highlighted);
-#endif
-
-
- view->cluster = bootstrap_graph_cluster(GTK_DISPLAY_PANEL(view)->binary,
- list, view->highlighted);
-
-
-
- g_graph_cluster_place(view->cluster, view);
-
- /**
- * Comme la taille du support ne peut pas être forcée et
- * étendue pour comprendre les ombres, on place un composant
- * minuscule à l'extrémité de ce support.
- */
-
- gtk_graph_view_compute_requested_size(view, &right, &bottom);
-
- g_object_ref(G_OBJECT(view->extender));
- gtk_fixed_put(GTK_FIXED(view->support), view->extender, right, bottom);
-
- /**
- * Si possible, on centre le contenu obtenu.
- */
-
- gtk_widget_get_allocation(GTK_WIDGET(view), &allocation);
-
- gtk_graph_view_update_support_margins(view, &allocation);
-
-
-
- }
- while (0);
-
-
-
- break;
-
- }
-
- }
-
- change_editor_items_current_view_content(GTK_DISPLAY_PANEL(view));
-
- g_object_unref(G_OBJECT(format));
-
- }
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : view = composant GTK à manipuler. *
-* *
-* Description : Indique la position courante du curseur. *
-* *
-* Retour : Emplacement courant du curseur ou NULL si aucun. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static const vmpa2t *gtk_graph_view_get_caret_location(const GtkGraphView *view)
-{
- return NULL; /* FIXME */
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : view = composant GTK à consulter. *
-* addr = adresse à présenter à l'écran. *
-* x = position horizontale au sein du composant. [OUT] *
-* y = position verticale au sein du composant. [OUT] *
-* tweak = adaptation finale à effectuer. *
-* *
-* Description : Indique la position d'affichage d'une adresse donnée. *
-* *
-* Retour : true si l'adresse fait partie du composant, false sinon. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static bool gtk_graph_view_get_address_coordinates(const GtkGraphView *view, const vmpa2t *addr, gint *x, gint *y, ScrollPositionTweak tweak)
-{
- /* TODO */
-
- return false;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : view = composant GTK à manipuler. *
-* x = abscisse proposée pour le nouvel emplacement. *
-* y = ordonnée proposée pour le nouvel emplacement. *
-* *
-* Description : Déplace le curseur à un emplacement défini. *
-* *
-* Retour : true si un traitement a été effectué, false sinon. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static bool gtk_graph_view_move_caret_to(GtkGraphView *view, gint x, gint y)
-{
- bool result; /* Bilan à retourner */
- size_t i; /* Boucle de parcours */
- GtkDisplayPanel *panel; /* Autre vision d'enfance */
- gint sub_x; /* Abscisse relative à l'enfant*/
- gint sub_y; /* Ordonnée relative à l'enfant*/
-
- result = false;
-
- for (i = 0; i < view->children_count; i++)
- {
- if (x < view->allocs[i].x || x >= (view->allocs[i].x + view->allocs[i].width)) continue;
- if (y < view->allocs[i].y || y >= (view->allocs[i].y + view->allocs[i].height)) continue;
-
- panel = GTK_DISPLAY_PANEL(view->children[i]);
-
- sub_x = x - view->allocs[i].x;
- sub_y = y - view->allocs[i].y;
-
- result = GTK_DISPLAY_PANEL_GET_CLASS(panel)->move_caret_to(panel, sub_x, sub_y);
- break;
-
- }
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : view = composant GTK à manipuler. *
-* cairo = assistant pour la création de rendus. *
-* area = taille de la surface réduite à disposition. *
-* scale = échelle vis à vis de la taille réelle. *
-* *
-* Description : Place en cache un rendu destiné à l'aperçu graphique rapide. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void gtk_graph_view_cache_glance(GtkGraphView *view, cairo_t *cairo, const GtkAllocation *area, double scale)
-{
- size_t i; /* Boucle de parcours */
- GtkAllocation sub_area; /* Emplacement réservé */
-
- for (i = 0; i < view->children_count; i++)
- {
- sub_area.x = view->allocs[i].x * scale;
- sub_area.y = view->allocs[i].y * scale;
- sub_area.width = view->allocs[i].width * scale + 1;
- sub_area.height = view->allocs[i].height * scale + 1;
-
- gtk_display_panel_cache_glance(GTK_DISPLAY_PANEL(view->children[i]), cairo, &sub_area, scale);
-
- }
-
- cairo_scale(cairo, scale, scale);
-
- /*
- if (view->layout != NULL)
- g_graph_layout_draw(view->layout, cairo, false);
- */
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : - *
-* *
-* Description : Crée un nouveau composant pour l'affichage en graphique. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GtkWidget *gtk_graph_view_new(void)
-{
- return g_object_new(GTK_TYPE_GRAPH_VIEW, NULL);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : view = composant GTK à mettre à jour. *
-* widget = composant GTK à insérer. *
-* x = abscisse du point d'insertion. *
-* y = ordonnée du point d'insertion. *
-* *
-* Description : Place une vue sous forme de bloc dans le graphique. *
-* *
-* Retour : Plutôt que de redéfinir *toutes* les méthodes de *
-* GtkContainer, on étend ! *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void gtk_graph_view_put(GtkGraphView *view, GtkWidget *widget, const GtkAllocation *alloc)
-{
- size_t i; /* Boucle de parcours */
- GtkWidget *parent; /* Parent en cas de réajustemt.*/
-
- /*
- for (i = 0; i < view->children_count; i++)
- if (GTK_WIDGET(view->children[i]) == widget)
- {
- view->allocs[i] = *alloc;
- break;
- }
-
- parent = gtk_widget_get_parent(widget);
-
- if (parent != NULL)
- {
- g_object_ref(G_OBJECT(widget));
- gtk_container_remove(GTK_CONTAINER(parent), widget);
- }
- */
-
- gtk_fixed_put(GTK_FIXED(view->support), widget, alloc->x, alloc->y);
-
- /*
- if (parent != NULL)
- g_object_unref(G_OBJECT(widget));
- */
-
-}
-
-
-
-/******************************************************************************
-* *
-* Paramètres : view = composant GTK à mettre à jour. *
-* edge = lien entre noeuds à conserver. *
-* *
-* Description : Intègre un lien entre blocs graphiques dans l'afficheur. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void gtk_graph_view_add_edge(GtkGraphView *view, GGraphEdge *edge)
-{
- view->edges = (GGraphEdge **)realloc(view->edges,
- ++view->edges_count * sizeof(GGraphEdge *));
-
- view->edges[view->edges_count - 1] = edge;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : view = instance GTK à réinitialiser. *
-* *
-* Description : Supprime tout contenu de l'afficheur de code en graphique. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void gtk_graph_view_reset(GtkGraphView *view)
-{
- size_t i; /* Boucle de parcours */
-
-
- void detach_all_blocks(GtkWidget *widget, GtkContainer *container)
- {
-
-
-
- gtk_container_remove(container, widget);
-
-
- }
-
-
- gtk_container_foreach(GTK_CONTAINER(view->support), (GtkCallback)detach_all_blocks, view->support);
-
-
- if (view->cluster != NULL)
- {
- g_object_unref(G_OBJECT(view->cluster));
- view->cluster = NULL;
- }
-
- for (i = 0; i < view->edges_count; i++)
- g_object_unref(G_OBJECT(view->edges[i]));
-
- if (view->edges_count > 0)
- {
- free(view->edges);
- view->edges = NULL;
-
- view->edges_count = 0;
-
- }
-
-
- /*
- for (i = 0; i < view->links_count; i++)
- gtk_object_destroy(GTK_OBJECT(view->links[i]));
-
- if (view->links_count > 0)
- {
- free(view->links);
- view->links = NULL;
-
- view->links_count = 0;
-
- }
- */
-
- if (view->highlighted)
- exit_segment_content_list(view->highlighted);
-
- for (i = 0; i < view->children_count; i++)
- {
- g_signal_handlers_disconnect_by_func(view->children[i], gtk_graph_view_reach_caret_limit, view);
- gtk_widget_destroy(GTK_WIDGET(view->children[i]));
- }
-
- if (view->children_count > 0)
- {
- free(view->children);
- view->children = NULL;
- free(view->allocs);
- view->allocs = NULL;
-
- view->children_count = 0;
-
- }
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : view = composant d'affichage GTK à mettre à jour. *
-* routine = routine à présenter via ledit composant. *
-* *
-* Description : Définit la liste complète des éléments du futur graphique. *
-* *
-* Retour : Liste d'éléments du graphique à placer. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static GtkBufferView **gtk_graph_view_load_nodes(GtkGraphView *view, GLoadedBinary *binary, const GBinRoutine *routine)
-{
- GtkBufferView **result; /* Liste à retourner */
- GCodeBuffer *buffer; /* Tampon brut à découper */
- size_t *count; /* Nombre d'éléments créés. */
- GInstrBlock *main_block; /* Premier bloc rattaché */
- GInstrBlock **blocks; /* Liste des blocs basiques */
- size_t i; /* Boucle de parcours */
- vmpa2t first; /* Début d'un groupe de lignes */
- vmpa2t last; /* Fin d'un groupe de lignes */
- GBufferView *subview; /* Partie affichée du tampon */
-
- buffer = g_loaded_binary_get_disassembled_buffer(binary);
-
- count = &view->children_count;
-
- main_block = g_binary_routine_get_basic_blocks(routine);
-
- blocks = NULL;
- *count = 0;
- g_instr_block_list_all_blocks(main_block, &blocks, count);
-
- result = (GtkBufferView **)calloc(*count, sizeof(GtkBufferView *));
-
- for (i = 0; i < *count; i++)
- {
- result[i] = GTK_BUFFER_VIEW(gtk_block_view_new());
- g_signal_connect(result[i], "reach-limit", G_CALLBACK(gtk_graph_view_reach_caret_limit), view);
- g_signal_connect(result[i], "highlight-changed", G_CALLBACK(gtk_graph_view_changed_highlights), view);
-
- gtk_widget_show(GTK_WIDGET(result[i]));
- gtk_display_panel_attach_binary(GTK_DISPLAY_PANEL(result[i]), binary, BVW_GRAPH);
-
- gtk_display_panel_show_border(GTK_DISPLAY_PANEL(result[i]), true);
-
- g_flow_block_get_boundary_addresses(G_FLOW_BLOCK(blocks[i]), &first, &last);
-
- subview = g_buffer_view_new(buffer, view->highlighted);
- g_buffer_view_restrict(subview, &first, &last);
- gtk_buffer_view_attach_buffer(result[i], subview);
-
- }
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : node = composant d'affichage GTK impliqué dans la procédure. *
-* view = support graphique de tous les noeuds. *
-* *
-* Description : Notifie un changement de surbrillance au sein d'un noeud. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void gtk_graph_view_changed_highlights(GtkBlockView *node, GtkGraphView *view)
-{
- size_t i; /* Boucle de parcours */
-
- for (i = 0; i < view->children_count; i++)
- {
- if (view->children[i] == GTK_BUFFER_VIEW(node))
- continue;
-
- gtk_widget_queue_draw(GTK_WIDGET(view->children[i]));
-
- }
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : node = composant d'affichage GTK impliqué dans la procédure. *
-* dir = direction du déplacement souhaité et impossible. *
-* view = support graphique de tous les noeuds. *
-* *
-* Description : Notifie une incapacité de déplacement au sein d'un noeud. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void gtk_graph_view_reach_caret_limit(GtkBufferView *node, GdkScrollDirection dir, GtkGraphView *view)
-{
- GBufferView *bview; /* Vue d'un tampon global */
- vmpa2t first; /* Début d'un groupe de lignes */
- vmpa2t last; /* Fin d'un groupe de lignes */
- const mrange_t *range; /* Couverture courante */
- GArchProcessor *proc; /* Processeur pour instructions*/
- vmpa2t iaddr; /* Adresse du prochain saut */
- instr_iter_t *iter; /* Boucle de parcours */
- GArchInstruction *instr; /* Instruction à venir visiter */
-#ifndef NDEBUG
- bool is_return; /* Est-ce une instruc. finale ?*/
-#endif
- size_t i; /* Boucle de parcours */
- bool updated; /* Besoin d'une mise à jour ? */
-
- /* Détermination de l'instruction à cibler */
-
- bview = gtk_buffer_view_get_buffer(node);
- g_buffer_view_get_restrictions(bview, &first, &last);
-
- range = g_binary_routine_get_range(view->routine);
-
- proc = g_loaded_binary_get_processor(GTK_DISPLAY_PANEL(view)->binary);
-
- init_vmpa(&iaddr, VMPA_NO_PHYSICAL, VMPA_NO_VIRTUAL);
-
-#ifndef NDEBUG
- is_return = false;
-#endif
-
- switch (dir)
- {
- case GDK_SCROLL_LEFT:
- case GDK_SCROLL_UP:
-
- if (cmp_vmpa(get_mrange_addr(range), &first) != 0)
- {
- iter = g_arch_processor_get_iter_from_address(proc, &first);
-
- if (iter != NULL)
- {
- instr = get_instruction_iterator_prev(iter);
-
- if (instr != NULL)
- {
- /* TODO : boucler si !HAS_CODE */
-
- if (mrange_contains_addr(range, &iaddr))
- copy_vmpa(&iaddr, get_mrange_addr(g_arch_instruction_get_range(instr)));
-
- g_object_unref(G_OBJECT(instr));
-
- }
-
- delete_instruction_iterator(iter);
-
- }
-
- }
-
- break;
-
- case GDK_SCROLL_RIGHT:
- case GDK_SCROLL_DOWN:
-
- iter = g_arch_processor_get_iter_from_address(proc, &last);
-
- if (iter != NULL)
- {
-#ifndef NDEBUG
- instr = get_instruction_iterator_current(iter);
- if (instr != NULL)
- {
- is_return = (g_arch_instruction_get_flags(instr) & AIF_RETURN_POINT);
- g_object_unref(G_OBJECT(instr));
- }
-#endif
-
- instr = get_instruction_iterator_next(iter);
-
- if (instr != NULL)
- {
- /* TODO : boucler si !HAS_CODE */
-
- copy_vmpa(&iaddr, get_mrange_addr(g_arch_instruction_get_range(instr)));
-
- if (!mrange_contains_addr(range, &iaddr))
- init_vmpa(&iaddr, VMPA_NO_PHYSICAL, VMPA_NO_VIRTUAL);
-
- g_object_unref(G_OBJECT(instr));
-
- }
-
- delete_instruction_iterator(iter);
-
- }
-
- break;
-
- case GDK_SCROLL_SMOOTH:
- assert(0); /* Argument jamais généré */
- break;
-
- }
-
- g_object_unref(G_OBJECT(proc));
-
- /* Recherche du bloc parent */
-
- /* FIXME : valid ! */
- if (iaddr.physical == VMPA_NO_PHYSICAL && iaddr.virtual == VMPA_NO_VIRTUAL)
- return;
-
- for (i = 0; i < view->children_count; i++)
- {
- bview = gtk_buffer_view_get_buffer(view->children[i]);
- g_buffer_view_get_restrictions(bview, &first, &last);
-
- if (cmp_vmpa(&first, &iaddr) <= 0 && cmp_vmpa(&iaddr, &last) <= 0)
- {
- assert(node != view->children[i]);
- break;
- }
-
- }
-
- assert(i < view->children_count || is_return);
-
- /* Affichage du nouveau curseur */
-
- /**
- * Il se peut qu'aucune adresse suivante ne soit disponible : c'est typiquement
- * le cas sous ARM, avec les valeurs brutes référencées dans le code. Ces valeurs
- * sont incluses dans la surface couverte par la routine concernée, mais ne sont
- * pas intégrées dans les blocs basiques associés.
- */
-
- if (i == view->children_count)
- return;
-
- gtk_widget_grab_focus(GTK_WIDGET(view->children[i]));
-
- switch (dir)
- {
- case GDK_SCROLL_LEFT:
- updated = gtk_buffer_view_move_caret_to(view->children[i], false, NULL);
- break;
-
- case GDK_SCROLL_UP:
- break;
-
- case GDK_SCROLL_RIGHT:
- updated = gtk_buffer_view_move_caret_to(view->children[i], true, NULL);
- break;
-
- case GDK_SCROLL_DOWN:
- break;
-
- case GDK_SCROLL_SMOOTH:
- assert(0); /* Argument jamais généré */
- break;
-
- }
-
- /* TODO : scrolling... */
-
-}