diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2010-04-11 16:39:38 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2010-04-11 16:39:38 (GMT) |
commit | 30258fa96ad48eed68924f259ec5464fc4fd8094 (patch) | |
tree | 6187f2ddbee31de8bcd1b4b6e930a38f858f922c /src/glibext | |
parent | 929150f18d23d82e8390bd98e31b1edb34bc09f1 (diff) |
Provided a faster than GTK display buffer.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@150 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
Diffstat (limited to 'src/glibext')
-rw-r--r-- | src/glibext/Makefile.am | 5 | ||||
-rw-r--r-- | src/glibext/gbufferline.c | 359 | ||||
-rw-r--r-- | src/glibext/gbufferline.h | 86 | ||||
-rw-r--r-- | src/glibext/gbuffersegment.c | 391 | ||||
-rw-r--r-- | src/glibext/gbuffersegment.h | 65 | ||||
-rw-r--r-- | src/glibext/gcodebuffer.c | 483 | ||||
-rw-r--r-- | src/glibext/gcodebuffer.h | 102 |
7 files changed, 1490 insertions, 1 deletions
diff --git a/src/glibext/Makefile.am b/src/glibext/Makefile.am index 334b49a..7712965 100644 --- a/src/glibext/Makefile.am +++ b/src/glibext/Makefile.am @@ -3,7 +3,10 @@ noinst_LTLIBRARIES = libglibext.la libglibext_la_SOURCES = \ delayed-int.h \ - delayed.h delayed.c + delayed.h delayed.c \ + gbufferline.h gbufferline.c \ + gbuffersegment.h gbuffersegment.c \ + gcodebuffer.h gcodebuffer.c libglibext_la_LDFLAGS = diff --git a/src/glibext/gbufferline.c b/src/glibext/gbufferline.c new file mode 100644 index 0000000..bfb77bb --- /dev/null +++ b/src/glibext/gbufferline.c @@ -0,0 +1,359 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * gbufferline.c - représentation de fragments de texte en ligne + * + * 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 "gbufferline.h" + + + + +#include <malloc.h> /* FIXME : à virer */ + + + +/* Informations sur le contenu d'une colonne */ +typedef struct _buffer_line_column +{ + GBufferSegment **segments; + size_t count; + + int max_width; /* Largeur max. de l'espace */ + +} buffer_line_column; + + + +/* Réinitialise une colonne de ligne. */ +static void reset_column(buffer_line_column *); + +/* Fournit la quantité de pixels requise pour l'impression. */ +static gint get_column_width(buffer_line_column *); + +/* Ajoute un fragment de texte à une colonne de ligne. */ +static void add_segment_to_column(buffer_line_column *, GBufferSegment *); + +/* Imprime le contenu d'une colonne de ligne de texte. */ +static void draw_segments_of_column(buffer_line_column *, GdkDrawable *, GdkGC *, gint, gint); + + + + +/* Représentation de fragments de texte en ligne (instance) */ +struct _GBufferLine +{ + GObject parent; /* A laisser en premier */ + + buffer_line_column columns[BLC_COUNT]; /* Répartition du texte */ + +}; + +/* Représentation de fragments de texte en ligne (classe) */ +struct _GBufferLineClass +{ + GObjectClass parent; /* A laisser en premier */ + +}; + + +/* Procède à l'initialisation d'une classe de représentation. */ +static void g_buffer_line_class_init(GBufferLineClass *); + +/* Procède à l'initialisation d'une représentation de fragments. */ +static void g_buffer_line_init(GBufferLine *); + + + + + + + +/****************************************************************************** +* * +* Paramètres : column = colonne de ligne à mettre à jour. * +* * +* Description : Réinitialise une colonne de ligne. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void reset_column(buffer_line_column *column) +{ + column->max_width = -1; + +} + + +/****************************************************************************** +* * +* Paramètres : column = colonne de ligne à consulter. * +* * +* Description : Fournit la quantité de pixels requise pour l'impression. * +* * +* Retour : Largeur requise par la colonne, en pixel. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static gint get_column_width(buffer_line_column *column) +{ + size_t i; + + if (column->max_width == -1) + { + column->max_width = 0; + + for (i = 0; i < column->count; i++) + column->max_width += g_buffer_segment_get_width(column->segments[i]); + + } + + return column->max_width; + +} + + +/****************************************************************************** +* * +* Paramètres : column = colonne de ligne à venir compléter. * +* segment = fragment de texte à ajouter à la colonne. * +* * +* Description : Ajoute un fragment de texte à une colonne de ligne. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void add_segment_to_column(buffer_line_column *column, GBufferSegment *segment) +{ + + /* FIXME : à remplacer */ + + + column->segments = (GBufferSegment **)realloc(column->segments, ++column->count * sizeof(GBufferSegment *)); + + + column->segments[column->count - 1] = segment; + + +} + + +/****************************************************************************** +* * +* Paramètres : column = colonne de ligne de texte à manipuler. * +* drawable = surface de rendu où travailler. * +* gc = contexte graphique à utiliser pour les pinceaux. * +* x_init = abscisse du point d'impression de départ. * +* y = ordonnée du point d'impression. * +* * +* Description : Imprime le contenu d'une colonne de ligne de texte. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void draw_segments_of_column(buffer_line_column *column, GdkDrawable *drawable, GdkGC *gc, gint x_init, gint y) +{ + gint x; + size_t i; + + x = x_init; + + for (i = 0; i < column->count; i++) + g_buffer_segment_draw(column->segments[i], drawable, gc, &x, y); + +} + + + + + + + + + + + + + + + + + + + + + + + +/* Détermine le type de la représentation de fragments de texte en ligne. */ +G_DEFINE_TYPE(GBufferLine, g_buffer_line, G_TYPE_OBJECT); + + + +/****************************************************************************** +* * +* Paramètres : class = classe de composant GTK à initialiser. * +* * +* Description : Procède à l'initialisation d'une classe de représentation. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_buffer_line_class_init(GBufferLineClass *class) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : line = composant GTK à initialiser. * +* * +* Description : Procède à l'initialisation d'une représentation de fragments.* +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_buffer_line_init(GBufferLine *line) +{ + unsigned int i; /* Boucle de parcours */ + + for (i = 0; i < BLC_COUNT; i++) + reset_column(&line->columns[i]); + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Crée une nouvelle représentation de fragments de texte. * +* * +* Retour : Composant GTK créé. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBufferLine *g_buffer_line_new(void) +{ + GBufferLine *result; /* Composant à retourner */ + + result = g_object_new(G_TYPE_BUFFER_LINE, NULL); + //result = g_new0(GBufferLine, 1); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : line = ligne à venir compléter. * +* index = index de la colonne visée par la procédure. * +* segment = fragment de texte à ajouter à la colonne. * +* * +* Description : Ajoute un fragment de texte à une colonne de ligne. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_buffer_line_add_segment(GBufferLine *line, BufferLineColumn index, GBufferSegment *segment) +{ + add_segment_to_column(&line->columns[index], segment); + +} + + +/****************************************************************************** +* * +* Paramètres : line = ligne à venir compléter. * +* index = index de la colonne visée par la procédure. * +* * +* Description : Fournit la largeur requise pour une colonne de ligne donnée. * +* * +* Retour : Largeur en pixel requise. * +* * +* Remarques : - * +* * +******************************************************************************/ + +gint g_buffer_line_get_width(GBufferLine *line, BufferLineColumn index) +{ + return get_column_width(&line->columns[index]); + +} + + +/****************************************************************************** +* * +* Paramètres : line = ligne de texte à manipuler. * +* drawable = surface de rendu où travailler. * +* gc = contexte graphique à utiliser pour les pinceaux.* +* max_widths = largeurs de colonne à respecter. * +* x_init = abscisse du point d'impression de départ. * +* y = ordonnée du point d'impression. * +* * +* Description : Imprime la ligne de texte représentée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_buffer_line_draw(GBufferLine *line, GdkDrawable *drawable, GdkGC *gc, const gint max_widths[BLC_COUNT], gint x_init, gint y) +{ + gint x; /* Point de départ d'impression*/ + unsigned int i; /* Boucle de parcours */ + + x = x_init; + + for (i = 0; i < BLC_COUNT; i++) + { + /* TODO : skip if... */ + + draw_segments_of_column(&line->columns[i], drawable, gc, x, y); + x += max_widths[i] + 23; + + } + +} diff --git a/src/glibext/gbufferline.h b/src/glibext/gbufferline.h new file mode 100644 index 0000000..4113c28 --- /dev/null +++ b/src/glibext/gbufferline.h @@ -0,0 +1,86 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * gbufferline.h - prototypes pour la représentation de fragments de texte en ligne + * + * 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/>. + */ + + +#ifndef _GLIBEXT_GBUFFERLINE_H +#define _GLIBEXT_GBUFFERLINE_H + + +#include <glib-object.h> + + +#include "gbuffersegment.h" + + + +#define G_TYPE_BUFFER_LINE (g_buffer_line_get_type()) +#define G_BUFFER_LINE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_BUFFER_LINE, GBufferLine)) +#define G_BUFFER_LINE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_BUFFER_LINE, GBufferLineClass)) +#define G_IS_BUFFER_LINE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_BUFFER_LINE)) +#define G_IS_BUFFER_LINE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_BUFFER_LINE)) +#define G_BUFFER_LINE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_BUFFER_LINE, GBufferLineClass)) + + + +/* Représentation de fragments de texte en ligne (instance) */ +typedef struct _GBufferLine GBufferLine; + +/* Représentation de fragments de texte en ligne (classe) */ +typedef struct _GBufferLineClass GBufferLineClass; + + +/* Désignation des colonnes d'une ligne */ +typedef enum _BufferLineColumn +{ + BLC_ADDRESS, /* Adresse virtuelle */ + BLC_BINARY, /* Contenu sous forme binaire */ + BLC_ASSEMBLY_HEAD, /* Instruction pour assembleur */ + BLC_ASSEMBLY, /* Code pour assembleur */ + BLC_COMMENTS, /* Commentaires éventuels */ + + BLC_COUNT + +} BufferLineColumn; + + +/* Accompagnement du dessin pour compléments */ +typedef void (* buffer_line_draw_fc) (GBufferLine *, GdkDrawable *, GdkGC *, gint, gint, void *); + + +/* Détermine le type de la représentation de fragments de texte en ligne. */ +GType g_buffer_line_get_type(void); + +/* Crée une nouvelle représentation de fragments de texte. */ +GBufferLine *g_buffer_line_new(void); + +/* Ajoute un fragment de texte à une colonne de ligne. */ +void g_buffer_line_add_segment(GBufferLine *, BufferLineColumn, GBufferSegment *); + +/* Fournit la largeur requise pour une colonne de ligne donnée. */ +gint g_buffer_line_get_width(GBufferLine *, BufferLineColumn); + +/* Imprime la ligne de texte représentée. */ +void g_buffer_line_draw(GBufferLine *, GdkDrawable *, GdkGC *, const gint [BLC_COUNT], gint, gint); + + + +#endif /* _GLIBEXT_GBUFFERLINE_H */ diff --git a/src/glibext/gbuffersegment.c b/src/glibext/gbuffersegment.c new file mode 100644 index 0000000..bcafa97 --- /dev/null +++ b/src/glibext/gbuffersegment.c @@ -0,0 +1,391 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * gbuffersegment.c - concentration d'un fragment de caractères aux propriétés communes + * + * 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 "gbuffersegment.h" + + +#include <stdbool.h> + + + + + + +/* Fragment de caractères aux propriétés communes (instance) */ +struct _GBufferSegment +{ + GObject parent; /* A laisser en premier */ + + PangoGlyphString *glyphs; /* Caractères traités */ + PangoFont *font; /* Police utilisée à l'analyse */ + + PangoRectangle logical; /* Dimension du texte */ + +}; + +/* Fragment de caractères aux propriétés communes (classe) */ +struct _GBufferSegmentClass +{ + GObjectClass parent; /* A laisser en premier */ + + PangoGlyphString *ascii_glyphs; /* Caractères ASCII prêts */ + PangoFont *ascii_font; /* Police utilisée pour ASCII */ + bool ascii_ready; /* Utilisation possible ? */ + + bool ascii_init_done; /* Initialisation tentée ? */ + +}; + + +/* Procède à l'initialisation d'une classe de fragment de texte. */ +static void g_buffer_segment_class_init(GBufferSegmentClass *); + +/* Procède à l'initialisation d'un fragment de texte. */ +static void g_buffer_segment_init(GBufferSegment *); + + + + + + + + + + +static bool ascii_glyph_table_init(GBufferSegmentClass *class, PangoContext *context) +{ + gint i; /* Boucle de parcours */ + char ascii_chars[128]; /* Table de caractères ASCII */ + PangoAttrList *attribs; /* Liste d'attributs (vide) */ + GList *list; /* Liste d'éléments distincts */ + + if (!class->ascii_init_done) + { + class->ascii_init_done = true; + + /* Construction d'une chaîne adéquate */ + + for (i = 0; i < 128; ++i) + switch (i) + { + case 0 ... 31: + ascii_chars[i] = '?'; + break; + case 32 ... 127: + ascii_chars[i] = i; + break; + default: + ascii_chars[i] = '?'; + break; + } + + /* Analyse de la chaîne créée */ + + attribs = pango_attr_list_new(); + list = pango_itemize(context, ascii_chars, 0, 128, attribs, NULL); + + class->ascii_ready = (list != NULL && list->next == NULL); + + if (class->ascii_ready) + { + PangoItem *item; + int width; + + item = (PangoItem *)list->data; + //width = gui.char_width * PANGO_SCALE; + + /* Remember the shape engine used for ASCII. */ + //default_shape_engine = item->analysis.shape_engine; + + class->ascii_font = item->analysis.font; + g_object_ref(class->ascii_font); + + class->ascii_glyphs = pango_glyph_string_new(); + + pango_shape(ascii_chars, 128, &item->analysis, class->ascii_glyphs); + + class->ascii_ready = (class->ascii_glyphs->num_glyphs == 128); + + + +#if 0 + for (i = 0; i < class->ascii_glyphs->num_glyphs; i++) + { + PangoGlyphGeometry *geom; + + geom = &class->ascii_glyphs->glyphs[i].geometry; + //geom->x_offset += MAX(0, width - geom->width) / 2; + //geom->width = /*width*/8 * PANGO_SCALE; + } +#endif + + } + + g_list_foreach(list, (GFunc)&pango_item_free, NULL); + g_list_free(list); + + pango_attr_list_unref(attribs); + + } + + return class->ascii_ready; + +} + + + + + + + +/****************************************************************************** +* * +* Paramètres : context = contexte Pango pour l'analyse des caractères. * +* attribs = propriétés de la zone de texte. * +* text = chaîne de caractères à traiter. * +* length = quantité de ces caractères. * +* * +* Description : Crée un nouveau fragment de texte avec des propriétés. * +* * +* Retour : Composant GTK créé. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_buffer_segment_prepare(GBufferSegment *segment, PangoContext *context, PangoAttrList *attribs, const char *text, size_t length) +{ + PangoGlyphString *glyphs; /* Caractères traités */ + + GList *item_list; + PangoItem *item; + + PangoRectangle logical; + + + char *max; + char *iter; + + GBufferSegmentClass *class; + + size_t i; + + PangoGlyphInfo *info; + gint *log_clusters; + PangoGlyphInfo *ref; + + glyphs = pango_glyph_string_new(); + + + + + /** + * Petite astuce empruntée à Vim... + * (cf. src/gui_gtk_x11.c, fonction gui_gtk2_draw_string()). + * On essaie de traiter à la main les morceaux de + * texte. Pour ceux en ASCII pur, le gain est non négligeable. + */ + + max = text + length; + + for (iter = text; iter < max; iter++) + if (*iter & 0x80) + goto not_ascii; + + class = G_BUFFER_SEGMENT_GET_CLASS(segment); + + if (!ascii_glyph_table_init(class, context)) + goto not_ascii; + + pango_glyph_string_set_size(glyphs, length); + + info = glyphs->glyphs; + log_clusters = glyphs->log_clusters; + ref = class->ascii_glyphs->glyphs; + + for (i = 0; i < length; i++) + { + info[i] = ref[text[i]]; + log_clusters[i] = i; + } + + goto next; + + not_ascii: + + item_list = pango_itemize(context, text, 0, length, attribs, NULL); + + /* + if (!(item_list != NULL && item_list->next == NULL)) + printf("ouich\n"); + */ + + item = (PangoItem *)item_list->data; + pango_shape(text, length, &item->analysis, glyphs); + + //segment->font = item->analysis.font;/* TODO : ref ! */ + + + next: + + + //pango_shape(text, length, &item->analysis, glyphs); + + + pango_glyph_string_extents(glyphs, class->ascii_font, NULL, &segment->logical); + + segment->logical.y /= PANGO_SCALE; + segment->logical.width /= PANGO_SCALE; + segment->logical.height /= PANGO_SCALE; + + segment->glyphs = glyphs; + +} + + + + + + + + + + + + + + +/* Détermine le type du fragment de caractères aux propriétés communes. */ +G_DEFINE_TYPE(GBufferSegment, g_buffer_segment, G_TYPE_OBJECT); + + + +/****************************************************************************** +* * +* Paramètres : class = classe de composant GTK à initialiser. * +* * +* Description : Procède à l'initialisation d'une classe de fragment de texte.* +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_buffer_segment_class_init(GBufferSegmentClass *class) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : segment = composant GTK à initialiser. * +* * +* Description : Procède à l'initialisation d'un fragment de texte. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_buffer_segment_init(GBufferSegment *segment) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : context = contexte Pango pour l'analyse des caractères. * +* attribs = propriétés de la zone de texte. * +* text = chaîne de caractères à traiter. * +* length = quantité de ces caractères. * +* * +* Description : Crée un nouveau fragment de texte avec des propriétés. * +* * +* Retour : Composant GTK créé. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBufferSegment *g_buffer_segment_new(PangoContext *context, PangoAttrList *attribs, const char *text, size_t length) +{ + GBufferSegment *result; /* Composant à retourner */ + + result = g_object_new(G_TYPE_BUFFER_SEGMENT, NULL); + //result = g_new(GBufferSegment, 1); + + g_buffer_segment_prepare(result, context, attribs, text, length); + + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : segment = fragment de texte à consulter. * +* * +* Description : Fournit la quantité de pixels requise pour l'impression. * +* * +* Retour : Largeur requise par la colonne, en pixel. * +* * +* Remarques : - * +* * +******************************************************************************/ + +gint g_buffer_segment_get_width(const GBufferSegment *segment) +{ + return segment->logical.width; + +} + + +/****************************************************************************** +* * +* Paramètres : segment = fragment de texte à manipuler. * +* drawable = surface de rendu où travailler. * +* gc = contexte graphique à utiliser pour les pinceaux. * +* x = abscisse du point d'impression (à maj). [OUT] * +* y = ordonnée du point d'impression. * +* * +* Description : Imprime le fragment de texte représenté. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_buffer_segment_draw(GBufferSegment *segment, GdkDrawable *drawable, GdkGC *gc, gint *x, gint y) +{ + gdk_draw_glyphs(drawable, gc, G_BUFFER_SEGMENT_GET_CLASS(segment)->ascii_font, + *x, y - segment->logical.y, segment->glyphs); + + *x += segment->logical.width; + +} diff --git a/src/glibext/gbuffersegment.h b/src/glibext/gbuffersegment.h new file mode 100644 index 0000000..28338b9 --- /dev/null +++ b/src/glibext/gbuffersegment.h @@ -0,0 +1,65 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * gbuffersegment.h - prototypes pour la concentration d'un fragment de caractères aux propriétés communes + * + * 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/>. + */ + + +#ifndef _GLIBEXT_GBUFFERSEGMENT_H +#define _GLIBEXT_GBUFFERSEGMENT_H + + +#include <glib-object.h> +#include <gdk/gdk.h> +#include <pango/pango.h> + + + +#define G_TYPE_BUFFER_SEGMENT (g_buffer_segment_get_type()) +#define G_BUFFER_SEGMENT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_BUFFER_SEGMENT, GBufferSegment)) +#define G_BUFFER_SEGMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_BUFFER_SEGMENT, GBufferSegmentClass)) +#define G_IS_BUFFER_SEGMENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_BUFFER_SEGMENT)) +#define G_IS_BUFFER_SEGMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_BUFFER_SEGMENT)) +#define G_BUFFER_SEGMENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_BUFFER_SEGMENT, GBufferSegmentClass)) + + + +/* Fragment de caractères aux propriétés communes (instance) */ +typedef struct _GBufferSegment GBufferSegment; + +/* Fragment de caractères aux propriétés communes (classe) */ +typedef struct _GBufferSegmentClass GBufferSegmentClass; + + + +/* Détermine le type du fragment de caractères aux propriétés communes. */ +GType g_buffer_segment_get_type(void); + +/* Crée un nouveau fragment de texte avec des propriétés. */ +GBufferSegment *g_buffer_segment_new(PangoContext *, PangoAttrList *, const char *, size_t); + +/* Fournit la quantité de pixels requise pour l'impression. */ +gint g_buffer_segment_get_width(const GBufferSegment *); + +/* Imprime le fragment de texte représenté. */ +void g_buffer_segment_draw(GBufferSegment *, GdkDrawable *, GdkGC *, gint *, gint); + + + +#endif /* _GLIBEXT_GBUFFERSEGMENT_H */ 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; + + } + +} diff --git a/src/glibext/gcodebuffer.h b/src/glibext/gcodebuffer.h new file mode 100644 index 0000000..9460530 --- /dev/null +++ b/src/glibext/gcodebuffer.h @@ -0,0 +1,102 @@ + +/* 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/>. + */ + + +#ifndef _GLIBEXT_GCODEBUFFER_H +#define _GLIBEXT_GCODEBUFFER_H + + +#include <glib-object.h> + + +#include "gbufferline.h" + + + +/* -------------------------- TAMPON POUR CODE DESASSEMBLE -------------------------- */ + + +#define G_TYPE_CODE_BUFFER (g_code_buffer_get_type()) +#define G_CODE_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_CODE_BUFFER, GCodeBuffer)) +#define G_CODE_BUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_CODE_BUFFER, GCodeBufferClass)) +#define G_IS_CODE_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_CODE_BUFFER)) +#define G_IS_CODE_BUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_CODE_BUFFER)) +#define G_CODE_BUFFER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_CODE_BUFFER, GCodeBufferClass)) + + +/* Tampon pour code désassemblé (instance) */ +typedef struct _GCodeBuffer GCodeBuffer; + +/* Tampon pour code désassemblé (classe) */ +typedef struct _GCodeBufferClass GCodeBufferClass; + + +/* Détermine le type du composant de tampon pour code désassemblé. */ +GType g_code_buffer_get_type(void); + +/* Crée un nouveau composant de tampon pour code désassemblé. */ +GCodeBuffer *g_code_buffer_new(void); + +/* Ajoute une nouvelle ligne à un tampon pour code désassemblé. */ +GBufferLine *g_code_buffer_append_new_line(GCodeBuffer *); + + + +/* ---------------------- VUE PARTICULIERE D'UN TAMPON DE CODE ---------------------- */ + + +#define G_TYPE_BUFFER_VIEW (g_buffer_view_get_type()) +#define G_BUFFER_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_BUFFER_VIEW, GBufferView)) +#define G_BUFFER_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_BUFFER_VIEW, GBufferViewClass)) +#define G_IS_BUFFER_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_BUFFER_VIEW)) +#define G_IS_BUFFER_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_BUFFER_VIEW)) +#define G_BUFFER_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_BUFFER_VIEW, GBufferViewClass)) + + +/* Vue d'un tampon pour code désassemblé (instance) */ +typedef struct _GBufferView GBufferView; + +/* Vue d'un tampon pour code désassemblé (classe) */ +typedef struct _GBufferViewClass GBufferViewClass; + + +/* Détermine le type de la vue d'un tampon pour code désassemblé. */ +GType g_buffer_view_get_type(void); + +/* Crée une nouvelle vue d'un tampon pour code désassemblé. */ +GBufferView *g_buffer_view_new(GCodeBuffer *); + +/* Fournit la hauteur d'impression d'une ligne visualisée. */ +gint g_buffer_view_get_line_height(GBufferView *); + +/* Fournit les dimensions requises par une visualisation. */ +void g_buffer_view_get_size(GBufferView *, gint *, gint *); + +/* Définit à une procédure à appeler lors des dessins de ligne. */ +void g_buffer_view_define_extra_drawing(GBufferView *, buffer_line_draw_fc, void *); + +/* Imprime la visualisation du tempon de code désassemblé. */ +void g_buffer_view_draw(const GBufferView *, const GdkEventExpose *, GdkGC *, gint, gint); + + + +#endif /* _GLIBEXT_GCODEBUFFER_H */ |