summaryrefslogtreecommitdiff
path: root/src/gtkext/gtkgraphview.c
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2015-04-20 23:09:13 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2015-04-20 23:09:13 (GMT)
commitea40f74566cd813722f49ae740ca3df04e522bb2 (patch)
tree7a61557efa0a80fcf3b58df9626f7fad9bd61455 /src/gtkext/gtkgraphview.c
parent874b812e720a8f9fb6248cb54e76bd8ab2b2a250 (diff)
Transmitted the focus when a limit has been reached while using he keyboard.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@514 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
Diffstat (limited to 'src/gtkext/gtkgraphview.c')
-rw-r--r--src/gtkext/gtkgraphview.c173
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... */
+
+}