diff options
Diffstat (limited to 'src/gtkext')
-rw-r--r-- | src/gtkext/graph/node.c | 2 | ||||
-rw-r--r-- | src/gtkext/gtkbufferview-int.h | 1 | ||||
-rw-r--r-- | src/gtkext/gtkbufferview.c | 186 | ||||
-rw-r--r-- | src/gtkext/gtkbufferview.h | 3 | ||||
-rw-r--r-- | src/gtkext/gtkgraphview.c | 173 | ||||
-rw-r--r-- | src/gtkext/gtkviewpanel.c | 23 |
6 files changed, 318 insertions, 70 deletions
diff --git a/src/gtkext/graph/node.c b/src/gtkext/graph/node.c index 4fd7a8e..9ff66b3 100644 --- a/src/gtkext/graph/node.c +++ b/src/gtkext/graph/node.c @@ -507,7 +507,7 @@ GtkBufferView *find_graph_view_by_start_address(GtkBufferView **views, size_t co for (i = 0; i < count && result == NULL; i++) { - buffer = gtk_buffer_view_get_buffer(GTK_BUFFER_VIEW(views[i])); + buffer = gtk_buffer_view_get_buffer(views[i]); g_buffer_view_get_restrictions(buffer, &start, NULL); if (cmp_vmpa(&start, addr) == 0) diff --git a/src/gtkext/gtkbufferview-int.h b/src/gtkext/gtkbufferview-int.h index e8e11a0..105d32b 100644 --- a/src/gtkext/gtkbufferview-int.h +++ b/src/gtkext/gtkbufferview-int.h @@ -65,6 +65,7 @@ struct _GtkBufferViewClass /* Signaux */ void (* caret_moved) (GtkBufferView *, const vmpa2t *); + void (* reach_limit) (GtkBufferView *, GdkScrollDirection); }; diff --git a/src/gtkext/gtkbufferview.c b/src/gtkext/gtkbufferview.c index 1a1f6f1..54c521e 100644 --- a/src/gtkext/gtkbufferview.c +++ b/src/gtkext/gtkbufferview.c @@ -48,7 +48,7 @@ static void gtk_buffer_view_dispose(GtkBufferView *); static void gtk_buffer_view_finalize(GtkBufferView *); /* Intègre le focus dans le rendu du composant. */ -static gboolean gtk_buffer_view_focus(GtkWidget *, GtkDirectionType); +static gboolean gtk_buffer_view_focus(GtkWidget *, GdkEventFocus *); /* Assure la gestion des clics de souris sur le composant. */ static gboolean gtk_buffer_view_button_press(GtkWidget *, GdkEventButton *); @@ -82,6 +82,9 @@ static void gtk_buffer_view_cache_glance(GtkBufferView *, cairo_t *, const GtkAl /* ------------------------------ ANIMATION DU CURSEUR ------------------------------ */ +/* Déplace le curseur à un emplacement défini. */ +static bool _gtk_buffer_view_move_caret_to(GtkBufferView *, gint, gint); + /* Déplace le curseur en effaçant son éventuelle position. */ static void gtk_buffer_view_relocate_caret(GtkBufferView *, const GdkRectangle *, const vmpa2t *); @@ -127,7 +130,8 @@ static void gtk_buffer_view_class_init(GtkBufferViewClass *class) object->dispose = (GObjectFinalizeFunc/* ! */)gtk_buffer_view_dispose; object->finalize = (GObjectFinalizeFunc)gtk_buffer_view_finalize; - widget_class->focus = gtk_buffer_view_focus; + widget_class->focus_in_event = gtk_buffer_view_focus; + widget_class->focus_out_event = gtk_buffer_view_focus; widget_class->button_press_event = gtk_buffer_view_button_press; widget_class->draw = gtk_buffer_view_draw; widget_class->key_press_event = gtk_buffer_view_key_press; @@ -147,6 +151,14 @@ static void gtk_buffer_view_class_init(GtkBufferViewClass *class) g_cclosure_user_marshal_VOID__UINT64, G_TYPE_NONE, 1, G_TYPE_UINT64); + g_signal_new("reach-limit", + GTK_TYPE_BUFFER_VIEW, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(GtkBufferViewClass, reach_limit), + NULL, NULL, + g_cclosure_marshal_VOID__ENUM, + G_TYPE_NONE, 1, GTK_TYPE_SCROLL_TYPE); + } @@ -213,7 +225,7 @@ static void gtk_buffer_view_finalize(GtkBufferView *view) /****************************************************************************** * * * Paramètres : widget = composant GTK visé par l'opération. * -* dir = sens de l'opération : perte ou gain de focus. * +* event = informations liées à l'événement. * * * * Description : Intègre le focus dans le rendu du composant. * * * @@ -223,13 +235,13 @@ static void gtk_buffer_view_finalize(GtkBufferView *view) * * ******************************************************************************/ -static gboolean gtk_buffer_view_focus(GtkWidget *widget, GtkDirectionType direction) +static gboolean gtk_buffer_view_focus(GtkWidget *widget, GdkEventFocus *event) { GtkBufferView *view; /* Autre version du composant */ gboolean has_focus; /* Etat courant */ view = GTK_BUFFER_VIEW(widget); - has_focus = gtk_widget_is_focus(widget); + has_focus = event->in; if (has_focus) restart_caret_blinking(view); @@ -265,16 +277,11 @@ static gboolean gtk_buffer_view_focus(GtkWidget *widget, GtkDirectionType direct static gboolean gtk_buffer_view_button_press(GtkWidget *widget, GdkEventButton *event) { GtkBufferView *view; /* Autre version du composant */ - GtkViewPanel *pview; /* Autre version du composant */ gint real_x; /* Abscisse absolue réelle */ gint real_y; /* Ordonnée absolue réelle */ - size_t index; /* Indice de ligne de tampon */ GBufferLine *line; /* Ligne à la position courante*/ - const vmpa2t *addr; /* Position mémoire associée */ - GdkRectangle new; /* Nouvel emplacement calculé */ view = GTK_BUFFER_VIEW(widget); - pview = GTK_VIEW_PANEL(widget); gtk_widget_grab_focus(widget); @@ -287,32 +294,17 @@ static gboolean gtk_buffer_view_button_press(GtkWidget *widget, GdkEventButton * real_x, real_y); - - line = g_buffer_view_find_line_at(view->buffer_view, real_y, &index); - if (line == NULL) return FALSE; - - - - printf(" [init ] %p - line = %p (y=%d)\n", view->buffer_view, line, real_y); - - - if (real_x < view->left_margin) { + line = g_buffer_view_find_line_at(view->buffer_view, real_y, NULL); + if (line == NULL) return FALSE; - - + /* TODO */ printf("Border Line :: %p\n", line); - } else - { - //addr = g_buffer_view_compute_caret_old(view->buffer_view, line, index, real_x, pview->display, &new); - //addr = g_buffer_view_compute_caret(view->buffer_view, real_x, real_y, pview->display, &new); - addr = g_buffer_view_compute_caret_full(view->buffer_view, line, index, real_x, pview->display, &new); - gtk_buffer_view_relocate_caret(view, &new, addr); - } + _gtk_buffer_view_move_caret_to(view, real_x, real_y); return FALSE; @@ -472,77 +464,67 @@ static gboolean gtk_buffer_view_draw(GtkWidget *widget, cairo_t *cr) static gboolean gtk_buffer_view_key_press(GtkWidget *widget, GdkEventKey *event) { gboolean result; /* Suites à renvoyer */ - GtkBufferView *view; /* Autre version du composant */ GtkViewPanel *pview; /* Autre version du composant */ - - bool ctrl; /* Statut de la touche Contrôle*/ - - - GdkRectangle area; - - const vmpa2t *addr; - + GdkScrollDirection dir; /* Direction du déplacement */ + GdkRectangle area; /* Emplacement de curseur */ + const vmpa2t *addr; /* Adresse du nouveau curseur */ result = FALSE; - - view = GTK_BUFFER_VIEW(widget); pview = GTK_VIEW_PANEL(widget); - - area = view->caret; - - - ctrl = (event->state & GDK_CONTROL_MASK); - switch (event->keyval) { case GDK_KEY_Left: - printf("LEFT\n"); - addr = g_buffer_view_move_caret(view->buffer_view, &area, ctrl, GDK_SCROLL_LEFT, pview->display); - gtk_buffer_view_relocate_caret(view, &area, view->caret_addr); + dir = GDK_SCROLL_LEFT; result = TRUE; break; case GDK_KEY_Up: - printf("UP\n"); - addr = g_buffer_view_move_caret(view->buffer_view, &area, ctrl, GDK_SCROLL_UP, pview->display); - gtk_buffer_view_relocate_caret(view, &area, view->caret_addr); + dir = GDK_SCROLL_UP; result = TRUE; break; case GDK_KEY_Right: - printf("RIGHT\n"); - addr = g_buffer_view_move_caret(view->buffer_view, &area, ctrl, GDK_SCROLL_RIGHT, pview->display); - gtk_buffer_view_relocate_caret(view, &area, view->caret_addr); + dir = GDK_SCROLL_RIGHT; result = TRUE; break; case GDK_KEY_Down: - printf("DOWN\n"); - addr = g_buffer_view_move_caret(view->buffer_view, &area, ctrl, GDK_SCROLL_DOWN, pview->display); - gtk_buffer_view_relocate_caret(view, &area, view->caret_addr); + dir = GDK_SCROLL_DOWN; result = TRUE; break; default: - addr = NULL; break; } + if (result) + { + area = view->caret; + ctrl = (event->state & GDK_CONTROL_MASK); + + addr = g_buffer_view_move_caret(view->buffer_view, &area, ctrl, dir, pview->display); + + if (addr != NULL) + { + gtk_buffer_view_relocate_caret(view, &area, addr); + gtk_view_panel_scroll_to_address(pview, addr, SPT_RAW); + } + else + g_signal_emit_by_name(view, "reach-limit", dir); - printf("ctrl ? %d -- keyval = %d -->> %d\n", ctrl, event->keyval, result); - if (addr != NULL) gtk_view_panel_scroll_to_address(pview, addr, SPT_RAW); + //if (addr == NULL) return FALSE; - printf("\n"); + } return result; @@ -815,6 +797,8 @@ void gtk_buffer_view_attach_buffer(GtkBufferView *view, GBufferView *buffer) GBufferView *gtk_buffer_view_get_buffer(const GtkBufferView *view) { + /* TODO : ref... */ + return view->buffer_view; } @@ -862,6 +846,84 @@ void gtk_buffer_view_compute_relative_coords(GtkBufferView *view, gint *x, gint /****************************************************************************** * * * 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_buffer_view_move_caret_to(GtkBufferView *view, gint x, gint y) +{ + size_t index; /* Indice de ligne de tampon */ + GBufferLine *line; /* Ligne à la position courante*/ + GtkViewPanel *pview; /* Autre version du composant */ + const vmpa2t *addr; /* Position mémoire associée */ + GdkRectangle new; /* Nouvel emplacement calculé */ + + if (x < view->left_margin) return false; + + line = g_buffer_view_find_line_at(view->buffer_view, y, &index); + if (line == NULL) return false; + + pview = GTK_VIEW_PANEL(view); + + addr = g_buffer_view_compute_caret_full(view->buffer_view, line, index, x, pview->display, &new); + + if (addr != NULL) + gtk_buffer_view_relocate_caret(view, &new, addr); + + return (addr != NULL); + +} + + +/****************************************************************************** +* * +* Paramètres : view = composant GTK à manipuler. * +* beginning = précise le coin où se retrouvera le curseur. * +* same_x = tente de conserver une même abscisse ou NULL ? * +* * +* Description : Déplace le curseur à un emplacement en extrémité. * +* * +* Retour : true si un traitement a été effectué, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool gtk_buffer_view_move_caret_to(GtkBufferView *view, bool beginning, gint *same_x) +{ + bool result; /* Bilan à remonter */ + gint x; /* Abscisse d'emplacement */ + gint y; /* Ordonnée d'emplacement */ + + if (beginning) + { + x = same_x != NULL ? *same_x : view->left_margin * 2; + y = 0; + } + else + { + if (same_x != NULL) x = *same_x; + gtk_buffer_view_compute_requested_size(view, same_x != NULL ? NULL : &x, &y); + y--; + } + + result = _gtk_buffer_view_move_caret_to(view, x, y); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : view = composant GTK à manipuler. * * area = emplacement pour le dessin d'un curseur. * * addr = position dans la mémoire représentée du curseur. * * * diff --git a/src/gtkext/gtkbufferview.h b/src/gtkext/gtkbufferview.h index 0cdcf4f..ed26fd5 100644 --- a/src/gtkext/gtkbufferview.h +++ b/src/gtkext/gtkbufferview.h @@ -70,6 +70,9 @@ void gtk_buffer_view_compute_relative_coords(GtkBufferView *, gint *, gint *); /* ------------------------------ ANIMATION DU CURSEUR ------------------------------ */ +/* Déplace le curseur à un emplacement en extrémité. */ +bool gtk_buffer_view_move_caret_to(GtkBufferView *, bool, gint *); + /* Indique la position courante du curseur. */ const vmpa2t *gtk_buffer_view_get_caret_location(const GtkBufferView *); 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... */ + +} diff --git a/src/gtkext/gtkviewpanel.c b/src/gtkext/gtkviewpanel.c index 7f29574..e36da71 100644 --- a/src/gtkext/gtkviewpanel.c +++ b/src/gtkext/gtkviewpanel.c @@ -297,6 +297,7 @@ static void gtk_view_panel_realize(GtkWidget *widget) attributes.event_mask = gtk_widget_get_events(widget) | GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK + | GDK_FOCUS_CHANGE_MASK | GDK_SCROLL_MASK | GDK_SMOOTH_SCROLL_MASK; attributes_mask = GDK_WA_X | GDK_WA_Y; @@ -792,6 +793,8 @@ static void on_view_panel_binary_display_change(GLoadedBinary *binary, BinaryVie GLoadedBinary *gtk_view_panel_get_binary(const GtkViewPanel *panel) { + /* TODO : ref */ + return panel->binary; } @@ -836,6 +839,7 @@ bool gtk_view_panel_contain_address(const GtkViewPanel *panel, vmpa_t addr) void gtk_view_panel_scroll_to_address(GtkViewPanel *panel, const vmpa2t *addr, ScrollPositionTweak tweak) { + GtkWidget *parent; /* Support parent à valider */ gint x; /* Abscisse à garantir */ gint y; /* Ordonnée à garantir */ GtkWidget *viewport; /* Parent avec défilement */ @@ -844,6 +848,25 @@ void gtk_view_panel_scroll_to_address(GtkViewPanel *panel, const vmpa2t *addr, S gdouble page_size; /* Taille de l'affichage */ double value; /* Valeur courante */ + /** + * Si une vue partielle se déplacer via cette fonction, il faut potentiellement + * rediriger l'appel vers la vue en graphiques parente. + */ + + parent = gtk_widget_get_parent(GTK_WIDGET(panel)); + parent = gtk_widget_get_parent(GTK_WIDGET(parent)); + + printf(" Widgets : %s -> %s\n", + G_OBJECT_TYPE_NAME(parent), G_OBJECT_TYPE_NAME(panel)); + + if (GTK_IS_VIEW_PANEL(parent)) + { + printf("reparent !\n"); + panel = GTK_VIEW_PANEL(parent); + } + else + printf("no need reparent !\n"); + if (GTK_VIEW_PANEL_GET_CLASS(panel)->define != NULL) GTK_VIEW_PANEL_GET_CLASS(panel)->define(panel, addr); |