summaryrefslogtreecommitdiff
path: root/src/glibext/gcodebuffer.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/glibext/gcodebuffer.c')
-rw-r--r--src/glibext/gcodebuffer.c483
1 files changed, 483 insertions, 0 deletions
diff --git a/src/glibext/gcodebuffer.c b/src/glibext/gcodebuffer.c
new file mode 100644
index 0000000..fda2c01
--- /dev/null
+++ b/src/glibext/gcodebuffer.c
@@ -0,0 +1,483 @@
+
+/* 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 <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "gcodebuffer.h"
+
+
+#include <malloc.h>
+#include <sys/param.h>
+
+
+
+/* -------------------------- 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;
+
+ }
+
+}