diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2015-12-28 23:27:12 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2015-12-28 23:27:12 (GMT) |
commit | b57e8ef5522dcbe126157fc2c50fcf879aa7d743 (patch) | |
tree | 1ecfd9de39073fee3a2c1a4afa9ce5da574b26df /src/glibext | |
parent | 276b75e6e9ff99a930bd36045e55b1117bb29579 (diff) |
Defined layers to register all kinds of binary portions.
Diffstat (limited to 'src/glibext')
-rw-r--r-- | src/glibext/gbinportion.c | 904 | ||||
-rw-r--r-- | src/glibext/gbinportion.h | 81 |
2 files changed, 662 insertions, 323 deletions
diff --git a/src/glibext/gbinportion.c b/src/glibext/gbinportion.c index 920fcfe..790614a 100644 --- a/src/glibext/gbinportion.c +++ b/src/glibext/gbinportion.c @@ -24,6 +24,7 @@ #include "gbinportion.h" +#include <assert.h> #include <malloc.h> #include <stdlib.h> #include <string.h> @@ -44,27 +45,16 @@ struct _GBinPortion { GObject parent; /* A laisser en premier */ - unsigned int level; /* Profondeur de la portion */ - GBinPortion *container; /* Portion parente ou racine */ + const unsigned int *level; /* Profondeur de la portion */ char *code; /* Code de la couleur de fond */ char *desc; /* Désignation humaine */ mrange_t range; /* Emplacement dans le code */ - vmpa2t addr; /* Emplacement dans le code */ /* TODO : clean */ - off_t size; /* Taille de la partie */ /* TODO : clean */ PortionAccessRights rights; /* Droits d'accès */ - GBinPortion **sub_portions; /* Portions incluses */ - size_t sub_count; /* Quantité d'inclusions */ - -#ifdef DEBUG - unsigned int valid; /* Instructions reconnues */ - unsigned int db; /* Instructions non traduites */ -#endif - }; /* Portion de données binaires quelconques (classe) */ @@ -75,10 +65,10 @@ struct _GBinPortionClass }; -/* Initialise la classe des blocs de données binaires. */ +/* Initialise la classe des portions de données binaires. */ static void g_binary_portion_class_init(GBinPortionClass *); -/* Initialise une instance de bloc de données binaires. */ +/* Initialise une instance de portion de données binaires. */ static void g_binary_portion_init(GBinPortion *); /* Supprime toutes les références externes. */ @@ -88,10 +78,57 @@ static void g_binary_portion_dispose(GBinPortion *); static void g_binary_portion_finalize(GBinPortion *); /* Définit le niveau de profondeur pour une branche de portions. */ -static void g_binary_portion_set_level(GBinPortion *, unsigned int); +static void g_binary_portion_set_level(GBinPortion *, const unsigned int *); /* Détermine l'aire d'une sous-portion. */ -static bool g_binary_portion_compute_sub_area(GBinPortion *, GBinPortion *, const GdkRectangle *, GdkRectangle *); +static bool g_binary_portion_compute_sub_area(const GBinPortion *, phys_t, const GdkRectangle *, GdkRectangle *); + +/* Détermine si une portion contient une adresse donnée. */ +static bool g_portion_layer_contains_addr(const GBinPortion *, const vmpa2t *); + + + +/* -------------------------- COUCHES DE PORTIONS BINAIRES -------------------------- */ + + +/* Couche de portions binaires quelconques (instance) */ +struct _GPortionLayer +{ + GObject parent; /* A laisser en premier */ + + phys_t length; /* Taille de portion globale */ + const char *name; /* Désignation de la couche */ + + unsigned int level; /* Profondeur de la portion */ + + GPortionLayer *sub_layer; /* Eventuelle couche inférieure*/ + + GBinPortion **portions; /* Portions incluses */ + size_t count; /* Quantité d'inclusions */ + +}; + +/* Couche de portions binaires quelconques (classe) */ +struct _GPortionLayerClass +{ + GObjectClass parent; /* A laisser en premier */ + +}; + + +/* Initialise la classe des couches de portions binaires. */ +static void g_portion_layer_class_init(GPortionLayerClass *); + +/* Initialise une instance de couche de portions binaires. */ +static void g_portion_layer_init(GPortionLayer *); + +/* Supprime toutes les références externes. */ +static void g_portion_layer_dispose(GPortionLayer *); + +/* Procède à la libération totale de la mémoire. */ +static void g_portion_layer_finalize(GPortionLayer *); + + @@ -100,7 +137,7 @@ static bool g_binary_portion_compute_sub_area(GBinPortion *, GBinPortion *, cons /* ---------------------------------------------------------------------------------- */ -/* Indique le type défini par la GLib pour les blocs de données. */ +/* Indique le type défini par la GLib pour les portions de données binaires. */ G_DEFINE_TYPE(GBinPortion, g_binary_portion, G_TYPE_OBJECT); @@ -108,7 +145,7 @@ G_DEFINE_TYPE(GBinPortion, g_binary_portion, G_TYPE_OBJECT); * * * Paramètres : klass = classe à initialiser. * * * -* Description : Initialise la classe des blocs de données binaires. * +* Description : Initialise la classe des portions de données binaires. * * * * Retour : - * * * @@ -133,7 +170,7 @@ static void g_binary_portion_class_init(GBinPortionClass *klass) * * * Paramètres : portion = instance à initialiser. * * * -* Description : Initialise une instance de bloc de données binaires. * +* Description : Initialise une instance de portion de données binaires. * * * * Retour : - * * * @@ -143,7 +180,7 @@ static void g_binary_portion_class_init(GBinPortionClass *klass) static void g_binary_portion_init(GBinPortion *portion) { - portion->level = 0; + portion->level = NULL; } @@ -162,11 +199,6 @@ static void g_binary_portion_init(GBinPortion *portion) static void g_binary_portion_dispose(GBinPortion *portion) { - size_t i; /* Boucle de parcours */ - - for (i = 0; i < portion->sub_count; i++) - g_object_unref(G_OBJECT(portion->sub_portions[i])); - G_OBJECT_CLASS(g_binary_portion_parent_class)->dispose(G_OBJECT(portion)); } @@ -191,9 +223,6 @@ static void g_binary_portion_finalize(GBinPortion *portion) if (portion->desc != NULL) free(portion->desc); - if (portion->sub_portions != NULL) - free(portion->sub_portions); - G_OBJECT_CLASS(g_binary_portion_parent_class)->finalize(G_OBJECT(portion)); } @@ -205,7 +234,7 @@ static void g_binary_portion_finalize(GBinPortion *portion) * * * Description : Crée une description de partie de code vierge. * * * -* Retour : - * +* Retour : Instance mise en place. * * * * Remarques : - * * * @@ -226,6 +255,26 @@ GBinPortion *g_binary_portion_new(const char *code) /****************************************************************************** * * +* Paramètres : portion = description de partie à mettre à jour. * +* level = niveau de profondeur à associer. * +* * +* Description : Définit le niveau de profondeur pour une branche de portions.* +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_binary_portion_set_level(GBinPortion *portion, const unsigned int *level) +{ + portion->level = level; + +} + + +/****************************************************************************** +* * * Paramètres : a = premières informations à consulter. * * b = secondes informations à consulter. * * * @@ -240,15 +289,32 @@ GBinPortion *g_binary_portion_new(const char *code) int g_binary_portion_compare(const GBinPortion **a, const GBinPortion **b) { int result; /* Bilan à retourner */ + const vmpa2t *addr_a; /* Adresse de la portion 'a' */ + const vmpa2t *addr_b; /* Adresse de la portion 'b' */ + const unsigned int *level_a; /* Niveau de la portion 'a' */ + const unsigned int *level_b; /* Niveau de la portion 'b' */ - if ((*a)->level < (*b)->level) - result = -1; + addr_a = get_mrange_addr(&(*a)->range); + addr_b = get_mrange_addr(&(*b)->range); - else if ((*a)->level > (*b)->level) - result = 1; + result = cmp_vmpa(addr_a, addr_b); - else - result = cmp_mrange(&(*a)->range, &(*b)->range); + if (result == 0) + { + level_a = (*a)->level; + level_b = (*b)->level; + + if (level_a != NULL && level_b != NULL) + { + if (*level_a < *level_b) + result = -1; + + else if (*level_a > *level_b) + result = 1; + + } + + } return result; @@ -312,9 +378,6 @@ const char *g_binary_portion_get_desc(const GBinPortion *portion) void g_binary_portion_set_values(GBinPortion *portion, const vmpa2t *addr, phys_t size) { - copy_vmpa(&portion->addr, addr); - portion->size = size; - init_mrange(&portion->range, addr, size); } @@ -380,10 +443,81 @@ PortionAccessRights g_binary_portion_get_rights(const GBinPortion *portion) /****************************************************************************** * * -* Paramètres : portion = description de partie à mettre à jour. * -* sub = portion à inclure dans la définition courante. * +* Paramètres : portion = portion mère à consulter. * +* full = taille totale de la couche parente. * +* area = étendue de représentation de la portion mère. * +* sub_area = étendue de représentation de la portion fille. * +* * +* Description : Détermine l'aire d'une sous-portion. * * * -* Description : Procède à l'inclusion d'une portion dans une autre. * +* Retour : true si la sous-surface a été calculée correctement. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_binary_portion_compute_sub_area(const GBinPortion *portion, phys_t full, const GdkRectangle *area, GdkRectangle *sub_area) +{ + phys_t length; /* Taille de la portion */ + phys_t start; /* Position de départ */ + + length = get_mrange_length(&portion->range); + + /* On saute les portions comme le segment GNU_STACK... */ + if (length == 0) return false; + + start = get_phy_addr(get_mrange_addr(&portion->range)); + + sub_area->y = area->y; + sub_area->height = area->height; + + sub_area->x = area->x + (start * area->width) / full; + sub_area->width = (length * area->width) / full; + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : portion = portion mère à consulter. * +* addr = adresse du point de recherche. * +* * +* Description : Détermine si une portion contient une adresse donnée. * +* * +* Retour : true ou false selon le résultat. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_portion_layer_contains_addr(const GBinPortion *portion, const vmpa2t *addr) +{ + bool result; /* Bilan à retourner */ + + result = false; + + /* Portion non allouée en mémoire -> adresse nulle ; on écarte */ + if (get_virt_addr(get_mrange_addr(&portion->range)) == 0) + goto not_found; + + result = mrange_contains_addr(&portion->range, addr); + + not_found: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : portion = description de partie à consulter. * +* buffer = espace où placer ledit contenu. * +* msize = taille idéale des positions et adresses; * +* * +* Description : Insère dans un tampon une description de portion. * * * * Retour : - * * * @@ -391,14 +525,68 @@ PortionAccessRights g_binary_portion_get_rights(const GBinPortion *portion) * * ******************************************************************************/ -void g_binary_portion_include(GBinPortion *portion, GBinPortion *sub) +void g_binary_portion_print(const GBinPortion *portion, GCodeBuffer *buffer, MemoryDataSize msize) { - portion->sub_portions = (GBinPortion **)realloc(portion->sub_portions, - ++portion->sub_count * sizeof(GBinPortion *)); + mrange_t range; /* Couverture à fournir */ + GBufferLine *line; /* Nouvelle ligne à éditer */ + char rights[64]; /* Traduction en texte */ + + /* On ne traite pas les portions anonymes ! */ + if (portion->desc == NULL) return; + + init_mrange(&range, get_mrange_addr(&portion->range), 0); + + line = g_code_buffer_append_new_line(buffer, &range); + g_buffer_line_fill_mrange(line, msize, msize); + + g_buffer_line_add_flag(line, BLF_WIDTH_MANAGER); + + /* Séparation */ + + line = g_code_buffer_append_new_line(buffer, &range); + g_buffer_line_fill_mrange(line, msize, msize); + + g_buffer_line_start_merge_at(line, BLC_ASSEMBLY_HEAD); + g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, + "; ======================================================", 56, RTT_COMMENT); - portion->sub_portions[portion->sub_count - 1] = sub; + /* Retour à la ligne */ + + line = g_code_buffer_append_new_line(buffer, &range); + g_buffer_line_fill_mrange(line, msize, msize); + + g_buffer_line_start_merge_at(line, BLC_ASSEMBLY_HEAD); + g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "; ", 2, RTT_COMMENT); + + /* Description */ + + line = g_code_buffer_append_new_line(buffer, &range); + g_buffer_line_fill_mrange(line, msize, msize); + + g_buffer_line_start_merge_at(line, BLC_ASSEMBLY_HEAD); + + g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "; ", 2, RTT_COMMENT); + + g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, portion->desc, strlen(portion->desc), RTT_COMMENT); - g_binary_portion_set_level(sub, portion->level + 1); + snprintf(rights, sizeof(rights), " (%s%s%s%s)", + _("rights: "), + portion->rights & PAC_READ ? "r" : "-", + portion->rights & PAC_WRITE ? "w" : "-", + portion->rights & PAC_EXEC ? "x" : "-"); + + g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, rights, strlen(rights), RTT_COMMENT); + + /* Retour à la ligne */ + + line = g_code_buffer_append_new_line(buffer, &range); + g_buffer_line_fill_mrange(line, msize, msize); + + g_buffer_line_start_merge_at(line, BLC_ASSEMBLY_HEAD); + g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "; ", 2, RTT_COMMENT); + + line = g_code_buffer_append_new_line(buffer, &range); + g_buffer_line_fill_mrange(line, msize, msize); } @@ -406,9 +594,9 @@ void g_binary_portion_include(GBinPortion *portion, GBinPortion *sub) /****************************************************************************** * * * Paramètres : portion = description de partie à mettre à jour. * -* level = niveau de profondeur à associer. * +* tooltip = astuce à compléter. [OUT] * * * -* Description : Définit le niveau de profondeur pour une branche de portions.* +* Description : Prépare une astuce concernant une portion pour son affichage.* * * * Retour : - * * * @@ -416,91 +604,231 @@ void g_binary_portion_include(GBinPortion *portion, GBinPortion *sub) * * ******************************************************************************/ -static void g_binary_portion_set_level(GBinPortion *portion, unsigned int level) +void g_binary_portion_query_tooltip(GBinPortion *portion, GtkTooltip *tooltip) { - size_t i; /* Boucle de parcours */ + char *markup; /* Description à construire */ + VMPA_BUFFER(value); /* Traduction en texte */ - portion->level = level; + /* Nom */ + + if (portion->desc != NULL) + { + markup = strdup("<b>"); + markup = stradd(markup, portion->desc); + markup = stradd(markup, "</b>\n"); + markup = stradd(markup, "\n"); + + } + else markup = strdup(""); + + markup = stradd(markup, "taille : "); + mrange_length_to_string(&portion->range, MDS_UNDEFINED, value, NULL); + markup = stradd(markup, value); + markup = stradd(markup, "\n"); + + /* Localisation */ + + markup = stradd(markup, "<b>"); + markup = stradd(markup, _("Localisation")); + markup = stradd(markup, "</b>\n"); + + markup = stradd(markup, _("physical: from ")); + + mrange_phys_to_string(&portion->range, MDS_UNDEFINED, true, value, NULL); + markup = stradd(markup, value); + markup = stradd(markup, _(" to ")); + mrange_phys_to_string(&portion->range, MDS_UNDEFINED, false, value, NULL); + markup = stradd(markup, value); + markup = stradd(markup, "\n"); + + markup = stradd(markup, _("memory: from ")); - for (i = 0; i < portion->sub_count; i++) - g_binary_portion_set_level(portion->sub_portions[i], level + 1); + mrange_virt_to_string(&portion->range, MDS_UNDEFINED, true, value, NULL); + markup = stradd(markup, value); + markup = stradd(markup, _(" to ")); + mrange_virt_to_string(&portion->range, MDS_UNDEFINED, false, value, NULL); + markup = stradd(markup, value); + + markup = stradd(markup, "\n\n"); + + /* Droits d'accès */ + + markup = stradd(markup, "<b>"); + markup = stradd(markup, _("Rights")); + markup = stradd(markup, "</b>\n"); + + snprintf(value, 2 * VMPA_MAX_SIZE, "%s%s%s", + portion->rights & PAC_READ ? "r" : "-", + portion->rights & PAC_WRITE ? "w" : "-", + portion->rights & PAC_EXEC ? "x" : "-"); + + markup = stradd(markup, value); + + /* Impression finale */ + + gtk_tooltip_set_markup(tooltip, markup); + free(markup); } /****************************************************************************** * * -* Paramètres : portion = description de partie à mettre à jour. * +* Paramètres : portion = description de partie à consulter. * +* cr = contexte graphique pour le dessin. * +* area = étendue mise à disposition. * * * -* Description : Indique le niveau de profondeur d'une portion donnée. * +* Description : Représente la portion sur une bande dédiée. * * * -* Retour : Niveau de profondeur positif ou nul. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -unsigned int g_binary_portion_get_level(GBinPortion *portion) +void g_binary_portion_draw(const GBinPortion *portion, GtkStyleContext *context, cairo_t *cr, const GdkRectangle *area) { - return portion->level; + //cairo_set_line_width(cr, 1.0); + + cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE); + + gtk_style_context_save(context); + + gtk_style_context_add_class(context, portion->code); + + gtk_render_background(context, cr, area->x, area->y, area->width, area->height); + + gtk_render_frame(context, cr, area->x, area->y, area->width, area->height); + + gtk_style_context_restore(context); } + +/* ---------------------------------------------------------------------------------- */ +/* COUCHES DE PORTIONS BINAIRES */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini par la GLib pour les couches de portions binaires. */ +G_DEFINE_TYPE(GPortionLayer, g_portion_layer, G_TYPE_OBJECT); + + /****************************************************************************** * * -* Paramètres : portion = portion mère à consulter. * -* sub = portion fille à traiter. * -* area = étendue de représentation de la portion mère. * -* sub_area = étendue de représentation de la portion fille. * +* Paramètres : klass = classe à initialiser. * * * -* Description : Détermine l'aire d'une sous-portion. * +* Description : Initialise la classe des couches de portions binaires. * * * -* Retour : true si la sous-surface a été calculée correctement. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -static bool g_binary_portion_compute_sub_area(GBinPortion *portion, GBinPortion *sub, const GdkRectangle *area, GdkRectangle *sub_area) +static void g_portion_layer_class_init(GPortionLayerClass *klass) { - /* On saute les portions comme le segment GNU_STACK... */ - if (sub->size == 0) return false; + GObjectClass *object; /* Autre version de la classe */ - sub_area->y = area->y; - sub_area->height = area->height; + object = G_OBJECT_CLASS(klass); - sub_area->x = area->x + (get_phy_addr(&sub->addr) * area->width) / portion->size; - sub_area->width = (sub->size * area->width) / portion->size; + object->dispose = (GObjectFinalizeFunc/* ! */)g_portion_layer_dispose; + object->finalize = (GObjectFinalizeFunc)g_portion_layer_finalize; - return true; } /****************************************************************************** * * -* Paramètres : portion = première portion amorçant la visite. * -* visitor = fonction à appeler à chaque étape de la descente. * -* data = adresse pointant vers des données de l'utilisateur.* +* Paramètres : layer = instance à initialiser. * * * -* Description : Parcours un ensemble de portions binaires. * +* Description : Initialise une instance de couche de portions binaires. * * * -* Retour : true si la visite a été jusqu'à son terme, false sinon. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -bool g_binary_portion_visit(GBinPortion *portion, visit_portion_fc visitor, void *data) +static void g_portion_layer_init(GPortionLayer *layer) +{ + layer->level = 0; + +} + + +/****************************************************************************** +* * +* Paramètres : layer = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_portion_layer_dispose(GPortionLayer *layer) { - bool result; /* Etat à retourner */ size_t i; /* Boucle de parcours */ - result = visitor(portion, data); + if (layer->sub_layer != NULL) + g_object_unref(G_OBJECT(layer->sub_layer)); + + for (i = 0; i < layer->count; i++) + g_object_unref(G_OBJECT(layer->portions[i])); + + G_OBJECT_CLASS(g_portion_layer_parent_class)->dispose(G_OBJECT(layer)); + +} + + +/****************************************************************************** +* * +* Paramètres : layer = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_portion_layer_finalize(GPortionLayer *layer) +{ + if (layer->portions != NULL) + free(layer->portions); + + G_OBJECT_CLASS(g_portion_layer_parent_class)->finalize(G_OBJECT(layer)); + +} + + +/****************************************************************************** +* * +* Paramètres : length = +* name = désignation pouvant servir de suffixe aux portions. * +* * +* Description : Crée une nouvelle couche de portions binaires. * +* * +* Retour : Instance mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GPortionLayer *g_portion_layer_new(phys_t length, const char *name) +{ + GPortionLayer *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_BIN_PORTION, NULL); - for (i = 0; i < portion->sub_count && result; i++) - result = g_binary_portion_visit(portion->sub_portions[i], visitor, data); + result->length = length; + result->name = name; return result; @@ -509,10 +837,127 @@ bool g_binary_portion_visit(GBinPortion *portion, visit_portion_fc visitor, void /****************************************************************************** * * -* Paramètres : portion = description de partie à mettre à jour. * -* x = abscisse du point de recherche. * -* y = ordonnée du point de recherche. * -* area = étendue de portion mère, puis celle trouvée. [OUT] * +* Paramètres : layer = couche rassemblant des portions à modifier. * +* Paramètres : sub = couche inférieure à rattacher à la couche courante. * +* * +* Description : Attache une couche à une autre en tant que couche inférieure.* +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_portion_layer_attach_sub(GPortionLayer *layer, GPortionLayer *sub) +{ + void set_layers_length(GPortionLayer *parent, GPortionLayer *child) + { + if (child->length == NO_LENGTH_YET) + { + assert(parent->length != NO_LENGTH_YET); + + child->length = parent->length; + + if (child->sub_layer != NULL) + set_layers_length(child, child->sub_layer); + + } + + } + + void set_layers_depth(GPortionLayer *parent, GPortionLayer *child) + { + child->level = parent->level + 1; + + if (child->sub_layer != NULL) + set_layers_length(child, child->sub_layer); + + } + + set_layers_length(layer, sub); + + set_layers_depth(layer, sub); + + layer->sub_layer = sub; + +} + + +/****************************************************************************** +* * +* Paramètres : layer = couche rassemblant les portions d'un même niveau. * +* portion = portion à inclure dans la définition courante. * +* * +* Description : Procède à l'inclusion d'une portion dans une couche. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_portion_layer_include(GPortionLayer *layer, GBinPortion *portion) +{ + layer->portions = (GBinPortion **)realloc(layer->portions, + ++layer->count * sizeof(GBinPortion *)); + + layer->portions[layer->count - 1] = portion; + + g_binary_portion_set_level(portion, &layer->level); + + qsort(layer->portions, layer->count, sizeof(GBinPortion *), (__compar_fn_t)g_binary_portion_compare); + +} + + +/****************************************************************************** +* * +* Paramètres : layer = couche première à parcourir intégralement. * +* count = nombre de portions trouvées et renvoyées. [OUT] * +* * +* Description : Fournit une liste triée de portions d'un binaire. * +* * +* Retour : Liste de définitions de zones à libérer après usage. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBinPortion **g_portion_layer_collect_all_portions(const GPortionLayer *layer, size_t *count) +{ + GBinPortion **result; /* Liste construite à renvoyer */ + + GBinPortion **do_collect(const GPortionLayer *l, GBinPortion **lst, size_t *c) + { + size_t start; /* Indice de départ des ajouts */ + size_t i; /* Boucle de parcours */ + + start = *c; + *c += l->count; + + lst = (GBinPortion **)realloc(lst, *c * sizeof(GBinPortion *)); + + for (i = 0; i < l->count; i++) + lst[start + i] = l->portions[i]; + + return lst; + + } + + result = do_collect(layer, NULL, count); + + qsort(result, *count, sizeof(GBinPortion *), (__compar_fn_t)g_binary_portion_compare); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : layer = couche de portions à parcourir pour les recherches. * +* x = abscisse du point de recherche. * +* area = étendue de portion mère, puis celle trouvée. [OUT] * * * * Description : Recherche la portion présente à un point donné. * * * @@ -522,20 +967,23 @@ bool g_binary_portion_visit(GBinPortion *portion, visit_portion_fc visitor, void * * ******************************************************************************/ -GBinPortion *g_binary_portion_find_at_pos(GBinPortion *portion, gint x, GdkRectangle *area) +GBinPortion *g_portion_layer_find_portion_at_pos(const GPortionLayer *layer, gint x, GdkRectangle *area) { GBinPortion *result; /* Portion à retourner */ size_t i; /* Boucle de parcours */ GBinPortion *sub; /* Portion incluse à traiter */ GdkRectangle sub_area; /* Etendue d'une sous-portion */ - result = NULL; + if (layer->sub_layer != NULL) + result = g_portion_layer_find_portion_at_pos(layer->sub_layer, x, area); + else + result = NULL; - for (i = 0; i < portion->sub_count && !result; i++) + for (i = 0; i < layer->count && result == NULL; i++) { - sub = portion->sub_portions[i]; + sub = layer->portions[i]; - if (!g_binary_portion_compute_sub_area(portion, sub, area, &sub_area)) + if (!g_binary_portion_compute_sub_area(sub, layer->length, area, &sub_area)) continue; if (sub_area.x <= x && x < (sub_area.x + sub_area.width)) @@ -546,9 +994,6 @@ GBinPortion *g_binary_portion_find_at_pos(GBinPortion *portion, gint x, GdkRecta } - if (result == NULL) - result = portion; - return result; } @@ -556,9 +1001,9 @@ GBinPortion *g_binary_portion_find_at_pos(GBinPortion *portion, gint x, GdkRecta /****************************************************************************** * * -* Paramètres : portion = description de partie à mettre à jour. * -* addr = adresse du point de recherche. * -* area = étendue de portion mère, puis celle trouvée. [OUT] * +* Paramètres : layer = couche de portions à parcourir pour les recherches. * +* addr = adresse du point de recherche. * +* area = étendue de portion mère, puis celle trouvée. [OUT] * * * * Description : Recherche la portion présente à une adresse donnée. * * * @@ -568,47 +1013,33 @@ GBinPortion *g_binary_portion_find_at_pos(GBinPortion *portion, gint x, GdkRecta * * ******************************************************************************/ -GBinPortion *g_binary_portion_find_at_addr(GBinPortion *portion, const vmpa2t *addr, GdkRectangle *area) +GBinPortion *g_portion_layer_find_portion_at_addr(const GPortionLayer *layer, const vmpa2t *addr, GdkRectangle *area) { GBinPortion *result; /* Portion à retourner */ size_t i; /* Boucle de parcours #1 */ GBinPortion *sub; /* Portion incluse à traiter */ GdkRectangle sub_area; /* Etendue d'une sous-portion */ - size_t j; /* Boucle de parcours #2 */ - result = NULL; + if (layer->sub_layer != NULL) + result = g_portion_layer_find_portion_at_addr(layer->sub_layer, addr, area); + else + result = NULL; - for (i = 0; i < portion->sub_count && result == NULL; i++) + for (i = 0; i < layer->count && result == NULL; i++) { - sub = portion->sub_portions[i]; - - /* FIXME : cmp ? */ + sub = layer->portions[i]; - /* Portion non allouée en mémoire -> adresse nulle ; on écarte */ - if (get_virt_addr(&sub->addr) == 0) + if (!g_portion_layer_contains_addr(sub, addr)) continue; - if (get_virt_addr(addr) < get_virt_addr(&sub->addr) - || get_virt_addr(addr) >= (get_virt_addr(&sub->addr) + sub->size)) + if (!g_binary_portion_compute_sub_area(sub, layer->length, area, &sub_area)) continue; - if (!g_binary_portion_compute_sub_area(portion, sub, area, &sub_area)) - continue; - - for (j = 0; j < sub->sub_count && !result; j++) - result = g_binary_portion_find_at_addr(sub->sub_portions[j], addr, &sub_area); - - if (result == NULL) - { - result = sub; - *area = sub_area; - } + result = sub; + *area = sub_area; } - if (result == NULL) - result = portion; - return result; } @@ -616,10 +1047,10 @@ GBinPortion *g_binary_portion_find_at_addr(GBinPortion *portion, const vmpa2t *a /****************************************************************************** * * -* Paramètres : portion = description de partie à mettre à jour. * -* x = abscisse du point de recherche. * -* area = étendue de représentation de la portion mère. * -* addr = adresse correspondante. [OUT] * +* Paramètres : layer = couche de portions à parcourir pour les recherches. * +* x = abscisse du point de recherche. * +* area = étendue de représentation de la portion mère. * +* addr = adresse correspondante. [OUT] * * * * Description : Fournit la position correspondant à une adresse donnée. * * * @@ -629,19 +1060,19 @@ GBinPortion *g_binary_portion_find_at_addr(GBinPortion *portion, const vmpa2t *a * * ******************************************************************************/ -bool g_binary_portion_get_addr_from_pos(GBinPortion *portion, gint x, const GdkRectangle *area, vmpa2t *addr) +bool g_portion_layer_get_addr_from_pos(GPortionLayer *layer, gint x, const GdkRectangle *area, vmpa2t *addr) { GdkRectangle owner_area; /* Aire de contenance */ GBinPortion *owner; /* Conteneur propriétaire */ owner_area = *area; - owner = g_binary_portion_find_at_pos(portion, x, &owner_area); + owner = g_portion_layer_find_portion_at_pos(layer, x, &owner_area); if (owner == NULL) return false; - copy_vmpa(addr, &owner->addr); + copy_vmpa(addr, get_mrange_addr(&owner->range)); - advance_vmpa(addr, (owner->size * (x - owner_area.x)) / owner_area.width); + advance_vmpa(addr, (get_mrange_length(&owner->range) * (x - owner_area.x)) / owner_area.width); return true; @@ -650,10 +1081,10 @@ bool g_binary_portion_get_addr_from_pos(GBinPortion *portion, gint x, const GdkR /****************************************************************************** * * -* Paramètres : portion = description de partie à mettre à jour. * -* addr = adresse du point de recherche. * -* area = étendue de représentation de la portion mère. * -* x = position correspondante. [OUT] * +* Paramètres : layer = couche de portions à parcourir pour les recherches. * +* addr = adresse du point de recherche. * +* area = étendue de représentation de la portion mère. * +* x = position correspondante. [OUT] * * * * Description : Fournit l'adresse correspondant à une position donnée. * * * @@ -663,20 +1094,20 @@ bool g_binary_portion_get_addr_from_pos(GBinPortion *portion, gint x, const GdkR * * ******************************************************************************/ -bool g_binary_portion_get_pos_from_addr(GBinPortion *portion, const vmpa2t *addr, const GdkRectangle *area, gint *x) +bool g_portion_layer_get_pos_from_addr(GPortionLayer *layer, const vmpa2t *addr, const GdkRectangle *area, gint *x) { GdkRectangle owner_area; /* Aire de contenance */ GBinPortion *owner; /* Conteneur propriétaire */ - off_t diff; /* Décallage à appliquer */ + phys_t diff; /* Décallage à appliquer */ owner_area = *area; - owner = g_binary_portion_find_at_addr(portion, addr, &owner_area); + owner = g_portion_layer_find_portion_at_addr(layer, addr, &owner_area); if (owner == NULL) return false; - diff = compute_vmpa_diff(addr, &owner->addr); + diff = compute_vmpa_diff(addr, get_mrange_addr(&owner->range)); - *x = owner_area.x + (diff * owner_area.width) / owner->size; + *x = owner_area.x + (diff * owner_area.width) / get_mrange_length(&owner->range); return true; @@ -685,87 +1116,39 @@ bool g_binary_portion_get_pos_from_addr(GBinPortion *portion, const vmpa2t *addr /****************************************************************************** * * -* Paramètres : portion = description de partie à consulter. * -* buffer = espace où placer ledit contenu. * -* msize = taille idéale des positions et adresses; * +* Paramètres : layer = première couche amorçant la visite. * +* visitor = fonction à appeler à chaque étape de la descente. * +* data = adresse pointant vers des données de l'utilisateur.* * * -* Description : Insère dans un tampon une description de portion. * +* Description : Parcours un ensemble de portions binaires. * * * -* Retour : - * +* Retour : true si la visite a été jusqu'à son terme, false sinon. * * * * Remarques : - * * * ******************************************************************************/ -void g_binary_portion_print(const GBinPortion *portion, GCodeBuffer *buffer, MemoryDataSize msize) +bool g_portion_layer_visit(const GPortionLayer *layer, visit_portion_fc visitor, void *data) { - mrange_t range; /* Couverture à fournir */ - GBufferLine *line; /* Nouvelle ligne à éditer */ - char rights[64]; /* Traduction en texte */ - - /* On ne traite pas les portions anonymes ! */ - if (portion->desc == NULL) return; - - init_mrange(&range, get_mrange_addr(&portion->range), 0); - - line = g_code_buffer_append_new_line(buffer, &range); - g_buffer_line_fill_mrange(line, msize, msize); - - g_buffer_line_add_flag(line, BLF_WIDTH_MANAGER); - - /* Séparation */ - - line = g_code_buffer_append_new_line(buffer, &range); - g_buffer_line_fill_mrange(line, msize, msize); - - g_buffer_line_start_merge_at(line, BLC_ASSEMBLY_HEAD); - g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, - "; ======================================================", 56, RTT_COMMENT); - - /* Retour à la ligne */ - - line = g_code_buffer_append_new_line(buffer, &range); - g_buffer_line_fill_mrange(line, msize, msize); - - g_buffer_line_start_merge_at(line, BLC_ASSEMBLY_HEAD); - g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "; ", 2, RTT_COMMENT); - - /* Description */ - - line = g_code_buffer_append_new_line(buffer, &range); - g_buffer_line_fill_mrange(line, msize, msize); - - g_buffer_line_start_merge_at(line, BLC_ASSEMBLY_HEAD); - - g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "; ", 2, RTT_COMMENT); - - g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, portion->desc, strlen(portion->desc), RTT_COMMENT); - - snprintf(rights, sizeof(rights), " (%s%s%s%s)", - _("rights: "), - portion->rights & PAC_READ ? "r" : "-", - portion->rights & PAC_WRITE ? "w" : "-", - portion->rights & PAC_EXEC ? "x" : "-"); - - g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, rights, strlen(rights), RTT_COMMENT); - - /* Retour à la ligne */ + bool result; /* Etat à retourner */ + size_t i; /* Boucle de parcours */ - line = g_code_buffer_append_new_line(buffer, &range); - g_buffer_line_fill_mrange(line, msize, msize); + if (layer->sub_layer != NULL) + result = g_portion_layer_visit(layer->sub_layer, visitor, data); + else + result = true; - g_buffer_line_start_merge_at(line, BLC_ASSEMBLY_HEAD); - g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "; ", 2, RTT_COMMENT); + for (i = 0; i < layer->count && result; i++) + result = visitor(layer->portions[i], data); - line = g_code_buffer_append_new_line(buffer, &range); - g_buffer_line_fill_mrange(line, msize, msize); + return result; } /****************************************************************************** * * -* Paramètres : portion = description de partie à mettre à jour. * +* Paramètres : layer = couche de portions à consulter. * * x = abscisse du point de recherche. * * y = ordonnée du point de recherche. * * area = étendue de représentation de la portion mère. * @@ -779,81 +1162,14 @@ void g_binary_portion_print(const GBinPortion *portion, GCodeBuffer *buffer, Mem * * ******************************************************************************/ -gboolean g_binary_portion_query_tooltip(GBinPortion *portion, gint x, gint y, const GdkRectangle *area, GtkTooltip *tooltip) +gboolean g_portion_layer_query_tooltip(const GPortionLayer *layer, gint x, gint y, const GdkRectangle *area, GtkTooltip *tooltip) { GBinPortion *selected; /* Portion à décrire ici */ - char *markup; /* Description à construire */ - GBinPortion *iter; /* Remontée hiérarchique */ - char value[2 * VMPA_MAX_SIZE]; /* Traduction en texte */ - - selected = g_binary_portion_find_at_pos(portion, x, (GdkRectangle []) { *area }); - - /* Nom */ - - if (selected->desc != NULL) - { - markup = strdup("<b>"); - markup = stradd(markup, selected->desc); - markup = stradd(markup, "</b>\n"); - - for (iter = selected->container; iter != NULL; iter = iter->container) - if (iter->desc != NULL) - { - markup = stradd(markup, selected->desc); - markup = stradd(markup, "\n"); - } - - markup = stradd(markup, "\n"); - - } - else markup = strdup(""); - - markup = stradd(markup, "taille : "); - snprintf(value, 2 * VMPA_MAX_SIZE, OFF_FMT, OFF_CAST(selected->size)); - markup = stradd(markup, value); - markup = stradd(markup, "\n"); - - /* Localisation */ - - markup = stradd(markup, "<b>"); - markup = stradd(markup, _("Localisation")); - markup = stradd(markup, "</b>\n"); - - markup = stradd(markup, _("physical: from ")); - snprintf(value, 2 * VMPA_MAX_SIZE, OFF_FMT, OFF_CAST(get_phy_addr(&selected->addr))); - markup = stradd(markup, value); - markup = stradd(markup, _(" to ")); - snprintf(value, 2 * VMPA_MAX_SIZE, OFF_FMT, OFF_CAST(get_phy_addr(&selected->addr) + selected->size)); - markup = stradd(markup, value); - markup = stradd(markup, "\n"); - - markup = stradd(markup, _("memory: from ")); -#if 0 - snprintf(value, 2 * VMPA_MAX_SIZE, VMPA_FMT_LONG, VMPA_CAST(selected->addr)); - markup = stradd(markup, value); - markup = stradd(markup, _(" to ")); - snprintf(value, 2 * VMPA_MAX_SIZE, VMPA_FMT_LONG, VMPA_CAST(selected->addr + selected->size)); - markup = stradd(markup, value); -#endif - markup = stradd(markup, "\n\n"); - - /* Droits d'accès */ - - markup = stradd(markup, "<b>"); - markup = stradd(markup, _("Rights")); - markup = stradd(markup, "</b>\n"); - - snprintf(value, 2 * VMPA_MAX_SIZE, "%s%s%s", - selected->rights & PAC_READ ? "r" : "-", - selected->rights & PAC_WRITE ? "w" : "-", - selected->rights & PAC_EXEC ? "x" : "-"); - markup = stradd(markup, value); - - /* Impression finale */ + selected = g_portion_layer_find_portion_at_pos(layer, x, (GdkRectangle []) { *area }); + if (selected == NULL) return FALSE; - gtk_tooltip_set_markup(tooltip, markup); - free(markup); + g_binary_portion_query_tooltip(selected, tooltip); return TRUE; @@ -862,11 +1178,11 @@ gboolean g_binary_portion_query_tooltip(GBinPortion *portion, gint x, gint y, co /****************************************************************************** * * -* Paramètres : portion = description de partie à consulter. * -* cr = contexte graphique pour le dessin. * -* area = étendue mise à disposition. * +* Paramètres : layer = couche de portions à consulter. * +* cr = contexte graphique pour le dessin. * +* area = étendue mise à disposition. * * * -* Description : Représente la portion sur une bande dédiée. * +* Description : Représente une couche de portions sur une bande dédiée. * * * * Retour : - * * * @@ -874,42 +1190,24 @@ gboolean g_binary_portion_query_tooltip(GBinPortion *portion, gint x, gint y, co * * ******************************************************************************/ -void g_binary_portion_draw(GBinPortion *portion, GtkStyleContext *context, cairo_t *cr, const GdkRectangle *area) +void g_portion_layer_draw(const GPortionLayer *layer, GtkStyleContext *context, cairo_t *cr, const GdkRectangle *area) { size_t i; /* Boucle de parcours */ GBinPortion *sub; /* Portion incluse à montrer */ GdkRectangle sub_area; /* Etendue d'une sous-portion */ - /* Dessin de la portion courante */ - - //cairo_set_line_width(cr, 1.0); - - cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE); - - gtk_style_context_save(context); - - gtk_style_context_add_class(context, portion->code); - - gtk_render_background(context, cr, area->x, area->y, area->width, area->height); - - gtk_render_frame(context, cr, area->x, area->y, area->width, area->height); - - gtk_style_context_restore(context); - - /* Dessin des portions incluses */ - - sub_area.y = area->y; - sub_area.height = area->height; - - for (i = 0; i < portion->sub_count; i++) + for (i = 0; i < layer->count; i++) { - sub = portion->sub_portions[i]; + sub = layer->portions[i]; - if (!g_binary_portion_compute_sub_area(portion, sub, area, &sub_area)) + if (!g_binary_portion_compute_sub_area(sub, layer->length, area, &sub_area)) continue; g_binary_portion_draw(sub, context, cr, &sub_area); } + if (layer->sub_layer != NULL) + g_portion_layer_draw(layer->sub_layer, context, cr, area); + } diff --git a/src/glibext/gbinportion.h b/src/glibext/gbinportion.h index f92b87e..e5c7830 100644 --- a/src/glibext/gbinportion.h +++ b/src/glibext/gbinportion.h @@ -36,6 +36,9 @@ +/* ------------------------------- PORTION DE BINAIRE ------------------------------- */ + + /** * Couleurs de représentation. */ @@ -73,11 +76,7 @@ typedef enum _PortionAccessRights } PortionAccessRights; -/* Fonction appelée à chaque visite de portion.*/ -typedef bool (* visit_portion_fc) (GBinPortion *, void *); - - -/* Indique le type défini par la GLib pour les blocs de données. */ +/* Indique le type défini par la GLib pour les portions de données binaires. */ GType g_binary_portion_get_type(void); /* Crée une description de partie de code vierge. */ @@ -104,35 +103,77 @@ void g_binary_portion_set_rights(GBinPortion *, PortionAccessRights); /* Fournit les droits associés à une partie de code. */ PortionAccessRights g_binary_portion_get_rights(const GBinPortion *); -/* Procède à l'inclusion d'une portion dans une autre. */ -void g_binary_portion_include(GBinPortion *, GBinPortion *); +/* Insère dans un tampon une description de portion. */ +void g_binary_portion_print(const GBinPortion *, GCodeBuffer *, MemoryDataSize); -/* Indique le niveau de profondeur d'une portion donnée. */ -unsigned int g_binary_portion_get_level(GBinPortion *); +/* Prépare une astuce concernant une portion pour son affichage. */ +void g_binary_portion_query_tooltip(GBinPortion *, GtkTooltip *); + +/* Représente la portion sur une bande dédiée. */ +void g_binary_portion_draw(const GBinPortion *, GtkStyleContext *, cairo_t *, const GdkRectangle *); + + + +/* -------------------------- COUCHES DE PORTIONS BINAIRES -------------------------- */ + + +#define G_TYPE_PORTION_LAYER (g_portion_layer_get_type()) +#define G_PORTION_LAYER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_PORTION_LAYER, GPortionLayer)) +#define G_IS_PORTION_LAYER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_PORTION_LAYER)) +#define G_PORTION_LAYER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_PORTION_LAYER, GPortionLayerClass)) +#define G_IS_PORTION_LAYER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_PORTION_LAYER)) +#define G_PORTION_LAYER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_PORTION_LAYER, GPortionLayerClass)) -/* Parcours un ensemble de portions binaires. */ -bool g_binary_portion_visit(GBinPortion *, visit_portion_fc, void *); + +/* Couche de portions binaires quelconques (instance) */ +typedef struct _GPortionLayer GPortionLayer; + +/* Couche de portions binaires quelconques (classe) */ +typedef struct _GPortionLayerClass GPortionLayerClass; + + +/* Taille à définir lors d'un rattachement */ +#define NO_LENGTH_YET VMPA_NO_PHYSICAL + + +/* Indique le type défini par la GLib pour les couches de portions binaires. */ +GType g_portion_layer_get_type(void); + +/* Crée une nouvelle couche de portions binaires. */ +GPortionLayer *g_portion_layer_new(phys_t, const char *); + +/* Attache une couche à une autre en tant que couche inférieure. */ +void g_portion_layer_attach_sub(GPortionLayer *, GPortionLayer *); + +/* Procède à l'inclusion d'une portion dans une couche. */ +void g_portion_layer_include(GPortionLayer *, GBinPortion *); + +/* Fournit une liste triée de portions d'un binaire. */ +GBinPortion **g_portion_layer_collect_all_portions(const GPortionLayer *, size_t *); /* Recherche la portion présente à un point donné. */ -GBinPortion *g_binary_portion_find_at_pos(GBinPortion *, gint, GdkRectangle *); +GBinPortion *g_portion_layer_find_portion_at_pos(const GPortionLayer *, gint, GdkRectangle *); /* Recherche la portion présente à une adresse donnée. */ -GBinPortion *g_binary_portion_find_at_addr(GBinPortion *, const vmpa2t *, GdkRectangle *); +GBinPortion *g_portion_layer_find_portion_at_addr(const GPortionLayer *, const vmpa2t *, GdkRectangle *); /* Fournit la position correspondant à une adresse donnée. */ -bool g_binary_portion_get_addr_from_pos(GBinPortion *, gint, const GdkRectangle *, vmpa2t *); +bool g_portion_layer_get_addr_from_pos(GPortionLayer *, gint, const GdkRectangle *, vmpa2t *); /* Fournit l'adresse correspondant à une position donnée. */ -bool g_binary_portion_get_pos_from_addr(GBinPortion *, const vmpa2t *, const GdkRectangle *, gint *); +bool g_portion_layer_get_pos_from_addr(GPortionLayer *, const vmpa2t *, const GdkRectangle *, gint *); -/* Insère dans un tampon une description de portion. */ -void g_binary_portion_print(const GBinPortion *, GCodeBuffer *, MemoryDataSize); +/* Fonction appelée à chaque visite de portion.*/ +typedef bool (* visit_portion_fc) (GBinPortion *, void *); + +/* Parcours un ensemble de portions binaires. */ +bool g_portion_layer_visit(const GPortionLayer *, visit_portion_fc, void *); /* Prépare une astuce concernant une portion pour son affichage. */ -gboolean g_binary_portion_query_tooltip(GBinPortion *, gint, gint, const GdkRectangle *, GtkTooltip *); +gboolean g_portion_layer_query_tooltip(const GPortionLayer *, gint, gint, const GdkRectangle *, GtkTooltip *); -/* Représente la portion sur une bande dédiée. */ -void g_binary_portion_draw(GBinPortion *, GtkStyleContext *, cairo_t *, const GdkRectangle *); +/* Représente une couche de portions sur une bande dédiée. */ +void g_portion_layer_draw(const GPortionLayer *, GtkStyleContext *, cairo_t *, const GdkRectangle *); |