From c644db0ad3b1a276f2c3bf9be72026c3581dd35f Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Wed, 9 Dec 2015 23:06:59 +0100 Subject: Avoided to throw comments too far by defining local columns managers. --- ChangeLog | 15 +++ src/analysis/disass/disassembler.c | 12 +- src/analysis/disass/output.c | 20 +++- src/glibext/gbinportion.c | 2 + src/glibext/gbufferline.c | 239 +++++++++++++++++++++++++++++++++---- src/glibext/gbufferline.h | 25 ++-- src/glibext/gcodebuffer.c | 113 ++++++++++++------ 7 files changed, 353 insertions(+), 73 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5ccb406..856036d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +15-12-09 Cyrille Bagard + + * src/analysis/disass/disassembler.c: + Mark the first line of a disassembly as a line starting a group. + + * src/analysis/disass/output.c: + * src/glibext/gbinportion.c: + Mark some lines as lines managing a local group of columns widths. + + * src/glibext/gbufferline.c: + * src/glibext/gbufferline.h: + * src/glibext/gcodebuffer.c: + Avoid to throw comments too far by defining local columns managers. + Clean and update code. + 15-12-04 Cyrille Bagard * configure.ac: diff --git a/src/analysis/disass/disassembler.c b/src/analysis/disass/disassembler.c index ce2e6ff..c563b2e 100644 --- a/src/analysis/disass/disassembler.c +++ b/src/analysis/disass/disassembler.c @@ -625,13 +625,20 @@ static void build_disass_prologue(GCodeBuffer *buffer, const char *filename, con { GLangOutput *output; /* Modèle de sortie adéquat */ GBufferLine *line; /* Ligne de destination */ + bool managed; /* Groupe déjà défini ? */ size_t len; /* Taille du texte */ char *content; /* Contenu textuel d'une ligne */ output = g_asm_output_new(); line = g_lang_output_start_comments(output, buffer); - if (line != NULL) g_buffer_line_start_merge_at(line, BLC_PHYSICAL); + if (line != NULL) + { + g_buffer_line_start_merge_at(line, BLC_PHYSICAL); + g_buffer_line_add_flag(line, BLF_WIDTH_MANAGER); + } + + managed = (line != NULL); /* Introduction */ @@ -639,6 +646,9 @@ static void build_disass_prologue(GCodeBuffer *buffer, const char *filename, con SL(_("Disassembly generated by Chrysalide"))); g_buffer_line_start_merge_at(line, BLC_PHYSICAL); + if (!managed) + g_buffer_line_add_flag(line, BLF_WIDTH_MANAGER); + line = g_lang_output_continue_comments(output, buffer, SL(_("Chrysalide is free software - © 2008-2015 Cyrille Bagard"))); g_buffer_line_start_merge_at(line, BLC_PHYSICAL); diff --git a/src/analysis/disass/output.c b/src/analysis/disass/output.c index d698c71..727c34f 100644 --- a/src/analysis/disass/output.c +++ b/src/analysis/disass/output.c @@ -236,12 +236,29 @@ void print_disassembled_instructions(GCodeBuffer *buffer, const GExeFormat *form if (cmp_vmpa(iaddr, saddr) == 0) { - /* Point d'entrée ? */ if (g_binary_symbol_get_target_type(symbols[sym_index]) == STP_ENTRY_POINT) g_buffer_line_add_flag(line, BLF_ENTRYPOINT); + /* Début d'un groupe bien cohérent avec les alignements ? */ + + switch (g_binary_symbol_get_target_type(symbols[sym_index])) + { + case STP_ROUTINE: + case STP_OBJECT: + case STP_FUNCTION: + case STP_ENTRY_POINT: + case STP_STRING: + case STP_RO_STRING: + g_buffer_line_add_flag(line, BLF_WIDTH_MANAGER); + break; + + default: + break; + + } + /* Commentaire ? */ comment = g_binary_symbol_get_comment(symbols[sym_index]); @@ -266,7 +283,6 @@ void print_disassembled_instructions(GCodeBuffer *buffer, const GExeFormat *form sym_index++; - } } diff --git a/src/glibext/gbinportion.c b/src/glibext/gbinportion.c index 16f4814..bd4702b 100644 --- a/src/glibext/gbinportion.c +++ b/src/glibext/gbinportion.c @@ -711,6 +711,8 @@ void g_binary_portion_print(const GBinPortion *portion, GCodeBuffer *buffer, Mem line = g_code_buffer_append_new_line(buffer, &range); g_buffer_line_fill_mrange(line, msize, msize); + g_buffer_line_add_flag(line, BLF_WIDTH_MANAGER); + /* Séparation */ line = g_code_buffer_append_new_line(buffer, &range); diff --git a/src/glibext/gbufferline.c b/src/glibext/gbufferline.c index 7768a0e..c998fce 100644 --- a/src/glibext/gbufferline.c +++ b/src/glibext/gbufferline.c @@ -99,6 +99,16 @@ struct _GBufferLine BufferLineFlags flags; /* Drapeaux particuliers */ + union + { + struct + { + 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 */ + }; + }; /* Représentation de fragments de texte en ligne (classe) */ @@ -122,6 +132,12 @@ static void g_buffer_line_class_init(GBufferLineClass *); /* Procède à l'initialisation d'une représentation de fragments. */ static void g_buffer_line_init(GBufferLine *); +/* Supprime toutes les références externes. */ +static void g_buffer_line_dispose(GBufferLine *); + +/* Procède à la libération totale de la mémoire. */ +static void g_buffer_line_finalize(GBufferLine *); + /* ---------------------------------------------------------------------------------- */ @@ -453,8 +469,14 @@ G_DEFINE_TYPE(GBufferLine, g_buffer_line, G_TYPE_OBJECT); static void g_buffer_line_class_init(GBufferLineClass *class) { + GObjectClass *object; /* Autre version de la classe */ gchar *filename; /* Chemin d'accès à utiliser */ + object = G_OBJECT_CLASS(class); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_buffer_line_dispose; + object->finalize = (GObjectFinalizeFunc)g_buffer_line_finalize; + filename = find_pixmap_file("entrypoint.png"); assert(filename != NULL); @@ -507,6 +529,49 @@ static void g_buffer_line_init(GBufferLine *line) /****************************************************************************** * * +* Paramètres : line = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_buffer_line_dispose(GBufferLine *line) +{ + if (line->flags & BLF_WIDTH_MANAGER) + g_object_unref(G_OBJECT(line->manager)); + + G_OBJECT_CLASS(g_buffer_line_parent_class)->dispose(G_OBJECT(line)); + +} + + +/****************************************************************************** +* * +* Paramètres : line = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_buffer_line_finalize(GBufferLine *line) +{ + /* TODO : segments des colonnes... */ + + G_OBJECT_CLASS(g_buffer_line_parent_class)->finalize(G_OBJECT(line)); + +} + + +/****************************************************************************** +* * * Paramètres : range = emplacement où va se situer la ligne. * * main = colonne à référencer comme étant la principale. * * * @@ -792,7 +857,7 @@ GBufferSegment *g_buffer_line_get_segment_at(const GBufferLine *line, const gint if (i < line->merge_start) { - width = max_widths[i]; + width = g_buffer_line_compute_max_width(line, i, max_widths); if ((i + 1) < BLC_COUNT) limit = width + COL_MARGIN / 2; else limit = width; @@ -863,7 +928,10 @@ GBufferSegment *g_buffer_line_get_segment_at(const GBufferLine *line, const gint printf(" -- update to col %u -- x = %d\n", i, *offset); if ((i - 1) < line->merge_start) - *base += (max_widths[i - 1] + COL_MARGIN); + { + width = g_buffer_line_compute_max_width(line, i - 1, max_widths); + *base += (width + COL_MARGIN); + } else *base += get_column_width(&line->columns[i - 1]); @@ -998,7 +1066,10 @@ GBufferSegment *g_buffer_line_find_near_segment(const GBufferLine *line, GBuffer displayed = (k < BLC_DISPLAY ? display[k] : true); if (displayed) - *offset += max_widths[k] + COL_MARGIN; + { + *offset += g_buffer_line_compute_max_width(line, k, max_widths); + if (k < line->merge_start) *offset += COL_MARGIN; + } } @@ -1118,55 +1189,147 @@ char *g_buffer_line_get_text(const GBufferLine *line, BufferLineColumn first, Bu /****************************************************************************** * * -* Paramètres : line = ligne à venir compléter. * -* index = index de la colonne visée par la procédure. * +* Paramètres : line = ligne à venir consulter/compléter. * +* manager = ligne de départ d'un groupe de ligne. * * * -* Description : Fournit la largeur requise pour une colonne de ligne donnée. * +* Description : Retient les largeurs d'une ligne si maximales. * * * -* Retour : Largeur en pixel requise. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -gint g_buffer_line_get_column_width(GBufferLine *line, BufferLineColumn index) +void g_buffer_line_update_max_widths(GBufferLine *line, GBufferLine *manager) { - gint result; /* Largeur à retourner */ + BufferLineColumn i; /* Boucle de parcours */ + GBufferLine *old; /* Ancienne ligne associée */ + gint merged_width; /* Largeur cumulée avant fusion*/ + gint width; /* Largeur d'une colonne */ - if (index >= line->merge_start) result = 0; - else result = get_column_width(&line->columns[index]); + /* Réinitialisation ? */ - return result; + if (line == manager) + { + assert(line->flags & BLF_WIDTH_MANAGER); + + for (i = 0; i < BLC_COUNT; i++) + line->max_widths[i] = 0; + + line->merged_width = 0; + + } + else + { + assert((line->flags & BLF_WIDTH_MANAGER) == 0); + + old = line->manager; + + g_object_ref(G_OBJECT(manager)); + line->manager = manager; + + g_object_unref(G_OBJECT(old)); + + } + + /* Mises à jour */ + + merged_width = 0; + + for (i = 0; i < BLC_COUNT; i++) + { + width = get_column_width(&line->columns[i]); + + if (i < line->merge_start) + manager->max_widths[i] = MAX(manager->max_widths[i], width); + + if (i >= BLC_DISPLAY) + { + merged_width += width; + + if (i < line->merge_start && (i + 1) < BLC_COUNT) + merged_width += COL_MARGIN; + + } + + } + + if (line->merge_start != BLC_COUNT) + manager->merged_width = MAX(manager->merged_width, merged_width); } /****************************************************************************** * * -* Paramètres : line = ligne à venir compléter. * -* merge = précise la première colonne marquant la fusion. [OUT]* -* display = règles d'affichage des colonnes modulables. * +* Paramètres : line = ligne à venir consulter. * +* max_widths = tableau résumant les largeurs maximales. [OUT]* +* merged_width = largeur maximale en cas de fusion. |OUT] * * * -* Description : Fournit la dernière largeur d'une ligne avec fusion. * +* Description : Filtre des largeurs de lignes et ne garde que les maximales. * * * -* Retour : Largeur en pixel requise. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -gint g_buffer_line_get_merge_width(GBufferLine *line, BufferLineColumn *merge, const bool *display) +void g_buffer_line_apply_max_widths(GBufferLine *line, gint *max_widths, gint *merged_width) +{ + GBufferLine *manager; /* Gestionnaire de groupe */ + BufferLineColumn i; /* Boucle de parcours */ + + if (line->flags & BLF_WIDTH_MANAGER) + manager = line; + else + manager = line->manager; + + for (i = 0; i < BLC_COUNT; i++) + max_widths[i] = MAX(manager->max_widths[i], max_widths[i]); + + *merged_width = MAX(manager->merged_width, *merged_width); + +} + + +/****************************************************************************** +* * +* Paramètres : line = ligne à venir consulter. * +* index = indice de la colonne visée. * +* max_widths = tableau résumant les largeurs maximales. * +* * +* Description : Fournit la largeur d'une colonne finalement appliquée. * +* * +* Retour : Largeur globale ou spécifique, selon l'indice communiqué. * +* * +* Remarques : - * +* * +******************************************************************************/ + +gint g_buffer_line_compute_max_width(const GBufferLine *line, BufferLineColumn index, const gint *max_widths) { gint result; /* Largeur à retourner */ - result = 0; + assert(index < BLC_COUNT); + + if (index >= line->merge_start) + result = get_column_width(&line->columns[index]); + + else + { + if (index < BLC_ASSEMBLY) + result = max_widths[index]; - /* TODO : wtf ?! quelle est l'utilité des arguments booléens ? */ + else + { + if (line->flags & BLF_WIDTH_MANAGER) + result = line->max_widths[index]; + else + result = line->manager->max_widths[index]; - *merge = line->merge_start; + } - if (line->merge_start < BLC_COUNT) - result = get_column_width(&line->columns[line->merge_start]); + } return result; @@ -1175,6 +1338,25 @@ gint g_buffer_line_get_merge_width(GBufferLine *line, BufferLineColumn *merge, c /****************************************************************************** * * +* Paramètres : line = ligne à venir consulter. * +* * +* Description : Fournit la colonne à partir de laquelle une fusion opère. * +* * +* Retour : Début de la première (et unique) zone globale. * +* * +* Remarques : - * +* * +******************************************************************************/ + +BufferLineColumn g_buffer_line_get_merge_start(const GBufferLine *line) +{ + return line->merge_start; + +} + + +/****************************************************************************** +* * * Paramètres : line = ligne à venir compléter. * * start = début de la première (et unique) zone globale. * * * @@ -1290,6 +1472,7 @@ void g_buffer_line_draw(GBufferLine *line, cairo_t *cairo, const gint max_widths GBufferLineClass *class; /* Stockage de briques de base */ gint x; /* Point de départ d'impression*/ BufferLineColumn i; /* Boucle de parcours */ + gint max_width; /* Largeur maximale de colonne */ if (line->flags != BLF_NONE && line->flags != BLF_HAS_CODE) { @@ -1300,6 +1483,9 @@ void g_buffer_line_draw(GBufferLine *line, cairo_t *cairo, const gint max_widths else if (line->flags & BLF_BOOKMARK) cairo_set_source_surface(cairo, class->bookmark_img, 5, y); + ////////////////// + cairo_set_source_surface(cairo, class->entrypoint_img, 5, y); + cairo_paint(cairo); } @@ -1313,7 +1499,12 @@ void g_buffer_line_draw(GBufferLine *line, cairo_t *cairo, const gint max_widths draw_segments_of_column(&line->columns[i], cairo, x, y, list); if (i < line->merge_start) - x += max_widths[i] + COL_MARGIN; + { + max_width = g_buffer_line_compute_max_width(line, i, max_widths); + + x += max_width + COL_MARGIN; + + } } diff --git a/src/glibext/gbufferline.h b/src/glibext/gbufferline.h index 0da5ffd..7ba5467 100644 --- a/src/glibext/gbufferline.h +++ b/src/glibext/gbufferline.h @@ -87,12 +87,13 @@ typedef enum _BufferLineColumn /* Propriétés particulières supplémentaires */ typedef enum _BufferLineFlags { - BLF_NONE = 0 << 0, /* Aucune */ - BLF_HAS_CODE = 1 << 0, /* La ligne contient du code */ - BLF_ENTRYPOINT = 1 << 1, /* Représentation d'une entrée */ - BLF_BOOKMARK = 1 << 2, /* Signet associé */ + BLF_NONE = 0 << 0, /* Aucune */ + BLF_HAS_CODE = 1 << 0, /* La ligne contient du code */ + BLF_ENTRYPOINT = 1 << 1, /* Représentation d'une entrée */ + BLF_BOOKMARK = 1 << 2, /* Signet associé */ + BLF_WIDTH_MANAGER = 1 << 3, /* Début de groupe des largeurs*/ - BLF_ALL = ((1 << 3) - 1) + BLF_ALL = ((1 << 4) - 1) } BufferLineFlags; @@ -127,11 +128,17 @@ GBufferSegment *g_buffer_line_insert_text(GBufferLine *, BufferLineColumn, const /* Donne le texte représenté par une ligne de tampon. */ char *g_buffer_line_get_text(const GBufferLine *, BufferLineColumn, BufferLineColumn, bool); -/* Fournit la largeur requise pour une colonne de ligne donnée. */ -gint g_buffer_line_get_column_width(GBufferLine *, BufferLineColumn); +/* Retient les largeurs d'une ligne si maximales. */ +void g_buffer_line_update_max_widths(GBufferLine *, GBufferLine *); -/* Fournit la dernière largeur d'une ligne avec fusion. */ -gint g_buffer_line_get_merge_width(GBufferLine *, BufferLineColumn *, const bool *); +/* Filtre des largeurs de lignes et ne garde que les maximales. */ +void g_buffer_line_apply_max_widths(GBufferLine *, gint *, gint *); + +/* Fournit la largeur d'une colonne finalement appliquée. */ +gint g_buffer_line_compute_max_width(const GBufferLine *, BufferLineColumn, const gint *); + +/* Fournit la colonne à partir de laquelle une fusion opère. */ +BufferLineColumn g_buffer_line_get_merge_start(const GBufferLine *); /* Définit la colonne à partir de laquelle la fusion opère. */ void g_buffer_line_start_merge_at(GBufferLine *, BufferLineColumn); diff --git a/src/glibext/gcodebuffer.c b/src/glibext/gcodebuffer.c index c676b7c..b211c4a 100644 --- a/src/glibext/gcodebuffer.c +++ b/src/glibext/gcodebuffer.c @@ -24,6 +24,7 @@ #include "gcodebuffer.h" +#include #include #include #include @@ -132,6 +133,9 @@ static size_t _g_code_buffer_get_index_from_address_new(const GCodeBuffer *, con /* Convertit une adresse en indice de ligne. */ static size_t g_code_buffer_get_index_from_address(GCodeBuffer *, const vmpa2t *, bool); +/* Actualise les largeurs maximales par groupes de lignes. */ +static void g_code_buffer_update_line_max_widths(const GCodeBuffer *, size_t, size_t); + /* ---------------------- VUE PARTICULIERE D'UN TAMPON DE CODE ---------------------- */ @@ -149,11 +153,10 @@ struct _GBufferView size_t last_index; /* Indice de la dernière ligne */ /* FIXME : idem */ gint line_height; /* Hauteur maximale des lignes */ - gint max_widths[BLC_COUNT]; /* Taille cachée des colonnes */ gint left_margin; /* Marge gauche + espace */ gint left_text; /* Début d'impression du code */ - gint last_width; /* Plus grande col. de fusion */ - BufferLineColumn last_merge; /* Colonne de fusion extrême */ + gint max_widths[BLC_COUNT]; /* Taille cachée des colonnes */ + gint merged_width; /* Plus grande taille de fusion*/ segcnt_list *highlighted; /* Segments mis en évidence */ bool external; /* Note l'origine de la liste */ @@ -634,6 +637,60 @@ static size_t g_code_buffer_get_index_from_address(GCodeBuffer *buffer, const vm /****************************************************************************** * * +* Paramètres : buffer = tampon contentenant un ensemble de lignes. * +* first = première ligne modifiée à considérer. * +* last = dernière ligne modifiée à considérer. * +* * +* Description : Actualise les largeurs maximales par groupes de lignes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_code_buffer_update_line_max_widths(const GCodeBuffer *buffer, size_t first, size_t last) +{ + GBufferLine **lines; /* Liste des lignes à traiter */ + size_t start; /* Début de groupe de largeurs */ + size_t end; /* Fin de groupe de largeurs */ + GBufferLine *manager; /* Ligne de gestion de largeurs*/ + size_t i; /* Boucle de parcours */ + + assert(buffer->used > 0); + + lines = buffer->lines; + + /* Recherche des bornes du groupe de largeurs courant */ + + for (start = first; start > 0; start--) + if (g_buffer_line_get_flags(lines[start]) & BLF_WIDTH_MANAGER) + break; + + for (end = last; end < (buffer->used - 1); end++) + if (g_buffer_line_get_flags(lines[end + 1]) & BLF_WIDTH_MANAGER) + break; + + /* Réinitialisation ciblée des largeurs */ + + assert(g_buffer_line_get_flags(lines[start]) & BLF_WIDTH_MANAGER); + + manager = NULL; + + for (i = start; i <= end; i++) + { + if (g_buffer_line_get_flags(lines[i]) & BLF_WIDTH_MANAGER) + manager = lines[i]; + + g_buffer_line_update_max_widths(lines[i], manager); + + } + +} + + +/****************************************************************************** +* * * Paramètres : buffer = composant GTK à mettre à jour. * * range = emplacement où va se situer la ligne. * * * @@ -1144,6 +1201,8 @@ static void g_buffer_view_reset_required_widths(GBufferView *view) for (i = 0; i < BLC_COUNT; i++) view->max_widths[i] = -1; + view->merged_width = 0; + } @@ -1184,10 +1243,7 @@ static void g_buffer_view_compute_required_widths(GBufferView *view, const bool GBufferLine **lines; /* Liste des lignes à traiter */ size_t first; /* Première ligne intégrée */ size_t last; /* Dernière ligne intégrée */ - size_t i; /* Boucle de parcours #1 */ - unsigned int j; /* Boucle de parcours #2 */ - gint width; /* Largeur d'une colonne */ - BufferLineColumn merge; /* Début de fusion de colonnes */ + size_t i; /* Boucle de parcours */ if (!HEIGHT_CACHED(view)) g_buffer_view_compute_required_height(view); @@ -1200,32 +1256,14 @@ static void g_buffer_view_compute_required_widths(GBufferView *view, const bool view->left_margin = 2 * view->line_height; view->left_text = 2.5 * view->line_height; - view->last_width = 0; - view->last_merge = BLC_INVALID; - if (view->buffer->used > 0) - for (i = first; i <= last; i++) - { - for (j = 0; j < BLC_COUNT; j++) - { - width = g_buffer_line_get_column_width(lines[i], j); - view->max_widths[j] = MAX(view->max_widths[j], width); - } - - width = g_buffer_line_get_merge_width(lines[i], &merge, display); - view->last_width = MAX(view->last_width, width); - if (merge != BLC_COUNT) - { - if (view->last_merge == BLC_INVALID) - view->last_merge = merge; - else - view->last_merge = MAX(view->last_merge, merge); - } + { + g_code_buffer_update_line_max_widths(view->buffer, first, last); - } + for (i = first; i <= last; i++) + g_buffer_line_apply_max_widths(lines[i], view->max_widths, &view->merged_width); - if (view->last_merge == BLC_INVALID) - view->last_merge = BLC_COUNT; + } } @@ -1295,18 +1333,15 @@ gint g_buffer_view_get_width(GBufferView *view, const bool *display) /* Seconde méthode */ - for (i = 0; i < view->last_merge; i++) + for (i = 0; i < BLC_DISPLAY; i++) { - if (i < BLC_DISPLAY && !display[i]) continue; - - full_width += view->max_widths[i]; + if (!display[i]) continue; - if ((i + 1) < view->last_merge) - full_width += COL_MARGIN; + full_width += view->max_widths[i] + COL_MARGIN; } - full_width += view->last_width + COL_MARGIN; + full_width += view->merged_width; /* Mise en concurrence et poursuite... */ @@ -1712,7 +1747,11 @@ const vmpa2t *g_buffer_view_move_caret(GBufferView *view, GdkRectangle *caret, b for (i = BLC_ASSEMBLY_HEAD; i < BLC_COUNT; i++) right_pos += view->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 = view->left_text; -- cgit v0.11.2-87-g4458