diff options
Diffstat (limited to 'src/gtkext/gtkgraphview.c')
-rw-r--r-- | src/gtkext/gtkgraphview.c | 173 |
1 files changed, 166 insertions, 7 deletions
diff --git a/src/gtkext/gtkgraphview.c b/src/gtkext/gtkgraphview.c index 875c1b4..6d7ab0d 100644 --- a/src/gtkext/gtkgraphview.c +++ b/src/gtkext/gtkgraphview.c @@ -24,6 +24,9 @@ #include "gtkgraphview.h" +#include <assert.h> + + #include "gtkblockview.h" #include "gtkbufferview.h" #include "gtkviewpanel-int.h" @@ -43,7 +46,7 @@ struct _GtkGraphView vmpa_t start; /* Début de la portion vue */ /* FIXME : à garder ? */ vmpa_t end; /* Fin de la portion affichée */ /* FIXME : à garder ? */ - GtkViewPanel **children; /* Liste des sous-blocs */ + GtkBufferView **children; /* Liste des sous-blocs */ GtkAllocation *allocs; /* Emplacements prévisibles */ size_t children_count; /* Taille de cette liste */ @@ -93,10 +96,11 @@ static void gtk_graph_view_cache_glance(GtkGraphView *, cairo_t *, const GtkAllo /* 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. * -* * -* Retour : Liste d'éléments du graphique à placer. */ -static GtkViewPanel **gtk_graph_view_load_nodes(GtkGraphView *, GLoadedBinary *, const GBinRoutine *); +/* Définit la liste complète des éléments du futur graphique. */ +static GtkBufferView **gtk_graph_view_load_nodes(GtkGraphView *, GLoadedBinary *, const GBinRoutine *); + +/* Notifie une incapacité de déplacement au sein d'un noeud. */ +static void gtk_graph_view_reach_caret_limit(GtkBufferView *, GdkScrollDirection, GtkGraphView *); @@ -423,7 +427,7 @@ static void gtk_graph_view_cache_glance(GtkGraphView *view, cairo_t *cairo, cons sub_area.width = view->allocs[i].width * scale + 1; sub_area.height = view->allocs[i].height * scale + 1; - gtk_view_panel_cache_glance(view->children[i], cairo, &sub_area, scale); + gtk_view_panel_cache_glance(GTK_VIEW_PANEL(view->children[i]), cairo, &sub_area, scale); } @@ -554,7 +558,10 @@ static void gtk_graph_view_reset(GtkGraphView *view) */ 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) { @@ -583,7 +590,7 @@ static void gtk_graph_view_reset(GtkGraphView *view) * * ******************************************************************************/ -static GtkViewPanel **gtk_graph_view_load_nodes(GtkGraphView *view, GLoadedBinary *binary, const GBinRoutine *routine) +static GtkBufferView **gtk_graph_view_load_nodes(GtkGraphView *view, GLoadedBinary *binary, const GBinRoutine *routine) { GtkViewPanel **result; /* Liste à retourner */ GCodeBuffer *buffer; /* Tampon brut à découper */ @@ -610,6 +617,8 @@ static GtkViewPanel **gtk_graph_view_load_nodes(GtkGraphView *view, GLoadedBinar for (i = 0; i < *count; i++) { result[i] = GTK_VIEW_PANEL(gtk_block_view_new()); + g_signal_connect(result[i], "reach-limit", G_CALLBACK(gtk_graph_view_reach_caret_limit), view); + gtk_widget_show(GTK_WIDGET(result[i])); gtk_view_panel_attach_binary(result[i], binary, BVW_BLOCK); @@ -626,3 +635,153 @@ static GtkViewPanel **gtk_graph_view_load_nodes(GtkGraphView *view, GLoadedBinar return result; } + + +/****************************************************************************** +* * +* 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*/ + GArchInstruction *ref; /* Point de référence */ +#ifndef NDEBUG + bool is_return; /* Est-ce une instruc. finale ?*/ +#endif + vmpa2t iaddr; /* Position de l'instructin */ + 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_VIEW_PANEL(view)->binary); + + ref = NULL; + +#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) + { + ref = g_arch_processor_find_instr_by_address(proc, &first); + + if (ref != NULL) + ref = g_arch_processor_get_prev_instr(proc, ref); + + /* TODO : boucler si !HAS_CODE */ + + if (ref != NULL) + copy_vmpa(&iaddr, get_mrange_addr(g_arch_instruction_get_range(ref))); + + } + break; + + case GDK_SCROLL_RIGHT: + case GDK_SCROLL_DOWN: + + ref = g_arch_processor_find_instr_by_address(proc, &last); + +#ifndef NDEBUG + if (ref != NULL) + is_return = g_arch_instruction_is_return(ref); +#endif + + if (ref != NULL) + ref = g_arch_processor_get_next_instr(proc, ref); + + /* TODO : boucler si !HAS_CODE */ + + if (ref != NULL) + { + copy_vmpa(&iaddr, get_mrange_addr(g_arch_instruction_get_range(ref))); + + if (!mrange_contains_addr(range, &iaddr)) + ref = NULL; + + } + + break; + + } + + g_object_unref(G_OBJECT(proc)); + + /* Recherche du bloc parent */ + + if (ref == NULL) + 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; + + } + + /* TODO : scrolling... */ + +} |