diff options
Diffstat (limited to 'src/glibext')
-rw-r--r-- | src/glibext/Makefile.am | 9 | ||||
-rw-r--r-- | src/glibext/gbinportion.c | 345 | ||||
-rw-r--r-- | src/glibext/gbinportion.h | 4 | ||||
-rw-r--r-- | src/glibext/gbuffercache.c | 1625 | ||||
-rw-r--r-- | src/glibext/gbuffercache.h | 121 | ||||
-rw-r--r-- | src/glibext/gbufferline.c | 176 | ||||
-rw-r--r-- | src/glibext/gbufferline.h | 9 | ||||
-rw-r--r-- | src/glibext/gbufferview.c | 810 | ||||
-rw-r--r-- | src/glibext/gbufferview.h | 47 | ||||
-rw-r--r-- | src/glibext/gcodebuffer.c | 1778 | ||||
-rw-r--r-- | src/glibext/gcodebuffer.h | 155 | ||||
-rw-r--r-- | src/glibext/generator-int.h | 52 | ||||
-rw-r--r-- | src/glibext/generators/Makefile.am | 15 | ||||
-rw-r--r-- | src/glibext/generators/prologue.c | 359 | ||||
-rw-r--r-- | src/glibext/generators/prologue.h | 58 | ||||
-rw-r--r-- | src/glibext/generators/rborder.c | 361 | ||||
-rw-r--r-- | src/glibext/generators/rborder.h | 60 | ||||
-rw-r--r-- | src/glibext/gwidthtracker.c | 59 | ||||
-rw-r--r-- | src/glibext/gwidthtracker.h | 10 | ||||
-rw-r--r-- | src/glibext/linecolumn.c | 2 | ||||
-rw-r--r-- | src/glibext/linegen-int.h | 67 | ||||
-rw-r--r-- | src/glibext/linegen.c | 208 | ||||
-rw-r--r-- | src/glibext/linegen.h | 68 | ||||
-rw-r--r-- | src/glibext/linesegment.c | 9 | ||||
-rw-r--r-- | src/glibext/linesegment.h | 9 |
25 files changed, 3775 insertions, 2641 deletions
diff --git a/src/glibext/Makefile.am b/src/glibext/Makefile.am index aa7a9a3..fe7565a 100644 --- a/src/glibext/Makefile.am +++ b/src/glibext/Makefile.am @@ -9,16 +9,21 @@ libglibext_la_SOURCES = \ delayed-int.h \ delayed.h delayed.c \ gbinportion.h gbinportion.c \ + gbuffercache.h gbuffercache.c \ gbufferline.h gbufferline.c \ gbufferview.h gbufferview.c \ - gcodebuffer.h gcodebuffer.c \ gnhash.h gnhash.c \ gwidthtracker.h gwidthtracker.c \ linecolumn.h linecolumn.c \ + linegen-int.h \ + linegen.h linegen.c \ linesegment.h linesegment.c \ proto.h \ signal.h signal.c +libglibext_la_LIBADD = \ + generators/libglibextgenerators.la + libglibext_la_LDFLAGS = @@ -26,7 +31,7 @@ AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) -SUBDIRS = +SUBDIRS = generators chrysamarshal.h: chrysamarshal.list diff --git a/src/glibext/gbinportion.c b/src/glibext/gbinportion.c index 4137763..eec9651 100644 --- a/src/glibext/gbinportion.c +++ b/src/glibext/gbinportion.c @@ -26,6 +26,7 @@ #include <assert.h> #include <malloc.h> +#include <stdio.h> #include <stdlib.h> #include <string.h> @@ -33,8 +34,10 @@ #include <i18n.h> +#include "../analysis/human/asm/lang.h" // TODO : REMME -> format ! #include "../common/extstr.h" #include "../common/sort.h" +#include "../glibext/linegen-int.h" @@ -49,6 +52,8 @@ struct _GBinPortion char *code; /* Code de la couleur de fond */ char *desc; /* Désignation humaine */ + char **text; /* Lignes brutes à représenter */ + size_t lcount; /* Quantité de ces lignes */ mrange_t range; /* Emplacement dans le code */ @@ -73,6 +78,9 @@ static void g_binary_portion_class_init(GBinPortionClass *); /* Initialise une instance de portion de données binaires. */ static void g_binary_portion_init(GBinPortion *); +/* Procède à l'initialisation de l'interface de génération. */ +static void g_binary_portion_interface_init(GLineGeneratorInterface *); + /* Supprime toutes les références externes. */ static void g_binary_portion_dispose(GBinPortion *); @@ -84,6 +92,26 @@ static bool g_binary_portion_compute_sub_area(const GBinPortion *, phys_t, const +/* ------------------------ OFFRE DE CAPACITES DE GENERATION ------------------------ */ + + +/* Indique le nombre de ligne prêtes à être générées. */ +static size_t g_binary_portion_count_lines(const GBinPortion *); + +/* Retrouve l'emplacement correspondant à une position donnée. */ +static void g_binary_portion_compute_addr(const GBinPortion *, gint, vmpa2t *, size_t, size_t); + +/* Détermine si le conteneur s'inscrit dans une plage donnée. */ +static int g_binary_portion_contains_addr(const GBinPortion *, const vmpa2t *, size_t, size_t); + +/* Renseigne sur les propriétés liées à un générateur. */ +static BufferLineFlags g_binary_portion_get_flags(const GBinPortion *, size_t, size_t); + +/* Imprime dans une ligne de rendu le contenu représenté. */ +static void g_binary_portion_print(GBinPortion *, GBufferLine *, size_t, size_t); + + + /* ------------------------ PARCOURS D'ENSEMBLES DE PORTIONS ------------------------ */ @@ -98,7 +126,8 @@ static bool g_portion_layer_contains_addr(const GBinPortion *, const vmpa2t *); /* 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); +G_DEFINE_TYPE_WITH_CODE(GBinPortion, g_binary_portion, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE(G_TYPE_LINE_GENERATOR, g_binary_portion_interface_init)); /****************************************************************************** @@ -140,6 +169,32 @@ static void g_binary_portion_class_init(GBinPortionClass *klass) static void g_binary_portion_init(GBinPortion *portion) { + portion->desc = NULL; + portion->text = NULL; + portion->lcount = 0; + +} + + +/****************************************************************************** +* * +* Paramètres : iface = interface GLib à initialiser. * +* * +* Description : Procède à l'initialisation de l'interface de génération. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_binary_portion_interface_init(GLineGeneratorInterface *iface) +{ + iface->count = (linegen_count_lines_fc)g_binary_portion_count_lines; + iface->compute = (linegen_compute_fc)g_binary_portion_compute_addr; + iface->contains = (linegen_contains_fc)g_binary_portion_contains_addr; + iface->get_flags = (linegen_get_flags_fc)g_binary_portion_get_flags; + iface->print = (linegen_print_fc)g_binary_portion_print; } @@ -177,11 +232,19 @@ static void g_binary_portion_dispose(GBinPortion *portion) static void g_binary_portion_finalize(GBinPortion *portion) { + size_t i; /* Boucle de parcours */ + free(portion->code); if (portion->desc != NULL) free(portion->desc); + for (i = 0; i < portion->lcount; i++) + free(portion->text[i]); + + if (portion->text != NULL) + free(portion->text); + G_OBJECT_CLASS(g_binary_portion_parent_class)->finalize(G_OBJECT(portion)); } @@ -260,9 +323,66 @@ int g_binary_portion_compare(const GBinPortion **a, const GBinPortion **b) void g_binary_portion_set_desc(GBinPortion *portion, const char *desc) { - if (portion->desc != NULL) free(portion->desc); + size_t i; /* Boucle de parcours */ + GCodingLanguage *lang; /* Langage de sortie préféré */ + + if (portion->desc != NULL) + { + free(portion->desc); + + for (i = 0; i < portion->lcount; i++) + free(portion->text[i]); + + if (portion->text != NULL) + { + free(portion->text); + portion->text = NULL; + } + + } + + if (desc == NULL) + portion->desc = NULL; + + else + { + portion->desc = strdup(desc); + + /* Constitution du rendu */ + + portion->text = calloc(4, sizeof(char *)); + portion->lcount = 4; + + portion->text[0] = strdup("======================================================"); + portion->text[1] = strdup(""); + + asprintf(&portion->text[2], "%s (%s%s%s%s)", portion->desc, _("rights: "), + portion->rights & PAC_READ ? "r" : "-", + portion->rights & PAC_WRITE ? "w" : "-", + portion->rights & PAC_EXEC ? "x" : "-"); - portion->desc = strdup(desc); + portion->text[3] = strdup(""); + portion->text[4] = strdup("======================================================"); + + /* Ajout de la touche "commentaires" */ + + lang = g_asm_language_new(); + + g_coding_language_encapsulate_comments(lang, &portion->text, &portion->lcount); + + g_object_unref(G_OBJECT(lang)); + + /* Ajout de deux bordures vides */ + + portion->lcount += 2; + portion->text = realloc(portion->text, portion->lcount * sizeof(char *)); + + memmove(&portion->text[1], &portion->text[0], (portion->lcount - 2) * sizeof(char *)); + + portion->text[0] = NULL; + portion->text[portion->lcount - 1] = NULL; + + } } @@ -346,98 +466,6 @@ PortionAccessRights g_binary_portion_get_rights(const GBinPortion *portion) /****************************************************************************** * * -* 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 : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_binary_portion_print(const GBinPortion *portion, GCodeBuffer *buffer, MemoryDataSize msize) -{ - 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_prepare_new_line(buffer, &range); - g_buffer_line_fill_mrange(line, msize, msize); - - g_buffer_line_add_flag(line, BLF_WIDTH_MANAGER); - - g_code_buffer_append_new_line(buffer, line); - - /* Séparation */ - - line = g_code_buffer_prepare_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_append_text(line, BLC_ASSEMBLY_HEAD, - "; ======================================================", 56, RTT_COMMENT, NULL); - - g_code_buffer_append_new_line(buffer, line); - - /* Retour à la ligne */ - - line = g_code_buffer_prepare_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_append_text(line, BLC_ASSEMBLY_HEAD, "; ", 2, RTT_COMMENT, NULL); - - g_code_buffer_append_new_line(buffer, line); - - /* Description */ - - line = g_code_buffer_prepare_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_append_text(line, BLC_ASSEMBLY_HEAD, "; ", 2, RTT_COMMENT, NULL); - - g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, portion->desc, strlen(portion->desc), RTT_COMMENT, NULL); - - 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_append_text(line, BLC_ASSEMBLY_HEAD, rights, strlen(rights), RTT_COMMENT, NULL); - - g_code_buffer_append_new_line(buffer, line); - - /* Retour à la ligne */ - - line = g_code_buffer_prepare_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_append_text(line, BLC_ASSEMBLY_HEAD, "; ", 2, RTT_COMMENT, NULL); - - g_code_buffer_append_new_line(buffer, line); - - line = g_code_buffer_prepare_new_line(buffer, &range); - g_buffer_line_fill_mrange(line, msize, msize); - g_code_buffer_append_new_line(buffer, line); - - -} - - -/****************************************************************************** -* * * Paramètres : portion = description de partie à mettre à jour. * * tooltip = astuce à compléter. [OUT] * * * @@ -724,6 +752,133 @@ bool g_binary_portion_visit(GBinPortion *portion, visit_portion_fc visitor, void /* ---------------------------------------------------------------------------------- */ +/* OFFRE DE CAPACITES DE GENERATION */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : portion = générateur à consulter. * +* * +* Description : Indique le nombre de ligne prêtes à être générées. * +* * +* Retour : Nombre de lignes devant apparaître au final. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static size_t g_binary_portion_count_lines(const GBinPortion *portion) +{ + return portion->lcount; + +} + + +/****************************************************************************** +* * +* Paramètres : portion = générateur à consulter. * +* x = position géographique sur la ligne concernée. * +* addr = position en mémoire à analyser. * +* index = indice de cette même ligne dans le tampon global. * +* repeat = indice d'utilisations successives du générateur. * +* * +* Description : Retrouve l'emplacement correspondant à une position donnée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_binary_portion_compute_addr(const GBinPortion *portion, gint x, vmpa2t *addr, size_t index, size_t repeat) +{ + copy_vmpa(addr, get_mrange_addr(&portion->range)); + +} + + +/****************************************************************************** +* * +* Paramètres : portion = générateur à consulter. * +* addr = position en mémoire à analyser. * +* index = indice de cette même ligne dans le tampon global. * +* repeat = indice d'utilisations successives du générateur. * +* * +* Description : Détermine si le conteneur s'inscrit dans une plage donnée. * +* * +* Retour : Bilan de la détermination, utilisable en comparaisons. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static int g_binary_portion_contains_addr(const GBinPortion *portion, const vmpa2t *addr, size_t index, size_t repeat) +{ + int result; /* Conclusion à retourner */ + + result = cmp_vmpa(addr, get_mrange_addr(&portion->range)); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : portion = générateur à consulter. * +* index = indice de cette même ligne dans le tampon global. * +* repeat = indice d'utilisations successives du générateur. * +* * +* Description : Renseigne sur les propriétés liées à un générateur. * +* * +* Retour : Propriétés particulières associées. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static BufferLineFlags g_binary_portion_get_flags(const GBinPortion *portion, size_t index, size_t repeat) +{ + return (repeat == 0 ? BLF_WIDTH_MANAGER : BLF_HAS_CODE); + +} + + +/****************************************************************************** +* * +* Paramètres : portion = générateur à utiliser pour l'impression. * +* line = ligne de rendu à compléter. * +* index = indice de cette même ligne dans le tampon global. * +* repeat = indice d'utilisations successives du générateur. * +* * +* Description : Imprime dans une ligne de rendu le contenu représenté. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_binary_portion_print(GBinPortion *portion, GBufferLine *line, size_t index, size_t repeat) +{ + assert(repeat < portion->lcount); + + g_buffer_line_fill_vmpa(line, get_mrange_addr(&portion->range), MDS_32_BITS_UNSIGNED, MDS_32_BITS_UNSIGNED); + + if (portion->text[repeat] != NULL) + { + g_buffer_line_start_merge_at(line, BLC_ASSEMBLY_HEAD); + + g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, SL(portion->text[repeat]), RTT_COMMENT, NULL); + + } + +} + + + +/* ---------------------------------------------------------------------------------- */ /* PARCOURS D'ENSEMBLES DE PORTIONS */ /* ---------------------------------------------------------------------------------- */ diff --git a/src/glibext/gbinportion.h b/src/glibext/gbinportion.h index 2aa5e1a..4f4b3be 100644 --- a/src/glibext/gbinportion.h +++ b/src/glibext/gbinportion.h @@ -30,7 +30,6 @@ #include <gtk/gtk.h> -#include "gcodebuffer.h" #include "../arch/vmpa.h" #include "../common/fnv1a.h" @@ -100,9 +99,6 @@ 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 *); -/* Insère dans un tampon une description de portion. */ -void g_binary_portion_print(const GBinPortion *, GCodeBuffer *, MemoryDataSize); - /* Prépare une astuce concernant une portion pour son affichage. */ void g_binary_portion_query_tooltip(GBinPortion *, GtkTooltip *); diff --git a/src/glibext/gbuffercache.c b/src/glibext/gbuffercache.c new file mode 100644 index 0000000..57a9487 --- /dev/null +++ b/src/glibext/gbuffercache.c @@ -0,0 +1,1625 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * gbuffercache.c - affichage à la demande d'un ensemble de lignes + * + * Copyright (C) 2016 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide 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. + * + * Chrysalide 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 "gbuffercache.h" + + +#include <assert.h> +#include <malloc.h> +#include <stdlib.h> + + +#include "chrysamarshal.h" + + + +/* --------------------- FONCTIONS AUXILIAIRES DE MANIPULATIONS --------------------- */ + + +/* Informations rattachées à la génération d'une ligne */ +typedef struct _generator_link +{ + GLineGenerator *instance; /* Fournisseur de contenu */ + size_t repeat; /* Compteur de successions */ + +} generator_link; + +/* Suivi interne de l'état d'une ligne */ +typedef struct _cache_info +{ + union + { + generator_link generator; /* Générateur unique */ + generator_link *generators; /* Liste de générateurs */ + }; + size_t count; /* Taille de cette liste */ + + GBufferLine *line; /* Ligne en place ou NULL */ + + BufferLineFlags extra_flags; /* Propriétés supplémentaires */ + +} cache_info; + + +/* Gros verrou global pour alléger les structures... */ +G_LOCK_DEFINE_STATIC(_line_update); + + +/* Met en place un nouvel ensemble d'information sur une ligne. */ +static void init_cache_info(cache_info *, GLineGenerator *, size_t, BufferLineFlags); + +/* Libère la mémoire occupée par des informations sur une ligne. */ +static void release_cache_info(cache_info *); + +/* Ajoute un générateur aux informations sur une ligne. */ +static void extend_cache_info(cache_info *, GLineGenerator *); + +/* Retire un générateur aux informations d'une ligne. */ +static void remove_from_cache_info(cache_info *, GLineGenerator *); + +/* Retrouve l'emplacement correspondant à une position de ligne. */ +static void get_cache_info_addr(const cache_info *, size_t, gint, vmpa2t *); + +/* Suivit les variations du compteur de références d'une ligne. */ +static void on_line_ref_toggle(cache_info *, GBufferLine *, gboolean); + +/* Fournit la ligne de tampon correspondant aux générateurs. */ +static GBufferLine *get_cache_info_line(cache_info *, size_t); + +/* Force la réinitialisation d'une éventuelle ligne cachée. */ +static void reset_cache_info_line(cache_info *); + + + +/* -------------------------- TAMPON POUR CODE DESASSEMBLE -------------------------- */ + + +/* Tampon pour gestion de lignes optimisée (instance) */ +struct _GBufferCache +{ + GObject parent; /* A laisser en premier */ + + cache_info *lines; /* Liste des lignes intégrées */ + size_t count; /* Quantité en cache */ + size_t used; /* Quantité utilisée */ + + GWidthTracker *tracker; /* Suivi des largeurs */ + +}; + +/* Tampon pour gestion de lignes optimisée (classe) */ +struct _GBufferCacheClass +{ + GObjectClass parent; /* A laisser en premier */ + + gint line_height; /* Hauteur maximale des lignes */ + gint left_margin; /* Marge gauche + espace */ + gint text_pos; /* Début d'impression du code */ + + /* Signaux */ + + void (* size_changed) (GBufferCache *, bool, size_t, size_t); + +}; + + +/* Taille des allocations de masse */ +#define LINE_ALLOC_BULK 1000 + + +/* Procède à l'initialisation d'une classe de tampon de lignes. */ +static void g_buffer_cache_class_init(GBufferCacheClass *); + +/* Procède à l'initialisation d'un tampon de gestion de lignes. */ +static void g_buffer_cache_init(GBufferCache *); + +/* Supprime toutes les références externes. */ +static void g_buffer_cache_dispose(GBufferCache *); + +/* Procède à la libération totale de la mémoire. */ +static void g_buffer_cache_finalize(GBufferCache *); + +/* Calcule l'indice d'apparition d'un générateur dans le tampon. */ +static size_t g_buffer_cache_compute_repetition(GBufferCache *, size_t, GLineGenerator *); + + + +/* ---------------------------------------------------------------------------------- */ +/* FONCTIONS AUXILIAIRES DE MANIPULATIONS */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : info = informations concernant une ligne à constituer. * +* generator = générateur à associer à toutes les lignes. * +* repeat = compteur de répétition entre les lignes. * +* flags = propriétés supplémentaires à associer à la ligne.* +* * +* Description : Met en place un nouvel ensemble d'information sur une ligne. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void init_cache_info(cache_info *info, GLineGenerator *generator, size_t repeat, BufferLineFlags flags) +{ + info->generator.instance = generator; + info->generator.repeat = repeat; + + g_object_ref(G_OBJECT(generator)); + + info->count = 1; + + info->line = NULL; + + info->extra_flags = flags; + +} + + +/****************************************************************************** +* * +* Paramètres : info = informations concernant une ligne à constituer. * +* * +* Description : Libère la mémoire occupée par des informations sur une ligne.* +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void release_cache_info(cache_info *info) +{ + size_t i; /* Boucle de parcours */ + + if (info->count == 1) + g_object_unref(G_OBJECT(info->generator.instance)); + + else + for (i = 0; i < info->count; i++) + g_object_unref(G_OBJECT(info->generators[i].instance)); + + reset_cache_info_line(info); + +} + + +/****************************************************************************** +* * +* Paramètres : info = informations concernant une ligne à actualiser. * +* generator = générateur à associer à toutes les lignes. * +* * +* Description : Ajoute un générateur aux informations sur une ligne. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void extend_cache_info(cache_info *info, GLineGenerator *generator) +{ + generator_link first; /* Générateur déjà en place */ + generator_link *new; /* Nouveau générateur placé */ + + if (info->count == 1) + { + first = info->generator; + + info->generators = (generator_link *)calloc(2, sizeof(generator_link)); + + info->generators[0] = first; + info->count = 2; + + new = &info->generators[1]; + + } + else + { + info->generators = (generator_link *)realloc(info->generators, + ++info->count * sizeof(generator_link)); + + new = &info->generators[info->count - 1]; + + } + + new->instance = generator; + new->repeat = 0; + + g_object_ref(G_OBJECT(generator)); + + reset_cache_info_line(info); + +} + + +/****************************************************************************** +* * +* Paramètres : info = informations concernant une ligne à actualiser. * +* generator = générateur à dissocier de toutes les lignes. * +* * +* Description : Retire un générateur aux informations d'une ligne. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void remove_from_cache_info(cache_info *info, GLineGenerator *generator) +{ + generator_link *link; /* Accès simplifié */ + size_t i; /* Boucle de parcours */ + generator_link *old; /* Mémorisation avant opérat° */ + + if (info->count == 1) + { + link = &info->generator; + + assert(link->instance == generator); + + g_object_unref(G_OBJECT(generator)); + + info->count = 0; + + } + + else + { + for (i = 0; i < info->count; i++) + { + link = &info->generators[i]; + + if (link->instance == generator) + { + if ((i + 1) < info->count) + memmove(&info->generators[i], &info->generators[i + 1], + (info->count - i - 1) * sizeof(generator_link)); + + if (info->count == 2) + { + old = info->generators; + + info->count = 1; + info->generator = info->generators[0]; + + free(old); + + } + else + info->generators = (generator_link *)realloc(info->generators, + --info->count * sizeof(generator_link)); + + break; + + } + + } + +#ifndef NDEBUG + + /** + * Attention : si l'élément était en dernière position, + * l'indice de parcours est désormais égal au nombre de générateurs présents ! + */ + assert(i <= info->count); + + for ( ; i < info->count; i++) + { + link = &info->generators[i]; + + assert(link->instance != generator); + + } + +#endif + + } + + reset_cache_info_line(info); + +} + + +/****************************************************************************** +* * +* Paramètres : info = informations sur une ligne à venir consulter. * +* index = indice de la ligne visée par la consultation. * +* x = position géographique sur la ligne concernée. * +* addr = adresse à renseigner. [OUT] * +* * +* Description : Retrouve l'emplacement correspondant à une position de ligne.* +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void get_cache_info_addr(const cache_info *info, size_t index, gint x, vmpa2t *addr) +{ + const generator_link *generator; /* Générateur retenu */ + + if (info->count == 1) + generator = &info->generator; + else + generator = &info->generators[0]; + + g_line_generator_compute_addr(generator->instance, x, addr, index, generator->repeat); + +} + + +/****************************************************************************** +* * +* Paramètres : info = informations sur une ligne à venir manipuler. * +* line = tampon de lignes à venir supprimer au besoin. * +* last = indication sur la valeur du compteur de références. * +* * +* Description : Suivit les variations du compteur de références d'une ligne. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void on_line_ref_toggle(cache_info *info, GBufferLine *line, gboolean last) +{ + if (last) + { + G_LOCK(_line_update); + + assert(info->line != NULL); + + info->line = NULL; + + G_UNLOCK(_line_update); + + } + +} + + +/****************************************************************************** +* * +* Paramètres : info = informations sur une ligne à venir manipuler. * +* index = indice de la ligne à constituer. * +* * +* Description : Fournit la ligne de tampon correspondant aux générateurs. * +* * +* Retour : Ligne déjà en place ou créée pour le besoin. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GBufferLine *get_cache_info_line(cache_info *info, size_t index) +{ + GBufferLine *result; /* Construction à retourner */ + size_t i; /* Boucle de parcours */ + + G_LOCK(_line_update); + + result = info->line; + + if (result == NULL) + { + result = g_buffer_line_new((mrange_t []){ { { 0 }, 0 } }, 0/* !! */); + + g_object_add_toggle_ref(G_OBJECT(result), (GToggleNotify)on_line_ref_toggle, info); + + if (info->count == 1) + g_line_generator_print(info->generator.instance, result, index, info->generator.repeat); + + else + for (i = 0; i < info->count; i++) + g_line_generator_print(info->generators[i].instance, result, index, info->generators[i].repeat); + + info->line = result; + + } + + else + g_object_ref(G_OBJECT(result)); + + G_UNLOCK(_line_update); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : info = informations sur une ligne à venir manipuler. * +* * +* Description : Force la réinitialisation d'une éventuelle ligne cachée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void reset_cache_info_line(cache_info *info) +{ + G_LOCK(_line_update); + + if (info->line != NULL) + { + g_object_remove_toggle_ref(G_OBJECT(info->line), (GToggleNotify)on_line_ref_toggle, info); + + g_object_unref(G_OBJECT(info->line)); + + info->line = NULL; + + } + + G_UNLOCK(_line_update); + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* TAMPON POUR CODE DESASSEMBLE */ +/* ---------------------------------------------------------------------------------- */ + + +/* Détermine le type du composant de tampon pour gestion de lignes optimisée. */ +G_DEFINE_TYPE(GBufferCache, g_buffer_cache, G_TYPE_OBJECT); + + +/****************************************************************************** +* * +* Paramètres : class = classe de composant GLib à initialiser. * +* * +* Description : Procède à l'initialisation d'une classe de tampon de lignes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_buffer_cache_class_init(GBufferCacheClass *class) +{ + GObjectClass *object; /* Autre version de la classe */ + + object = G_OBJECT_CLASS(class); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_buffer_cache_dispose; + object->finalize = (GObjectFinalizeFunc)g_buffer_cache_finalize; + + class->line_height = 17; + class->left_margin = 2 * class->line_height; + class->text_pos = 2.5 * class->line_height; + + /* Signaux */ + + g_signal_new("size-changed", + G_TYPE_BUFFER_CACHE, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(GBufferCacheClass, size_changed), + NULL, NULL, + g_cclosure_user_marshal_VOID__BOOLEAN_ULONG_ULONG, + G_TYPE_NONE, 3, G_TYPE_BOOLEAN, G_TYPE_ULONG, G_TYPE_ULONG); + +} + + +/****************************************************************************** +* * +* Paramètres : cache = composant GLib à initialiser. * +* * +* Description : Procède à l'initialisation d'un tampon de gestion de lignes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_buffer_cache_init(GBufferCache *cache) +{ + cache->tracker = g_width_tracker_new(cache); + +} + + +/****************************************************************************** +* * +* Paramètres : cache = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_buffer_cache_dispose(GBufferCache *cache) +{ + size_t i; /* Boucle de parcours #1 */ + cache_info *info; /* Accès directe à une ligne */ + size_t j; /* Boucle de parcours #2 */ + + for (i = 0; i < cache->used; i++) + { + info = &cache->lines[i]; + + if (info->count == 1) + g_object_unref(G_OBJECT(info->generator.instance)); + + else + for (j = 0; j < info->count; j++) + g_object_unref(G_OBJECT(info->generators[j].instance)); + + if (info->line) + g_object_unref(G_OBJECT(info->line)); + + } + + g_object_unref(G_OBJECT(cache->tracker)); + + G_OBJECT_CLASS(g_buffer_cache_parent_class)->dispose(G_OBJECT(cache)); + +} + + +/****************************************************************************** +* * +* Paramètres : cache = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_buffer_cache_finalize(GBufferCache *cache) +{ + size_t i; /* Boucle de parcours */ + cache_info *info; /* Accès directe à une ligne */ + + for (i = 0; i < cache->used; i++) + { + info = &cache->lines[i]; + + if (info->count > 1) + free(info->generators); + + } + + if (cache->lines != NULL) + free(cache->lines); + + G_OBJECT_CLASS(g_buffer_cache_parent_class)->finalize(G_OBJECT(cache)); + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Crée un nouveau composant de tampon pour code désassemblé. * +* * +* Retour : Composant GLib créé. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBufferCache *g_buffer_cache_new(void) +{ + GBufferCache *result; /* Composant à retourner */ + + result = g_object_new(G_TYPE_BUFFER_CACHE, NULL); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : cache = tampon de lignes à consulter. * +* * +* Description : Fournit la hauteur d'impression d'une ligne visualisée. * +* * +* Retour : Hauteur de ligne en pixels. * +* * +* Remarques : - * +* * +******************************************************************************/ + +gint g_buffer_cache_get_line_height(const GBufferCache *cache) +{ + GBufferCacheClass *class; /* Classe des tampons */ + + class = G_BUFFER_CACHE_GET_CLASS(cache); + + return class->line_height; + +} + + +/****************************************************************************** +* * +* Paramètres : cache = tampon de lignes à consulter. * +* * +* Description : Fournit la taille réservée pour la marge gauche. * +* * +* Retour : Largeur en pixels. * +* * +* Remarques : - * +* * +******************************************************************************/ + +gint g_buffer_cache_get_left_margin(const GBufferCache *cache) +{ + GBufferCacheClass *class; /* Classe des tampons */ + + class = G_BUFFER_CACHE_GET_CLASS(cache); + + return class->left_margin; + +} + + +/****************************************************************************** +* * +* Paramètres : cache = tampon de lignes à consulter. * +* * +* Description : Fournit la position de départ pour l'impression de texte. * +* * +* Retour : Position en pixels. * +* * +* Remarques : - * +* * +******************************************************************************/ + +gint g_buffer_cache_get_text_position(const GBufferCache *cache) +{ + GBufferCacheClass *class; /* Classe des tampons */ + + class = G_BUFFER_CACHE_GET_CLASS(cache); + + return class->text_pos; + +} + + +/****************************************************************************** +* * +* Paramètres : cache = instance GLib à consulter. * +* * +* Description : Compte le nombre de lignes rassemblées dans un tampon. * +* * +* Retour : Nombre de lignes constituant le tampon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +size_t g_buffer_cache_count_lines(const GBufferCache *cache) +{ + return cache->used; + +} + + +/****************************************************************************** +* * +* Paramètres : cache = composant GLib à consulter. * +* * +* Description : Fournit un lien vers la structure de suivi de largeurs. * +* * +* Retour : Gestionnaire de largeurs de lignes. * +* * +* Remarques : - * +* * +******************************************************************************/ + +const GWidthTracker *g_buffer_cache_get_width_tracker(const GBufferCache *cache) +{ + return cache->tracker; + +} + + + + + +/****************************************************************************** +* * +* Paramètres : cache = instance GLib à consulter. * +* index = indice de la ligne où se trouve le générateur. * +* generator = générateur associé à au moins une ligne. * +* * +* Description : Calcule l'indice d'apparition d'un générateur dans le tampon.* +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static size_t g_buffer_cache_compute_repetition(GBufferCache *cache, size_t index, GLineGenerator *generator) +{ + size_t result; /* Compteur à retourner */ + cache_info *info; /* Accès directe à une ligne */ + size_t i; /* Boucle de parcours */ + + result = 0; + + if (index > 0) + { + info = &cache->lines[index - 1]; + + if (info->count == 1) + { + if (info->generator.instance == generator) + result = info->generator.repeat + 1; + + } + + else + for (i = 0; i < info->count; i++) + if (info->generators[i].instance == generator) + { + result = info->generators[i].repeat + 1; + break; + } + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : cache = instance GLib à modifier. * +* index = point d'insertion, puis de sauvegarde. * +* generator = générateur à insérer dans les lignes. * +* before = précise l'emplacement final des nouvelles lignes.* +* after = précise l'emplacement final des nouvelles lignes.* +* * +* Description : Insère un générateur dans des lignes à une position donnée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_buffer_cache_insert_at(GBufferCache *cache, size_t index, GLineGenerator *generator, bool before, bool after) +{ +#ifndef NDEBUG + vmpa2t gen_addr; /* Position du générateur */ + vmpa2t line_addr; /* Position de la ligne */ +#endif + size_t needed; /* Emplacements nécessaires */ + size_t i; /* Boucle de parcours */ + + assert(index < cache->used); + + assert(!(before && after)); + +#ifndef NDEBUG + + g_line_generator_compute_addr(generator, 0, &gen_addr, index, 0); + + get_cache_info_addr(&cache->lines[index], index, 0, &line_addr); + + /////////////////////////////////////// + if (cmp_vmpa(&gen_addr, &line_addr) != 0) return; + + assert(cmp_vmpa(&gen_addr, &line_addr) == 0); + +#endif + + /* Cas particulier d'ajout en fin de cache... */ + if (after && (index + 1) == cache->used) + { + g_buffer_cache_append(cache, generator, BLF_NONE); + goto gbcia_done; + } + + /* Adaptation de l'espace */ + + needed = g_line_generator_count_lines(generator); + + if (before || after) + { + if ((cache->used + needed) >= cache->count) + { + cache->count += needed + LINE_ALLOC_BULK; + cache->lines = (cache_info *)realloc(cache->lines, cache->count * sizeof(cache_info)); + } + } +#ifndef NDEBUG + else + assert(needed == 1); +#endif + + /* Insertion du générateur */ + + if (after) + index++; + + if (before || after) + { + memmove(&cache->lines[index], &cache->lines[index + needed], (cache->used - index) * sizeof(cache_info)); + + for (i = 0; i < needed; i++) + init_cache_info(&cache->lines[index + i], generator, i, BLF_NONE); + + cache->used += needed; + + g_width_tracker_update_added(cache->tracker, index, needed); + + g_signal_emit_by_name(cache, "size-changed", true, index, needed); + + } + + else + { + extend_cache_info(&cache->lines[index], generator); + + g_width_tracker_update(cache->tracker, index); + + g_signal_emit_by_name(cache, "size-changed", true, index, 1); + + } + + gbcia_done: + + ; + +} + + +/****************************************************************************** +* * +* Paramètres : cache = instance GLib à modifier. * +* index = point d'insertion, puis de sauvegarde. * +* type = type de générateurs à retirer des lignes visées. * +* before = précise l'emplacement final de l'élément visé. * +* after = précise l'emplacement final de l'élément visé. * +* * +* Description : Retire un type de générateur de lignes. * +* * +* Retour : Générateur éventuellement trouvé ou NULL si aucun. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GLineGenerator *g_buffer_cache_delete_type_at(GBufferCache *cache, size_t index, GType type, bool before, bool after) +{ + GLineGenerator *result; /* Prédécesseur à retourner */ + cache_info *info; /* Accès directe à une ligne */ + generator_link *link; /* Accès simplifié */ + size_t i; /* Boucle de parcours */ + size_t count; /* Emplacements occupés */ + size_t delete; /* Indice de suppression */ + + assert(index < cache->used); + + assert(!(before && after)); + + result = NULL; + + /* Recherche d'un générateur correspondant */ + + if (before) + info = &cache->lines[index - 1]; + else if (after) + info = &cache->lines[index + 1]; + else + info = &cache->lines[index]; + + if (info->count == 1) + { + link = &info->generator; + + if (G_OBJECT_TYPE(link->instance) == type) + result = link->instance; + + } + + else + for (i = 0; i < info->count && result == NULL; i++) + { + link = &info->generators[i]; + + if (G_OBJECT_TYPE(link->instance) == type) + result = link->instance; + + } + + /* Retrait de l'instance trouvée */ + + if (result != NULL) + { + count = g_line_generator_count_lines(result); + +#ifndef NDEBUG + if (!before && !after) + assert(count == 1); +#endif + + g_object_ref(G_OBJECT(result)); + + /* Suppression de l'élément */ + + for (i = 0; i < count; i++) + { + if (before) + info = &cache->lines[index - 1 - i]; + else if (after) + info = &cache->lines[index + 1 + i]; + else + info = &cache->lines[index]; + + remove_from_cache_info(info, result); + + } + + /* Suppression des lignes associées */ + + for (i = 0; i < count; i++) + { + if (before) + delete = index - 1; + else if (after) + delete = index + 1; + else + delete = index; + + info = &cache->lines[delete]; + + if (info->count == 0) + { + release_cache_info(info); + + if ((delete + 1) < cache->used) + memmove(&cache->lines[delete], &cache->lines[delete + 1], + (cache->used - delete - 1) * sizeof(cache_info)); + + cache->used--; + + g_width_tracker_update_deleted(cache->tracker, delete, delete); + + g_signal_emit_by_name(cache, "size-changed", false, delete, 1); + + } + + } + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : cache = instance GLib à modifier. * +* generator = générateur à associer à toutes les lignes. * +* flags = propriétés supplémentaires à associer à la ligne.* +* * +* Description : Ajoute en fin de tampon un générateur de lignes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_buffer_cache_append(GBufferCache *cache, GLineGenerator *generator, BufferLineFlags flags) +{ + size_t count; /* Nombre de lignes générées */ + size_t index; /* Point d'insertion */ + size_t i; /* Boucle de parcours */ + cache_info *info; /* Accès directe à une ligne */ + + count = g_line_generator_count_lines(generator); + + assert(count > 0); + + assert((flags != BLF_NONE && count == 1) || flags == BLF_NONE); + + if ((cache->used + count) > cache->count) + { + cache->count += count + LINE_ALLOC_BULK; + cache->lines = (cache_info *)realloc(cache->lines, cache->count * sizeof(cache_info)); + } + + index = cache->used; + + for (i = 0; i < count; i++) + { + info = &cache->lines[index + i]; + + info->generator.instance = generator; + info->generator.repeat = g_buffer_cache_compute_repetition(cache, index + i, generator); + + g_object_ref(G_OBJECT(generator)); + + info->count = 1; + + info->line = NULL; + + info->extra_flags = flags; + + } + + cache->used += count; + + g_object_unref(G_OBJECT(generator)); + + g_width_tracker_update_added(cache->tracker, index, count); + + g_signal_emit_by_name(cache, "size-changed", true, index, count); + +} + + +/****************************************************************************** +* * +* Paramètres : cache = instance GLib à modifier. * +* count = quantité totale de lignes à avoir à disposition. * +* generator = générateur à associer à toutes les lignes. * +* * +* Description : Etend un tampon avec un générateur de lignes unique. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_buffer_cache_extend_with(GBufferCache *cache, size_t count, GLineGenerator *generator) +{ + size_t index; /* Point d'insertion */ + size_t i; /* Boucle de parcours */ + cache_info *info; /* Accès directe à une ligne */ + size_t added; /* Nombre d'ajouts effectués */ + + assert(count >= cache->used); + + if (count > cache->count) + { + cache->lines = (cache_info *)realloc(cache->lines, count * sizeof(cache_info)); + cache->count = count; + } + + index = cache->used; + + for (i = index; i < count; i++) + { + info = &cache->lines[i]; + + info->generator.instance = generator; + info->generator.repeat = g_buffer_cache_compute_repetition(cache, i, generator); + + g_object_ref(G_OBJECT(generator)); + + info->count = 1; + + info->line = NULL; + + } + + added = count - cache->used; + + cache->used = count; + + g_object_unref(G_OBJECT(generator)); + + if (added > 0) + { + g_width_tracker_update_added(cache->tracker, index, added); + + g_signal_emit_by_name(cache, "size-changed", true, index, added); + + } + +} + + +/****************************************************************************** +* * +* Paramètres : cache = instance GLib à modifier. * +* max = nombre maximal de lignes à conserver. * +* * +* Description : Réduit le tampon à une quantité de lignes précise. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_buffer_cache_truncate(GBufferCache *cache, size_t max) +{ + size_t i; /* Boucle de parcours #1 */ + cache_info *info; /* Accès directe à une ligne */ + size_t j; /* Boucle de parcours #2 */ + size_t removed; /* Nombre de retraits effectués*/ + + assert(max <= cache->used); + + for (i = max; i < cache->used; i++) + { + info = &cache->lines[i]; + + if (info->count == 1) + g_object_unref(G_OBJECT(info->generator.instance)); + + else + { + for (j = 0; j < info->count; j++) + g_object_unref(G_OBJECT(info->generators[j].instance)); + + free(info->generators); + + } + + reset_cache_info_line(info); + + } + + removed = cache->used - max; + + cache->used = max - 1; + + if (removed > 0) + { + g_width_tracker_update_deleted(cache->tracker, max, max + removed - 1); + + g_signal_emit_by_name(cache, "size-changed", false, max, removed); + + } + +} + + +/****************************************************************************** +* * +* Paramètres : cache = tampon de lignes à venir consulter. * +* index = indice de la ligne visée par la consultation. * +* x = position géographique sur la ligne concernée. * +* addr = adresse à renseigner. [OUT] * +* * +* Description : Retrouve l'emplacement correspondant à une position de ligne.* +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_buffer_cache_get_line_addr(const GBufferCache *cache, size_t index, gint x, vmpa2t *addr) +{ + assert(index < cache->used); + + get_cache_info_addr(&cache->lines[index], index, x, addr); + +} + + +/****************************************************************************** +* * +* Paramètres : cache = tampon de lignes à venir consulter. * +* index = indice de la ligne visée par la consultation. * +* * +* Description : Détermine l'ensemble des propriétés attachées à une ligne. * +* * +* Retour : Somme de toutes les propriétés enregistrées. * +* * +* Remarques : - * +* * +******************************************************************************/ + +BufferLineFlags g_buffer_cache_get_line_flags(const GBufferCache *cache, size_t index) +{ + BufferLineFlags result; /* Somme à renvoyer */ + cache_info *info; /* Accès directe à une ligne */ + const generator_link *generator; /* Générateur retenu */ + size_t i; /* Boucle de parcours */ + + assert(index < cache->used); + + info = &cache->lines[index]; + + result = info->extra_flags; + + if (info->count == 1) + { + generator = &info->generator; + result |= g_line_generator_get_flags(generator->instance, index, generator->repeat); + } + + else + for (i = 0; i < info->count; i++) + { + generator = &info->generators[i]; + result |= g_line_generator_get_flags(generator->instance, index, generator->repeat); + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : cache = tampon de lignes à consulter. * +* index = indice de la ligne recherchée. * +* * +* Description : Retrouve une ligne au sein d'un tampon avec un indice. * +* * +* Retour : Line retrouvée ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBufferLine *g_buffer_cache_find_line_by_index(const GBufferCache *cache, size_t index) +{ + GBufferLine *result; /* Ligne trouvée à retourner */ + + if (index < cache->used) + result = get_cache_info_line(&cache->lines[index], index); + else + result = NULL; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : cache = tampon de lignes à venir consulter. * +* index = indice de la ligne à mesurer. * +* summary = largeurs maximales à faire évoluer. * +* * +* Description : Fait remonter les largeurs requises par une ligne donnée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_buffer_cache_collect_widths(GBufferCache *cache, size_t index, line_width_summary *summary) +{ + GBufferLine *line; /* Ligne éphémère à mesurer */ + + line = get_cache_info_line(&cache->lines[index], index); + + g_buffer_line_collect_widths(line, summary); + + g_object_unref(G_OBJECT(line)); + +} + + +/****************************************************************************** +* * +* Paramètres : cache = visualisation à représenter. * +* cr = contexte graphique dédié à la procédure. * +* first = première ligne à dessiner. * +* last = dernière ligne à dessiner. * +* area = position et surface à traiter. * +* display = règles d'affichage des colonnes modulables. * +* selected = ordonnée d'une ligne sélectionnée ou NULL. * +* list = liste de contenus à mettre en évidence. * +* * +* Description : Imprime une partie choisie du tampon contenant des lignes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_buffer_cache_draw(const GBufferCache *cache, cairo_t *cr, size_t first, size_t last, const cairo_rectangle_int_t *area, const bool *display, const gint *selected, const segcnt_list *list) +{ + GBufferCacheClass *class; /* Classe des tampons */ + gint y; /* Point de départ en ordonnée */ + bool wait_selection; /* Sélection déjà passée ? */ + size_t i; /* Boucle de parcours */ + cache_info *info; /* Accès directe à une ligne */ + line_width_summary summary; /* Résumé concis des largeurs */ + GBufferLine *line; /* Ligne à venir dessiner */ + + class = G_BUFFER_CACHE_GET_CLASS(cache); + + y = 0; + + wait_selection = true; + + if (cache->used > 0) + for (i = first; i <= last; i++) + { + /* Si sélection, on sousligne la ligne concernée */ + if (wait_selection && selected != NULL && *selected == y) + { + cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.05); + + cairo_rectangle(cr, area->x, y, area->width, class->line_height); + cairo_fill(cr); + + wait_selection = false; + + } + + info = &cache->lines[i]; + + if (i == first || (g_buffer_cache_get_line_flags(cache, i) & BLF_WIDTH_MANAGER)) + g_width_tracker_get_local_width_summary(cache->tracker, i, &summary); + + line = get_cache_info_line(info, i); + + g_buffer_line_draw(line, cr, &summary, class->text_pos, y, display, list); + + g_object_unref(G_OBJECT(line)); + + y += class->line_height; + + } + +} + + +/****************************************************************************** +* * +* Paramètres : cache = tampon de lignes à consulter. * +* addr = adresse à retrouver dans le tampon. * +* first = indique si on l'arrête à la première ou la dernière. * +* start = borne inférieure des recherches (incluse). * +* end = borne supérieure des recherches (incluse). * +* * +* Description : Indique l'indice correspondant à une adresse donnée. * +* * +* Retour : Indice des infos à l'adresse demandée, ou nombre de lignes. * +* * +* Remarques : - * +* * +******************************************************************************/ + +size_t _g_buffer_cache_find_index_by_addr(const GBufferCache *cache, const vmpa2t *addr, bool first, size_t start, size_t end) +{ + size_t result; /* Indice à retourner */ + cache_info *found; /* Eventuel élément trouvé */ + + int find_containing_generator(const vmpa2t *a, const cache_info *i) + { + const generator_link *generator; /* Générateur retenu */ + + if (i->count == 1) + generator = &i->generator; + else + generator = &i->generators[0]; + + return g_line_generator_contains_addr(generator->instance, addr, + i - cache->lines, generator->repeat); + + } + + found = (cache_info *)bsearch(addr, &cache->lines[start], end - start + 1, + sizeof(cache_info), (__compar_fn_t)find_containing_generator); + + if (found == NULL) + result = cache->used; + + else + { + result = (found - cache->lines); + assert(start <= result && result <= end); + + /* On s'assure d'un arrêt sur la bonne ligne */ + + if (first) + for (; result > start; result--) + { + found = &cache->lines[result - 1]; + + if (find_containing_generator(addr, found) != 0) + break; + + } + + else + for (; result < end; result++) + { + found = &cache->lines[result + 1]; + + if (find_containing_generator(addr, found) != 0) + break; + + } + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : cache = tampon de lignes à consulter. * +* addr = adresse à retrouver dans le tampon. * +* first = indique si on l'arrête à la première ou la dernière. * +* * +* Description : Indique l'indice correspondant à une adresse donnée. * +* * +* Retour : Indice des infos à l'adresse demandée, ou nombre de lignes. * +* * +* Remarques : - * +* * +******************************************************************************/ + +size_t g_buffer_cache_find_index_by_addr(const GBufferCache *cache, const vmpa2t *addr, bool first) +{ + size_t result; /* Indice à retourner */ + + if (cache->used == 0) + result = 0; + else + result = _g_buffer_cache_find_index_by_addr(cache, addr, first, 0, cache->used - 1); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : cache = tampon de lignes à consulter. * +* start = point de départ du parcours. * +* flag = propriétés à retrouver si possible. * +* * +* Description : Avance autant que possible vers une ligne idéale. * +* * +* Retour : Indice de la ligne recherchée, si elle existe. * +* * +* Remarques : - * +* * +******************************************************************************/ + +size_t g_buffer_cache_look_for_flag(const GBufferCache *cache, size_t start, BufferLineFlags flag) +{ + size_t result; /* Indice de ligne à retourner */ + vmpa2t start_addr; /* Localisation de départ */ + size_t i; /* Boucle de parcours */ + vmpa2t addr; /* Localisation suivante */ + + assert(start < cache->used); + + result = start; + + get_cache_info_addr(&cache->lines[start], start, 0, &start_addr); + + for (i = start + 1; i < cache->used; i++) + { + get_cache_info_addr(&cache->lines[i], i, 0, &addr); + + if (cmp_vmpa(&start_addr, &addr) != 0) + break; + + if ((g_buffer_cache_get_line_flags(cache, i) & flag) != 0) + { + result = i; + break; + } + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : cache = tampon de lignes à consulter. * +* addr = adresse à présenter à l'écran. * +* first = borne inférieure des recherches (incluse). * +* last = borne supérieure des recherches (incluse). * +* code = s'arrête si possible à une ligne avec code. * +* x = position horizontale au sein du composant. [OUT] * +* y = position verticale au sein du composant. [OUT] * +* * +* Description : Indique la position d'affichage d'une adresse donnée. * +* * +* Retour : true si l'adresse fait partie du composant, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_buffer_cache_get_address_coordinates(const GBufferCache *cache, const vmpa2t *addr, size_t first, size_t last, bool code, gint *x, gint *y) +{ + bool result; /* Bilan à retourner */ + size_t index; /* Indice de correspondance */ + gint lheight; /* Hauteur d'une ligne */ + const cache_info *info; /* Infos sur une ligne donnée */ + const generator_link *generator; /* Générateur retenu */ + + index = _g_buffer_cache_find_index_by_addr(cache, addr, true, first, last); + + result = (index < cache->used); + + if (result) + { + lheight = G_BUFFER_CACHE_GET_CLASS(cache)->line_height; + + *x = 0; + *y = (index - first) * G_BUFFER_CACHE_GET_CLASS(cache)->line_height; + + for (; code && index <= last; index++) + { + if (g_buffer_cache_get_line_flags(cache, index) & BLF_HAS_CODE) + break; + + if (index == last) + break; + + info = &cache->lines[index + 1]; + + if (info->count == 1) + generator = &info->generator; + else + generator = &info->generators[0]; + + if (!g_line_generator_contains_addr(generator->instance, addr, index + 1, generator->repeat)) + break; + + *y += lheight; + + } + + } + + return result; + +} diff --git a/src/glibext/gbuffercache.h b/src/glibext/gbuffercache.h new file mode 100644 index 0000000..6e9c314 --- /dev/null +++ b/src/glibext/gbuffercache.h @@ -0,0 +1,121 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * gbuffercache.h - prototypes pour l'affichage à la demande d'un ensemble de lignes + * + * Copyright (C) 2016 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide 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. + * + * Chrysalide 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_GBUFFERCACHE_H +#define _GLIBEXT_GBUFFERCACHE_H + + +#include <glib-object.h> +#include <stdbool.h> +#include <gdk/gdk.h> + + +#include "gwidthtracker.h" +#include "linegen.h" + + + +/* -------------------------- TAMPON POUR CODE DESASSEMBLE -------------------------- */ + + +#define G_TYPE_BUFFER_CACHE (g_buffer_cache_get_type()) +#define G_BUFFER_CACHE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_CODE_BUFFER, GBufferCache)) +#define G_BUFFER_CACHE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_CODE_BUFFER, GBufferCacheClass)) +#define G_IS_BUFFER_CACHE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_CODE_BUFFER)) +#define G_IS_BUFFER_CACHE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_CODE_BUFFER)) +#define G_BUFFER_CACHE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_CODE_BUFFER, GBufferCacheClass)) + + +/* Tampon pour gestion de lignes optimisée (instance) */ +typedef struct _GBufferCache GBufferCache; + +/* Tampon pour gestion de lignes optimisée (classe) */ +typedef struct _GBufferCacheClass GBufferCacheClass; + + +/* Détermine le type du composant de tampon pour gestion de lignes optimisée. */ +GType g_buffer_cache_get_type(void); + +/* Crée un nouveau composant de tampon pour code désassemblé. */ +GBufferCache *g_buffer_cache_new(void); + +/* Fournit la hauteur d'impression d'une ligne visualisée. */ +gint g_buffer_cache_get_line_height(const GBufferCache *); + +/* Fournit la taille réservée pour la marge gauche. */ +gint g_buffer_cache_get_left_margin(const GBufferCache *); + +/* Fournit la position de départ pour l'impression de texte. */ +gint g_buffer_cache_get_text_position(const GBufferCache *); + +/* Compte le nombre de lignes rassemblées dans un tampon. */ +size_t g_buffer_cache_count_lines(const GBufferCache *); + +/* Fournit un lien vers la structure de suivi de largeurs. */ +const GWidthTracker *g_buffer_cache_get_width_tracker(const GBufferCache *); + +/* Insère un générateur dans des lignes à une position donnée. */ +void g_buffer_cache_insert_at(GBufferCache *, size_t, GLineGenerator *, bool, bool); + +/* Retire un type de générateur de lignes. */ +GLineGenerator *g_buffer_cache_delete_type_at(GBufferCache *, size_t, GType, bool, bool); + +/* Ajoute en fin de tampon un générateur de lignes. */ +void g_buffer_cache_append(GBufferCache *, GLineGenerator *, BufferLineFlags); + +/* Etend un tampon avec un générateur de lignes unique. */ +void g_buffer_cache_extend_with(GBufferCache *, size_t, GLineGenerator *); + +/* Réduit le tampon à une quantité de lignes précise. */ +void g_buffer_cache_truncate(GBufferCache *, size_t); + +/* Retrouve l'emplacement correspondant à une position de ligne. */ +void g_buffer_cache_get_line_addr(const GBufferCache *, size_t, gint, vmpa2t *); + +/* Détermine l'ensemble des propriétés attachées à une ligne. */ +BufferLineFlags g_buffer_cache_get_line_flags(const GBufferCache *, size_t); + +/* Retrouve une ligne au sein d'un tampon avec un indice. */ +GBufferLine *g_buffer_cache_find_line_by_index(const GBufferCache *, size_t); + +/* Fait remonter les largeurs requises par une ligne donnée. */ +void g_buffer_cache_collect_widths(GBufferCache *, size_t, line_width_summary *); + +/* Imprime une partie choisie du tampon contenant des lignes. */ +void g_buffer_cache_draw(const GBufferCache *, cairo_t *, size_t, size_t, const cairo_rectangle_int_t *, const bool *, const gint *, const segcnt_list *); + +/* Indique l'indice correspondant à une adresse donnée. */ +size_t _g_buffer_cache_find_index_by_addr(const GBufferCache *, const vmpa2t *, bool, size_t, size_t); + +/* Indique l'indice correspondant à une adresse donnée. */ +size_t g_buffer_cache_find_index_by_addr(const GBufferCache *, const vmpa2t *, bool); + +/* Avance autant que possible vers une ligne idéale. */ +size_t g_buffer_cache_look_for_flag(const GBufferCache *, size_t, BufferLineFlags); + +/* Indique la position d'affichage d'une adresse donnée. */ +bool g_buffer_cache_get_address_coordinates(const GBufferCache *, const vmpa2t *, size_t, size_t, bool, gint *, gint *); + + + +#endif /* _GLIBEXT_GBUFFERCACHE_H */ diff --git a/src/glibext/gbufferline.c b/src/glibext/gbufferline.c index 5f1756d..768cbca 100644 --- a/src/glibext/gbufferline.c +++ b/src/glibext/gbufferline.c @@ -56,7 +56,7 @@ struct _GBufferLine mrange_t range; /* Couverture geographique */ BufferLineColumn main_column; /* Colonne principale */ - line_column columns[BLC_COUNT]; /* Répartition du texte */ + line_column columns[BLC_COUNT]; /* Répartition du texte */ BufferLineColumn merge_start; /* Début de la zone globale */ BufferLineColumn last_used; /* Dernière colonne utilisée */ @@ -72,7 +72,6 @@ struct _GBufferLine gint max_widths[BLC_COUNT]; /* Taille cachée des colonnes */ gint merged_width; /* Largeur cumulée avant fusion*/ }; - GBufferLine *manager; /* Représentante d'un groupe */ }; }; @@ -214,9 +213,6 @@ static void g_buffer_line_dispose(GBufferLine *line) { size_t i; /* Boucle de parcours */ - if (line->flags & BLF_WIDTH_MANAGER) - g_object_unref(G_OBJECT(line->manager)); - for (i = 0; i < line->ocount; i++) g_object_unref(G_OBJECT(line->origins[i].creator)); @@ -298,9 +294,9 @@ const mrange_t *g_buffer_line_get_range(const GBufferLine *line) /****************************************************************************** * * -* Paramètres : line = ligne à venir compléter. * -* psize = taille souhaitée de l'impression des positions. * -* vsize = taille souhaitée de l'impression des adresses. * +* Paramètres : line = ligne à venir compléter. * +* size = taille souhaitée de l'impression des positions. * +* addr = localisation physique à venir représenter. * * * * Description : Construit le tronc commun d'une ligne autour de sa position. * * * @@ -310,61 +306,105 @@ const mrange_t *g_buffer_line_get_range(const GBufferLine *line) * * ******************************************************************************/ -void g_buffer_line_fill_mrange(GBufferLine *line, MemoryDataSize psize, MemoryDataSize vsize) +void g_buffer_line_fill_phys(GBufferLine *line, MemoryDataSize size, const vmpa2t *addr) { + VMPA_BUFFER(position); /* Emplacement au format texte */ size_t len; /* Taille de l'élément inséré */ - VMPA_BUFFER(address); /* Adresse au format texte */ - size_t i; /* Boucle de parcours */ + size_t i; /* Boucle de parcours #1 */ - /* Position physique */ + vmpa2_phys_to_string(addr, size, position, &len); - if (has_phys_addr(get_mrange_addr(&line->range))) - { - mrange_phys_to_string(&line->range, psize, true, address, &len); + for (i = 2; i < len; i++) + if (position[i] != '0') break; - for (i = 2; i < len; i++) - if (address[i] != '0') break; + if (i == len) + i = len - 1; - if (i == len) - g_buffer_line_append_text(line, BLC_PHYSICAL, address, len, RTT_PHYS_ADDR_PAD, NULL); + if (i > 0) + g_buffer_line_append_text(line, BLC_PHYSICAL, position, i, RTT_PHYS_ADDR_PAD, NULL); - else - { - g_buffer_line_append_text(line, BLC_PHYSICAL, address, 2, RTT_PHYS_ADDR, NULL); + g_buffer_line_append_text(line, BLC_PHYSICAL, &position[i], len - i, RTT_PHYS_ADDR, NULL); - if (i > 2) - g_buffer_line_append_text(line, BLC_PHYSICAL, &address[2], i - 2, RTT_PHYS_ADDR_PAD, NULL); +} - g_buffer_line_append_text(line, BLC_PHYSICAL, &address[i], len - i, RTT_PHYS_ADDR, NULL); - } +/****************************************************************************** +* * +* Paramètres : line = ligne à venir compléter. * +* size = taille souhaitée de l'impression des positions. * +* addr = localisation virtuelle à venir représenter. * +* * +* Description : Construit le tronc commun d'une ligne autour de sa position. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ - } +void g_buffer_line_fill_virt(GBufferLine *line, MemoryDataSize size, const vmpa2t *addr) +{ + VMPA_BUFFER(position); /* Emplacement au format texte */ + size_t len; /* Taille de l'élément inséré */ + size_t i; /* Boucle de parcours #1 */ + + vmpa2_virt_to_string(addr, size, position, &len); + + for (i = 2; i < len; i++) + if (position[i] != '0') break; + + if (i == len) + i = len - 1; + + if (i > 0) + g_buffer_line_append_text(line, BLC_VIRTUAL, position, i, RTT_PHYS_ADDR_PAD, NULL); - /* Adresse virtuelle */ + g_buffer_line_append_text(line, BLC_VIRTUAL, &position[i], len - i, RTT_PHYS_ADDR, NULL); + +} - if (has_virt_addr(get_mrange_addr(&line->range))) - { - mrange_virt_to_string(&line->range, vsize, true, address, &len); - for (i = 2; i < len; i++) - if (address[i] != '0') break; +/****************************************************************************** +* * +* Paramètres : line = ligne à venir compléter. * +* addr = localisation à afficher. * +* psize = taille souhaitée de l'impression des positions. * +* vsize = taille souhaitée de l'impression des adresses. * +* * +* Description : Construit le tronc commun d'une ligne autour de sa position. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ - if (i == len) - g_buffer_line_append_text(line, BLC_VIRTUAL, address, len, RTT_VIRT_ADDR_PAD, NULL); +void g_buffer_line_fill_vmpa(GBufferLine *line, const vmpa2t *addr, MemoryDataSize psize, MemoryDataSize vsize) +{ + g_buffer_line_fill_phys(line, psize, addr); - else - { - g_buffer_line_append_text(line, BLC_VIRTUAL, address, 2, RTT_VIRT_ADDR, NULL); + g_buffer_line_fill_virt(line, vsize, addr); - if (i > 2) - g_buffer_line_append_text(line, BLC_VIRTUAL, &address[2], i - 2, RTT_VIRT_ADDR_PAD, NULL); +} - g_buffer_line_append_text(line, BLC_VIRTUAL, &address[i], len - i, RTT_VIRT_ADDR, NULL); - } +/****************************************************************************** +* * +* Paramètres : line = ligne à venir compléter. * +* psize = taille souhaitée de l'impression des positions. * +* vsize = taille souhaitée de l'impression des adresses. * +* * +* Description : Construit le tronc commun d'une ligne autour de sa position. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ - } +void g_buffer_line_fill_mrange(GBufferLine *line, MemoryDataSize psize, MemoryDataSize vsize) +{ + g_buffer_line_fill_vmpa(line, get_mrange_addr(&line->range), psize, vsize); } @@ -531,7 +571,7 @@ void g_buffer_line_append_text(GBufferLine *line, BufferLineColumn column, const assert(length > 0); if (column == BLC_MAIN) - column = line->main_column; + column = BLC_ASSEMBLY;//line->main_column; if (column == BLC_LAST_USED) column = line->last_used; @@ -938,6 +978,13 @@ void g_buffer_line_collect_widths(GBufferLine *line, line_width_summary *summary { width = get_column_width(&line->columns[i]); + + /* + if (i == BLC_ASSEMBLY_HEAD) + assert(width > 0); + */ + + if (i < line->merge_start) summary->max_widths[i] = MAX(summary->max_widths[i], width); @@ -1008,7 +1055,10 @@ const line_segment *g_buffer_line_get_segment_from_coord(const GBufferLine *line { line_segment *result; /* Trouvaille à retourner */ - result = get_line_column_content_from_index(&line->columns[coord->column], coord->index); + if (coord->column < BLC_COUNT) + result = get_line_column_content_from_index(&line->columns[coord->column], coord->index); + else + result = false; return result; @@ -1069,6 +1119,9 @@ bool g_buffer_line_get_coord_at(const GBufferLine *line, const line_width_summar { width = g_buffer_line_compute_max_width(line, i, summary); + /* Si la colonne n'est absolument pas visible, on ne s'arrête pas dessus ! */ + if (width == 0) continue; + if ((i + 1) < BLC_COUNT) limit = width + COL_MARGIN / 2; else limit = width; @@ -1139,7 +1192,10 @@ bool g_buffer_line_get_coord_at(const GBufferLine *line, const line_width_summar if ((i - 1) < line->merge_start) { width = g_buffer_line_compute_max_width(line, i - 1, summary); - *base += (width + COL_MARGIN); + + if (width > 0) + *base += (width + COL_MARGIN); + } else *base += get_column_width(&line->columns[i - 1]); @@ -1183,8 +1239,19 @@ bool g_buffer_line_get_coord_at(const GBufferLine *line, const line_width_summar } } + + /* Il n'y a rien sur la ligne ! */ else - result = false; + { + result = true; + + *base = 0; + *offset = 0; + + coord->column = BLC_COUNT; + coord->index = -1; + + } } else @@ -1305,6 +1372,7 @@ bool g_buffer_line_find_near_coord(const GBufferLine *line, col_coord_t *coord, BufferLineColumn i; /* Boucle de parcours #1 */ bool displayed; /* Confort de lecture */ BufferLineColumn k; /* Boucle de parcours #2 */ + gint width; /* Largeur d'une colonne donnée*/ result = false; @@ -1381,8 +1449,14 @@ bool g_buffer_line_find_near_coord(const GBufferLine *line, col_coord_t *coord, if (displayed) { - *offset += g_buffer_line_compute_max_width(line, k, summary); - if (k < line->merge_start) *offset += COL_MARGIN; + width = g_buffer_line_compute_max_width(line, k, summary); + + if (width > 0) + { + *offset += width; + if (k < line->merge_start) *offset += COL_MARGIN; + } + } } @@ -1469,10 +1543,8 @@ void g_buffer_line_draw(GBufferLine *line, cairo_t *cairo, const line_width_summ { max_width = g_buffer_line_compute_max_width(line, i, summary); - x += max_width; - if (max_width > 0) - x += COL_MARGIN; + x += max_width + COL_MARGIN; } diff --git a/src/glibext/gbufferline.h b/src/glibext/gbufferline.h index be7e138..a8d2f3f 100644 --- a/src/glibext/gbufferline.h +++ b/src/glibext/gbufferline.h @@ -109,6 +109,15 @@ GBufferLine *g_buffer_line_new(const mrange_t *, BufferLineColumn); const mrange_t *g_buffer_line_get_range(const GBufferLine *); /* Construit le tronc commun d'une ligne autour de sa position. */ +void g_buffer_line_fill_phys(GBufferLine *, MemoryDataSize, const vmpa2t *); + +/* Construit le tronc commun d'une ligne autour de sa position. */ +void g_buffer_line_fill_virt(GBufferLine *, MemoryDataSize, const vmpa2t *); + +/* Construit le tronc commun d'une ligne autour de sa position. */ +void g_buffer_line_fill_vmpa(GBufferLine *, const vmpa2t *, MemoryDataSize, MemoryDataSize); + +/* Construit le tronc commun d'une ligne autour de sa position. */ void g_buffer_line_fill_mrange(GBufferLine *, MemoryDataSize, MemoryDataSize); /* Construit le tronc commun d'une ligne d'instruction. */ diff --git a/src/glibext/gbufferview.c b/src/glibext/gbufferview.c index 20d60ed..cd17191 100644 --- a/src/glibext/gbufferview.c +++ b/src/glibext/gbufferview.c @@ -24,14 +24,21 @@ #include "gbufferview.h" +#include <assert.h> + + /* Vue d'un tampon pour code désassemblé (instance) */ struct _GBufferView { GObject parent; /* A laisser en premier */ - GCodeBuffer *buffer; /* Tampon de code visualisé */ + GBufferCache *cache; /* Tampon du contenu visualisé */ + + segcnt_list *highlighted; /* Segments mis en évidence */ + bool external; /* Note l'origine de la liste */ + bool unrestricted; /* Validité des informations */ vmpa2t start; /* Première ligne intégrée */ vmpa2t end; /* Dernière ligne intégrée */ @@ -45,11 +52,6 @@ struct _GBufferView GWidthTracker *tracker; /* Suivi pour usage interne */ }; - bool unrestricted; /* Validité des informations */ - - segcnt_list *highlighted; /* Segments mis en évidence */ - bool external; /* Note l'origine de la liste */ - }; /* Vue d'un tampon pour code désassemblé (classe) */ @@ -57,10 +59,6 @@ struct _GBufferViewClass { GObjectClass parent; /* A laisser en premier */ - gint line_height; /* Hauteur maximale des lignes */ - gint left_margin; /* Marge gauche + espace */ - gint left_text; /* Début d'impression du code */ - /* Signaux */ void (* need_redraw) (GBufferView *); @@ -81,15 +79,23 @@ static void g_buffer_view_dispose(GBufferView *); static void g_buffer_view_finalize(GBufferView *); /* Accompagne une variation de la quantité de lignes du tampon. */ -static void on_buffer_size_changed(const GCodeBuffer *, bool, size_t, size_t, GBufferView *); +static void on_buffer_cache_size_changed(const GBufferCache *, bool, size_t, size_t, GBufferView *); -/* Réagit à un changement de contenu d'une ligne donnée. */ -static void on_buffer_line_changed(GCodeBuffer *, GBufferLine *, line_segment *, GBufferView *); +/* Calcule la position idéale de curseur pour un point donné. */ +bool _g_buffer_view_compute_caret_full(GBufferView *, gint, GBufferLine *, size_t, const bool *, GdkRectangle *, vmpa2t *); /* Déplace le curseur au sein d'une vue de tampon. */ static bool _g_buffer_view_move_caret(GBufferView *, const GBufferLine *, size_t, GdkRectangle *, bool, GdkScrollDirection, const bool *); +/* Fournit la ligne présente à une ordonnée donnée. */ +static GBufferLine *g_buffer_view_find_line_at(GBufferView *, gint, size_t *); + + + + + + /* Détermine le type de la vue d'un tampon pour code désassemblé. */ G_DEFINE_TYPE(GBufferView, g_buffer_view, G_TYPE_OBJECT); @@ -116,10 +122,7 @@ static void g_buffer_view_class_init(GBufferViewClass *class) object->dispose = (GObjectFinalizeFunc/* ! */)g_buffer_view_dispose; object->finalize = (GObjectFinalizeFunc)g_buffer_view_finalize; - class->line_height = 17; - class->left_margin = 2 * class->line_height; - class->left_text = 2.5 * class->line_height; - + /* Sigaux */ g_signal_new("need-redraw", G_TYPE_BUFFER_VIEW, @@ -146,7 +149,10 @@ static void g_buffer_view_class_init(GBufferViewClass *class) static void g_buffer_view_init(GBufferView *view) { - view->unrestricted = true; + /** + * Inversion du statut pour forcer l'actualisation lors de la création. + */ + view->unrestricted = false; } @@ -165,7 +171,10 @@ static void g_buffer_view_init(GBufferView *view) static void g_buffer_view_dispose(GBufferView *view) { - g_object_unref(G_OBJECT(view->buffer)); + g_object_unref(G_OBJECT(view->cache)); + + if (!view->unrestricted) + g_object_unref(G_OBJECT(view->int_tracker)); G_OBJECT_CLASS(g_buffer_view_parent_class)->dispose(G_OBJECT(view)); @@ -207,22 +216,17 @@ static void g_buffer_view_finalize(GBufferView *view) * * ******************************************************************************/ -GBufferView *g_buffer_view_new(GCodeBuffer *buffer, segcnt_list *highlighted) +GBufferView *g_buffer_view_new(GBufferCache *cache, segcnt_list *highlighted) { GBufferView *result; /* Composant à retourner */ result = g_object_new(G_TYPE_BUFFER_VIEW, NULL); - g_object_ref(G_OBJECT(buffer)); - result->buffer = buffer; + result->cache = cache; g_buffer_view_restrict(result, NULL, NULL); - g_code_buffer_register_view_callback(buffer, - (buffer_size_changed_cb)on_buffer_size_changed, - G_OBJECT(result)); - - g_signal_connect(buffer, "line-changed", G_CALLBACK(on_buffer_line_changed), result); + g_signal_connect(cache, "size-changed", G_CALLBACK(on_buffer_cache_size_changed), result); if (highlighted != NULL) result->highlighted = highlighted; @@ -238,11 +242,11 @@ GBufferView *g_buffer_view_new(GCodeBuffer *buffer, segcnt_list *highlighted) /****************************************************************************** * * -* Paramètres : buffer = tampon de lignes cohérentes à manipuler. * -* added = indication sur la variation de la taille du tampon. * -* index = indice de la première ligne à traiter. * -* count = nombre de lignes à traiter. * -* view = vue active du tampon de lignes concerné. * +* Paramètres : cache = tampon de lignes cohérentes à manipuler. * +* added = indication sur la variation de la taille du tampon. * +* index = indice de la première ligne à traiter. * +* count = nombre de lignes à traiter. * +* view = vue active du tampon de lignes concerné. * * * * Description : Accompagne une variation de la quantité de lignes du tampon. * * * @@ -252,11 +256,11 @@ GBufferView *g_buffer_view_new(GCodeBuffer *buffer, segcnt_list *highlighted) * * ******************************************************************************/ -static void on_buffer_size_changed(const GCodeBuffer *buffer, bool added, size_t index, size_t count, GBufferView *view) +static void on_buffer_cache_size_changed(const GBufferCache *cache, bool added, size_t index, size_t count, GBufferView *view) { - size_t i; /* Boucle de parcours */ - GBufferLine *line; /* Ligne à manipuler */ - const vmpa2t *addr; /* Localisation de ligne */ + //size_t i; /* Boucle de parcours */ + //GBufferLine *line; /* Ligne à manipuler */ + //const vmpa2t *addr; /* Localisation de ligne */ /** * Il n'y a pas besoin de verrou ici car la fonction est appelée directement par le tampon. @@ -270,6 +274,8 @@ static void on_buffer_size_changed(const GCodeBuffer *buffer, bool added, size_t else { +#if 0 + /* Avant la zone représentée ? */ if (index < view->first) { @@ -281,6 +287,8 @@ static void on_buffer_size_changed(const GCodeBuffer *buffer, bool added, size_t else if (view->first == index) for (i = 0; i < count; i++) { + g_buffer_cache_get_line_addr(const GBufferCache *, size_t, gint, vmpa2t *); + line = g_code_buffer_find_line_by_index(buffer, index + i); addr = get_mrange_addr(g_buffer_line_get_range(line)); @@ -302,6 +310,8 @@ static void on_buffer_size_changed(const GCodeBuffer *buffer, bool added, size_t else if ((view->last + 1) == index) for (i = 0; i < count; i++) { + g_buffer_cache_get_line_addr(const GBufferCache *, size_t, gint, vmpa2t *); + line = g_code_buffer_find_line_by_index(buffer, index + i); addr = get_mrange_addr(g_buffer_line_get_range(line)); @@ -312,7 +322,8 @@ static void on_buffer_size_changed(const GCodeBuffer *buffer, bool added, size_t } - g_width_tracker_update_added(view->int_tracker, index, count); + //g_width_tracker_update_added(view->int_tracker, index, count); +#endif } @@ -338,38 +349,36 @@ static void on_buffer_size_changed(const GCodeBuffer *buffer, bool added, size_t } - g_width_tracker_update_deleted(view->int_tracker, index, index + count - 1); + //g_width_tracker_update_deleted(view->int_tracker, index, index + count - 1); } - g_signal_emit_by_name(view, "need-redraw"); + //g_signal_emit_by_name(view, "need-redraw"); } /****************************************************************************** * * -* Paramètres : buffer = tampon de lignes cohérentes à manipuler. * -* line = ligne dont la définition vient d'évoluer. * -* segment = éventuel segment qui vient d'évoluer ou NULL. * -* view = vue active du tampon de lignes concerné. * +* Paramètres : view = visualisateur à consulter. * * * -* Description : Réagit à un changement de contenu d'une ligne donnée. * +* Description : Fournit le tampon de code lié à un visualisateur donné. * * * -* Retour : - * +* Retour : Tampon de code associé au gestionnaire d'affichage. * * * * Remarques : - * * * ******************************************************************************/ -static void on_buffer_line_changed(GCodeBuffer *buffer, GBufferLine *line, line_segment *segment, GBufferView *view) +GBufferCache *g_buffer_view_get_cache(const GBufferView *view) { - const vmpa2t *addr; /* Localisation de ligne */ + GBufferCache *result; /* Instance à retourner */ - addr = get_mrange_addr(g_buffer_line_get_range(line)); + result = view->cache; - if (cmp_vmpa(&view->start, addr) <= 0 && cmp_vmpa(addr, &view->end) <= 0) - g_signal_emit_by_name(view, "need-redraw"); + g_object_ref(G_OBJECT(result)); + + return result; } @@ -390,33 +399,41 @@ static void on_buffer_line_changed(GCodeBuffer *buffer, GBufferLine *line, line_ void g_buffer_view_restrict(GBufferView *view, const vmpa2t *start, const vmpa2t *end) { + bool state; /* Nouvel état à proclamer */ const GWidthTracker *template; /* Suivi déjà en place */ - if (!view->unrestricted) - g_object_unref(G_OBJECT(view->int_tracker)); + state = (start == NULL || end == NULL); - view->unrestricted = (start == NULL || end == NULL); + if (view->unrestricted != state) + { + view->unrestricted = state; - template = g_code_buffer_get_width_tracker(view->buffer); + template = g_buffer_cache_get_width_tracker(view->cache); - if (view->unrestricted) - { - view->first = 0; - view->last = g_code_buffer_count_lines(view->buffer) - 1; + if (view->unrestricted) + { + /* Vérification pour le cas particulier du démarrage */ + if (view->int_tracker != NULL) + g_object_unref(G_OBJECT(view->int_tracker)); - view->ext_tracker = template; + view->first = 0; + view->last = g_buffer_cache_count_lines(view->cache) - 1; - } + view->ext_tracker = template; - else - { - copy_vmpa(&view->start, start); - copy_vmpa(&view->end, end); + } + + else + { + copy_vmpa(&view->start, start); + copy_vmpa(&view->end, end); + + view->first = g_buffer_cache_find_index_by_addr(view->cache, start, true); + view->last = g_buffer_cache_find_index_by_addr(view->cache, end, false); - view->first = g_code_buffer_get_index_from_address(view->buffer, start, true); - view->last = g_code_buffer_get_index_from_address(view->buffer, end, false); + view->ext_tracker = g_width_tracker_new_restricted(template, view->first, view->last); - view->ext_tracker = g_width_tracker_new_restricted(template, view->first, view->last); + } } @@ -425,7 +442,7 @@ void g_buffer_view_restrict(GBufferView *view, const vmpa2t *start, const vmpa2t /****************************************************************************** * * -* Paramètres : view = visualisateur à mettre à jour. * +* Paramètres : view = visualisateur à consulter. * * first = première ligne à imprimer ou NULL. [OUT] * * last = première ligne hors cadre ou NULL. [OUT] * * * @@ -437,7 +454,7 @@ void g_buffer_view_restrict(GBufferView *view, const vmpa2t *start, const vmpa2t * * ******************************************************************************/ -bool g_buffer_view_get_restrictions(GBufferView *view, vmpa2t *start, vmpa2t *end) +bool g_buffer_view_get_restrictions(const GBufferView *view, vmpa2t *start, vmpa2t *end) { if (!view->unrestricted) { @@ -450,44 +467,11 @@ bool g_buffer_view_get_restrictions(GBufferView *view, vmpa2t *start, vmpa2t *en } -/****************************************************************************** -* * -* Paramètres : view = visualisateur à consulter. * -* * -* Description : Fournit le tampon de code lié à un visualisateur donné. * -* * -* Retour : Tampon de code associé au gestionnaire d'affichage. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GCodeBuffer *g_buffer_view_get_buffer(const GBufferView *view) -{ - g_object_ref(G_OBJECT(view->buffer)); - - return view->buffer; -} -/****************************************************************************** -* * -* 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) -{ - return G_BUFFER_VIEW_GET_CLASS(view)->line_height; -} /****************************************************************************** @@ -507,7 +491,7 @@ gint g_buffer_view_get_width(GBufferView *view, const bool *display) { gint result; /* Taille à retourner */ - result = G_BUFFER_VIEW_GET_CLASS(view)->left_text; + result = g_buffer_cache_get_text_position(view->cache); result += g_width_tracker_get_width(view->tracker, display); @@ -533,7 +517,7 @@ gint g_buffer_view_get_margin(GBufferView *view, const bool *display) { gint result; /* Taille à retourner */ - result = G_BUFFER_VIEW_GET_CLASS(view)->left_text; + result = g_buffer_cache_get_text_position(view->cache); result += g_width_tracker_get_margin(view->tracker, display); @@ -558,7 +542,7 @@ gint g_buffer_view_get_height(const GBufferView *view) { gint result; /* Taille à retourner */ - result = G_BUFFER_VIEW_GET_CLASS(view)->line_height; + result = g_buffer_cache_get_line_height(view->cache); result *= (view->last - view->first + 1); @@ -567,50 +551,66 @@ gint g_buffer_view_get_height(const GBufferView *view) } + + + + + + + + + + + /****************************************************************************** * * * Paramètres : view = vue de tampon à mettre à jour. * -* x = abscisse de la zone principale à traiter. * -* y = ordonnée de la zone principale à traiter. * +* x = abscisse proposée pour le nouvel emplacement. * +* y = ordonnée proposée pour le nouvel emplacement. * * display = règles d'affichage des colonnes modulables. * * caret = position du curseur à construire. [OUT] * +* addr = adresse correspondant à cette même position. [OUT] * * * * Description : Calcule la position idéale de curseur pour un point donné. * * * -* Retour : Adresse si une a pu être déterminée, NULL sinon. * +* Retour : true si les deux derniers arguments ont pu être constitués. * * * * Remarques : - * * * ******************************************************************************/ -const vmpa2t *g_buffer_view_compute_caret(GBufferView *view, gint x, gint y, const bool *display, GdkRectangle *caret) +bool g_buffer_view_compute_caret_full(GBufferView *view, gint x, gint y, const bool *display, GdkRectangle *caret, vmpa2t *addr) { - gint remaining; /* Copie de travail modifiable */ + bool result; /* Bilan à retourner */ + gint lheight; /* Hauteur d'une ligne */ size_t index; /* Indice de ligne de tampon */ GBufferLine *line; /* Ligne à la position courante*/ - const line_segment *segment; /* Segment présent sur la place*/ - GBufferViewClass *class; /* Classe pour les vues */ - remaining = x; + result = false; - line = g_buffer_view_find_line_and_segment_at(view, &remaining, y, &index, display, &segment); + /* Détermination de la ligne courante */ - /* FIXME : unref() ! */ - if (line == NULL) return NULL; - if (segment == NULL) printf(" -- no segment\n"); - if (segment == NULL) return NULL; + lheight = g_buffer_cache_get_line_height(view->cache); + index = y / lheight; + index += view->first; - class = G_BUFFER_VIEW_GET_CLASS(view); + if (index > view->last) + goto gbvccf_done; - caret->x = /*view->left_text +*/ (x - remaining) + get_caret_position_from_line_segment(segment, remaining); + line = g_buffer_cache_find_line_by_index(view->cache, index); - caret->y = (index - view->first) * class->line_height; + assert(line != NULL); - caret->width = 2; - caret->height = class->line_height; + /* Calcul d'une position */ + + result = _g_buffer_view_compute_caret_full(view, x, line, index, display, caret, addr); + + g_object_unref(G_OBJECT(line)); + + gbvccf_done: - return get_mrange_addr(g_buffer_line_get_range(line)); + return result; } @@ -618,50 +618,69 @@ const vmpa2t *g_buffer_view_compute_caret(GBufferView *view, gint x, gint y, con /****************************************************************************** * * * Paramètres : view = vue de tampon à mettre à jour. * +* x = abscisse proposée pour le nouvel emplacement. * * line = ligne correspondant à la position. * * index = indice de cette même ligne dans le tampon. * -* x = abscisse de la zone principale à traiter. * * display = règles d'affichage des colonnes modulables. * * caret = position du curseur à construire. [OUT] * +* addr = adresse correspondant à cette même position. [OUT] * * * * Description : Calcule la position idéale de curseur pour un point donné. * * * -* Retour : Adresse si une a pu être déterminée, NULL sinon. * +* Retour : true si les deux derniers arguments ont pu être constitués. * * * * Remarques : - * * * ******************************************************************************/ -const vmpa2t *g_buffer_view_compute_caret_full(GBufferView *view, GBufferLine *line, size_t index, gint x, const bool *display, GdkRectangle *caret) +bool _g_buffer_view_compute_caret_full(GBufferView *view, gint x, GBufferLine *line, size_t index, const bool *display, GdkRectangle *caret, vmpa2t *addr) { - GBufferViewClass *class; /* Classe pour les vues */ - gint offset; /* Point de travail modifiable */ + bool result; /* Bilan à retourner */ + gint text_pos; /* Abscisse de départ du texte */ line_width_summary summary; /* Résumé concis des largeurs */ gint base; /* Position absolue de segment */ bool status; /* Bilan de la localisation */ + gint lheight; /* Hauteur d'une ligne */ - class = G_BUFFER_VIEW_GET_CLASS(view); + result = false; - offset = x; + /* Zone d'intervention bornée ! */ - offset -= class->left_text; - if (offset < 0) return NULL; + text_pos = g_buffer_cache_get_text_position(view->cache); + + if (x < text_pos) + goto gbvccf_done; + + /* Calcul d'une position */ g_width_tracker_get_local_width_summary(view->tracker, index, &summary); - /* Traitement pour mise à jour de l'abscisse uniquement */ - status = g_buffer_line_get_coord_at(line, &summary, display, &base, &offset, + x -= text_pos; + + status = g_buffer_line_get_coord_at(line, &summary, display, &base, &x, GDK_SCROLL_LEFT, true, (col_coord_t []) { { 0 } }); - if (!status) return NULL; - caret->x = class->left_text + base + offset; + if (!status) + goto gbvccf_done; + + /* Transmission des informations */ + + lheight = g_buffer_cache_get_line_height(view->cache); - caret->y = (index - view->first) * class->line_height; + caret->x = text_pos + base + x; + + caret->y = (index - view->first) * lheight; caret->width = 2; - caret->height = class->line_height; + caret->height = lheight; + + g_buffer_cache_get_line_addr(view->cache, index, caret->x, addr); + + result = true; - return get_mrange_addr(g_buffer_line_get_range(line)); + gbvccf_done: + + return result; } @@ -687,16 +706,24 @@ const vmpa2t *g_buffer_view_compute_caret_full(GBufferView *view, GBufferLine *l static bool _g_buffer_view_move_caret(GBufferView *view, const GBufferLine *line, size_t index, GdkRectangle *caret, bool ctrl, GdkScrollDirection dir, const bool *display) { bool result; /* Bilan à retourner */ + gint text_pos; /* Abscisse de départ du texte */ gint offset; /* Point de travail modifiable */ line_width_summary summary; /* Résumé concis des largeurs */ gint base; /* Position absolue de segment */ col_coord_t coord; /* Coordonnées en interne */ const line_segment *segment; /* Bribe de texte trouvée */ - offset = caret->x; - offset -= G_BUFFER_VIEW_GET_CLASS(view)->left_text; - if (offset < 0) return false; + result = false; + + /* Zone d'intervention bornée ! */ + + text_pos = g_buffer_cache_get_text_position(view->cache); + + if (caret->x < text_pos) + goto gbvmc_done; + + offset = caret->x - text_pos; g_width_tracker_get_local_width_summary(view->tracker, index, &summary); @@ -725,7 +752,9 @@ static bool _g_buffer_view_move_caret(GBufferView *view, const GBufferLine *line /* Mise à jour éventuelle */ if (result) - caret->x = G_BUFFER_VIEW_GET_CLASS(view)->left_text + base + offset; + caret->x = text_pos + base + offset; + + gbvmc_done: return result; @@ -735,82 +764,35 @@ static bool _g_buffer_view_move_caret(GBufferView *view, const GBufferLine *line /****************************************************************************** * * * Paramètres : view = vue de tampon à mettre à jour. * -* caret = position du curseur à faire évoluer. * * ctrl = indique la demande d'un parcours rapide. * * dir = direction du parcours. * * display = règles d'affichage des colonnes modulables. * +* caret = position du curseur à faire évoluer. [OUT] * +* addr = adresse correspondant à cette même position. [OUT] * * * * Description : Déplace le curseur au sein d'une vue de tampon. * * * -* Retour : Adresse si une a pu être déterminée, VMPA_INVALID sinon. * +* Retour : true si les deux derniers arguments ont pu être constitués. * * * * Remarques : - * * * ******************************************************************************/ -const vmpa2t *g_buffer_view_move_caret(GBufferView *view, GdkRectangle *caret, bool ctrl, GdkScrollDirection dir, const bool *display) +bool g_buffer_view_move_caret(GBufferView *view, bool ctrl, GdkScrollDirection dir, const bool *display, GdkRectangle *caret, vmpa2t *addr) { - const vmpa2t *result; /* Actualisation à renvoyer */ + bool result; /* Bilan à retourner */ size_t index; /* Indice de ligne de tampon */ GBufferLine *line; /* Ligne sous le pointeur */ - - - line_width_summary summary; /* Résumé concis des largeurs */ - gint left_pos; /* Retour à la ligne */ - gint right_pos; /* Position d'extrème droite */ - BufferLineColumn i; /* Boucle de parcours */ size_t first; /* Première ligne intégrée */ size_t last; /* Dernière ligne intégrée */ - - - - + GBufferLine *other; /* Ligne voisine à visiter */ bool moved; /* Mémorisation d'une évolut° */ + gint text_pos; /* Abscisse de départ du texte */ - - - - - - - - - result = NULL; - - + result = false; line = g_buffer_view_find_line_at(view, caret->y, &index); - if (line == NULL) return NULL; - - g_width_tracker_get_local_width_summary(view->tracker, index, &summary); - - switch (dir) - { - case GDK_SCROLL_UP: - case GDK_SCROLL_DOWN: - break; - case GDK_SCROLL_LEFT: - case GDK_SCROLL_RIGHT: - left_pos = G_BUFFER_VIEW_GET_CLASS(view)->left_text; - if (display[BLC_PHYSICAL]) left_pos += summary.max_widths[BLC_PHYSICAL] + COL_MARGIN; - if (display[BLC_VIRTUAL]) left_pos += summary.max_widths[BLC_VIRTUAL] + COL_MARGIN; - if (display[BLC_BINARY]) left_pos += summary.max_widths[BLC_BINARY] + COL_MARGIN; - right_pos = left_pos; - for (i = BLC_ASSEMBLY_HEAD; i < BLC_COUNT; i++) - right_pos += summary.max_widths[i] + COL_MARGIN; - - /* -gint g_buffer_line_compute_max_width(const GBufferLine *line, BufferLineColumn index, const gint *max_widths) - -BufferLineColumn g_buffer_line_get_merge_start(const GBufferLine *line) - */ - - left_pos = G_BUFFER_VIEW_GET_CLASS(view)->left_text; - - break; - default: /* GDK_SCROLL_SMOOTH */ - break; - } + if (line == NULL) goto gbvmc_done; first = view->first; last = view->last; @@ -821,8 +803,12 @@ BufferLineColumn g_buffer_line_get_merge_start(const GBufferLine *line) if (index > first) { - line = g_code_buffer_find_line_by_index(view->buffer, index - 1); - result = g_buffer_view_compute_caret_full(view, line, index - 1, caret->x, display, caret); + index--; + + other = g_buffer_cache_find_line_by_index(view->cache, index); + result = _g_buffer_view_compute_caret_full(view, caret->x, other, index, display, caret, addr); + g_object_unref(G_OBJECT(other)); + } break; @@ -831,48 +817,58 @@ BufferLineColumn g_buffer_line_get_merge_start(const GBufferLine *line) if (index < last) { - line = g_code_buffer_find_line_by_index(view->buffer, index + 1); - result = g_buffer_view_compute_caret_full(view, line, index + 1, caret->x, display, caret); + index++; + + other = g_buffer_cache_find_line_by_index(view->cache, index); + result = _g_buffer_view_compute_caret_full(view, caret->x, other, index, display, caret, addr); + g_object_unref(G_OBJECT(other)); + } break; case GDK_SCROLL_LEFT: - /* - line = g_buffer_view_find_line_at(view, caret->y, &index); - if (line == NULL) break; - */ - moved = _g_buffer_view_move_caret(view, line, index, caret, ctrl, GDK_SCROLL_LEFT, display); if (moved) - result = get_mrange_addr(g_buffer_line_get_range(line)); + { + g_buffer_cache_get_line_addr(view->cache, index, caret->x, addr); + result = true; + } else if (index > first) { - line = g_code_buffer_find_line_by_index(view->buffer, index - 1); - result = g_buffer_view_compute_caret_full(view, line, index - 1, INT_MAX, display, caret); + index--; + + other = g_buffer_cache_find_line_by_index(view->cache, index); + result = _g_buffer_view_compute_caret_full(view, INT_MAX, other, index, display, caret, addr); + g_object_unref(G_OBJECT(other)); + } break; case GDK_SCROLL_RIGHT: - /* - line = g_buffer_view_find_line_at(view, caret->y, &index); - if (line == NULL) break; - */ - moved = _g_buffer_view_move_caret(view, line, index, caret, ctrl, GDK_SCROLL_RIGHT, display); if (moved) - result = get_mrange_addr(g_buffer_line_get_range(line)); + { + g_buffer_cache_get_line_addr(view->cache, index, caret->x, addr); + result = true; + } else if (index < last) { - line = g_code_buffer_find_line_by_index(view->buffer, index + 1); - result = g_buffer_view_compute_caret_full(view, line, index + 1, left_pos, display, caret); + index++; + + text_pos = g_buffer_cache_get_text_position(view->cache); + + other = g_buffer_cache_find_line_by_index(view->cache, index); + result = _g_buffer_view_compute_caret_full(view, text_pos, other, index, display, caret, addr); + g_object_unref(G_OBJECT(other)); + } break; @@ -882,11 +878,27 @@ BufferLineColumn g_buffer_line_get_merge_start(const GBufferLine *line) } + g_object_unref(G_OBJECT(line)); + + gbvmc_done: + return result; } + + + + + + + + + + + + /****************************************************************************** * * * Paramètres : view = vue de tampon à mettre à jour. * @@ -927,23 +939,64 @@ bool g_buffer_view_unhighlight_segments(GBufferView *view) bool g_buffer_view_highlight_segments(GBufferView *view, gint x, gint y, const bool *display) { - bool need_redraw; /* Besoin d'actualisation ? */ + bool result; /* Besoin à faire remonter */ + gint text_pos; /* Abscisse de départ du texte */ + gint lheight; /* Hauteur d'une ligne */ + size_t index; /* Indice de ligne de tampon */ + GBufferLine *line; /* Ligne à la position courante*/ + line_width_summary summary; /* Résumé concis des largeurs */ const line_segment *segment; /* Segment sélectionnable */ + /* Réinitialisation */ + if (view->highlighted != NULL) - need_redraw = g_buffer_view_unhighlight_segments(view); + result = g_buffer_view_unhighlight_segments(view); else - need_redraw = false; + result = false; + + /* Zone d'intervention bornée ! */ + + text_pos = g_buffer_cache_get_text_position(view->cache); + + if (x < text_pos) + goto gbvhs_done; + + /* Détermination de la ligne concernée */ - g_buffer_view_find_line_and_segment_at(view, &x, y, NULL, display, &segment); + lheight = g_buffer_cache_get_line_height(view->cache); + index = y / lheight; + + index += view->first; + + if (index > view->last) + goto gbvhs_done; + + line = g_buffer_cache_find_line_by_index(view->cache, index); + + assert(line != NULL); + + /* Recherche d'un segment et de son empreinte */ + + g_width_tracker_get_local_width_summary(view->tracker, index, &summary); + + x -= text_pos; + + segment = g_buffer_line_get_segment_at(line, &summary, display, + (gint []) { 0 }, &x, GDK_SCROLL_LEFT, true); - if (segment) - need_redraw |= add_segment_content_to_selection_list(view->highlighted, segment); + g_object_unref(G_OBJECT(line)); - if (need_redraw) + /* Conclusion */ + + if (segment != NULL) + result |= add_segment_content_to_selection_list(view->highlighted, segment); + + if (result) g_signal_emit_by_name(view, "need-redraw"); - return true; + gbvhs_done: + + return result; } @@ -952,13 +1005,12 @@ bool g_buffer_view_highlight_segments(GBufferView *view, gint x, gint y, const b * * * Paramètres : view = visualisation à représenter. * * cr = contexte graphique dédié à la procédure. * -* fake_x = abscisse réelle du point 0 à l'écran. * -* fake_y = ordonnée réelle du point 0 à l'écran. * +* virt_y = ordonnée réelle du point 0 à l'écran. * * area = position et surface à traiter. * * display = règles d'affichage des colonnes modulables. * * selected = ordonnée d'une ligne sélectionnée ou NULL. * * * -* Description : Imprime la visualisation du tampon de code désassemblé. * +* Description : Imprime la visualisation du tampon de lignes quelconques. * * * * Retour : - * * * @@ -966,148 +1018,57 @@ bool g_buffer_view_highlight_segments(GBufferView *view, gint x, gint y, const b * * ******************************************************************************/ -void g_buffer_view_draw(const GBufferView *view, cairo_t *cr, gint fake_x, gint fake_y, const cairo_rectangle_int_t *area, const bool *display, const gint *selected) +void g_buffer_view_draw(const GBufferView *view, cairo_t *cr, gint virt_y, const cairo_rectangle_int_t *area, const bool *display, gint *selected) { - GBufferViewClass *class; /* Classe pour les vues */ - gint real_x; /* Abscisse réelle pour tampon */ - gint real_y; /* Ordonnée réelle pour tampon */ + gint line_height; /* Hauteur d'une ligne */ + gint cr_y; /* Ordonnée pour le dessin */ 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 */ - bool wait_selection; /* Sélection déjà passée ? */ - gint rel_selected; /* Position relative de sélect°*/ - size_t i; /* Boucle de parcours */ - GBufferLine *line; /* Ligne à dessiner à l'écran */ - line_width_summary summary; /* Résumé concis des largeurs */ + size_t last; /* Dernière ligne visée */ - class = G_BUFFER_VIEW_GET_CLASS(view); + line_height = g_buffer_cache_get_line_height(view->cache); - real_x = fake_x + class->left_text; - real_y = fake_y + area->y; + /* Indice et point de départ */ first = view->first; - first += (real_y / class->line_height); - - last = first + (area->height / class->line_height); - if (area->height % class->line_height > 0) last++; - - last = MIN(last, view->last); - - y = area->y - (real_y % class->line_height); - - wait_selection = true; + first += (virt_y / line_height); - if (selected != NULL) - rel_selected = *selected - fake_y; - - if (g_code_buffer_count_lines(view->buffer) > 0) - for (i = first; i <= last; i++) - { - /* Si sélection, on sousligne la ligne concernée */ - if (wait_selection && selected != NULL && rel_selected == y) - { - cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.05); + cr_y = area->y - (virt_y % line_height); - cairo_rectangle(cr, area->x, y, area->width, class->line_height); - cairo_fill(cr); + /* Indice de d'arrivée */ - wait_selection = false; + last = first + (area->height / line_height); + if (area->height % line_height > 0) last++; - } + last = MIN(last, view->last); - line = g_code_buffer_find_line_by_index(view->buffer, i); + /* Phase de dessin ! */ - if (i == first || (g_buffer_line_get_flags(line) & BLF_WIDTH_MANAGER)) - g_width_tracker_get_local_width_summary(view->tracker, i, &summary); + /** + * Le contexte n'est pas sauvegardé avant modification ici car + * l'appelant l'a fait pour nous avant sa translation sur les abscisses. + */ - g_buffer_line_draw(line, cr, &summary, real_x, y, display, view->highlighted); + cairo_translate(cr, 0, cr_y); - y += class->line_height; + if (selected != NULL) + *selected -= cr_y; - } + g_buffer_cache_draw(view->cache, cr, first, last, area, display, selected, view->highlighted); } -/****************************************************************************** -* * -* Paramètres : view = visualisation à consulter. * -* addr = adresse où retrouver la ligne recherchée. * -* flags = propriétés à vérifier en tout ou partie. * -* idx = indice de la ligne trouvée ou NULL. [OUT] * -* * -* Description : Retrouve une ligne au sein d'un tampon avec une adresse. * -* * -* Retour : Line retrouvée ou NULL en cas d'échec. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GBufferLine *g_buffer_view_find_line_by_addr(const GBufferView *view, const vmpa2t *addr, BufferLineFlags flags, size_t *idx) -{ - GBufferLine *result; /* Ligne trouvée à retourner */ - phys_t length; /* Taille de la vue */ - mrange_t vrange; /* Couverture de la vue */ - bool allowed; /* Rechercher validée ? */ - - /* Vérification des bornes */ - - if (!view->unrestricted) - { - length = compute_vmpa_diff(&view->start, &view->end); - init_mrange(&vrange, &view->start, length); - allowed = mrange_contains_addr_inclusive(&vrange, addr); - } - else allowed = true; - /* Lancement des recherches ? */ - if (allowed) - result = g_code_buffer_find_line_by_addr(view->buffer, addr, flags, idx); - else - result = NULL; - return result; - -} -/****************************************************************************** -* * -* Paramètres : view = visualisation à consulter. * -* index = indice de la ligne recherchée. * -* * -* Description : Retrouve une ligne au sein d'un tampon avec un indice. * -* * -* Retour : Line retrouvée ou NULL en cas d'échec. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GBufferLine *g_buffer_view_find_line_by_index(const GBufferView *view, size_t index) -{ - GBufferLine *result; /* Ligne trouvée à retourner */ - bool allowed; /* Rechercher validée ? */ - /* Vérification des bornes */ - allowed = (view->first <= index && index <= view->last); - /* Lancement des recherches ? */ - - if (allowed) - result = g_code_buffer_find_line_by_index(view->buffer, index); - else - result = NULL; - - return result; - -} /****************************************************************************** @@ -1124,19 +1085,19 @@ GBufferLine *g_buffer_view_find_line_by_index(const GBufferView *view, size_t in * * ******************************************************************************/ -GBufferLine *g_buffer_view_find_line_at(GBufferView *view, gint y, size_t *idx) +static GBufferLine *g_buffer_view_find_line_at(GBufferView *view, gint y, size_t *idx) { GBufferLine *result; /* Ligne trouvée à retourner */ gint lheight; /* Hauteur d'une ligne */ size_t index; /* Indice attendu */ - lheight = g_buffer_view_get_line_height(view); + lheight = g_buffer_cache_get_line_height(view->cache); index = y / lheight; index += view->first; if (index <= view->last) - result = g_code_buffer_find_line_by_index(view->buffer, index); + result = g_buffer_cache_find_line_by_index(view->cache, index); else result = NULL; @@ -1148,125 +1109,26 @@ GBufferLine *g_buffer_view_find_line_at(GBufferView *view, gint y, size_t *idx) } -/****************************************************************************** -* * -* Paramètres : view = visualisation à consulter. * -* x = abscisse comprise dans le segment recherché. [OUT] * -* y = ordonnée comprise dans la ligne recherchée. * -* idx = indice de la ligne trouvée ou NULL. [OUT] * -* display = règles d'affichage des colonnes modulables. * -* segment = portion de texte recherchée ou NULL. [OUT] * -* * -* Description : Fournit la ligne et son segment présents à une position. * -* * -* Retour : Ligne retrouvée ou NULL si aucune. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GBufferLine *g_buffer_view_find_line_and_segment_at(GBufferView *view, gint *x, gint y, size_t *idx, const bool *display, const line_segment **segment) -{ - GBufferLine *result; /* Ligne trouvée à retourner */ - size_t index; /* Indice de la ligne trouvée */ - GBufferViewClass *class; /* Classe pour les vues */ - line_width_summary summary; /* Résumé concis des largeurs */ - - /* Recherche d'une ligne correspondante */ - result = g_buffer_view_find_line_at(view, y, &index); - if (idx != NULL) *idx = index; - /* Recherche du segment visé éventuel */ - if (result != NULL && segment != NULL) - { - class = G_BUFFER_VIEW_GET_CLASS(view); - if (*x < class->left_text) - *segment = NULL; - else - { - g_width_tracker_get_local_width_summary(view->tracker, index, &summary); - *x -= class->left_text; - *segment = g_buffer_line_get_segment_at(result, &summary, display, - (gint []) { 0 }, x, GDK_SCROLL_LEFT, true); - } - } - return result; -} /****************************************************************************** * * -* Paramètres : view = visualisation à consulter. * -* x = abscisse comprise dans le segment recherché. [OUT] * -* y = ordonnée comprise dans la ligne recherchée. * -* idx = indice de la ligne trouvée ou NULL. [OUT] * -* display = règles d'affichage des colonnes modulables. * -* creator = instance à l'origine de la représentation. [OUT] * -* * -* Description : Fournit la ligne et son segment présents à une position. * -* * -* Retour : Ligne retrouvée ou NULL si aucune. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GBufferLine *g_buffer_view_find_line_and_creator_at(GBufferView *view, gint *x, gint y, size_t *idx, const bool *display, GObject **creator) -{ - GBufferLine *result; /* Ligne trouvée à retourner */ - size_t index; /* Indice de la ligne trouvée */ - GBufferViewClass *class; /* Classe pour les vues */ - line_width_summary summary; /* Résumé concis des largeurs */ - - /* Recherche d'une ligne correspondante */ - - result = g_buffer_view_find_line_at(view, y, &index); - - if (idx != NULL) *idx = index; - - /* Recherche du segment visé éventuel */ - - if (result != NULL && creator != NULL) - { - class = G_BUFFER_VIEW_GET_CLASS(view); - - if (*x < class->left_text) - *creator = NULL; - - else - { - g_width_tracker_get_local_width_summary(view->tracker, index, &summary); - - *x -= class->left_text; - *creator = g_buffer_line_get_creator_at(result, &summary, display, - (gint []) { 0 }, x, GDK_SCROLL_LEFT, true); - - } - - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : view = composant GTK à consulter. * +* Paramètres : view = visualisation à consulter. * * addr = adresse à présenter à l'écran. * +* code = s'arrête si possible à une ligne avec code. * * x = position horizontale au sein du composant. [OUT] * * y = position verticale au sein du composant. [OUT] * -* code = s'arrête si possible à une ligne avec code. * * * * Description : Indique la position d'affichage d'une adresse donnée. * * * @@ -1276,61 +1138,11 @@ GBufferLine *g_buffer_view_find_line_and_creator_at(GBufferView *view, gint *x, * * ******************************************************************************/ -bool g_buffer_view_get_address_coordinates(GBufferView *view, const vmpa2t *addr, gint *x, gint *y, bool code) +bool g_buffer_view_get_address_coordinates(GBufferView *view, const vmpa2t *addr, bool code, gint *x, gint *y) { bool result; /* Bilan à retourner */ - gint lheight; /* Hauteur d'une ligne */ - size_t i; /* Boucle de parcours */ - GBufferLine *line; /* Ligne à consulter */ - const mrange_t *range; /* Emplacement parcouru */ - - result = false; - - *x = 0; - *y = 0; - - lheight = g_buffer_view_get_line_height(view); - - for (i = view->first; i <= view->last; i++) - { - /** - * Si l'adresse recherchée est plus petite que l'adresse de départ, - * on va effectuer un parcours complet pour rien. - * - * On considère cependant que le seul cas où celà peut arriver - * est lorsque que des découpages en blocs sont impliqués. - * - * Les découpages conduisent alors à la formation de petites zones, - * rapides à parcourir. - */ - - line = g_code_buffer_find_line_by_index(view->buffer, i); - range = g_buffer_line_get_range(line); - - result = mrange_contains_addr(range, addr); - if (result) break; - - *y += lheight; - } - - if (result && code) - for (; i <= view->last; i++) - { - line = g_code_buffer_find_line_by_index(view->buffer, i); - - if (g_buffer_line_get_flags(line) & BLF_HAS_CODE) break; - - if (i == view->last) break; - - line = g_code_buffer_find_line_by_index(view->buffer, i + 1); - - range = g_buffer_line_get_range(line); - if (!mrange_contains_addr(range, addr)) break; - - *y += lheight; - - } + result = g_buffer_cache_get_address_coordinates(view->cache, addr, view->first, view->last, code, x, y); return result; diff --git a/src/glibext/gbufferview.h b/src/glibext/gbufferview.h index 0aa26a6..dc1d704 100644 --- a/src/glibext/gbufferview.h +++ b/src/glibext/gbufferview.h @@ -28,7 +28,7 @@ #include <glib-object.h> -#include "gcodebuffer.h" +#include "gbuffercache.h" @@ -47,23 +47,22 @@ typedef struct _GBufferView GBufferView; typedef struct _GBufferViewClass GBufferViewClass; -/* Détermine le type de la vue d'un tampon pour code désassemblé. */ +/* Détermine le type de la vue d'un tampon pour lignes générées. */ 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 *, segcnt_list *); +/* Crée une nouvelle vue d'un tampon pour lignes générées. */ +GBufferView *g_buffer_view_new(GBufferCache *, segcnt_list *); + +/* Fournit le tampon de code lié à un visualisateur donné. */ +GBufferCache *g_buffer_view_get_cache(const GBufferView *); /* Restreint le champ d'application de l'affichage. */ void g_buffer_view_restrict(GBufferView *, const vmpa2t *, const vmpa2t *); /* Indique le champ d'application de l'affichage. */ -bool g_buffer_view_get_restrictions(GBufferView *, vmpa2t *, vmpa2t *); +bool g_buffer_view_get_restrictions(const GBufferView *, vmpa2t *, vmpa2t *); -/* Fournit le tampon de code lié à un visualisateur donné. */ -GCodeBuffer *g_buffer_view_get_buffer(const GBufferView *); -/* Fournit la hauteur d'impression d'une ligne visualisée. */ -gint g_buffer_view_get_line_height(GBufferView *); /* Fournit la largeur requise par une visualisation. */ gint g_buffer_view_get_width(GBufferView *, const bool *); @@ -74,14 +73,18 @@ gint g_buffer_view_get_margin(GBufferView *, const bool *); /* Fournit la hauteur requise par une visualisation. */ gint g_buffer_view_get_height(const GBufferView *); -/* Calcule la position idéale de curseur pour un point donné. */ -const vmpa2t *g_buffer_view_compute_caret(GBufferView *, gint, gint, const bool *, GdkRectangle *); + + + /* Calcule la position idéale de curseur pour un point donné. */ -const vmpa2t *g_buffer_view_compute_caret_full(GBufferView *, GBufferLine *, size_t, gint, const bool *, GdkRectangle *); +bool g_buffer_view_compute_caret_full(GBufferView *, gint, gint, const bool *, GdkRectangle *, vmpa2t *); /* Déplace le curseur au sein d'une vue de tampon. */ -const vmpa2t *g_buffer_view_move_caret(GBufferView *, GdkRectangle *, bool, GdkScrollDirection, const bool *); +bool g_buffer_view_move_caret(GBufferView *, bool, GdkScrollDirection, const bool *, GdkRectangle *, vmpa2t *); + + + /* Supprime toute mise en évidence de segments. */ bool g_buffer_view_unhighlight_segments(GBufferView *); @@ -89,26 +92,18 @@ bool g_buffer_view_unhighlight_segments(GBufferView *); /* Surligne tous les segments similaires à celui sous la souris. */ bool g_buffer_view_highlight_segments(GBufferView *, gint, gint, const bool *); -/* Imprime la visualisation du tampon de code désassemblé. */ -void g_buffer_view_draw(const GBufferView *, cairo_t *, gint, gint, const cairo_rectangle_int_t *, const bool *, const gint *); +/* Imprime la visualisation du tampon de lignes quelconques. */ +void g_buffer_view_draw(const GBufferView *, cairo_t *, gint, const cairo_rectangle_int_t *, const bool *, gint *); -/* Retrouve une ligne au sein d'un tampon avec une adresse. */ -GBufferLine *g_buffer_view_find_line_by_addr(const GBufferView *, const vmpa2t *, BufferLineFlags, size_t *); -/* Retrouve une ligne au sein d'un tampon avec un indice. */ -GBufferLine *g_buffer_view_find_line_by_index(const GBufferView *, size_t ); -/* Fournit la ligne présente à une ordonnée donnée. */ -GBufferLine *g_buffer_view_find_line_at(GBufferView *, gint, size_t *); -/* Fournit la ligne et son segment présents à une position. */ -GBufferLine *g_buffer_view_find_line_and_segment_at(GBufferView *, gint *, gint, size_t *, const bool *, const line_segment **); -/* Fournit la ligne et son segment présents à une position. */ -GBufferLine *g_buffer_view_find_line_and_creator_at(GBufferView *, gint *, gint, size_t *, const bool *, GObject **); /* Indique la position d'affichage d'une adresse donnée. */ -bool g_buffer_view_get_address_coordinates(GBufferView *, const vmpa2t *, gint *, gint *, bool); +bool g_buffer_view_get_address_coordinates(GBufferView *, const vmpa2t *, bool, gint *, gint *); + + diff --git a/src/glibext/gcodebuffer.c b/src/glibext/gcodebuffer.c deleted file mode 100644 index e9f1762..0000000 --- a/src/glibext/gcodebuffer.c +++ /dev/null @@ -1,1778 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * gcodebuffer.c - affichage d'un fragment de code d'assemblage - * - * Copyright (C) 2010-2014 Cyrille Bagard - * - * This file is part of Chrysalide. - * - * Chrysalide 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. - * - * Chrysalide 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 <assert.h> -#include <malloc.h> -#include <stdlib.h> -#include <string.h> - - -#include "chrysamarshal.h" -#include "delayed-int.h" -#include "../common/extstr.h" - - - -/* -------------------------- PARCOURS DU CODE D'UN TAMPON -------------------------- */ - - -#define G_TYPE_BUFFER_SCAN g_buffer_scan_get_type() -#define G_BUFFER_SCAN(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_buffer_scan_get_type(), GDelayedExport)) -#define G_IS_BUFFER_SCAN(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_buffer_scan_get_type())) -#define G_BUFFER_SCAN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_BUFFER_SCAN, GDelayedExportClass)) -#define G_IS_BUFFER_SCAN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_BUFFER_SCAN)) -#define G_BUFFER_SCAN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_BUFFER_SCAN, GDelayedExportClass)) - - -/* Ensembles binaires à désassembler (instance) */ -typedef struct _GBufferScan -{ - GDelayedWork parent; /* A laisser en premier */ - - GCodeBuffer *buffer; /* Tampon à manipuler */ - - vmpa2t start; /* Début du parcours */ - bool has_start; /* Validité des données #1 */ - vmpa2t end; /* Fin du parcours */ - bool has_end; /* Validité des données #2 */ - - char *message; /* Message de progression */ - - process_line_fc process; /* Fonction de traitement réel */ - void *user_data; /* Données à faire suivre */ - -} GBufferScan; - -/* Ensembles binaires à désassembler (classe) */ -typedef struct _GBufferScanClass -{ - GDelayedWorkClass parent; /* A laisser en premier */ - -} GBufferScanClass; - - -/* Indique le type défini pour les tâches d'exportation différée. */ -static GType g_buffer_scan_get_type(void); - -/* Initialise la classe des tâches d'exportation différée. */ -static void g_buffer_scan_class_init(GBufferScanClass *); - -/* Initialise une tâche d'exportation différée. */ -static void g_buffer_scan_init(GBufferScan *); - -/* Supprime toutes les références externes. */ -static void g_buffer_scan_dispose(GBufferScan *); - -/* Procède à la libération totale de la mémoire. */ -static void g_buffer_scan_finalize(GBufferScan *); - -/* Crée une tâche d'exportation différée. */ -static GBufferScan *g_buffer_scan_new(GCodeBuffer *, const vmpa2t *, const vmpa2t *, const char *, process_line_fc, void *); - -/* Assure l'exportation en différé. */ -static void g_buffer_scan_process(GBufferScan *, GtkStatusStack *); - - - -/* -------------------------- TAMPON POUR CODE DESASSEMBLE -------------------------- */ - - -/* Suivi distant des évolutions */ -typedef struct _view_callback -{ - buffer_size_changed_cb size_changed; /* Evolution de taille */ - GObject *data; /* Données à associer */ - -} view_callback; - - -/* Tampon pour code désassemblé (instance) */ -struct _GCodeBuffer -{ - GObject parent; /* A laisser en premier */ - - BufferLineColumn main_column; /* Colonne principale */ - - GBufferLine **lines; /* Liste des lignes intégrées */ - size_t count; /* Quantité en cache */ - size_t used; /* Quantité utilisée */ - - GWidthTracker *tracker; /* Suivi des largeurs */ - - size_t indent; /* Indentation des lignes */ - - view_callback *vcallbacks; /* Vues à mettre à jour */ - size_t vcount; /* Quantité de ces vues */ - -}; - -/* Tampon pour code désassemblé (classe) */ -struct _GCodeBufferClass -{ - GObjectClass parent; /* A laisser en premier */ - - /* Signaux */ - - void (* line_changed) (GCodeBuffer *, GBufferLine *, line_segment *); - -}; - - -/* 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 *); - -/* Réagit à un changement de contenu d'une ligne donnée. */ -static void on_line_content_change(GBufferLine *, line_segment *, GCodeBuffer *); - -/* Réagit à un changement de propriété rattachée à une ligne. */ -static void on_line_flag_flip(GBufferLine *, BufferLineFlags, BufferLineFlags, GCodeBuffer *); - -/* Ajoute de nouvelles lignes à une position donnée. */ -static void g_code_buffer_insert_lines_at(GCodeBuffer *, GBufferLine **, size_t, size_t); - - - -/* ------------------------- CONFORTS POUR LES COMMENTAIRES ------------------------- */ - - -/* Affiche un commentaire sur une ligne de tampon donnée. */ -static bool _g_code_buffer_write_inlined_comment(GCodeBuffer *, GBufferLine *, const char *, GObject *); - -/* Affiche un commentaire sur une ligne de tampon dédiée. */ -static bool _g_code_buffer_write_comment_area(GCodeBuffer *, GBufferLine *, const char *, bool, GObject *); - -/* Retrouve la première ligne d'une zone de commentaire. */ -static size_t g_code_buffer_find_first_line_comment(const GCodeBuffer *, size_t); - -/* Retrouve la dernière ligne d'une zone de commentaire. */ -static size_t g_code_buffer_find_last_line_comment(const GCodeBuffer *, size_t); - -/* Supprime un commentaire existant. */ -static bool _g_code_buffer_delete_lines_comment(GCodeBuffer *, GBufferLine *); - - - -/* ------------------------- SIGNAUX IMMEDIATS POUR UNE VUE ------------------------- */ - - -/* Fait suivre une variation de la quantité de lignes du tampon. */ -static void g_code_buffer_notify_size_changed(const GCodeBuffer *, bool, size_t, size_t); - - - -/* ---------------------------------------------------------------------------------- */ -/* PARCOURS DU CODE D'UN TAMPON */ -/* ---------------------------------------------------------------------------------- */ - - -/* Indique le type défini pour les tâches d'exportation différée. */ -G_DEFINE_TYPE(GBufferScan, g_buffer_scan, G_TYPE_DELAYED_WORK); - - -/****************************************************************************** -* * -* Paramètres : klass = classe à initialiser. * -* * -* Description : Initialise la classe des tâches d'exportation différée. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_buffer_scan_class_init(GBufferScanClass *klass) -{ - GObjectClass *object; /* Autre version de la classe */ - GDelayedWorkClass *work; /* Version en classe parente */ - - object = G_OBJECT_CLASS(klass); - - object->dispose = (GObjectFinalizeFunc/* ! */)g_buffer_scan_dispose; - object->finalize = (GObjectFinalizeFunc)g_buffer_scan_finalize; - - work = G_DELAYED_WORK_CLASS(klass); - - work->run = (run_task_fc)g_buffer_scan_process; - -} - - -/****************************************************************************** -* * -* Paramètres : scan = instance à initialiser. * -* * -* Description : Initialise une tâche d'exportation différée. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_buffer_scan_init(GBufferScan *scan) -{ - -} - - -/****************************************************************************** -* * -* Paramètres : scan = instance d'objet GLib à traiter. * -* * -* Description : Supprime toutes les références externes. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_buffer_scan_dispose(GBufferScan *scan) -{ - g_object_unref(G_OBJECT(scan->buffer)); - - G_OBJECT_CLASS(g_buffer_scan_parent_class)->dispose(G_OBJECT(scan)); - -} - - -/****************************************************************************** -* * -* Paramètres : scan = instance d'objet GLib à traiter. * -* * -* Description : Procède à la libération totale de la mémoire. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_buffer_scan_finalize(GBufferScan *scan) -{ - free(scan->message); - - G_OBJECT_CLASS(g_buffer_scan_parent_class)->finalize(G_OBJECT(scan)); - -} - - -/****************************************************************************** -* * -* Paramètres : buffer = tampon à manipuler. * -* start = première adresse visée ou NULL. * -* end = dernière adresse visée ou NULL. * -* message = message à afficher lors de la progression. * -* process = fonction assurant le traitement effectif. * -* data = données utilisateur à faire suivre. * -* * -* Description : Crée une tâche d'exportation différée. * -* * -* Retour : Tâche créée. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static GBufferScan *g_buffer_scan_new(GCodeBuffer *buffer, const vmpa2t *start, const vmpa2t *end, const char *message, process_line_fc process, void *data) -{ - GBufferScan *result; /* Tâche à retourner */ - - result = g_object_new(G_TYPE_BUFFER_SCAN, NULL); - - result->buffer = buffer; - g_object_ref(G_OBJECT(buffer)); - - result->has_start = (start != NULL); - - if (result->has_start) - copy_vmpa(&result->start, start); - - result->has_end = (end != NULL); - - if (result->has_end) - copy_vmpa(&result->end, end); - - result->message = strdup(message); - - result->process = process; - result->user_data = data; - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : scan = parcours à mener. * -* status = barre de statut à tenir informée. * -* * -* Description : Assure l'exportation en différé. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_buffer_scan_process(GBufferScan *scan, GtkStatusStack *status) -{ - size_t first; /* Première ligne visée */ - size_t last; /* Dernière ligne visée + 1 */ - GBufferLine **lines; /* Liste des lignes à traiter */ - //bstatus_id_t id; /* Identifiant de statut */ - size_t i; /* Boucle de parcours */ - - /* TODO : lock scan->buffer->lines */ - - if (scan->has_start) - first = g_code_buffer_get_index_from_address(scan->buffer, &scan->start, true); - else - first = 0; - - if (scan->has_end) - last = g_code_buffer_get_index_from_address(scan->buffer, &scan->end, false); - else - last = scan->buffer->used - 1; - - lines = scan->buffer->lines; - - //id = gtk_extended_status_bar_push(statusbar, scan->message, true); - - if (scan->buffer->used > 0) - for (i = first; i <= last; i++) - { - if (!scan->process(scan->buffer, lines[i], scan->user_data)) - break; - - /* - gtk_extended_status_bar_update_activity(statusbar, id, - (i - first) * 1.0 / (last - first)); - */ - - } - - /* TODO : unlock scan->buffer->lines */ - - //gtk_extended_status_bar_remove(statusbar, id); - -} - - - -/* ---------------------------------------------------------------------------------- */ -/* 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) -{ - g_signal_new("line-changed", - G_TYPE_CODE_BUFFER, - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET(GCodeBufferClass, line_changed), - NULL, NULL, - g_cclosure_user_marshal_VOID__OBJECT_OBJECT, - G_TYPE_NONE, 2, G_TYPE_OBJECT, G_TYPE_OBJECT); - -} - - -/****************************************************************************** -* * -* 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) -{ - buffer->tracker = g_width_tracker_new(buffer); - -} - - -/****************************************************************************** -* * -* Paramètres : main = colonne à référencer comme étant la principale. * -* * -* Description : Crée un nouveau composant de tampon pour code désassemblé. * -* * -* Retour : Composant GTK créé. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GCodeBuffer *g_code_buffer_new(BufferLineColumn main) -{ - GCodeBuffer *result; /* Composant à retourner */ - - result = g_object_new(G_TYPE_CODE_BUFFER, NULL); - - result->main_column = main; - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : buffer = composant GLib à consulter. * -* * -* Description : Compte le nombre de lignes rassemblées dans un tampon. * -* * -* Retour : Nombre de lignes constituant le tampon. * -* * -* Remarques : - * -* * -******************************************************************************/ - -size_t g_code_buffer_count_lines(const GCodeBuffer *buffer) -{ - return buffer->used; - -} - - -/****************************************************************************** -* * -* Paramètres : buffer = composant GLib à consulter. * -* * -* Description : Fournit un lien vers la structure de suivi de largeurs. * -* * -* Retour : Gestionnaire de largeurs de lignes. * -* * -* Remarques : - * -* * -******************************************************************************/ - -const GWidthTracker *g_code_buffer_get_width_tracker(const GCodeBuffer *buffer) -{ - return buffer->tracker; - -} - - -/****************************************************************************** -* * -* Paramètres : buffer = composant GLib à consulter. * -* range = emplacement où va se situer la ligne. * -* * -* Description : Initie une nouvelle ligne devant être insérée dans le tampon.* -* * -* Retour : Nouvelle ligne vierge à écrire. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GBufferLine *g_code_buffer_prepare_new_line(GCodeBuffer *buffer, const mrange_t *range) -{ - GBufferLine *result; /* Instance à retourner */ - size_t i; /* Boucle de parcours */ - - result = g_buffer_line_new(range, buffer->main_column); - - for (i = 0; i < buffer->indent; i++) - g_buffer_line_append_text(result, BLC_ASSEMBLY_HEAD, " ", 4, RTT_RAW, NULL); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : line = ligne dont la définition vient d'évoluer. * -* segment = éventuel segment qui vient d'évoluer ou NULL. * -* buffer = tampon de lignes cohérentes à manipuler. * -* * -* Description : Réagit à un changement de contenu d'une ligne donnée. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void on_line_content_change(GBufferLine *line, line_segment *segment, GCodeBuffer *buffer) -{ - g_signal_emit_by_name(buffer, "line-changed", line, segment); - -} - - -/****************************************************************************** -* * -* Paramètres : line = ligne dont la définition vient d'évoluer. * -* old = ancien groupe de propriétés associées. * -* old = nouveau groupe de propriétés associées. * -* buffer = tampon de lignes cohérentes à manipuler. * -* * -* Description : Réagit à un changement de propriété rattachée à une ligne. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void on_line_flag_flip(GBufferLine *line, BufferLineFlags old, BufferLineFlags new, GCodeBuffer *buffer) -{ - g_signal_emit_by_name(buffer, "line-changed", line, NULL); - -} - - -/****************************************************************************** -* * -* Paramètres : buffer = composant GLib à mettre à jour. * -* lines = liste de lignes à insérer. * -* count = taille de cette liste. * -* index = point d'insertion de la première ligne. * -* * -* Description : Ajoute de nouvelles lignes à une position donnée. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_code_buffer_insert_lines_at(GCodeBuffer *buffer, GBufferLine **lines, size_t count, size_t index) -{ - size_t i; /* Boucle de parcours */ - - /* Elaboration d'un espace suffisant */ - - if ((buffer->used + count) > buffer->count) - { - if (count > LINE_ALLOC_BULK) - buffer->count += count; - else - buffer->count += LINE_ALLOC_BULK; - - buffer->lines = (GBufferLine **)realloc(buffer->lines, - buffer->count * sizeof(GBufferLine *)); - - } - - /* Insertion des lignes */ - - if (index < buffer->used) - { - memmove(&buffer->lines[index + count], &buffer->lines[index], - (buffer->used - index) * sizeof(GBufferLine *)); - } - - buffer->used += count; - - for (i = 0; i < count; i++) - { - assert((index + i) < buffer->used); - - buffer->lines[index + i] = lines[i]; - - g_signal_connect(lines[i], "content-changed", G_CALLBACK(on_line_content_change), buffer); - g_signal_connect(lines[i], "flip-flag", G_CALLBACK(on_line_flag_flip), buffer); - - } - - /* Recueil initial des largeurs */ - - g_width_tracker_update_added(buffer->tracker, index, count); - - g_code_buffer_notify_size_changed(buffer, true, index, count); - -} - - -/****************************************************************************** -* * -* Paramètres : buffer = composant GLib à mettre à jour. * -* line = lign à insérer à la fin du tampon. * -* * -* Description : Ajoute une nouvelle ligne en fin de tampon. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_code_buffer_append_new_line(GCodeBuffer *buffer, GBufferLine *line) -{ - g_code_buffer_insert_lines_at(buffer, (GBufferLine *[]) { line }, 1, buffer->used); - -} - - -/****************************************************************************** -* * -* Paramètres : buffer = composant GLib à mettre à jour. * -* lines = liste de lignes à insérer. * -* count = taille de cette liste. * -* point = point d'insertion du bloc de ligne. * -* before = emplacement de l'insertion par rapport au point. * -* * -* Description : Ajoute de nouvelles lignes par rapport à une ligne donnée. * -* * -* Retour : Bilan : insertion réussie ou non ? * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool g_code_buffer_insert_lines(GCodeBuffer *buffer, GBufferLine **lines, size_t count, const GBufferLine *point, bool before) -{ - bool result; /* Bilan à retourner */ - size_t index; /* Indice d'insertion final */ - - result = false; - - index = g_code_buffer_find_index_by_line(buffer, point); - - if (index == buffer->used) - goto gcbil_exit; - - if (!before) - index++; - - g_code_buffer_insert_lines_at(buffer, lines, count, index); - - - - - result = true; - - gcbil_exit: - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : buffer = composant GLib à mettre à jour. * -* start = première ligne devant être supprimée. * -* end = dernière ligne devant être supprimée. * -* * -* Description : Supprime une ou plusieurs lignes du tampon indiqué. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_code_buffer_delete_lines(GCodeBuffer *buffer, size_t start, size_t end) -{ - size_t i; /* Boucle de parcours */ - GBufferLine *line; /* Ligne en cours de traitement*/ - - assert(start < buffer->used); - assert(end < buffer->used); - - for (i = start; i <= end; i++) - { - line = buffer->lines[i]; - - g_signal_handlers_disconnect_by_func(line, G_CALLBACK(on_line_content_change), buffer); - g_signal_handlers_disconnect_by_func(line, G_CALLBACK(on_line_flag_flip), buffer); - - g_object_unref(G_OBJECT(line)); - - } - - if ((end + 1) < buffer->used) - memmove(&buffer->lines[start], &buffer->lines[end + 1], - (buffer->used - end - 1) * sizeof(GBufferLine *)); - - buffer->used -= (end - start + 1); - - g_width_tracker_update_deleted(buffer->tracker, start, end); - - g_code_buffer_notify_size_changed(buffer, false, start, end - start + 1); - -} - - -/****************************************************************************** -* * -* Paramètres : buffer = composant GTK à mettre à jour. * -* addr = adresse où retrouver la ligne recherchée. * -* flags = propriétés à vérifier en tout ou partie. * -* idx = indice de la ligne trouvée ou NULL. [OUT] * -* * -* Description : Retrouve une ligne au sein d'un tampon avec une adresse. * -* * -* Retour : Line retrouvée ou NULL en cas d'échec. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GBufferLine *g_code_buffer_find_line_by_addr(const GCodeBuffer *buffer, const vmpa2t *addr, BufferLineFlags flags, size_t *idx) -{ - GBufferLine *result; /* Instance à retourner */ - size_t index; /* Indice de la ligne visée */ - - index = g_code_buffer_get_index_from_address(buffer, addr, true); - - if (index == buffer->used) - result = NULL; - - else - { - if (idx != NULL) - *idx = index; - - result = buffer->lines[index]; - - if (flags != BLF_NONE) - while ((g_buffer_line_get_flags(result) & flags) != flags) - { - if ((index + 1) == buffer->used) break; - - /* FIXME : vérifier que l'adresse est toujours celle recherchée ! */ - - if (idx != NULL) - (*idx)++; - - result = buffer->lines[++index]; - - } - - g_object_ref(G_OBJECT(result)); - - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : buffer = tampon de lignes à consulter. * -* index = indice de la ligne recherchée. * -* * -* Description : Retrouve une ligne au sein d'un tampon avec un indice. * -* * -* Retour : Line retrouvée ou NULL en cas d'échec. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GBufferLine *g_code_buffer_find_line_by_index(const GCodeBuffer *buffer, size_t index) -{ - GBufferLine *result; /* Ligne trouvée à retourner */ - - /* TODO : ref */ - - if (index < buffer->used) - result = buffer->lines[index]; - else - result = NULL; - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : buffer = composant GTK à mettre à jour. * -* addr = adresse où va se situer la ligne. * -* first = indique si on l'arrête à la première ou la dernière.* -* * -* Description : Convertit une adresse en indice de ligne. * -* * -* Retour : Indice de l'adresse trouvée, ou le nombre de lignes sinon. * -* * -* Remarques : - * -* * -******************************************************************************/ - -size_t g_code_buffer_get_index_from_address(const GCodeBuffer *buffer, const vmpa2t *addr, bool first) -{ - size_t result; /* Indice à retourner */ - GBufferLine **found; /* Renvoi vers une trouvaille */ - const mrange_t *range; /* Couverture d'une ligne */ - - /** - * Si aucune adresse (ie. aucune limite ?) n'est précisée, on se base sur - * la direction pour trouver le bon indice. - */ - - if (addr == NULL) - result = (first ? 0 : buffer->used - 1); - - /** - * Sinon on parcourt méthodiquement toutes les lignes ! - */ - - else - { - /* Recherche dichotomique grossière */ - - int cmp_addr_and_line(const vmpa2t *addr, const GBufferLine **line) - { - int status; /* Bilan d'une comparaison */ - const mrange_t *lrange; /* Couverture d'une ligne */ - - lrange = g_buffer_line_get_range(*line); - - status = cmp_mrange_with_vmpa(lrange, addr); - - return status; - - } - - found = bsearch(addr, buffer->lines, buffer->used, sizeof(GBufferLine *), - (__compar_fn_t)cmp_addr_and_line); - - /* Dernier raffinage pour approcher la cible réelle */ - - if (found == NULL) - result = buffer->used; - - else - { - result = found - buffer->lines; - - if (first) - for (; result > 0; result--) - { - range = g_buffer_line_get_range(buffer->lines[result - 1]); - if (!mrange_contains_addr(range, addr)) break; - } - - else - for (; (result + 1) < buffer->used; result++) - { - range = g_buffer_line_get_range(buffer->lines[result + 1]); - if (!mrange_contains_addr(range, addr)) break; - } - - } - - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : buffer = tampon de lignes à consulter. * -* line = ligne dont l'indice est à retrouver. * -* * -* Description : Retrouve l'indice associé à une ligne au sein d'un tampon. * -* * -* Retour : Indice de l'adresse trouvée, ou le nombre de lignes sinon. * -* * -* Remarques : - * -* * -******************************************************************************/ - -size_t g_code_buffer_find_index_by_line(const GCodeBuffer *buffer, const GBufferLine *line) -{ - size_t result; /* Indice trouvé à retourner */ - const mrange_t *range; /* Emplacement de la ligne */ - const mrange_t *next; /* Emplacement suivant */ - - range = g_buffer_line_get_range(line); - - result = g_code_buffer_get_index_from_address(buffer, get_mrange_addr(range), true); - - /** - * Comme plusieurs lignes consécutives peuvent avoir la même adresse, - * on parcourt les lignes suivantes pour retrouver la ligne recherchée. - */ - - if (result < buffer->used) - { - while (buffer->lines[result] != line) - { - if (++result == buffer->used) - break; - - next = g_buffer_line_get_range(buffer->lines[result]); - - if (cmp_vmpa(get_mrange_addr(range), get_mrange_addr(next)) != 0) - { - result = buffer->used; - break; - } - - } - - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : buffer = composant GTK à mettre à jour. * -* * -* Description : Augmente l'indentation des prochaines lignes. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_code_buffer_inc_indentation(GCodeBuffer *buffer) -{ - buffer->indent++; - -} - - -/****************************************************************************** -* * -* Paramètres : buffer = composant GTK à mettre à jour. * -* * -* Description : Diminue l'indentation des prochaines lignes. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_code_buffer_dec_indentation(GCodeBuffer *buffer) -{ - /* BUG_ON(buffer->indent == 0) */ - - buffer->indent--; - -} - - -/****************************************************************************** -* * -* Paramètres : buffer = tampon de données à utiliser. * -* start = première adresse visée ou 0. * -* end = dernière adresse visée ou VMPA_MAX. * -* message = message à afficher lors de la progression. * -* process = fonction assurant le traitement effectif. * -* data = données utilisateur à faire suivre. * -* * -* Description : Lance un parcours des différentes lignes du tampon de code. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -GDelayedWork *g_buffer_code_scan(GCodeBuffer *buffer, const vmpa2t *start, const vmpa2t *end, const char *message, process_line_fc process, void *data) -{ - GBufferScan *result; /* Procédure à créer / renvoyer*/ - GWorkQueue *queue; /* Gestionnaire de différés */ - - result = g_buffer_scan_new(buffer, start, end, message, process, data); - g_object_ref(G_OBJECT(result)); - - queue = get_work_queue(); - g_work_queue_schedule_work(queue, G_DELAYED_WORK(result), DEFAULT_WORK_GROUP); - - return G_DELAYED_WORK(result); - -} - - - -/* ---------------------------------------------------------------------------------- */ -/* CONFORTS POUR LES COMMENTAIRES */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* Paramètres : buffer = tampon de lignes à consulter. * -* line = ligne à l'intérieur d'un commentaire. * -* comment = nouveau commentaire à inscrire à la ligne donnée. * -* creator = créateur à l'origine de la construction. * -* * -* Description : Affiche un commentaire sur une ligne de tampon donnée. * -* * -* Retour : Bilan de l'opération : ajout ou non ? * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool _g_code_buffer_write_inlined_comment(GCodeBuffer *buffer, GBufferLine *line, const char *comment, GObject *creator) -{ - bool result; /* Bilan à retourner */ - const mrange_t *range; /* Emplace de ligne à utiliser */ - char *wcopy; /* Copie de travail */ - GBufferLine **extra; /* Lignes supplémentaires */ - size_t extra_count; /* Quantité de ces lignes */ - char *saveptr; /* Sauvegarde pour la sécurité */ - char *token; /* Fragment à insérer */ - size_t len; /* Taille dudit fragment */ - GBufferLine *new; /* Nouvelle ligne créée */ - size_t i; /* Boucle de parcours */ - - assert(!g_buffer_line_has_comment(line)); - - result = false; - - range = g_buffer_line_get_range(line); - - wcopy = strdup(comment); - - extra = NULL; - extra_count = 0; - - for (token = strtok_r(wcopy, COMMENT_LINE_SEP, &saveptr); - token != NULL; - token = strtok_r(NULL, COMMENT_LINE_SEP, &saveptr)) - { - len = strlen(token); - - if (!result) - g_buffer_line_append_text(line, BLC_COMMENTS, token, len, RTT_COMMENT, creator); - - else - { - new = g_code_buffer_prepare_new_line(buffer, range); - - g_buffer_line_append_text(new, BLC_COMMENTS, token, len, RTT_COMMENT, creator); - - extra = (GBufferLine **)realloc(extra, ++extra_count * sizeof(GBufferLine *)); - - extra[extra_count - 1] = new; - - } - - result = true; - - } - - free(wcopy); - - if (extra_count > 0) - { - result &= g_code_buffer_insert_lines(buffer, extra, extra_count, line, false); - - if (!result) - for (i = 0; i < extra_count; i++) - g_object_unref(G_OBJECT(extra[i])); - - free(extra); - - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : buffer = tampon de lignes à consulter. * -* line = ligne à l'intérieur d'un commentaire. * -* comment = nouveau commentaire à inscrire à la ligne donnée. * -* creator = créateur à l'origine de la construction. * -* * -* Description : Affiche un commentaire sur une ligne de tampon donnée. * -* * -* Retour : Bilan de l'opération : ajout ou non ? * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool g_code_buffer_update_inlined_comment(GCodeBuffer *buffer, GBufferLine *line, const char *comment, GObject *creator) -{ - bool result; /* Bilan à retourner */ - - if (g_buffer_line_has_comment(line)) - result = _g_code_buffer_delete_lines_comment(buffer, line); - else - result = true; - - if (result) - result = _g_code_buffer_write_inlined_comment(buffer, line, comment, creator); - - /* TODO : emit() */ - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : buffer = tampon de lignes à consulter. * -* line = ligne à l'intérieur d'un commentaire. * -* comment = nouveau commentaire à inscrire à la ligne donnée. * -* before = précise la position du commentaire. * -* creator = créateur à l'origine de la construction. * -* * -* Description : Affiche un commentaire sur une ligne de tampon dédiée. * -* * -* Retour : Bilan de l'opération : ajout ou non ? * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool _g_code_buffer_write_comment_area(GCodeBuffer *buffer, GBufferLine *line, const char *comment, bool before, GObject *creator) -{ - bool result; /* Bilan à retourner */ - const mrange_t *range; /* Emplace de ligne à utiliser */ - char *wcopy; /* Copie de travail */ - GBufferLine **extra; /* Lignes supplémentaires */ - size_t extra_count; /* Quantité de ces lignes */ - char *saveptr; /* Sauvegarde pour la sécurité */ - char *token; /* Fragment à insérer */ - size_t len; /* Taille dudit fragment */ - GBufferLine *new; /* Nouvelle ligne créée */ - size_t i; /* Boucle de parcours */ - - assert(!g_buffer_line_has_comment(line)); - - result = false; - - range = g_buffer_line_get_range(line); - - wcopy = strdup(comment); - - extra = NULL; - extra_count = 0; - - for (token = strtok_r(wcopy, COMMENT_LINE_SEP, &saveptr); - token != NULL; - token = strtok_r(NULL, COMMENT_LINE_SEP, &saveptr)) - { - len = strlen(token); - - new = g_code_buffer_prepare_new_line(buffer, range); - g_buffer_line_start_merge_at(new, BLC_DISPLAY); - - g_buffer_line_append_text(new, BLC_DISPLAY, token, len, RTT_COMMENT, creator); - - extra = (GBufferLine **)realloc(extra, ++extra_count * sizeof(GBufferLine *)); - - extra[extra_count - 1] = new; - - result = true; - - } - - free(wcopy); - - if (extra_count > 0) - { - result &= g_code_buffer_insert_lines(buffer, extra, extra_count, line, before); - - if (!result) - for (i = 0; i < extra_count; i++) - g_object_unref(G_OBJECT(extra[i])); - - free(extra); - - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : buffer = tampon de lignes à consulter. * -* line = ligne à l'intérieur d'un commentaire. * -* comment = nouveau commentaire à inscrire à la ligne donnée. * -* before = précise la position du commentaire. * -* creator = créateur à l'origine de la construction. * -* * -* Description : Affiche un commentaire sur une ligne de tampon dédiée. * -* * -* Retour : Bilan de l'opération : ajout ou non ? * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool g_code_buffer_update_comment_area(GCodeBuffer *buffer, GBufferLine *line, const char *comment, bool before, GObject *creator) -{ - bool result; /* Bilan à retourner */ - - if (g_buffer_line_has_comment(line)) - result = _g_code_buffer_delete_lines_comment(buffer, line); - else - result = true; - - if (result) - result = _g_code_buffer_write_comment_area(buffer, line, comment, before, creator); - - /* TODO : emit() */ - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : buffer = tampon de lignes à consulter. * -* index = indice de ligne à l'intérieur d'un commentaire. * -* * -* Description : Retrouve la première ligne d'une zone de commentaire. * -* * -* Retour : Indice de l'adresse trouvée, ou le nombre de lignes sinon. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static size_t g_code_buffer_find_first_line_comment(const GCodeBuffer *buffer, size_t index) -{ - size_t result; /* Indice trouvé à retourner */ - GBufferLine *prev; /* Ligne précédente */ - - assert(index < buffer->used); - - bool is_first_line_of_comment(const GBufferLine *ln, const GBufferLine *pv) - { - bool first; /* Statut à renvoyer */ - BufferLineColumn merge_col; /* Colonne de fusion #1 */ - BufferLineColumn prev_merge_col; /* Colonne de fusion #2 */ - - merge_col = g_buffer_line_get_merge_start(ln); - - /** - * La ligne consultée contient toujours un commentaire. - * - * Deux cas de figures sont possibles ici : - * - * - soit du texte est présent dans la colonne "commentaires". - * Si du texte est présent avant, alors il s'agit forcément de - * la première (et unique ?) ligne de commentaire. - * - * - soit la ligne effectue une fusion des colonnes depuis BLC_DISPLAY. - * Si la ligne qui précède fait de même, il s'agit alors d'une étiquette - * ou de l'amont du commentaire. - * - */ - - if (g_buffer_line_has_text(ln, BLC_COMMENTS, BLC_COUNT)) - { - first = g_buffer_line_has_text(ln, BLC_DISPLAY, BLC_COMMENTS); - - if (!first) - { - /* La ligne d'avant doit avoir un commentaire ! */ - first = !g_buffer_line_has_text(pv, BLC_COMMENTS, BLC_COUNT); - } - - } - - else - { - /** - * Le prologue "merge_col == BLC_FIRST" n'étant pas éditable, - * la seule fusion possible ici est la suivante. - */ - assert(merge_col == BLC_DISPLAY); - - /** - * La première ligne d'un tampon est toujours un prologue. - */ - assert(pv != NULL); - - prev_merge_col = g_buffer_line_get_merge_start(pv); - - first = (prev_merge_col != BLC_DISPLAY); - - if (!first) - first = (g_buffer_line_get_flags(pv) & BLF_IS_LABEL); - - } - - return first; - - } - - for (result = index; result > 0; result--) - { - prev = (result > 0 ? buffer->lines[result - 1] : NULL); - - if (is_first_line_of_comment(buffer->lines[result], prev)) - break; - - } - - if (result == 0) - { - if (!is_first_line_of_comment(buffer->lines[0], NULL)) - result = buffer->used; - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : buffer = tampon de lignes à consulter. * -* index = indice de ligne à l'intérieur d'un commentaire. * -* * -* Description : Retrouve la dernière ligne d'une zone de commentaire. * -* * -* Retour : Indice de l'adresse trouvée, ou le nombre de lignes sinon. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static size_t g_code_buffer_find_last_line_comment(const GCodeBuffer *buffer, size_t index) -{ - size_t result; /* Indice trouvé à retourner */ - GBufferLine *next; /* Ligne suivante */ - - assert(index < buffer->used); - - bool is_last_line_of_comment(const GBufferLine *ln, const GBufferLine *nx) - { - bool last; /* Statut à renvoyer */ - BufferLineColumn merge_col; /* Colonne de fusion #1 */ - BufferLineColumn next_merge_col; /* Colonne de fusion #2 */ - - merge_col = g_buffer_line_get_merge_start(ln); - - /** - * La ligne consultée contient toujours un commentaire. - * - * Deux cas de figures sont possibles ici : - * - * - soit du texte est présent dans la colonne "commentaires". - * Si la ligne suivante est similaire et si du texte est présent avant, - * alors il s'agit forcément de d'un nouveau commentaire. S'il n'y a - * aucun texte, il s'agit de la suite du commentaire. - * - * - soit la ligne effectue une fusion des colonnes depuis BLC_DISPLAY. - * Si la ligne qui suit fait de même, il s'agit alors d'une étiquette - * ou de l'aval du commentaire. - * - */ - - if (g_buffer_line_has_text(ln, BLC_COMMENTS, BLC_COUNT)) - { - last = !g_buffer_line_has_text(nx, BLC_COMMENTS, BLC_COUNT); - - if (!last) - last = g_buffer_line_has_text(nx, BLC_DISPLAY, BLC_COMMENTS); - - } - - else - { - /** - * Le prologue "merge_col == BLC_FIRST" n'étant pas éditable, - * la seule fusion possible ici est la suivante. - */ - assert(merge_col == BLC_DISPLAY); - - if (nx == NULL) - last = true; - - else - { - next_merge_col = g_buffer_line_get_merge_start(nx); - - last = (next_merge_col != BLC_DISPLAY); - - if (!last) - last = (g_buffer_line_get_flags(nx) & BLF_IS_LABEL); - - } - - } - - return last; - - } - - for (result = index; result < buffer->used; result++) - { - next = ((result + 1) < buffer->used ? buffer->lines[result + 1] : NULL); - - if (is_last_line_of_comment(buffer->lines[result], next)) - break; - - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : buffer = tampon de lignes à consulter. * -* line = ligne à l'intérieur d'un commentaire. * -* * -* Description : Retrouve le créateur d'un commentaire existant. * -* * -* Retour : Instance trouvée à déréférencer ensuite ou NULL si aucune. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GObject *g_code_buffer_get_comment_creator(const GCodeBuffer *buffer, const GBufferLine *line) -{ - GObject *result; /* Instance à retourner */ - BufferLineColumn merge_col; /* Colonne de fusion */ - - if (g_buffer_line_has_comment(line)) - { - merge_col = g_buffer_line_get_merge_start(line); - - if (merge_col == BLC_DISPLAY) - result = g_buffer_line_find_first_segment_creator(line, BLC_DISPLAY); - else - result = g_buffer_line_find_first_segment_creator(line, BLC_COMMENTS); - - } - - else - result = NULL; - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : buffer = tampon de lignes à consulter. * -* line = ligne à l'intérieur d'un commentaire. * -* * -* Description : Récupère le contenu d'un commentaire existant. * -* * -* Retour : Commentaire retrouver à libérer ou NULL en cas d'échec. * -* * -* Remarques : - * -* * -******************************************************************************/ - -char *g_code_buffer_get_lines_comment(const GCodeBuffer *buffer, const GBufferLine *line) -{ - char *result; /* Contenu à retourner */ - size_t index; /* Indice de la ligne fournie */ - size_t start; /* Ligne de départ */ - size_t end; /* Ligne d'arrivée */ - BufferLineColumn merge_col; /* Colonne de fusion */ - size_t i; /* Boucle de parcours */ - char *extra; /* Commentaire supplémentaire */ - - /* Pas de prologue ici ! */ - assert(g_buffer_line_has_comment(line)); - - result = NULL; - - index = g_code_buffer_find_index_by_line(buffer, line); - - if (index == buffer->used) - goto gcbglc_exit; - - start = g_code_buffer_find_first_line_comment(buffer, index); - - if (start == buffer->used) - goto gcbglc_exit; - - end = g_code_buffer_find_last_line_comment(buffer, index); - - if (end == buffer->used) - goto gcbglc_exit; - - merge_col = g_buffer_line_get_merge_start(line); - - for (i = start; i <= end; i++) - { - if (merge_col == BLC_DISPLAY) - extra = g_buffer_line_get_text(buffer->lines[i], BLC_DISPLAY, BLC_COUNT, false); - - else - extra = g_buffer_line_get_text(buffer->lines[i], BLC_COMMENTS, BLC_COUNT, false); - - assert(extra != NULL); - - if (result == NULL) - result = extra; - - else - { - result = stradd(result, extra); - free(extra); - } - - } - - gcbglc_exit: - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : buffer = tampon de lignes à modifier. * -* line = ligne à l'intérieur d'un commentaire. * -* * -* Description : Supprime un commentaire existant. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool _g_code_buffer_delete_lines_comment(GCodeBuffer *buffer, GBufferLine *line) -{ - bool result; /* Bilan à retourner */ - size_t index; /* Indice de la ligne fournie */ - size_t start; /* Ligne de départ */ - size_t end; /* Ligne d'arrivée */ - BufferLineColumn merge_col; /* Colonne de fusion */ - - /* Pas de prologue ici ! */ - assert(g_buffer_line_has_comment(line)); - - result = false; - - index = g_code_buffer_find_index_by_line(buffer, line); - - if (index == buffer->used) - goto gcbdlc_exit; - - start = g_code_buffer_find_first_line_comment(buffer, index); - - if (start == buffer->used) - goto gcbdlc_exit; - - end = g_code_buffer_find_last_line_comment(buffer, index); - - if (end == buffer->used) - goto gcbdlc_exit; - - result = true; - - merge_col = g_buffer_line_get_merge_start(line); - - if (merge_col == BLC_DISPLAY) - g_code_buffer_delete_lines(buffer, start, end); - - else - { - g_buffer_line_delete_text(buffer->lines[start], BLC_COMMENTS, BLC_COUNT); - - if (end > start) - g_code_buffer_delete_lines(buffer, start + 1, end); - - } - - gcbdlc_exit: - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : buffer = tampon de lignes à modifier. * -* line = ligne à l'intérieur d'un commentaire. * -* * -* Description : Supprime un commentaire existant. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool g_code_buffer_delete_lines_comment(GCodeBuffer *buffer, GBufferLine *line) -{ - bool result; /* Bilan à retourner */ - - result = _g_code_buffer_delete_lines_comment(buffer, line); - - /* TODO : emit() */ - - return result; - -} - - -/* ---------------------------------------------------------------------------------- */ -/* SIGNAUX IMMEDIATS POUR UNE VUE */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* Paramètres : buffer = tampon de lignes à modifier. * -* cb = fonction à appeler au moment opportun. * -* data = object GLib à associer à l'appel. * -* * -* Description : Enregistre l'adresse d'une fonction de mise à jour de vue. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_code_buffer_register_view_callback(GCodeBuffer *buffer, buffer_size_changed_cb cb, GObject *data) -{ - view_callback *new; /* Informations sur l'appel */ - - buffer->vcount++; - - buffer->vcallbacks = (view_callback *)realloc(buffer->vcallbacks, buffer->vcount * sizeof(view_callback)); - - new = &buffer->vcallbacks[buffer->vcount - 1]; - - new->size_changed = cb; - new->data = data; - -} - - -/****************************************************************************** -* * -* Paramètres : buffer = tampon de lignes à modifier. * -* data = object GLib à associer à l'appel. * -* * -* Description : Supprime un élément des vues à contacter pour mises à jour. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_code_buffer_unregister_view_callback(GCodeBuffer *buffer, GObject *data) -{ - size_t i; /* Boucle de parcours */ - - for (i = 0; i < buffer->vcount; i++) - if (buffer->vcallbacks[i].data == data) - { - if ((i + 1) < buffer->vcount) - memmove(&buffer->vcallbacks[i], &buffer->vcallbacks[i + 1], - (buffer->vcount - i - 1) * sizeof(view_callback)); - - buffer->vcount--; - - buffer->vcallbacks = (view_callback *)realloc(buffer->vcallbacks, - buffer->vcount * sizeof(view_callback)); - - } - -} - - -/****************************************************************************** -* * -* Paramètres : buffer = tampon de lignes à diffuser. * -* added = indication sur la variation de la taille du tampon. * -* index = indice de la première ligne à traiter. * -* count = nombre de lignes à traiter. * -* * -* Description : Fait suivre une variation de la quantité de lignes du tampon.* -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_code_buffer_notify_size_changed(const GCodeBuffer *buffer, bool added, size_t index, size_t count) -{ - size_t i; /* Boucle de parcours */ - view_callback *cb; /* Informations sur l'appel */ - - for (i = 0; i < buffer->vcount; i++) - { - cb = &buffer->vcallbacks[i]; - - cb->size_changed(buffer, added, index, count, cb->data); - - } - -} diff --git a/src/glibext/gcodebuffer.h b/src/glibext/gcodebuffer.h deleted file mode 100644 index f600aee..0000000 --- a/src/glibext/gcodebuffer.h +++ /dev/null @@ -1,155 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * gcodebuffer.h - prototypes pour l'affichage d'un fragment de code d'assemblage - * - * Copyright (C) 2010-2014 Cyrille Bagard - * - * This file is part of Chrysalide. - * - * Chrysalide 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. - * - * Chrysalide 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 "delayed.h" -#include "gbufferline.h" -#include "gwidthtracker.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(BufferLineColumn); - -/* Compte le nombre de lignes rassemblées dans un tampon. */ -size_t g_code_buffer_count_lines(const GCodeBuffer *); - -/* Fournit un lien vers la structure de suivi de largeurs. */ -const GWidthTracker *g_code_buffer_get_width_tracker(const GCodeBuffer *); - -/* Initie une nouvelle ligne devant être insérée dans le tampon. */ -GBufferLine *g_code_buffer_prepare_new_line(GCodeBuffer *, const mrange_t *); - -/* Ajoute une nouvelle ligne en fin de tampon. */ -void g_code_buffer_append_new_line(GCodeBuffer *, GBufferLine *); - -/* Ajoute de nouvelles lignes par rapport à une ligne donnée. */ -bool g_code_buffer_insert_lines(GCodeBuffer *, GBufferLine **, size_t, const GBufferLine *, bool); - -/* Supprime une ou plusieurs lignes du tampon indiqué. */ -void g_code_buffer_delete_lines(GCodeBuffer *, size_t, size_t); - - - -/* FIXME */ -#define g_code_buffer_append_new_line_fixme(b) \ - g_code_buffer_prepare_new_line(b, (mrange_t []){ { 0, 0 }, 0 }) - -/* FIXME */ -#define g_code_buffer_insert_at(buf, a, b) NULL - - - -/* Retrouve une ligne au sein d'un tampon avec une adresse. */ -GBufferLine *g_code_buffer_find_line_by_addr(const GCodeBuffer *, const vmpa2t *, BufferLineFlags, size_t *); - -/* Retrouve une ligne au sein d'un tampon avec un indice. */ -GBufferLine *g_code_buffer_find_line_by_index(const GCodeBuffer *, size_t); - -/* Convertit une adresse en indice de ligne. */ -size_t g_code_buffer_get_index_from_address(const GCodeBuffer *, const vmpa2t *, bool); - -/* Retrouve l'indice associé à une ligne au sein d'un tampon. */ -size_t g_code_buffer_find_index_by_line(const GCodeBuffer *, const GBufferLine *); - -/* Augmente l'indentation des prochaines lignes. */ -void g_code_buffer_inc_indentation(GCodeBuffer *); - -/* Diminue l'indentation des prochaines lignes. */ -void g_code_buffer_dec_indentation(GCodeBuffer *); - -/* Traitement d'une ligne parcourue. */ -typedef bool (* process_line_fc) (GCodeBuffer *, GBufferLine *, void *); - -/* Lance un parcours des différentes lignes du tampon de code. */ -GDelayedWork *g_buffer_code_scan(GCodeBuffer *, const vmpa2t *, const vmpa2t *, const char *, process_line_fc, void *); - - - -/* ------------------------- CONFORTS POUR LES COMMENTAIRES ------------------------- */ - - -/* Séparateur commun à tous les plateformes */ -#define COMMENT_LINE_SEP "\n" - - -/* Affiche un commentaire sur une ligne de tampon donnée. */ -bool g_code_buffer_update_inlined_comment(GCodeBuffer *, GBufferLine *, const char *, GObject *); - -/* Affiche un commentaire sur une ligne de tampon dédiée. */ -bool g_code_buffer_update_comment_area(GCodeBuffer *, GBufferLine *, const char *, bool, GObject *); - -/* Retrouve le créateur d'un commentaire existant. */ -GObject *g_code_buffer_get_comment_creator(const GCodeBuffer *, const GBufferLine *); - -/* Récupère le contenu d'un commentaire existant. */ -char *g_code_buffer_get_lines_comment(const GCodeBuffer *, const GBufferLine *); - -/* Supprime un commentaire existant. */ -bool g_code_buffer_delete_lines_comment(GCodeBuffer *, GBufferLine *); - - - -/* ------------------------- SIGNAUX IMMEDIATS POUR UNE VUE ------------------------- */ - - -/* Accompagne une variation de la quantité de lignes du tampon. */ -typedef void (* buffer_size_changed_cb) (const GCodeBuffer *, bool, size_t, size_t, GObject *); - - -/* Enregistre l'adresse d'une fonction de mise à jour de vue. */ -void g_code_buffer_register_view_callback(GCodeBuffer *, buffer_size_changed_cb, GObject *); - -/* Supprime un élément des vues à contacter pour mises à jour. */ -void g_code_buffer_unregister_view_callback(GCodeBuffer *, GObject *); - - - -#endif /* _GLIBEXT_GCODEBUFFER_H */ diff --git a/src/glibext/generator-int.h b/src/glibext/generator-int.h new file mode 100644 index 0000000..d284d87 --- /dev/null +++ b/src/glibext/generator-int.h @@ -0,0 +1,52 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * generator-int.h - prototypes internes pour la génération de lignes à la volée + * + * Copyright (C) 2016 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide 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. + * + * Chrysalide 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_GENERATOR_INT_H +#define _GLIBEXT_GENERATOR_INT_H + + +#include "generator.h" + + + + + +/* Accès à un contenu binaire quelconque (interface) */ +struct _GBinContentIface +{ + GTypeInterface base_iface; /* A laisser en premier */ + + + + + + +}; + + +/* Redéfinition */ +typedef GBinContentIface GBinContentInterface; + + + +#endif /* _GLIBEXT_GENERATOR_INT_H */ diff --git a/src/glibext/generators/Makefile.am b/src/glibext/generators/Makefile.am new file mode 100644 index 0000000..5dd7133 --- /dev/null +++ b/src/glibext/generators/Makefile.am @@ -0,0 +1,15 @@ + +noinst_LTLIBRARIES = libglibextgenerators.la + +libglibextgenerators_la_SOURCES = \ + prologue.h prologue.c \ + rborder.h rborder.c + +libglibextgenerators_la_LDFLAGS = + + +AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) + +AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) + +SUBDIRS = diff --git a/src/glibext/generators/prologue.c b/src/glibext/generators/prologue.c new file mode 100644 index 0000000..7a4fea5 --- /dev/null +++ b/src/glibext/generators/prologue.c @@ -0,0 +1,359 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * prologue.c - génération à la volée de lignes d'introduction + * + * Copyright (C) 2016 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide 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. + * + * Chrysalide 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 "prologue.h" + + +#include <assert.h> +#include <malloc.h> + + +#include "../gbufferline.h" +#include "../linegen-int.h" +#include "../linesegment.h" + + + +/* Tampon pour générateur de lignes en prologue (instance) */ +struct _GIntroGenerator +{ + GObject parent; /* A laisser en premier */ + + char **text; /* Lignes brutes à représenter */ + size_t count; /* Quantité de ces lignes */ + +}; + +/* Tampon pour générateur de lignes en prologue (classe) */ +struct _GIntroGeneratorClass +{ + GObjectClass parent; /* A laisser en premier */ + +}; + + +/* Procède à l'initialisation d'une classe de générateur. */ +static void g_intro_generator_class_init(GIntroGeneratorClass *); + +/* Procède à l'initialisation d'un générateur de lignes d'intro. */ +static void g_intro_generator_init(GIntroGenerator *); + +/* Procède à l'initialisation de l'interface de génération. */ +static void g_intro_generator_interface_init(GLineGeneratorInterface *); + +/* Supprime toutes les références externes. */ +static void g_intro_generator_dispose(GIntroGenerator *); + +/* Procède à la libération totale de la mémoire. */ +static void g_intro_generator_finalize(GIntroGenerator *); + +/* Indique le nombre de ligne prêtes à être générées. */ +static size_t g_intro_generator_count_lines(const GIntroGenerator *); + +/* Retrouve l'emplacement correspondant à une position donnée. */ +static void g_intro_generator_compute_addr(const GIntroGenerator *, gint, vmpa2t *, size_t, size_t); + +/* Détermine si le conteneur s'inscrit dans une plage donnée. */ +static int g_intro_generator_contains_addr(const GIntroGenerator *, const vmpa2t *, size_t, size_t); + +/* Renseigne sur les propriétés liées à un générateur. */ +static BufferLineFlags g_intro_generator_get_flags(const GIntroGenerator *, size_t, size_t); + +/* Imprime dans une ligne de rendu le contenu représenté. */ +static void g_intro_generator_print(GIntroGenerator *, GBufferLine *, size_t, size_t); + + + +/* Détermine le type du générateur de lignes d'introduction à la volée. */ +G_DEFINE_TYPE_WITH_CODE(GIntroGenerator, g_intro_generator, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE(G_TYPE_LINE_GENERATOR, g_intro_generator_interface_init)); + + +/****************************************************************************** +* * +* Paramètres : class = classe de composant GLib à initialiser. * +* * +* Description : Procède à l'initialisation d'une classe de générateur. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_intro_generator_class_init(GIntroGeneratorClass *class) +{ + GObjectClass *object; /* Autre version de la classe */ + + object = G_OBJECT_CLASS(class); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_intro_generator_dispose; + object->finalize = (GObjectFinalizeFunc)g_intro_generator_finalize; + +} + + +/****************************************************************************** +* * +* Paramètres : generator = composant GLib à initialiser. * +* * +* Description : Procède à l'initialisation d'un générateur de lignes d'intro.* +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_intro_generator_init(GIntroGenerator *generator) +{ + generator->text = NULL; + generator->count = 0; + +} + + +/****************************************************************************** +* * +* Paramètres : iface = interface GLib à initialiser. * +* * +* Description : Procède à l'initialisation de l'interface de génération. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_intro_generator_interface_init(GLineGeneratorInterface *iface) +{ + iface->count = (linegen_count_lines_fc)g_intro_generator_count_lines; + iface->compute = (linegen_compute_fc)g_intro_generator_compute_addr; + iface->contains = (linegen_contains_fc)g_intro_generator_contains_addr; + iface->get_flags = (linegen_get_flags_fc)g_intro_generator_get_flags; + iface->print = (linegen_print_fc)g_intro_generator_print; + +} + + +/****************************************************************************** +* * +* Paramètres : generator = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_intro_generator_dispose(GIntroGenerator *generator) +{ + G_OBJECT_CLASS(g_intro_generator_parent_class)->dispose(G_OBJECT(generator)); + +} + + +/****************************************************************************** +* * +* Paramètres : generator = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_intro_generator_finalize(GIntroGenerator *generator) +{ + size_t i; /* Boucle de parcours */ + + for (i = 0; i < generator->count; i++) + free(generator->text[i]); + + if (generator->text != NULL) + free(generator->text); + + G_OBJECT_CLASS(g_intro_generator_parent_class)->finalize(G_OBJECT(generator)); + +} + + +/****************************************************************************** +* * +* Paramètres : lang = trauducteur pour l'impression finale. * +* text = tableau de lignes à conserver. * +* count = taille du tableau fourni. * +* * +* Description : Crée un nouveau générateur de lignes d'introduction. * +* * +* Retour : Composant GLib créé. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GIntroGenerator *g_intro_generator_new(const GCodingLanguage *lang, char **text, size_t count) +{ + GIntroGenerator *result; /* Composant à retourner */ + + result = g_object_new(G_TYPE_INTRO_GENERATOR, NULL); + + result->text = text; + result->count = count; + + g_coding_language_encapsulate_comments(lang, &result->text, &result->count); + + result->text = (char **)realloc(result->text, ++result->count * sizeof(char *)); + + result->text[result->count - 1] = NULL; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : generator = générateur à consulter. * +* * +* Description : Indique le nombre de ligne prêtes à être générées. * +* * +* Retour : Nombre de lignes devant apparaître au final. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static size_t g_intro_generator_count_lines(const GIntroGenerator *generator) +{ + return generator->count; + +} + + +/****************************************************************************** +* * +* Paramètres : generator = générateur à consulter. * +* x = position géographique sur la ligne concernée. * +* addr = position en mémoire à analyser. * +* index = indice de cette même ligne dans le tampon global.* +* repeat = indice d'utilisations successives du générateur. * +* * +* Description : Retrouve l'emplacement correspondant à une position donnée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_intro_generator_compute_addr(const GIntroGenerator *generator, gint x, vmpa2t *addr, size_t index, size_t repeat) +{ + init_vmpa(addr, 0, 0); + +} + + +/****************************************************************************** +* * +* Paramètres : generator = générateur à consulter. * +* addr = position en mémoire à analyser. * +* index = indice de cette même ligne dans le tampon global.* +* repeat = indice d'utilisations successives du générateur. * +* * +* Description : Détermine si le conteneur s'inscrit dans une plage donnée. * +* * +* Retour : Bilan de la détermination, utilisable en comparaisons. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static int g_intro_generator_contains_addr(const GIntroGenerator *generator, const vmpa2t *addr, size_t index, size_t repeat) +{ + /** + * Les lignes générées sont purement artificielles et sans attache. + * Elles n'existent donc pas. + */ + + return 1; + +} + + +/****************************************************************************** +* * +* Paramètres : generator = générateur à consulter. * +* index = indice de cette même ligne dans le tampon global.* +* repeat = indice d'utilisations successives du générateur. * +* * +* Description : Renseigne sur les propriétés liées à un générateur. * +* * +* Retour : Propriétés particulières associées. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static BufferLineFlags g_intro_generator_get_flags(const GIntroGenerator *generator, size_t index, size_t repeat) +{ + return BLF_NONE; + +} + + +/****************************************************************************** +* * +* Paramètres : generator = générateur à utiliser pour l'impression. * +* line = ligne de rendu à compléter. * +* index = indice de cette même ligne dans le tampon global.* +* repeat = indice d'utilisations successives du générateur. * +* * +* Description : Imprime dans une ligne de rendu le contenu représenté. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_intro_generator_print(GIntroGenerator *generator, GBufferLine *line, size_t index, size_t repeat) +{ + assert(repeat < generator->count); + + if ((repeat + 1) != generator->count) + { + g_buffer_line_start_merge_at(line, BLC_PHYSICAL); + + g_buffer_line_append_text(line, BLC_PHYSICAL, SL(generator->text[repeat]), RTT_COMMENT, NULL); + + if (repeat == 0) + g_buffer_line_add_flag(line, BLF_WIDTH_MANAGER); + + } + +} diff --git a/src/glibext/generators/prologue.h b/src/glibext/generators/prologue.h new file mode 100644 index 0000000..40cdce3 --- /dev/null +++ b/src/glibext/generators/prologue.h @@ -0,0 +1,58 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * prologue.h - prototypes pour la génération à la volée de lignes d'introduction + * + * Copyright (C) 2016 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide 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. + * + * Chrysalide 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_GENERATORS_PROLOGUE_H +#define _GLIBEXT_GENERATORS_PROLOGUE_H + + +#include <glib-object.h> + + +#include "../../analysis/human/lang.h" + + + +#define G_TYPE_INTRO_GENERATOR (g_intro_generator_get_type()) +#define G_INTRO_GENERATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_CODE_BUFFER, GIntroGenerator)) +#define G_INTRO_GENERATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_CODE_BUFFER, GIntroGeneratorClass)) +#define G_IS_INTRO_GENERATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_CODE_BUFFER)) +#define G_IS_INTRO_GENERATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_CODE_BUFFER)) +#define G_INTRO_GENERATOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_CODE_BUFFER, GIntroGeneratorClass)) + + +/* Tampon pour générateur de lignes en prologue (instance) */ +typedef struct _GIntroGenerator GIntroGenerator; + +/* Tampon pour générateur de lignes en prologue (classe) */ +typedef struct _GIntroGeneratorClass GIntroGeneratorClass; + + +/* Détermine le type du générateur de lignes d'introduction à la volée. */ +GType g_intro_generator_get_type(void); + +/* Crée un nouveau générateur de lignes d'introduction. */ +GIntroGenerator *g_intro_generator_new(const GCodingLanguage *, char **, size_t); + + + +#endif /* _GLIBEXT_GENERATORS_PROLOGUE_H */ diff --git a/src/glibext/generators/rborder.c b/src/glibext/generators/rborder.c new file mode 100644 index 0000000..ff34dfb --- /dev/null +++ b/src/glibext/generators/rborder.c @@ -0,0 +1,361 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * prologue.c - génération à la volée de délimitations de routines + * + * Copyright (C) 2016 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide 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. + * + * Chrysalide 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 "rborder.h" + + +#include <assert.h> +#include <malloc.h> +#include <string.h> + + +#include "../gbufferline.h" +#include "../linegen-int.h" +#include "../linesegment.h" + + + +/* Tampon pour générateur de délimitations de routines (instance) */ +struct _GBorderGenerator +{ + GObject parent; /* A laisser en premier */ + + GCodingLanguage *lang; /* Traduction de la sortie */ + + vmpa2t addr; /* Position de la limite */ + bool start; /* Début ou fin de routine ? */ + + MemoryDataSize msize; /* Taille du bus d'adresses */ + +}; + +/* Tampon pour générateur de délimitations de routines (classe) */ +struct _GBorderGeneratorClass +{ + GObjectClass parent; /* A laisser en premier */ + +}; + + +#define ROUTINE_INTRO_MSG "--------------- BEGIN OF PROCEDURE ---------------" + +#define ROUTINE_OUTRO_MSG "---------------- END OF PROCEDURE ----------------" + + +/* Procède à l'initialisation d'une classe de générateur. */ +static void g_border_generator_class_init(GBorderGeneratorClass *); + +/* Procède à l'initialisation d'un générateur de délimitations. */ +static void g_border_generator_init(GBorderGenerator *); + +/* Procède à l'initialisation de l'interface de génération. */ +static void g_border_generator_interface_init(GLineGeneratorInterface *); + +/* Supprime toutes les références externes. */ +static void g_border_generator_dispose(GBorderGenerator *); + +/* Procède à la libération totale de la mémoire. */ +static void g_border_generator_finalize(GBorderGenerator *); + +/* Indique le nombre de ligne prêtes à être générées. */ +static size_t g_border_generator_count_lines(const GBorderGenerator *); + +/* Retrouve l'emplacement correspondant à une position donnée. */ +static void g_border_generator_compute_addr(const GBorderGenerator *, gint, vmpa2t *, size_t, size_t); + +/* Détermine si le conteneur s'inscrit dans une plage donnée. */ +static int g_border_generator_contains_addr(const GBorderGenerator *, const vmpa2t *, size_t, size_t); + +/* Renseigne sur les propriétés liées à un générateur. */ +static BufferLineFlags g_border_generator_get_flags(const GBorderGenerator *, size_t, size_t); + +/* Imprime dans une ligne de rendu le contenu représenté. */ +static void g_border_generator_print(GBorderGenerator *, GBufferLine *, size_t, size_t); + + + +/* Détermine le type du générateur de délimitations de routines à la volée. */ +G_DEFINE_TYPE_WITH_CODE(GBorderGenerator, g_border_generator, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE(G_TYPE_LINE_GENERATOR, g_border_generator_interface_init)); + + +/****************************************************************************** +* * +* Paramètres : class = classe de composant GLib à initialiser. * +* * +* Description : Procède à l'initialisation d'une classe de générateur. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_border_generator_class_init(GBorderGeneratorClass *class) +{ + GObjectClass *object; /* Autre version de la classe */ + + object = G_OBJECT_CLASS(class); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_border_generator_dispose; + object->finalize = (GObjectFinalizeFunc)g_border_generator_finalize; + +} + + +/****************************************************************************** +* * +* Paramètres : generator = composant GLib à initialiser. * +* * +* Description : Procède à l'initialisation d'un générateur de délimitations. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_border_generator_init(GBorderGenerator *generator) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : iface = interface GLib à initialiser. * +* * +* Description : Procède à l'initialisation de l'interface de génération. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_border_generator_interface_init(GLineGeneratorInterface *iface) +{ + iface->count = (linegen_count_lines_fc)g_border_generator_count_lines; + iface->compute = (linegen_compute_fc)g_border_generator_compute_addr; + iface->contains = (linegen_contains_fc)g_border_generator_contains_addr; + iface->get_flags = (linegen_get_flags_fc)g_border_generator_get_flags; + iface->print = (linegen_print_fc)g_border_generator_print; + +} + + +/****************************************************************************** +* * +* Paramètres : generator = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_border_generator_dispose(GBorderGenerator *generator) +{ + g_object_unref(G_OBJECT(generator->lang)); + + G_OBJECT_CLASS(g_border_generator_parent_class)->dispose(G_OBJECT(generator)); + +} + + +/****************************************************************************** +* * +* Paramètres : generator = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_border_generator_finalize(GBorderGenerator *generator) +{ + G_OBJECT_CLASS(g_border_generator_parent_class)->finalize(G_OBJECT(generator)); + +} + + +/****************************************************************************** +* * +* Paramètres : lang = trauducteur pour l'impression finale. * +* addr = position correspondant à la délimitation à marquer. * +* start = indique le type de délimitation observée. * +* msize = taille des adresses représentées. * +* * +* Description : Crée un nouveau générateur de délimitations de routines. * +* * +* Retour : Composant GLib créé. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBorderGenerator *g_border_generator_new(GCodingLanguage *lang, const vmpa2t *addr, bool start, MemoryDataSize msize) +{ + GBorderGenerator *result; /* Composant à retourner */ + + result = g_object_new(G_TYPE_BORDER_GENERATOR, NULL); + + result->lang = lang; + g_object_ref(G_OBJECT(lang)); + + copy_vmpa(&result->addr, addr); + result->start = start; + + result->msize = msize; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : generator = générateur à consulter. * +* * +* Description : Indique le nombre de ligne prêtes à être générées. * +* * +* Retour : Nombre de lignes devant apparaître au final. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static size_t g_border_generator_count_lines(const GBorderGenerator *generator) +{ + return 3; + +} + + +/****************************************************************************** +* * +* Paramètres : generator = générateur à consulter. * +* x = position géographique sur la ligne concernée. * +* addr = position en mémoire à analyser. * +* index = indice de cette même ligne dans le tampon global.* +* repeat = indice d'utilisations successives du générateur. * +* * +* Description : Retrouve l'emplacement correspondant à une position donnée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_border_generator_compute_addr(const GBorderGenerator *generator, gint x, vmpa2t *addr, size_t index, size_t repeat) +{ + copy_vmpa(addr, &generator->addr); + +} + + +/****************************************************************************** +* * +* Paramètres : generator = générateur à consulter. * +* addr = position en mémoire à analyser. * +* index = indice de cette même ligne dans le tampon global.* +* repeat = indice d'utilisations successives du générateur. * +* * +* Description : Détermine si le conteneur s'inscrit dans une plage donnée. * +* * +* Retour : Bilan de la détermination, utilisable en comparaisons. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static int g_border_generator_contains_addr(const GBorderGenerator *generator, const vmpa2t *addr, size_t index, size_t repeat) +{ + return cmp_vmpa(addr, &generator->addr); + +} + + +/****************************************************************************** +* * +* Paramètres : generator = générateur à consulter. * +* index = indice de cette même ligne dans le tampon global.* +* repeat = indice d'utilisations successives du générateur. * +* * +* Description : Renseigne sur les propriétés liées à un générateur. * +* * +* Retour : Propriétés particulières associées. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static BufferLineFlags g_border_generator_get_flags(const GBorderGenerator *generator, size_t index, size_t repeat) +{ + return BLF_NONE; + +} + + +/****************************************************************************** +* * +* Paramètres : generator = générateur à utiliser pour l'impression. * +* line = ligne de rendu à compléter. * +* index = indice de cette même ligne dans le tampon global.* +* repeat = indice d'utilisations successives du générateur. * +* * +* Description : Imprime dans une ligne de rendu le contenu représenté. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_border_generator_print(GBorderGenerator *generator, GBufferLine *line, size_t index, size_t repeat) +{ + char *text; /* Texte principal à insérer */ + + assert(repeat < 3); + + g_buffer_line_fill_vmpa(line, &generator->addr, generator->msize, generator->msize); + + if (repeat == 1) + { + text = strdup(generator->start ? ROUTINE_INTRO_MSG : ROUTINE_OUTRO_MSG); + g_coding_language_encapsulate_comment(generator->lang, &text); + + g_buffer_line_start_merge_at(line, BLC_ASSEMBLY_HEAD); + g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, SL(text), RTT_COMMENT, NULL); + + free(text); + + } + +} diff --git a/src/glibext/generators/rborder.h b/src/glibext/generators/rborder.h new file mode 100644 index 0000000..fa12734 --- /dev/null +++ b/src/glibext/generators/rborder.h @@ -0,0 +1,60 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * rborder.h - prototypes pour la génération à la volée de délimitations de routines + * + * Copyright (C) 2016 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide 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. + * + * Chrysalide 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_GENERATORS_RBORDER_H +#define _GLIBEXT_GENERATORS_RBORDER_H + + +#include <glib-object.h> +#include <stdbool.h> + + +#include "../../analysis/human/lang.h" +#include "../../arch/vmpa.h" + + + +#define G_TYPE_BORDER_GENERATOR (g_border_generator_get_type()) +#define G_BORDER_GENERATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_CODE_BUFFER, GBorderGenerator)) +#define G_BORDER_GENERATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_CODE_BUFFER, GBorderGeneratorClass)) +#define G_IS_BORDER_GENERATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_CODE_BUFFER)) +#define G_IS_BORDER_GENERATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_CODE_BUFFER)) +#define G_BORDER_GENERATOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_CODE_BUFFER, GBorderGeneratorClass)) + + +/* Tampon pour générateur de délimitations de routines (instance) */ +typedef struct _GBorderGenerator GBorderGenerator; + +/* Tampon pour générateur de délimitations de routines (classe) */ +typedef struct _GBorderGeneratorClass GBorderGeneratorClass; + + +/* Détermine le type du générateur de délimitations de routines à la volée. */ +GType g_border_generator_get_type(void); + +/* Crée un nouveau générateur de délimitations de routines. */ +GBorderGenerator *g_border_generator_new(GCodingLanguage *, const vmpa2t *, bool, MemoryDataSize); + + + +#endif /* _GLIBEXT_GENERATORS_RBORDER_H */ diff --git a/src/glibext/gwidthtracker.c b/src/glibext/gwidthtracker.c index 3a1863e..cd452bc 100644 --- a/src/glibext/gwidthtracker.c +++ b/src/glibext/gwidthtracker.c @@ -30,7 +30,7 @@ #include <string.h> -#include "gcodebuffer.h" +#include "gbuffercache.h" @@ -51,7 +51,7 @@ struct _GWidthTracker { GObject parent; /* A laisser en premier */ - GCodeBuffer *buffer; /* Ensemble complet de lignes */ + GBufferCache *cache; /* Ensemble complet de lignes */ common_metrics *portions; /* Portions représentées */ size_t count; /* Quantité de ces portions */ @@ -163,7 +163,7 @@ static void g_width_tracker_init(GWidthTracker *tracker) static void g_width_tracker_dispose(GWidthTracker *tracker) { - g_object_unref(G_OBJECT(tracker->buffer)); + g_object_unref(G_OBJECT(tracker->cache)); G_OBJECT_CLASS(g_width_tracker_parent_class)->dispose(G_OBJECT(tracker)); @@ -203,14 +203,14 @@ static void g_width_tracker_finalize(GWidthTracker *tracker) * * ******************************************************************************/ -GWidthTracker *g_width_tracker_new(GCodeBuffer *buffer) +GWidthTracker *g_width_tracker_new(GBufferCache *cache) { GWidthTracker *result; /* Composant à retourner */ result = g_object_new(G_TYPE_WIDTH_TRACKER, NULL); - g_object_ref(G_OBJECT(buffer)); - result->buffer = buffer; + g_object_ref(G_OBJECT(cache)); + result->cache = cache; return result; @@ -240,8 +240,8 @@ GWidthTracker *g_width_tracker_new_restricted(const GWidthTracker *template, siz result = g_object_new(G_TYPE_WIDTH_TRACKER, NULL); - g_object_ref(G_OBJECT(template->buffer)); - result->buffer = template->buffer; + g_object_ref(G_OBJECT(template->cache)); + result->cache = template->cache; start = g_width_tracker_find_metrics(template, first); assert(start < template->count); @@ -404,7 +404,6 @@ static const line_width_summary *g_width_tracker_get_up_to_date_widths(GWidthTra { common_metrics *portion; /* Portion à actualiser */ size_t i; /* Boucle de parcours */ - GBufferLine *line; /* Ligne à manipuler */ assert(index < tracker->count); @@ -419,12 +418,7 @@ static const line_width_summary *g_width_tracker_get_up_to_date_widths(GWidthTra /* Collecte */ for (i = portion->first; i <= portion->last; i++) - { - line = g_code_buffer_find_line_by_index(tracker->buffer, i); - - g_buffer_line_collect_widths(line, &portion->summary); - - } + g_buffer_cache_collect_widths(tracker->cache, i, &portion->summary); /* Marquage pour mémoire */ @@ -441,6 +435,30 @@ static const line_width_summary *g_width_tracker_get_up_to_date_widths(GWidthTra * * * Paramètres : tracker = gestionnaire de largeurs de lignes à mettre jour. * * index = position de la première des lignes à ajouter. * +* * +* Description : Prend acte d'un changement sur une ligne pour les largeurs. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_width_tracker_update(GWidthTracker *tracker, size_t index) +{ + size_t current; /* Indice de portion visée */ + + current = g_width_tracker_find_metrics(tracker, index); + + g_width_tracker_reset_widths(tracker, current); + +} + + +/****************************************************************************** +* * +* Paramètres : tracker = gestionnaire de largeurs de lignes à mettre jour. * +* index = position de la première des lignes à ajouter. * * count = quantité de lignes devant être ajoutées. * * * * Description : Prend acte de l'ajout de lignes pour les largeurs. * @@ -457,7 +475,6 @@ void g_width_tracker_update_added(GWidthTracker *tracker, size_t index, size_t c common_metrics *portion; /* Portion sélectionnée */ size_t next; /* Prochaine portion à décaller*/ size_t i; /* Boucle de parcours */ - GBufferLine *line; /* Ligne à manipuler */ size_t dest; /* Destination d'une recopie */ size_t src; /* Source d'une recopie */ @@ -502,9 +519,7 @@ void g_width_tracker_update_added(GWidthTracker *tracker, size_t index, size_t c for (i = index + count - 1; i >= index; i--) { - line = g_code_buffer_find_line_by_index(tracker->buffer, i); - - if (g_buffer_line_get_flags(line) & BLF_WIDTH_MANAGER) + if (g_buffer_cache_get_line_flags(tracker->cache, i) & BLF_WIDTH_MANAGER) { /* Insertion d'une nouvelle place */ @@ -602,11 +617,11 @@ void g_width_tracker_update_deleted(GWidthTracker *tracker, size_t start, size_t /* Suppression de portions inutiles ? */ - keep_first = (tracker->portions[first].first > start || end < tracker->portions[first].last); + keep_first = (tracker->portions[first].first < start || end < tracker->portions[first].last); dest = (keep_first ? first + 1 : first); - keep_last = (tracker->portions[last].first > start || end < tracker->portions[last].last); + keep_last = (tracker->portions[last].first < start || end < tracker->portions[last].last); src = (keep_last ? last : last + 1); @@ -647,7 +662,7 @@ void g_width_tracker_update_deleted(GWidthTracker *tracker, size_t start, size_t if (end < tracker->portions[first].last) tracker->portions[first].last -= diff; else - tracker->portions[first].last = start; + tracker->portions[first].last = start - 1; } if (keep_last && last != first) diff --git a/src/glibext/gwidthtracker.h b/src/glibext/gwidthtracker.h index fe22088..b9d22ed 100644 --- a/src/glibext/gwidthtracker.h +++ b/src/glibext/gwidthtracker.h @@ -33,9 +33,8 @@ -/* gcodebuffer.h : Tampon pour code désassemblé (instance) */ -typedef struct _GCodeBuffer GCodeBuffer; - +/* gbuffercache.h : Tampon pour gestion de lignes optimisée (instance) */ +typedef struct _GBufferCache GBufferCache; #define G_TYPE_WIDTH_TRACKER (g_width_tracker_get_type()) @@ -57,11 +56,14 @@ typedef struct _GWidthTrackerClass GWidthTrackerClass; GType g_width_tracker_get_type(void); /* Crée un nouveau suivi de largeurs au sein de lignes. */ -GWidthTracker *g_width_tracker_new(GCodeBuffer *); +GWidthTracker *g_width_tracker_new(GBufferCache *); /* Crée un nouveau suivi de largeurs au sein de lignes. */ GWidthTracker *g_width_tracker_new_restricted(const GWidthTracker *, size_t, size_t); +/* Prend acte d'un changement sur une ligne pour les largeurs. */ +void g_width_tracker_update(GWidthTracker *, size_t); + /* Prend acte de l'ajout de lignes pour les largeurs. */ void g_width_tracker_update_added(GWidthTracker *, size_t, size_t); diff --git a/src/glibext/linecolumn.c b/src/glibext/linecolumn.c index 83413cf..5cce969 100644 --- a/src/glibext/linecolumn.c +++ b/src/glibext/linecolumn.c @@ -389,7 +389,7 @@ line_segment *get_line_column_content_from_index(const line_column *column, size { line_segment *result; /* Trouvaille à retourner */ - assert(index < column->count); + assert(index != -1 && index < column->count); result = column->segments[index]; diff --git a/src/glibext/linegen-int.h b/src/glibext/linegen-int.h new file mode 100644 index 0000000..f43b2f3 --- /dev/null +++ b/src/glibext/linegen-int.h @@ -0,0 +1,67 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * linegen-int.h - définitions internes propres aux intermédiaires de génération de lignes + * + * Copyright (C) 2016 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide 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. + * + * Chrysalide 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_LINEGEN_INT_H +#define _GLIBEXT_LINEGEN_INT_H + + +#include "linegen.h" + + + +/* Indique le nombre de ligne prêtes à être générées. */ +typedef size_t (* linegen_count_lines_fc) (const GLineGenerator *); + +/* Retrouve l'emplacement correspondant à une position donnée. */ +typedef void (* linegen_compute_fc) (const GLineGenerator *, gint, vmpa2t *, size_t, size_t); + +/* Détermine si le conteneur s'inscrit dans une plage donnée. */ +typedef int (* linegen_contains_fc) (const GLineGenerator *, const vmpa2t *, size_t, size_t); + +/* Renseigne sur les propriétés liées à un générateur. */ +typedef BufferLineFlags (* linegen_get_flags_fc) (const GLineGenerator *, size_t, size_t); + +/* Imprime dans une ligne de rendu le contenu représenté. */ +typedef void (* linegen_print_fc) (GLineGenerator *, GBufferLine *, size_t, size_t); + + +/* Intermédiaire pour la génération de lignes (interface) */ +struct _GLineGeneratorIface +{ + GTypeInterface base_iface; /* A laisser en premier */ + + linegen_count_lines_fc count; /* Décompte des lignes */ + linegen_compute_fc compute; /* Calcul d'emplacement */ + linegen_contains_fc contains; /* Inclusion de positions */ + linegen_get_flags_fc get_flags; /* Récupération des drapeaux */ + linegen_print_fc print; /* Impression d'une ligne */ + +}; + + +/* Redéfinition */ +typedef GLineGeneratorIface GLineGeneratorInterface; + + + +#endif /* _GLIBEXT_LINEGEN_INT_H */ diff --git a/src/glibext/linegen.c b/src/glibext/linegen.c new file mode 100644 index 0000000..fc0e01e --- /dev/null +++ b/src/glibext/linegen.c @@ -0,0 +1,208 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * linegen.c - intermédiaires de génération de lignes + * + * Copyright (C) 2016 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide 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. + * + * Chrysalide 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 "linegen.h" + + +#include <assert.h> + + +#include "linegen-int.h" + + + +/* Procède à l'initialisation de l'interface de génération. */ +static void g_line_generator_default_init(GLineGeneratorInterface *); + + + +/* Détermine le type d'une interface pour la mise en place de lignes. */ +G_DEFINE_INTERFACE(GLineGenerator, g_line_generator, G_TYPE_OBJECT) + + +/****************************************************************************** +* * +* Paramètres : iface = interface GLib à initialiser. * +* * +* Description : Procède à l'initialisation de l'interface de génération. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_line_generator_default_init(GLineGeneratorInterface *iface) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : generator = générateur à consulter. * +* * +* Description : Indique le nombre de ligne prêtes à être générées. * +* * +* Retour : Nombre de lignes devant apparaître au final. * +* * +* Remarques : - * +* * +******************************************************************************/ + +size_t g_line_generator_count_lines(const GLineGenerator *generator) +{ + size_t result; /* Décompte à retourner */ + GLineGeneratorIface *iface; /* Interface utilisée */ + + iface = G_LINE_GENERATOR_GET_IFACE(generator); + + result = iface->count(generator); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : generator = générateur à consulter. * +* x = position géographique sur la ligne concernée. * +* addr = position en mémoire à analyser. * +* index = indice de cette même ligne dans le tampon global.* +* repeat = indice d'utilisations successives du générateur. * +* * +* Description : Retrouve l'emplacement correspondant à une position donnée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_line_generator_compute_addr(const GLineGenerator *generator, gint x, vmpa2t *addr, size_t index, size_t repeat) +{ + GLineGeneratorIface *iface; /* Interface utilisée */ + + iface = G_LINE_GENERATOR_GET_IFACE(generator); + +#ifndef NDEBUG + if (iface->count != NULL) + assert(repeat < g_line_generator_count_lines(generator)); +#endif + + iface->compute(generator, x, addr, index, repeat); + +} + + +/****************************************************************************** +* * +* Paramètres : generator = générateur à consulter. * +* addr = position en mémoire à analyser. * +* index = indice de cette même ligne dans le tampon global.* +* repeat = indice d'utilisations successives du générateur. * +* * +* Description : Détermine si le conteneur s'inscrit dans une plage donnée. * +* * +* Retour : Bilan de la détermination, utilisable en comparaisons. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int g_line_generator_contains_addr(const GLineGenerator *generator, const vmpa2t *addr, size_t index, size_t repeat) +{ + GLineGeneratorIface *iface; /* Interface utilisée */ + + iface = G_LINE_GENERATOR_GET_IFACE(generator); + +#ifndef NDEBUG + if (iface->count != NULL) + assert(repeat < g_line_generator_count_lines(generator)); +#endif + + return iface->contains(generator, addr, index, repeat); + +} + + +/****************************************************************************** +* * +* Paramètres : generator = générateur à consulter. * +* index = indice de cette même ligne dans le tampon global.* +* repeat = indice d'utilisations successives du générateur. * +* * +* Description : Renseigne sur les propriétés liées à un générateur. * +* * +* Retour : Propriétés particulières associées. * +* * +* Remarques : - * +* * +******************************************************************************/ + +BufferLineFlags g_line_generator_get_flags(const GLineGenerator *generator, size_t index, size_t repeat) +{ + GLineGeneratorIface *iface; /* Interface utilisée */ + + iface = G_LINE_GENERATOR_GET_IFACE(generator); + +#ifndef NDEBUG + if (iface->count != NULL) + assert(repeat < g_line_generator_count_lines(generator)); +#endif + + return iface->get_flags(generator, index, repeat); + +} + + +/****************************************************************************** +* * +* Paramètres : generator = générateur à utiliser pour l'impression. * +* line = ligne de rendu à compléter. * +* index = indice de cette même ligne dans le tampon global.* +* repeat = indice d'utilisations successives du générateur. * +* * +* Description : Imprime dans une ligne de rendu le contenu représenté. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_line_generator_print(GLineGenerator *generator, GBufferLine *line, size_t index, size_t repeat) +{ + GLineGeneratorIface *iface; /* Interface utilisée */ + + iface = G_LINE_GENERATOR_GET_IFACE(generator); + +#ifndef NDEBUG + if (iface->count != NULL) + assert(repeat < g_line_generator_count_lines(generator)); +#endif + + return iface->print(generator, line, index, repeat); + +} diff --git a/src/glibext/linegen.h b/src/glibext/linegen.h new file mode 100644 index 0000000..c64baaa --- /dev/null +++ b/src/glibext/linegen.h @@ -0,0 +1,68 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * linegen.h - prototypes pour les intermédiaires de génération de lignes + * + * Copyright (C) 2016 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide 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. + * + * Chrysalide 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_LINEGEN_H +#define _GLIBEXT_LINEGEN_H + + + +#include "gbufferline.h" + + + +#define G_TYPE_LINE_GENERATOR (g_line_generator_get_type()) +#define G_LINE_GENERATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_LINE_GENERATOR, GLineGenerator)) +#define G_LINE_GENERATOR_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST((vtable), G_TYPE_LINE_GENERATOR, GLineGeneratorIface)) +#define GTK_IS_LINE_GENERATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_LINE_GENERATOR)) +#define GTK_IS_LINE_GENERATOR_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE((vtable), G_TYPE_LINE_GENERATOR)) +#define G_LINE_GENERATOR_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), G_TYPE_LINE_GENERATOR, GLineGeneratorIface)) + + +/* Intermédiaire pour la génération de lignes (coquille vide) */ +typedef struct _GLineGenerator GLineGenerator; + +/* Intermédiaire pour la génération de lignes (interface) */ +typedef struct _GLineGeneratorIface GLineGeneratorIface; + + +/* Détermine le type d'une interface pour la mise en place de lignes. */ +GType g_line_generator_get_type(void) G_GNUC_CONST; + +/* Indique le nombre de ligne prêtes à être générées. */ +size_t g_line_generator_count_lines(const GLineGenerator *); + +/* Retrouve l'emplacement correspondant à une position donnée. */ +void g_line_generator_compute_addr(const GLineGenerator *, gint, vmpa2t *, size_t, size_t); + +/* Détermine si le conteneur s'inscrit dans une plage donnée. */ +int g_line_generator_contains_addr(const GLineGenerator *, const vmpa2t *, size_t, size_t); + +/* Renseigne sur les propriétés liées à un générateur. */ +BufferLineFlags g_line_generator_get_flags(const GLineGenerator *, size_t, size_t); + +/* Imprime dans une ligne de rendu le contenu représenté. */ +void g_line_generator_print(GLineGenerator *, GBufferLine *, size_t, size_t); + + + +#endif /* _GLIBEXT_LINEGEN_H */ diff --git a/src/glibext/linesegment.c b/src/glibext/linesegment.c index 8306320..5208db6 100644 --- a/src/glibext/linesegment.c +++ b/src/glibext/linesegment.c @@ -47,7 +47,11 @@ static const char *_segment_names[RTT_COUNT] = { + [RTT_NONE] = SEGMENT_NAME("none"), [RTT_RAW] = SEGMENT_NAME("raw"), + [RTT_RAW_NULL] = SEGMENT_NAME("raw-null"), + [RTT_PRINTABLE] = SEGMENT_NAME("printable"), + [RTT_NOT_PRINTABLE] = SEGMENT_NAME("not-printable"), [RTT_COMMENT] = SEGMENT_NAME("comment"), [RTT_INDICATION] = SEGMENT_NAME("indication"), [RTT_PHYS_ADDR_PAD] = SEGMENT_NAME("phys-addr-padding"), @@ -55,6 +59,7 @@ static const char *_segment_names[RTT_COUNT] = { [RTT_VIRT_ADDR_PAD] = SEGMENT_NAME("virt-addr-padding"), [RTT_VIRT_ADDR] = SEGMENT_NAME("virt-addr"), [RTT_RAW_CODE] = SEGMENT_NAME("raw-code"), + [RTT_RAW_CODE_NULL] = SEGMENT_NAME("raw-code-null"), [RTT_LABEL] = SEGMENT_NAME("label"), [RTT_INSTRUCTION] = SEGMENT_NAME("instruction"), [RTT_IMMEDIATE] = SEGMENT_NAME("immediate"), @@ -162,6 +167,10 @@ struct _segcnt_list }; +/* Indique si le contenu d'un segment est notable ou non. */ +bool selection_list_has_segment_content(const segcnt_list *, const line_segment *); + + /* ---------------------------------------------------------------------------------- */ /* NATURE POUR UN FRAGMENT DE TEXTE */ diff --git a/src/glibext/linesegment.h b/src/glibext/linesegment.h index da43e7e..892dce2 100644 --- a/src/glibext/linesegment.h +++ b/src/glibext/linesegment.h @@ -66,7 +66,12 @@ void exit_segment_content_hash_table(void); /* Types de partie de rendu */ typedef enum _RenderingTagType { + RTT_NONE, /* Espace ou tabulation */ + RTT_RAW, /* Contenu brut */ + RTT_RAW_NULL, /* Contenu brut et nul */ + RTT_PRINTABLE, /* Caractère imprimable */ + RTT_NOT_PRINTABLE, /* Caractère non imprimable */ RTT_COMMENT, /* Commentaire */ RTT_INDICATION, /* Aide à la lecture */ @@ -76,6 +81,7 @@ typedef enum _RenderingTagType RTT_VIRT_ADDR_PAD, /* Adresse virtuelle (début) */ RTT_VIRT_ADDR, /* Adresse virtuelle */ RTT_RAW_CODE, /* Code binaire brut */ + RTT_RAW_CODE_NULL, /* Code binaire brut et nul */ RTT_LABEL, /* Etiquette sur une adresse */ @@ -188,9 +194,6 @@ bool reset_segment_content_list(segcnt_list *); /* Marque le contenu d'un segment comme remarquable. */ bool add_segment_content_to_selection_list(segcnt_list *, const line_segment *); -/* Indique si le contenu d'un segment est notable ou non. */ -bool selection_list_has_segment_content(const segcnt_list *, const line_segment *); - #endif /* _GLIBEXT_LINESEGMENT_H */ |