/* OpenIDA - Outil d'analyse de fichiers binaires * gcodebuffer.h - prototypes pour l'affichage d'un fragment de code d'assemblage * * Copyright (C) 2010 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 "gcodebuffer.h" #include #include /* -------------------------- TAMPON POUR CODE DESASSEMBLE -------------------------- */ /* Tampon pour code désassemblé (instance) */ struct _GCodeBuffer { GObject parent; /* A laisser en premier */ GBufferLine **lines; /* Liste des lignes intégrées */ size_t count; /* Quantité en cache */ size_t used; /* Quantité utilisée */ }; /* Tampon pour code désassemblé (classe) */ struct _GCodeBufferClass { GObjectClass parent; /* A laisser en premier */ }; /* Taille des allocations de masse */ #define LINE_ALLOC_BULK 20 /* Procède à l'initialisation d'une classe de tampon de code. */ static void g_code_buffer_class_init(GCodeBufferClass *); /* Procède à l'initialisation d'un tampon pour code désassemblé. */ static void g_code_buffer_init(GCodeBuffer *); /* ---------------------- VUE PARTICULIERE D'UN TAMPON DE CODE ---------------------- */ /* Vue d'un tampon pour code désassemblé (instance) */ struct _GBufferView { GObject parent; /* A laisser en premier */ GCodeBuffer *buffer; /* Tampon de code visualisé */ size_t first; /* Première ligne intégrée */ size_t last; /* Dernière ligne intégrée */ gint line_height; /* Hauteur maximale des lignes */ gint max_widths[BLC_COUNT]; /* Taille cachée des colonnes */ gint left_margin; /* Marge gauche + espace */ gint left_text; /* Début d'impression du code */ buffer_line_draw_fc drawing_extra; /* Fonction d'accompagnement */ void *drawing_data; /* Donnée utilisateur */ }; /* Vue d'un tampon pour code désassemblé (classe) */ struct _GBufferViewClass { GObjectClass parent; /* A laisser en premier */ }; #define WIDTHS_CACHED(view) ((view)->max_widths[0] != -1) /* Procède à l'initialisation d'une classe de vue de tampon. */ static void g_buffer_view_class_init(GBufferViewClass *); /* Procède à l'initialisation d'une vue d'un tampon pour code. */ static void g_buffer_view_init(GBufferView *); /* Réinitialise le cache des largeurs de colonne calculées. */ static void g_buffer_view_reset_required_widths(GBufferView *); /* Calcule les dimensions requises par une visualisation. */ static void g_buffer_view_compute_required_widths(GBufferView *); /* ---------------------------------------------------------------------------------- */ /* TAMPON POUR CODE DESASSEMBLE */ /* ---------------------------------------------------------------------------------- */ /* Détermine le type du composant de tampon pour code désassemblé. */ G_DEFINE_TYPE(GCodeBuffer, g_code_buffer, G_TYPE_OBJECT); /****************************************************************************** * * * Paramètres : class = classe de composant GTK à initialiser. * * * * Description : Procède à l'initialisation d'une classe de tampon de code. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_code_buffer_class_init(GCodeBufferClass *class) { } /****************************************************************************** * * * Paramètres : buffer = composant GTK à initialiser. * * * * Description : Procède à l'initialisation d'un tampon pour code désassemblé.* * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_code_buffer_init(GCodeBuffer *buffer) { } /****************************************************************************** * * * Paramètres : - * * * * Description : Crée un nouveau composant de tampon pour code désassemblé. * * * * Retour : Composant GTK créé. * * * * Remarques : - * * * ******************************************************************************/ GCodeBuffer *g_code_buffer_new(void) { GCodeBuffer *result; /* Composant à retourner */ result = g_object_new(G_TYPE_CODE_BUFFER, NULL); return result; } /****************************************************************************** * * * Paramètres : buffer = composant GTK à mettre à jour. * * * * Description : Ajoute une nouvelle ligne à un tampon pour code désassemblé. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ GBufferLine *g_code_buffer_append_new_line(GCodeBuffer *buffer) { GBufferLine *result; /* Instance à retourner */ if (buffer->used == buffer->count) { buffer->count += LINE_ALLOC_BULK; buffer->lines = (GBufferLine **)realloc(buffer->lines, buffer->count * sizeof(GBufferLine *)); } result = g_buffer_line_new(); buffer->lines[buffer->used++] = result; return result; } /* ---------------------------------------------------------------------------------- */ /* VUE PARTICULIERE D'UN TAMPON DE CODE */ /* ---------------------------------------------------------------------------------- */ /* Détermine le type de la vue d'un tampon pour code désassemblé. */ G_DEFINE_TYPE(GBufferView, g_buffer_view, G_TYPE_OBJECT); /****************************************************************************** * * * Paramètres : class = classe de composant GTK à initialiser. * * * * Description : Procède à l'initialisation d'une classe de vue de tampon. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_buffer_view_class_init(GBufferViewClass *class) { } /****************************************************************************** * * * Paramètres : buffer = composant GTK à initialiser. * * * * Description : Procède à l'initialisation d'une vue d'un tampon pour code. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_buffer_view_init(GBufferView *buffer) { } /****************************************************************************** * * * Paramètres : buffer = tamon à représenter à l'écran. * * * * Description : Crée une nouvelle vue d'un tampon pour code désassemblé. * * * * Retour : Composant GTK créé. * * * * Remarques : - * * * ******************************************************************************/ GBufferView *g_buffer_view_new(GCodeBuffer *buffer) { GBufferView *result; /* Composant à retourner */ result = g_object_new(G_TYPE_BUFFER_VIEW, NULL); result->buffer = buffer; result->first = 0; result->last = buffer->used; g_buffer_view_reset_required_widths(result); return result; } /****************************************************************************** * * * Paramètres : view = visualisation à consulter. * * * * Description : Réinitialise le cache des largeurs de colonne calculées. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_buffer_view_reset_required_widths(GBufferView *view) { unsigned int i; /* Boucle de parcours */ for (i = 0; i < BLC_COUNT; i++) view->max_widths[i] = -1; } /****************************************************************************** * * * Paramètres : view = visualisation à consulter. * * * * Description : Calcule les dimensions requises par une visualisation. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_buffer_view_compute_required_widths(GBufferView *view) { GBufferLine **lines; /* Liste des lignes à traiter */ size_t i; /* Boucle de parcours #1 */ unsigned int j; /* Boucle de parcours #2 */ gint width; /* Largeur d'une colonne */ lines = view->buffer->lines; view->line_height = 17; view->left_margin = 2 * view->line_height; view->left_text = 2.5 * view->line_height; for (i = view->first; i < view->last; i++) for (j = 0; j < BLC_COUNT; j++) { width = g_buffer_line_get_width(lines[i], j); view->max_widths[j] = MAX(view->max_widths[j], width); } } /****************************************************************************** * * * Paramètres : view = visualisation à consulter. * * * * Description : Fournit la hauteur d'impression d'une ligne visualisée. * * * * Retour : Hauteur de ligne en pixel. * * * * Remarques : - * * * ******************************************************************************/ gint g_buffer_view_get_line_height(GBufferView *view) { if (!WIDTHS_CACHED(view)) g_buffer_view_compute_required_widths(view); return view->line_height; } /****************************************************************************** * * * Paramètres : view = visualisation à consulter. * * width = largeur requise pour une pleine visualisation. [OUT]* * height = hauteur requise pour une pleine visualisation. [OUT]* * * * Description : Fournit les dimensions requises par une visualisation. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void g_buffer_view_get_size(GBufferView *view, gint *width, gint *height) { unsigned int i; /* Boucle de parcours */ *width = 0; *height = view->line_height; if (!WIDTHS_CACHED(view)) g_buffer_view_compute_required_widths(view); for (i = 0; i < BLC_COUNT; i++) *width += view->max_widths[i]; *height *= (view->last - view->first); } /****************************************************************************** * * * Paramètres : view = visualisation à mettre à jour. * * method = procédure à appeler à chaque dessin de ligne. * * data = donnée utilisateur à passer lors des appels. * * * * Description : Définit à une procédure à appeler lors des dessins de ligne. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void g_buffer_view_define_extra_drawing(GBufferView *view, buffer_line_draw_fc method, void *data) { view->drawing_extra = method; view->drawing_data = data; } /****************************************************************************** * * * Paramètres : view = visualisation à représenter. * * event = informations liées à l'événement. * * gc = contexte graphique à utiliser pour les pinceaux. * * fake_x = abscisse réelle du point 0 à l'écran. * * fake_y = ordonnée réelle du point 0 à l'écran. * * * * Description : Imprime la visualisation du tempon de code désassemblé. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void g_buffer_view_draw(const GBufferView *view, const GdkEventExpose *event, GdkGC *gc, gint fake_x, gint fake_y) { GdkDrawable *drawable; /* Surface de dessin */ gint real_x; /* Abscisse réelle pour tampon */ gint real_y; /* Ordonnée réelle pour tampon */ size_t first; /* Première ligne visée */ size_t last; /* Dernière ligne visée + 1 */ gint y; /* Point de départ + décallage */ GBufferLine **lines; /* Liste des lignes à traiter */ size_t i; /* Boucle de parcours */ drawable = GDK_DRAWABLE(event->window); real_x = fake_x + view->left_text; real_y = fake_y + event->area.y; first = (real_y / view->line_height); last = first + (event->area.height / view->line_height); if (event->area.height % view->line_height > 0) last++; y = event->area.y - (real_y % view->line_height); lines = view->buffer->lines; for (i = first; i < last; i++) { /* TODO : skip if... */ if (view->drawing_extra != NULL) view->drawing_extra(lines[i], drawable, gc, fake_x, y, view->drawing_data); g_buffer_line_draw(lines[i], drawable, gc, view->max_widths, real_x, y); y += view->line_height; } }