diff options
Diffstat (limited to 'src/gtkext')
-rw-r--r-- | src/gtkext/gtkbufferview.c | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/src/gtkext/gtkbufferview.c b/src/gtkext/gtkbufferview.c index 86a738a..8e4ffd4 100644 --- a/src/gtkext/gtkbufferview.c +++ b/src/gtkext/gtkbufferview.c @@ -27,6 +27,8 @@ #include <gdk/gdkkeysyms.h> +#include "../arch/target.h" +#include "../common/extstr.h" #include "../core/params.h" #include "../glibext/chrysamarshal.h" @@ -59,6 +61,9 @@ static gboolean gtk_buffer_view_draw(GtkWidget *, cairo_t *); /* Prend en compte une frappe de touche sur le composant. */ static gboolean gtk_buffer_view_key_press(GtkWidget *, GdkEventKey *); +/* Prépare l'affichage d'une astuce. */ +static gboolean gtk_buffer_view_query_tooltip(GtkWidget *, gint, gint, gboolean, GtkTooltip *); + /* Indique les dimensions de travail du composant d'affichage. */ static void gtk_buffer_view_compute_requested_size(GtkBufferView *, gint *, gint *); @@ -135,6 +140,7 @@ static void gtk_buffer_view_class_init(GtkBufferViewClass *class) 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; + widget_class->query_tooltip = gtk_buffer_view_query_tooltip; panel_class->compute_size = (compute_requested_size_fc)gtk_buffer_view_compute_requested_size; panel_class->compute_inc = (compute_scroll_inc_fc)gtk_buffer_view_compute_scroll_inc; @@ -176,6 +182,12 @@ static void gtk_buffer_view_class_init(GtkBufferViewClass *class) static void gtk_buffer_view_init(GtkBufferView *view) { + GObject *object; /* Autre version de l'instance */ + + object = G_OBJECT(view); + + g_object_set(object, "has-tooltip", TRUE, NULL); + view->caret.x = 10; view->caret.y = 10; view->caret.width = 100; @@ -484,7 +496,145 @@ static gboolean gtk_buffer_view_key_press(GtkWidget *widget, GdkEventKey *event) } +/****************************************************************************** +* * +* Paramètres : widget = composant GTK visé par l'opération. * +* x = abscisse de la position du message. * +* y = ordonnée de la position du message. * +* keyboard = indique une demande suite à obtiention du focus. * +* tooltip = astuce à compléter. [OUT] * +* * +* Description : Prépare l'affichage d'une astuce. * +* * +* Retour : TRUE pour un affichage validé, FALSE sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static gboolean gtk_buffer_view_query_tooltip(GtkWidget *widget, gint x, gint y, gboolean keyboard, GtkTooltip *tooltip) +{ + GtkBufferView *view; /* Autre version du composant */ + gint real_x; /* Abscisse absolue réelle */ + gint real_y; /* Ordonnée absolue réelle */ + GBufferLine *line; /* Ligne en cours de survol */ + GBufferSegment *segment; /* Segment actif s'il existe */ + GObject *creator; /* Créateur à l'orgine du seg. */ + virt_t virt; /* Adresse virtuelle */ + vmpa2t addr; /* Adresse de destination */ + GBinFormat *format; /* Format du fichier binaire */ + GBinSymbol *target_sym; /* Symbole présent à l'adresse */ + GBinSymbol *next_sym; /* Symbole suivant l'adresse */ + const vmpa2t *stop_addr; /* Adresse associée, pour fin */ + const mrange_t *lrange; /* Couverture d'une ligne */ + size_t count; /* Nbre de lignes max à traiter*/ + char *markup; /* Description à construire */ + size_t i; /* Boucle de parcours */ + size_t index; /* Indice d'une ligne imprimée */ + char *text; /* Contenu à ajouter */ + + if (keyboard) return FALSE; + + view = GTK_BUFFER_VIEW(widget); + + /* Récupération de la destination pointée */ + + real_x = x; + real_y = y; + gtk_view_panel_compute_real_coord(GTK_VIEW_PANEL(view), &real_x, &real_y); + + + line = g_buffer_view_find_line_and_segment_at(view->buffer_view, + &real_x, real_y, NULL, + GTK_VIEW_PANEL(view)->display, &segment); + + if (line == NULL || segment == NULL) goto no_tooltip; + + creator = g_buffer_segment_get_creator(segment); + if (creator == NULL) goto no_tooltip; + + /** + * On fait le pari de reposer uniquement sur des adresses virtuelles ! + * A changer dans un futur ? + */ + + virt = VMPA_NO_VIRTUAL; + + if (G_IS_TARGET_OPERAND(creator)) + virt = g_target_operand_get_addr(G_TARGET_OPERAND(creator)); + + else if (G_IS_IMM_OPERAND(creator)) + { + if (!g_imm_operand_to_virt_t(G_IMM_OPERAND(creator), &virt)) + virt = VMPA_NO_VIRTUAL; + } + + if (virt == VMPA_NO_VIRTUAL) goto no_tooltip; + + init_vmpa(&addr, VMPA_NO_PHYSICAL, virt); + + /* Construction du contenu textuel */ + + format = G_BIN_FORMAT(g_loaded_binary_get_format(GTK_VIEW_PANEL(view)->binary)); + + if (!g_binary_format_find_symbol_at(format, &addr, &target_sym)) + goto no_tooltip; + + g_object_unref(G_OBJECT(target_sym)); + + /* Construction du contenu textuel */ + + if (g_binary_format_find_next_symbol_at(format, &addr, &next_sym)) + stop_addr = get_mrange_addr(g_binary_symbol_get_range(next_sym)); + + count = 4; + + markup = NULL; + + for (i = 0, line = g_buffer_view_find_line_by_addr(view->buffer_view, &addr, BLF_NONE, &index); + i < count && line != NULL; + i++, line = g_buffer_view_find_line_by_index(view->buffer_view, index + i)) + { + + /* Si on commence à marcher sur les plates-bandes du symbole suivant... */ + if (next_sym != NULL) + { + lrange = g_buffer_line_get_range(line); + + if (mrange_contains_addr(lrange, stop_addr)) + break; + + } + + text = g_buffer_line_get_text(line, BLC_ASSEMBLY_HEAD, BLC_COUNT, true); + + if (markup != NULL) + markup = stradd(markup, "\n"); + + if (text != NULL) + markup = stradd(markup, text); + + free(text); + + } + + if (next_sym != NULL) + g_object_unref(G_OBJECT(next_sym)); + + if (markup == NULL) goto no_tooltip; + /* Impression finale */ + + gtk_tooltip_set_markup(tooltip, markup); + free(markup); + + return TRUE; + + no_tooltip: + + return FALSE; + +} /****************************************************************************** |