/* OpenIDA - Outil d'analyse de fichiers binaires
* gtksnippet.h - affichage d'un fragment de code d'assemblage
*
* Copyright (C) 2008 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 "gtksnippet.h"
#include
#include
#define CONTENT_BUFFER_LEN 64
static void gtk_snippet_class_init(GtkSnippetClass *klass);
static void gtk_snippet_init(GtkSnippet *cpu);
static void gtk_snippet_size_request(GtkWidget *widget,
GtkRequisition *requisition);
static void gtk_snippet_size_allocate(GtkWidget *widget,
GtkAllocation *allocation);
static void gtk_snippet_realize(GtkWidget *widget);
static gboolean gtk_snippet_expose(GtkWidget *widget,
GdkEventExpose *event);
static void gtk_snippet_paint(GtkWidget *widget);
static void gtk_snippet_destroy(GtkObject *object);
GtkType
gtk_snippet_get_type(void)
{
static GtkType gtk_snippet_type = 0;
if (!gtk_snippet_type) {
static const GtkTypeInfo gtk_snippet_info = {
"GtkSnippet",
sizeof(GtkSnippet),
sizeof(GtkSnippetClass),
(GtkClassInitFunc) gtk_snippet_class_init,
(GtkObjectInitFunc) gtk_snippet_init,
NULL,
NULL,
(GtkClassInitFunc) NULL
};
gtk_snippet_type = gtk_type_unique(GTK_TYPE_WIDGET, >k_snippet_info);
}
return gtk_snippet_type;
}
void
gtk_snippet_set_state(GtkSnippet *cpu, gint num)
{
cpu->sel = num;
gtk_snippet_paint(GTK_WIDGET(cpu));
}
GtkWidget * gtk_snippet_new()
{
GtkSnippet *result;
result = gtk_type_new(gtk_snippet_get_type());
return GTK_WIDGET(result);
}
static void
gtk_snippet_class_init(GtkSnippetClass *klass)
{
GtkWidgetClass *widget_class;
GtkObjectClass *object_class;
widget_class = (GtkWidgetClass *) klass;
object_class = (GtkObjectClass *) klass;
widget_class->realize = gtk_snippet_realize;
widget_class->size_request = gtk_snippet_size_request;
widget_class->size_allocate = gtk_snippet_size_allocate;
widget_class->expose_event = gtk_snippet_expose;
object_class->destroy = gtk_snippet_destroy;
}
static void
gtk_snippet_init(GtkSnippet *snippet)
{
snippet->sel = 0;
}
static void
gtk_snippet_size_request(GtkWidget *widget,
GtkRequisition *requisition)
{
g_return_if_fail(widget != NULL);
g_return_if_fail(GTK_IS_SNIPPET(widget));
g_return_if_fail(requisition != NULL);
requisition->width = 80;
requisition->height = 100;
}
static void
gtk_snippet_size_allocate(GtkWidget *widget,
GtkAllocation *allocation)
{
g_return_if_fail(widget != NULL);
g_return_if_fail(GTK_IS_SNIPPET(widget));
g_return_if_fail(allocation != NULL);
widget->allocation = *allocation;
if (GTK_WIDGET_REALIZED(widget)) {
gdk_window_move_resize(
widget->window,
allocation->x, allocation->y,
allocation->width, allocation->height
);
}
}
static void
gtk_snippet_realize(GtkWidget *widget)
{
GdkWindowAttr attributes;
guint attributes_mask;
GdkColor white; /* Couleur de fond normale */
g_return_if_fail(widget != NULL);
g_return_if_fail(GTK_IS_SNIPPET(widget));
GTK_WIDGET_SET_FLAGS(widget, GTK_REALIZED);
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_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_SNIPPET(widget)->layout = gtk_widget_create_pango_layout(widget, NULL);
GTK_SNIPPET(widget)->gc = gdk_gc_new(GDK_DRAWABLE(widget->window));
gtk_snippet_build_content(GTK_SNIPPET(widget));
}
static gboolean
gtk_snippet_expose(GtkWidget *widget,
GdkEventExpose *event)
{
g_return_val_if_fail(widget != NULL, FALSE);
g_return_val_if_fail(GTK_IS_SNIPPET(widget), FALSE);
g_return_val_if_fail(event != NULL, FALSE);
gtk_snippet_paint(widget);
return FALSE;
}
static void
gtk_snippet_paint(GtkWidget *widget)
{
/*
cairo_t *cr;
cr = gdk_cairo_create(widget->window);
cairo_translate(cr, 0, 7);
cairo_set_source_rgb(cr, 1, 1, 1);
cairo_paint(cr);
gint pos = GTK_SNIPPET(widget)->sel;
gint rect = pos / 5;
cairo_set_source_rgb(cr, 0.2, 0.4, 0);
gint i;
for ( i = 1; i <= 20; i++) {
if (i > 20 - rect) {
cairo_set_source_rgb(cr, 0.6, 1.0, 0);
} else {
cairo_set_source_rgb(cr, 0.2, 0.4, 0);
}
cairo_rectangle(cr, 8, i*4, 30, 3);
cairo_rectangle(cr, 42, i*4, 30, 3);
cairo_fill(cr);
}
cairo_destroy(cr);
printf("rendering...\n");
*/
gdk_draw_layout(GDK_DRAWABLE(widget->window), GTK_SNIPPET(widget)->gc,
0, 0, GTK_SNIPPET(widget)->layout);
}
static void
gtk_snippet_destroy(GtkObject *object)
{
GtkSnippet *cpu;
GtkSnippetClass *klass;
g_return_if_fail(object != NULL);
g_return_if_fail(GTK_IS_SNIPPET(object));
cpu = GTK_SNIPPET(object);
klass = gtk_type_class(gtk_widget_get_type());
if (GTK_OBJECT_CLASS(klass)->destroy) {
(* GTK_OBJECT_CLASS(klass)->destroy) (object);
}
}
void gtk_snippet_set_sel(GtkSnippet *cpu, gint sel)
{
cpu->sel = sel;
}
void gtk_snippet_test(GtkSnippet *snippet)
{
pango_layout_set_markup(snippet->layout, "int\t80", -1);
}
/******************************************************************************
* *
* Paramètres : snippet = composant GTK à mettre à jour. *
* proc = architecture à associer au contenu. *
* *
* Description : Définit l'architecture à laquelle le contenu est lié. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void gtk_snippet_set_processor(GtkSnippet *snippet, const asm_processor *proc)
{
snippet->proc = proc;
}
/******************************************************************************
* *
* Paramètres : snippet = composant GTK à mettre à jour. *
* offset = position de l'instruction à ajouter. *
* instr = instruction à représenter ou NULL. *
* comment = commentaire à imprimer ou NULL. *
* *
* Description : Ajoute une ligne dans le bloc de représentation. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void gtk_snippet_add_line(GtkSnippet *snippet, uint64_t offset, asm_instr *instr, const char *comment)
{
snippet->info = (code_line_info *)realloc(snippet->info, ++snippet->info_count * sizeof(code_line_info));
snippet->info[snippet->info_count - 1].offset = offset;
snippet->info[snippet->info_count - 1].instr = instr;
snippet->info[snippet->info_count - 1].comment = (comment != NULL ? strdup(comment) : NULL);
}
/******************************************************************************
* *
* Paramètres : snippet = composant GTK à mettre à jour. *
* *
* Description : Définit le contenu visuel à partir des infos enregistrées. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void gtk_snippet_build_content(GtkSnippet *snippet)
{
char *content; /* Contenu à définir */
size_t content_len; /* Taille du contenu */
AdressMode mode; /* Affichage des adresses */
unsigned int i; /* Boucle de traitement */
char buffer[CONTENT_BUFFER_LEN]; /* Zone tampon à utiliser */
int width; /* Largeur de l'objet actuelle */
int height; /* Hauteur de l'objet actuelle */
content_len = strlen("") + 1;
content = (char *)calloc(content_len, sizeof(char));
strcpy(content, "");
mode = ADM_32BITS; /* FIXME */
for (i = 0; i < snippet->info_count; i++)
{
if (i > 0)
{
content = (char *)realloc(content, ++content_len * sizeof(char));
strcat(content, "\n");
}
/* Adresse */
switch (mode)
{
case ADM_32BITS:
snprintf(buffer, CONTENT_BUFFER_LEN,
"0x%08llx",
snippet->info[i].offset);
break;
case ADM_64BITS:
snprintf(buffer, CONTENT_BUFFER_LEN,
"0x%16llx",
snippet->info[i].offset);
break;
}
content_len += strlen(buffer);
content = (char *)realloc(content, content_len * sizeof(char));
strcat(content, buffer);
/* Eventuelle instruction */
if (snippet->info[i].instr != NULL)
{
print_hinstruction(snippet->proc, snippet->info[i].instr, buffer, CONTENT_BUFFER_LEN, ASX_INTEL);
content_len += strlen("\t") + strlen(buffer);
content = (char *)realloc(content, content_len * sizeof(char));
strcat(content, "\t");
strcat(content, buffer);
}
/* Eventuel commantaire */
if (snippet->info[i].comment != NULL)
{
content_len += strlen("\t; ") + strlen(snippet->info[i].comment) + strlen("");
content = (char *)realloc(content, content_len * sizeof(char));
strcat(content, "\t; ");
strcat(content, snippet->info[i].comment);
strcat(content, "");
}
}
content_len += strlen("");
content = (char *)realloc(content, content_len * sizeof(char));
strcat(content, "");
pango_layout_set_markup(snippet->layout, content, content_len - 1);
pango_layout_get_pixel_size(snippet->layout, &width, &height);
gtk_widget_set_size_request(GTK_WIDGET(snippet), width, height);
}