/* OpenIDA - Outil d'analyse de fichiers binaires * gtkviewpanel.c - affichage de contenu de binaire * * Copyright (C) 2010-2012 Cyrille Bagard * * This file is part of OpenIDA. * * OpenIDA 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. * * OpenIDA 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 "gtkviewpanel.h" #include "gtkviewpanel-int.h" #include "../glibext/chrysamarshal.h" /* Procède à l'initialisation de l'afficheur générique. */ static void gtk_view_panel_class_init(GtkViewPanelClass *); /* Procède à l'initialisation de l'afficheur générique. */ static void gtk_view_panel_init(GtkViewPanel *); /* Enregistre les défilements à associer au composant GTK. */ static void gtk_view_panel_set_scroll_adjustments(GtkViewPanel *, GtkAdjustment *, GtkAdjustment *); /* Prend acte d'un nouveau défilement. */ static void gtk_view_panel_adj_value_changed(GtkAdjustment *, GtkViewPanel *); /* Encadre la construction graphique initiale de l'affichage. */ static void gtk_view_panel_realize(GtkWidget *); /* Met à jour l'affichage du composant d'affichage. */ static gboolean gtk_view_panel_expose(GtkWidget *, GdkEventExpose *); /* Détermine le type du composant d'affichage générique. */ G_DEFINE_TYPE(GtkViewPanel, gtk_view_panel, GTK_TYPE_FIXED) /****************************************************************************** * * * Paramètres : class = classe GTK à initialiser. * * * * Description : Procède à l'initialisation de l'afficheur générique. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void gtk_view_panel_class_init(GtkViewPanelClass *class) { GtkWidgetClass *widget_class; /* Classe de haut niveau */ widget_class = GTK_WIDGET_CLASS(class); widget_class->realize = gtk_view_panel_realize; widget_class->expose_event = gtk_view_panel_expose; class->set_scroll_adjustments = gtk_view_panel_set_scroll_adjustments; widget_class->set_scroll_adjustments_signal = g_signal_new(("set_scroll_adjustments"), GTK_TYPE_VIEW_PANEL, G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET(GtkViewPanelClass, set_scroll_adjustments), NULL, NULL, g_cclosure_user_marshal_VOID__OBJECT_OBJECT, G_TYPE_NONE, 2, GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT); } /****************************************************************************** * * * Paramètres : view = composant GTK à initialiser. * * * * Description : Procède à l'initialisation de l'afficheur générique. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void gtk_view_panel_init(GtkViewPanel *panel) { gtk_widget_set_has_window(GTK_WIDGET(panel), TRUE); } /****************************************************************************** * * * Paramètres : panel = vue à compléter. * * hadjustment = nouveau défilement horizontal à intégrer. * * vadjustment = nouveau défilement vertical à intégrer. * * * * Description : Enregistre les défilements à associer au composant GTK. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void gtk_view_panel_set_scroll_adjustments(GtkViewPanel *panel, GtkAdjustment *hadjustment, GtkAdjustment *vadjustment) { /* TODO : déconnecter les anciens ? */ panel->hadjustment = hadjustment; panel->vadjustment = vadjustment; /** * On vérifie que le support n'est pas en train de nous libérer, * avant de se connecter... */ if (hadjustment != NULL) g_signal_connect(hadjustment, "value_changed", G_CALLBACK(gtk_view_panel_adj_value_changed), panel); if (vadjustment != NULL) g_signal_connect(vadjustment, "value_changed", G_CALLBACK(gtk_view_panel_adj_value_changed), panel); } /****************************************************************************** * * * Paramètres : adj = défilement à l'origine de l'action. * * panel = composant GTK à redessiner. * * * * Description : Prend acte d'un nouveau défilement. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void gtk_view_panel_adj_value_changed(GtkAdjustment *adj, GtkViewPanel *panel) { panel->scroll(panel); } /****************************************************************************** * * * Paramètres : adj = valeurs de défilement à consulter. * * changed = note une mise à jour de valeur. [OUT] * * * * Description : S'assure que la valeur de défilement actuelle est valable. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void gtk_view_panel_reclamp_adjustment(GtkAdjustment *adj, gboolean *changed) { gdouble value; /* Valeur actuelle */ value = adj->value; value = CLAMP(value, 0, adj->upper - adj->page_size); if (value != adj->value) { adj->value = value; *changed = TRUE; } else *changed = FALSE; } /****************************************************************************** * * * Paramètres : panel = composant GTK à consulter. * * alloc = étendue à accorder à la vue. * * * * Description : Calcule la surface pleine utilisable pour le panneau. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void gtk_view_panel_compute_allocation(GtkViewPanel *panel, GtkAllocation *alloc) { GtkWidget *widget; /* Autre version de la vue */ GtkAllocation *allocation; /* Raccourci d'utilisation #1 */ gint border_width; /* Raccourci d'utilisation #2 */ widget = GTK_WIDGET(panel); allocation = &widget->allocation; border_width = GTK_CONTAINER(panel)->border_width; alloc->x = 0; alloc->y = 0; /* if (viewport->shadow_type != GTK_SHADOW_NONE) { alloc->x = widget->style->xthickness; alloc->y = widget->style->ythickness; } */ alloc->width = MAX(1, allocation->width - alloc->x * 2 - border_width * 2); alloc->height = MAX(1, allocation->height - alloc->y * 2 - border_width * 2); } /****************************************************************************** * * * Paramètres : widget = composant GTK à préparer. * * * * Description : Encadre la construction graphique initiale de l'affichage. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void gtk_view_panel_realize(GtkWidget *widget) { GdkWindowAttr attributes; /* Propriétés du composant */ guint attributes_mask; /* Masque de prise en compte */ GdkColor white; /* Couleur de fond normale */ gtk_widget_set_realized(widget, TRUE); attributes.window_type = GDK_WINDOW_CHILD; attributes.x = widget->allocation.x; attributes.y = widget->allocation.y; attributes.width = widget->allocation.width; attributes.height = widget->allocation.height; attributes.wclass = GDK_INPUT_OUTPUT; attributes.event_mask = gtk_widget_get_events(widget) | GDK_BUTTON_PRESS_MASK | GDK_EXPOSURE_MASK; attributes_mask = GDK_WA_X | GDK_WA_Y; widget->window = gdk_window_new(gtk_widget_get_parent_window(widget), &attributes, attributes_mask); gdk_window_set_user_data(widget->window, widget); widget->style = gtk_style_attach(widget->style, widget->window); gdk_color_white(gtk_widget_get_colormap(widget), &white); gtk_widget_modify_bg(widget, GTK_STATE_NORMAL, &white); GTK_VIEW_PANEL(widget)->gc = gdk_gc_new(GDK_DRAWABLE(widget->window)); } /****************************************************************************** * * * Paramètres : widget = composant GTK à redessiner. * * event = informations liées à l'événement. * * * * Description : Met à jour l'affichage du composant d'affichage. * * * * Retour : FALSE pour poursuivre la propagation de l'événement. * * * * Remarques : - * * * ******************************************************************************/ static gboolean gtk_view_panel_expose(GtkWidget *widget, GdkEventExpose *event) { GtkViewPanel *panel; GdkGCValues values; /* Propriétés du contexte */ GtkStyle *style; /* Style associé au composant */ GtkRequisition req; /* Taille allouée à l'élément */ GtkStateType state; /* Etat du composant */ panel = GTK_VIEW_PANEL(widget); if (panel->show_border) { gdk_gc_get_values(panel->gc, &values); style = gtk_widget_get_style(widget); gtk_widget_size_request(widget, &req); state = gtk_widget_get_state(widget); gdk_gc_set_foreground(panel->gc, &style->dark[state]); gdk_draw_rectangle(GDK_DRAWABLE(widget->window), panel->gc, FALSE, 0, 0, req.width - 1, req.height - 1); gdk_gc_set_foreground(panel->gc, &values.foreground); } return FALSE; } /****************************************************************************** * * * Paramètres : panel = composant GTK à mettre à jour. * * show = état de l'affichage auquel parvenir. * * * * Description : Définit si une bordure est à afficher. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void gtk_view_panel_show_border(GtkViewPanel *panel, bool show) { panel->show_border = show; } /****************************************************************************** * * * Paramètres : panel = composant GTK à mettre à jour. * * binary = binaire associé à intégrer. * * addr = indique si les positions doivent être affichées. * * code = indique si le code binaire doit être affiché. * * * * Description : Associe à un panneau d'affichage un binaire chargé. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void gtk_view_panel_attach_binary(GtkViewPanel *panel, GLoadedBinary *binary, bool *addr, bool *code) { g_object_ref(G_OBJECT(binary)); panel->binary = binary; panel->display_addr = addr; panel->display_code = code; if (panel->attach != NULL) /* REMME ? */ panel->attach(panel, binary, addr, code); } /****************************************************************************** * * * Paramètres : panel = composant GTK à consulter. * * * * Description : Indique si les adresses doivent apparaître dans le rendu. * * * * Retour : Consigne d'affichage. * * * * Remarques : - * * * ******************************************************************************/ bool gtk_view_panel_get_addresses_display(const GtkViewPanel *panel) { return *panel->display_addr; } /****************************************************************************** * * * Paramètres : panel = composant GTK à consulter. * * state = nouvel état à prendre en compte. * * * * Description : Définit si les adresses doivent apparaître dans le rendu. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void gtk_view_panel_set_addresses_display(GtkViewPanel *panel, bool state) { if (*panel->display_addr != state) { *panel->display_addr = state; if (panel->resize != NULL) panel->resize(panel); gtk_widget_queue_resize(gtk_widget_get_parent(GTK_WIDGET(panel))); gtk_widget_queue_resize(GTK_WIDGET(panel)); gtk_widget_queue_draw(GTK_WIDGET(panel)); } } /****************************************************************************** * * * Paramètres : panel = composant GTK à consulter. * * * * Description : Indique si le code doit apparaître dans le rendu. * * * * Retour : Consigne d'affichage. * * * * Remarques : - * * * ******************************************************************************/ bool gtk_view_panel_get_code_display(const GtkViewPanel *panel) { return *panel->display_code; } /****************************************************************************** * * * Paramètres : panel = composant GTK à consulter. * * state = nouvel état à prendre en compte. * * * * Description : Définit si le code doit apparaître dans le rendu. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void gtk_view_panel_set_code_display(GtkViewPanel *panel, bool state) { if (*panel->display_code != state) { *panel->display_code = state; if (panel->resize != NULL) panel->resize(panel); gtk_widget_queue_resize(gtk_widget_get_parent(GTK_WIDGET(panel))); gtk_widget_queue_resize(GTK_WIDGET(panel)); gtk_widget_queue_draw(GTK_WIDGET(panel)); } } /****************************************************************************** * * * Paramètres : panel = composant GTK à consulter. * * * * Description : Fournit le binaire associé à la représentation. * * * * Retour : Représentation de contenu binaire. * * * * Remarques : - * * * ******************************************************************************/ GLoadedBinary *gtk_view_panel_get_binary(const GtkViewPanel *panel) { return panel->binary; } /****************************************************************************** * * * Paramètres : view = composant GTK à manipuler. * * addr = adresse à rechercher. * * * * Description : Indique si la vue contient une addrese donnée. * * * * Retour : true si l'adresse est présente, false sinon. * * * * Remarques : - * * * ******************************************************************************/ bool gtk_view_panel_contain_address(const GtkViewPanel *panel, vmpa_t addr) { gint dummy_x; /* Abscisse pour l'appel */ gint dummy_y; /* Ordonnée pour l'appel */ return panel->get_coordinates(panel, addr, &dummy_x, &dummy_y); } /****************************************************************************** * * * Paramètres : panel = composant GTK à manipuler. * * addr = adresse à présenter à l'écran. * * * * Description : S'assure qu'une adresse donnée est visible à l'écran. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void gtk_view_panel_scroll_to_address(GtkViewPanel *panel, vmpa_t addr) { gint x; /* Abscisse à garantir */ gint y; /* Ordonnée à garantir */ GtkAdjustment *adj; /* Défilement à mettre à jour */ if (panel->define != NULL) panel->define(panel, addr); if (panel->get_coordinates(panel, addr, &x, &y)) { adj = panel->hadjustment; if (x > (adj->upper - adj->page_size)) x = adj->upper - adj->page_size; gtk_adjustment_set_value(adj, x); adj = panel->vadjustment; if (y > (adj->upper - adj->page_size)) y = adj->upper - adj->page_size; gtk_adjustment_set_value(adj, y); } } /****************************************************************************** * * * Paramètres : panel = composant GTK à manipuler. * * cairo = assistant pour la création de rendus. * * * * Description : Place en cache un rendu destiné à l'aperçu graphique rapide. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void gtk_view_panel_cache_glance(GtkViewPanel *panel, cairo_t *cairo) { if (panel->cache_glance != NULL) panel->cache_glance(panel, cairo); }