/* Chrysalide - Outil d'analyse de fichiers binaires * gtkblockdisplay.c - affichage d'un fragment de code d'assemblage * * Copyright (C) 2008-2012 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 . */ #include "gtkblockdisplay.h" #include "gtkbufferdisplay-int.h" /* Composant d'affichage de bloc d'assembleur (instance) */ struct _GtkBlockDisplay { GtkBufferDisplay parent; /* A laisser en premier */ }; /* Composant d'affichage de code d'assembleur (classe) */ struct _GtkBlockDisplayClass { GtkBufferDisplayClass parent; /* A laisser en premier */ /* Signaux */ void (* highlight_changed) (GtkBlockDisplay *); }; /* Procède à l'initialisation des afficheurs de bloc assembleur. */ static void gtk_block_display_class_init(GtkBlockDisplayClass *); /* Procède à l'initialisation de l'afficheur de bloc assembleur. */ static void gtk_block_display_init(GtkBlockDisplay *); /* Supprime toutes les références externes. */ static void gtk_block_display_dispose(GtkBlockDisplay *); /* Procède à la libération totale de la mémoire. */ static void gtk_block_display_finalize(GtkBlockDisplay *); /* Assure la gestion des clics de souris sur le composant. */ static gboolean gtk_block_display_button_press(GtkWidget *, GdkEventButton *); /* Redessine l'affichage suite à un changement visuel. */ static gboolean gtk_block_display_need_redraw(GtkBlockDisplay *, GBufferView *); /* Prend acte de l'association d'un binaire chargé. */ static void gtk_block_display_attach_binary(GtkBlockDisplay *, GLoadedBinary *); /* Réagit à un déplacement de curseur. */ static bool gtk_block_display_notify_caret_relocation(GtkBlockDisplay *, const GdkRectangle *, const vmpa2t *); /* Détermine le type du composant d'affichage de bloc en langage d'assemblage. */ G_DEFINE_TYPE(GtkBlockDisplay, gtk_block_display, GTK_TYPE_BUFFER_DISPLAY) /****************************************************************************** * * * Paramètres : class = classe GTK à initialiser. * * * * Description : Procède à l'initialisation des afficheurs de bloc assembleur.* * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void gtk_block_display_class_init(GtkBlockDisplayClass *class) { GObjectClass *object; /* Autre version de la classe */ GtkWidgetClass *widget_class; /* Classe version Widget */ GtkDisplayPanelClass *panel_class; /* Classe parente */ GtkBufferDisplayClass *buffer_class; /* Classe supérieure */ object = G_OBJECT_CLASS(class); object->dispose = (GObjectFinalizeFunc/* ! */)gtk_block_display_dispose; object->finalize = (GObjectFinalizeFunc)gtk_block_display_finalize; widget_class = GTK_WIDGET_CLASS(class); widget_class->button_press_event = gtk_block_display_button_press; panel_class = GTK_DISPLAY_PANEL_CLASS(class); panel_class->attach = (attach_binary_fc)gtk_block_display_attach_binary; buffer_class = GTK_BUFFER_DISPLAY_CLASS(class); buffer_class->notify_caret = (notify_caret_relocation_fc)gtk_block_display_notify_caret_relocation; /* Signaux */ g_signal_new("highlight-changed", GTK_TYPE_BLOCK_DISPLAY, G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(GtkBlockDisplayClass, highlight_changed), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); } /****************************************************************************** * * * Paramètres : view = composant GTK à initialiser. * * * * Description : Procède à l'initialisation de l'afficheur de bloc assembleur.* * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void gtk_block_display_init(GtkBlockDisplay *view) { } /****************************************************************************** * * * Paramètres : display = instance d'objet GLib à traiter. * * * * Description : Supprime toutes les références externes. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void gtk_block_display_dispose(GtkBlockDisplay *display) { G_OBJECT_CLASS(gtk_block_display_parent_class)->dispose(G_OBJECT(display)); } /****************************************************************************** * * * Paramètres : display = instance d'objet Gtk à traiter. * * * * Description : Procède à la libération totale de la mémoire. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void gtk_block_display_finalize(GtkBlockDisplay *display) { G_OBJECT_CLASS(gtk_block_display_parent_class)->finalize(G_OBJECT(display)); } /****************************************************************************** * * * Paramètres : - * * * * Description : Crée un nouveau composant pour l'affichage de bloc en ASM. * * * * Retour : Composant GTK créé. * * * * Remarques : - * * * ******************************************************************************/ GtkWidget *gtk_block_display_new(void) { GtkBlockDisplay *result; /* Composant à retourner */ result = g_object_new(GTK_TYPE_BLOCK_DISPLAY, NULL); return GTK_WIDGET(result); } /****************************************************************************** * * * Paramètres : widget = composant GTK visé par l'opération. * * event = informations liées à l'événement. * * * * 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_block_display_button_press(GtkWidget *widget, GdkEventButton *event) { GtkBlockDisplay *display; /* Autre version du composant */ gint real_x; /* Abscisse absolue réelle */ gint real_y; /* Ordonnée absolue réelle */ GBufferView *view; /* Vue du tampon représenté */ bool changed; /* Suivi des changements */ GTK_WIDGET_CLASS(gtk_block_display_parent_class)->button_press_event(widget, event); display = GTK_BLOCK_DISPLAY(widget); if (event->type == GDK_2BUTTON_PRESS) { real_x = event->x; real_y = event->y; gtk_display_panel_compute_real_coord(GTK_DISPLAY_PANEL(display), &real_x, &real_y); view = gtk_buffer_display_get_view(GTK_BUFFER_DISPLAY(display)); changed = g_buffer_view_highlight_segments(view, real_x, real_y, GTK_DISPLAY_PANEL(display)->display); g_object_unref(G_OBJECT(view)); if (changed) g_signal_emit_by_name(display, "highlight-changed"); } return FALSE; } /****************************************************************************** * * * Paramètres : display = composant GTK d'affichage. * * view = composant GLib interne. * * * * Description : Redessine l'affichage suite à un changement visuel. * * * * Retour : FALSE pour poursuivre la propagation de l'événement. * * * * Remarques : - * * * ******************************************************************************/ static gboolean gtk_block_display_need_redraw(GtkBlockDisplay *display, GBufferView *view) { gtk_widget_queue_draw(GTK_WIDGET(display)); return FALSE; } /****************************************************************************** * * * Paramètres : display = composant GTK à mettre à jour. * * binary = binaire associé à intégrer. * * * * Description : Prend acte de l'association d'un binaire chargé. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void gtk_block_display_attach_binary(GtkBlockDisplay *display, GLoadedBinary *binary) { GBufferCache *cache; /* Tampon par défaut */ GBufferView *view; /* Vue sur ce même tampon */ cache = g_loaded_binary_get_disassembled_cache(binary); view = g_buffer_view_new(cache, NULL); gtk_buffer_display_set_view(GTK_BUFFER_DISPLAY(display), view); g_signal_connect_swapped(G_OBJECT(view), "need-redraw", G_CALLBACK(gtk_block_display_need_redraw), display); } /****************************************************************************** * * * Paramètres : display = composant GTK à manipuler. * * area = emplacement pour le dessin d'un curseur. * * addr = position dans la mémoire représentée du curseur. * * * * Description : Réagit à un déplacement de curseur. * * * * Retour : true si un changement a été opéré. * * * * Remarques : - * * * ******************************************************************************/ static bool gtk_block_display_notify_caret_relocation(GtkBlockDisplay *display, const GdkRectangle *area, const vmpa2t *addr) { bool result; /* Bilan à retourner */ GBufferView *view; /* Vue du tampon représenté */ view = gtk_buffer_display_get_view(GTK_BUFFER_DISPLAY(display)); result = g_buffer_view_highlight_segments(view, area->x, area->y, GTK_DISPLAY_PANEL(display)->display); g_object_unref(G_OBJECT(view)); if (result) g_signal_emit_by_name(display, "highlight-changed"); return result; }