diff options
-rw-r--r-- | ChangeLog | 22 | ||||
-rwxr-xr-x | src/common/Makefile.am | 1 | ||||
-rw-r--r-- | src/common/fnv1a.c | 83 | ||||
-rw-r--r-- | src/common/fnv1a.h | 51 | ||||
-rw-r--r-- | src/glibext/gbufferline.c | 169 | ||||
-rw-r--r-- | src/glibext/gbufferline.h | 6 | ||||
-rw-r--r-- | src/glibext/gbuffersegment.c | 95 | ||||
-rw-r--r-- | src/glibext/gbuffersegment.h | 16 | ||||
-rw-r--r-- | src/glibext/gcodebuffer.c | 120 | ||||
-rw-r--r-- | src/glibext/gcodebuffer.h | 6 | ||||
-rw-r--r-- | src/gtkext/gtkblockview.c | 85 | ||||
-rw-r--r-- | src/gtkext/gtkbufferview-int.h | 7 | ||||
-rw-r--r-- | src/gtkext/gtkbufferview.c | 10 |
13 files changed, 641 insertions, 30 deletions
@@ -1,3 +1,25 @@ +12-09-23 Cyrille Bagard <nocbos@gmail.com> + + * src/common/fnv1a.c: + * src/common/fnv1a.h: + New entries: compute hashes of string values. + + * src/common/Makefile.am: + Add the fnv1a.[ch] files to libcommon_la_SOURCES. + + * src/glibext/gbufferline.c: + * src/glibext/gbufferline.h: + * src/glibext/gbuffersegment.c: + * src/glibext/gbuffersegment.h: + * src/glibext/gcodebuffer.c: + * src/glibext/gcodebuffer.h: + Select segments for highlighting. + + * src/gtkext/gtkblockview.c: + * src/gtkext/gtkbufferview.c: + * src/gtkext/gtkbufferview-int.h: + When selecting segments, highlight all the same content. + 12-09-17 Cyrille Bagard <nocbos@gmail.com> * plugins/python/androperms/androperms.py: diff --git a/src/common/Makefile.am b/src/common/Makefile.am index 391f35a..9232fc4 100755 --- a/src/common/Makefile.am +++ b/src/common/Makefile.am @@ -7,6 +7,7 @@ libcommon_la_SOURCES = \ endianness.h endianness.c \ environment.h environment.c \ extstr.h extstr.c \ + fnv1a.h fnv1a.c \ leb128.h leb128.c \ macros.h \ net.h net.c \ diff --git a/src/common/fnv1a.c b/src/common/fnv1a.c new file mode 100644 index 0000000..57fddf7 --- /dev/null +++ b/src/common/fnv1a.c @@ -0,0 +1,83 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * fnv1a.c - implémentaton du calcul rapide d'empreintes de chaînes + * + * Copyright (C) 2012 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * OpenIDA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "fnv1a.h" + + + +/* Constante d'initialisation */ +#define FNV1A_64_INIT 0xcbf29ce484222325ull + +/* Coefficient magique ! */ +#define FNV_64_PRIME 0x100000001b3ull + + + +/****************************************************************************** +* * +* Paramètres : a = première empreinte à manipuler. * +* b = seconde empreinte à manipuler. * +* * +* Description : Détermine si deux empreintes FNV1a sont indentiques ou non. * +* * +* Retour : Bilan de la comparaison. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool cmp_fnv_64a(fnv64_t a, fnv64_t b) +{ + return (a == b); + +} + + +/****************************************************************************** +* * +* Paramètres : str = chaîne de caractères à traiter. * +* * +* Description : Détermine l'empreinte FNV1a d'une chaîne de caractères. * +* * +* Retour : Valeur calculée. * +* * +* Remarques : - * +* * +******************************************************************************/ + +fnv64_t fnv_64a_hash(const char *str) +{ + fnv64_t result; /* Valeur à retourner */ + unsigned char *iter; /* Boucle de parcours */ + + result = FNV1A_64_INIT; + + for (iter = (unsigned char *)str; *iter; iter++) + { + result ^= (fnv64_t)*iter; + result *= FNV_64_PRIME; + } + + return result; + +} diff --git a/src/common/fnv1a.h b/src/common/fnv1a.h new file mode 100644 index 0000000..f379ec8 --- /dev/null +++ b/src/common/fnv1a.h @@ -0,0 +1,51 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * fnv1a.h - prototypes pour l'implémentaton du calcul rapide d'empreintes de chaînes + * + * Copyright (C) 2012 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * OpenIDA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _COMMON_FNV1A_H +#define _COMMON_FNV1A_H + + +#include <stdbool.h> +#include <stdint.h> + + +/** + * Plus d'informations avec les liens suivants : + * - http://en.wikipedia.org/wiki/Fowler-Noll-Vo_hash_function + * - http://isthe.com/chongo/tech/comp/fnv/ + */ + + +/* Détermination d'un type à part */ +typedef uint64_t fnv64_t; + + +/* Détermine si deux empreintes FNV1a sont indentiques ou non. */ +bool cmp_fnv_64a(fnv64_t, fnv64_t); + +/* Détermine l'empreinte FNV1a d'une chaîne de caractères. */ +fnv64_t fnv_64a_hash(const char *); + + + +#endif /* _COMMON_FNV1A_H */ diff --git a/src/glibext/gbufferline.c b/src/glibext/gbufferline.c index 08f5ae7..7f88bff 100644 --- a/src/glibext/gbufferline.c +++ b/src/glibext/gbufferline.c @@ -35,6 +35,14 @@ +/* Espace entre les colonnes */ +#define COL_MARGIN 23 + + + +/* ---------------------------- REGROUPEMENT PAR COLONNE ---------------------------- */ + + /* Informations sur le contenu d'une colonne */ typedef struct _buffer_line_column { @@ -56,11 +64,19 @@ static gint get_column_width(buffer_line_column *); /* Ajoute un fragment de texte à une colonne de ligne. */ static void add_segment_to_column(buffer_line_column *, GBufferSegment *); +/* Donne le segment d'une colonne présent à une abscisse donnée. */ +static GBufferSegment *get_segment_at(const buffer_line_column *, gint); + +/* Met en surbrillance des segments similaires. */ +GSList *highlight_all_same_segments(const buffer_line_column *, GSList *, const GBufferSegment *); + /* Imprime le contenu d'une colonne de ligne de texte. */ static void draw_segments_of_column(buffer_line_column *, GdkDrawable *, GdkGC *, gint, gint); +/* ---------------------------- GESTION DE LINE COMPLETE ---------------------------- */ + /* Représentation de fragments de texte en ligne (instance) */ struct _GBufferLine @@ -93,6 +109,10 @@ static void g_buffer_line_init(GBufferLine *); +/* ---------------------------------------------------------------------------------- */ +/* REGROUPEMENT PAR COLONNE */ +/* ---------------------------------------------------------------------------------- */ + @@ -130,7 +150,7 @@ static void reset_column(buffer_line_column *column) static gint get_column_width(buffer_line_column *column) { - size_t i; + size_t i; /* Boucle de parcours */ if (column->max_width == -1) { @@ -176,52 +196,106 @@ static void add_segment_to_column(buffer_line_column *column, GBufferSegment *se /****************************************************************************** * * -* Paramètres : column = colonne de ligne de texte à manipuler. * -* drawable = surface de rendu où travailler. * -* gc = contexte graphique à utiliser pour les pinceaux. * -* x_init = abscisse du point d'impression de départ. * -* y = ordonnée du point d'impression. * +* Paramètres : column = colonne de ligne de texte à consulter. * +* x = position de recherche à ajuster. * * * -* Description : Imprime le contenu d'une colonne de ligne de texte. * +* Description : Donne le segment d'une colonne présent à une abscisse donnée.* * * -* Retour : - * +* Retour : Segment trouvé ou NULL si hors borne. * * * * Remarques : - * * * ******************************************************************************/ -static void draw_segments_of_column(buffer_line_column *column, GdkDrawable *drawable, GdkGC *gc, gint x_init, gint y) +static GBufferSegment *get_segment_at(const buffer_line_column *column, gint x) { - gint x; - size_t i; + GBufferSegment *result; /* Trouvaille à retourner */ + size_t i; /* Boucle de parcours */ + gint width; /* Largeur à retirer */ - x = x_init; - - for (i = 0; i < column->count; i++) - g_buffer_segment_draw(column->segments[i], drawable, gc, &x, y); - -} + result = NULL; + for (i = 0; i < column->count && result == NULL; i++) + { + width = g_buffer_segment_get_width(column->segments[i]); + if (width <= x) + x -= width; + else + result = column->segments[i]; + } + return result; +} +/****************************************************************************** +* * +* Paramètres : column = colonne de ligne de texte à consulter. * +* list = liste de segments identiques à constituer. * +* ref = segment de référence à comparer avec les autres. * +* * +* Description : Met en surbrillance des segments similaires. * +* * +* Retour : Liste de segments identiques complétée. * +* * +* Remarques : - * +* * +******************************************************************************/ +GSList *highlight_all_same_segments(const buffer_line_column *column, GSList *list, const GBufferSegment *ref) +{ + size_t i; /* Boucle de parcours */ + for (i = 0; i < column->count; i++) + if (g_buffer_segment_compare(column->segments[i], ref)) + { + g_buffer_segment_set_style(column->segments[i], SRS_HIGHLIGHT_SAME); + g_object_ref(G_OBJECT(column->segments[i])); + list = g_slist_prepend(list, column->segments[i]); + } + return list; +} +/****************************************************************************** +* * +* Paramètres : column = colonne de ligne de texte à manipuler. * +* drawable = surface de rendu où travailler. * +* gc = contexte graphique à utiliser pour les pinceaux. * +* x_init = abscisse du point d'impression de départ. * +* y = ordonnée du point d'impression. * +* * +* Description : Imprime le contenu d'une colonne de ligne de texte. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ +static void draw_segments_of_column(buffer_line_column *column, GdkDrawable *drawable, GdkGC *gc, gint x_init, gint y) +{ + gint x; + size_t i; + x = x_init; + for (i = 0; i < column->count; i++) + g_buffer_segment_draw(column->segments[i], drawable, gc, &x, y); +} +/* ---------------------------------------------------------------------------------- */ +/* GESTION DE LINE COMPLETE */ +/* ---------------------------------------------------------------------------------- */ /* Détermine le type de la représentation de fragments de texte en ligne. */ @@ -469,6 +543,65 @@ void g_buffer_line_add_segment(GBufferLine *line, BufferLineColumn index, GBuffe /****************************************************************************** * * +* Paramètres : line = ligne à venir consulter. * +* max_widths = largeurs de colonne à respecter. * +* x = position à la colonne visée par la procédure. * +* * +* Description : Donne le segment présent à une abscisse donnée. * +* * +* Retour : Segment trouvé ou NULL si hors borne. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBufferSegment *g_buffer_line_get_segment_at(const GBufferLine *line, const gint max_widths[BLC_COUNT], gint x) +{ + GBufferSegment *result; /* Trouvaille à retourner */ + BufferLineColumn i; /* Boucle de parcours */ + + result = NULL; + + for (i = BLC_ADDRESS; i < BLC_COUNT; i++) + if (x < max_widths[i]) break; + else x -= (max_widths[i] + COL_MARGIN); + + if (i < BLC_COUNT) + result = get_segment_at(&line->columns[i], x); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : line = ligne à venir consulter. * +* list = liste de segments identiques à constituer. * +* ref = segment de référence à comparer avec tous les autres. * +* * +* Description : Met en surbrillance des segments similaires. * +* * +* Retour : Liste de segments identiques complétée. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GSList *g_buffer_line_highlight_all_same_segments(const GBufferLine *line, GSList *list, const GBufferSegment *ref) +{ + BufferLineColumn i; /* Boucle de parcours */ + + for (i = BLC_ADDRESS; i < BLC_COUNT; i++) + list = highlight_all_same_segments(&line->columns[i], list, ref); + + return list; + +} + + +/****************************************************************************** +* * * Paramètres : line = ligne à venir compléter. * * column = colonne de la ligne visée par l'insertion. * * text = texte à insérer dans l'existant. * @@ -605,7 +738,7 @@ void g_buffer_line_draw(GBufferLine *line, GdkDrawable *drawable, GdkGC *gc, con draw_segments_of_column(&line->columns[i], drawable, gc, x, y); if (i < line->merge_start) - x += max_widths[i] + 23; + x += max_widths[i] + COL_MARGIN; } diff --git a/src/glibext/gbufferline.h b/src/glibext/gbufferline.h index a9f6391..1bba0ba 100644 --- a/src/glibext/gbufferline.h +++ b/src/glibext/gbufferline.h @@ -118,6 +118,12 @@ vmpa_t g_buffer_line_get_address(const GBufferLine *); /* Ajoute un fragment de texte à une colonne de ligne. */ void g_buffer_line_add_segment(GBufferLine *, BufferLineColumn, GBufferSegment *); +/* Donne le segment présent à une abscisse donnée. */ +GBufferSegment *g_buffer_line_get_segment_at(const GBufferLine *, const gint [BLC_COUNT], gint); + +/* Met en surbrillance des segments similaires. */ +GSList *g_buffer_line_highlight_all_same_segments(const GBufferLine *, GSList *, const GBufferSegment *); + /* Ajoute du texte à formater dans une ligne donnée. */ void g_buffer_line_insert_text(GBufferLine *, BufferLineColumn, const char *, size_t, RenderingTagType); diff --git a/src/glibext/gbuffersegment.c b/src/glibext/gbuffersegment.c index 6e862ad..5125631 100644 --- a/src/glibext/gbuffersegment.c +++ b/src/glibext/gbuffersegment.c @@ -28,6 +28,9 @@ #include <string.h> +#include "../common/fnv1a.h" + + /* Utilisation du champ pixel des couleurs cachées */ #define COLOR_NOT_SET 0 @@ -40,10 +43,16 @@ struct _GBufferSegment GObject parent; /* A laisser en premier */ char *text; /* Texte brut conservé */ + fnv64_t hash; /* Empreinte pour comparaisons */ PangoAttrList *attribs; /* Propriétés du rendu */ - GdkColor cache_fg; /* Couleur d'impression */ + SegRenderingStyle style; /* Apparence du segment */ + + GdkColor cache_bg; /* Fond d'impression */ + GdkColor cache_fg; /* Couleur d'impression #1 */ + GdkColor cache_alt_fg; /* Couleur d'impression #2 */ + GdkColor *cache_used_fg; /* Couleur d'impression utile */ PangoGlyphString *glyphs; /* Caractères traités */ PangoFont *font; /* Police utilisée à l'analyse */ @@ -380,6 +389,7 @@ GBufferSegment *g_buffer_segment_new(PangoContext *context, PangoAttrList *attri //result = g_new(GBufferSegment, 1); result->text = strdup(text); + result->hash = fnv_64a_hash(text); result->attribs = pango_attr_list_ref(attribs); @@ -387,6 +397,34 @@ GBufferSegment *g_buffer_segment_new(PangoContext *context, PangoAttrList *attri g_buffer_segment_cache_colors(result); + g_buffer_segment_set_style(result, SRS_CLASSIC); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : segment = fragment de texte à consulter. * +* ref = segment de référence servant à la comparaison. * +* * +* Description : Indique si les textes de deux segments sont identiques. * +* * +* Retour : Bilan de la comparaison. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_buffer_segment_compare(const GBufferSegment *segment, const GBufferSegment *ref) +{ + bool result; /* Bilan à retourner */ + + result = cmp_fnv_64a(segment->hash, ref->hash); + + result &= (strcmp(segment->text, ref->text) == 0); + return result; } @@ -472,6 +510,49 @@ void g_buffer_segment_cache_colors(GBufferSegment *segment) /****************************************************************************** * * +* Paramètres : segment = fragment de texte à manipuler. * +* style = style de rendu pour le segment. * +* * +* Description : Module l'apparence finale du composant. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_buffer_segment_set_style(GBufferSegment *segment, SegRenderingStyle style) +{ + segment->style = style; + + switch (style) + { + default: + case SRS_CLASSIC: + segment->cache_used_fg = &segment->cache_fg; + break; + + case SRS_HIGHLIGHT_SAME: + + segment->cache_bg.red = 0; + segment->cache_bg.green = 0; + segment->cache_bg.blue = 65535; + + segment->cache_alt_fg.red = 65535 - segment->cache_fg.red; + segment->cache_alt_fg.green = 65535 - segment->cache_fg.green; + segment->cache_alt_fg.blue = 65535 - segment->cache_fg.blue; + + segment->cache_used_fg = &segment->cache_alt_fg; + + break; + + } + +} + + +/****************************************************************************** +* * * Paramètres : segment = fragment de texte à manipuler. * * drawable = surface de rendu où travailler. * * gc = contexte graphique à utiliser pour les pinceaux. * @@ -488,10 +569,20 @@ void g_buffer_segment_cache_colors(GBufferSegment *segment) void g_buffer_segment_draw(GBufferSegment *segment, GdkDrawable *drawable, GdkGC *gc, gint *x, gint y) { + /* Fond du texte */ + if (segment->style != SRS_CLASSIC) + { + gdk_gc_set_rgb_fg_color(gc, &segment->cache_bg); + + gdk_draw_rectangle(drawable, gc, TRUE, + *x, y, segment->logical.width, segment->logical.height); + + } + /* Couleur d'impression */ if (segment->cache_fg.pixel == COLOR_SET) - gdk_gc_set_rgb_fg_color(gc, &segment->cache_fg); + gdk_gc_set_rgb_fg_color(gc, segment->cache_used_fg); /* Impression du texte */ diff --git a/src/glibext/gbuffersegment.h b/src/glibext/gbuffersegment.h index ead0560..edbf44c 100644 --- a/src/glibext/gbuffersegment.h +++ b/src/glibext/gbuffersegment.h @@ -26,6 +26,7 @@ #include <glib-object.h> +#include <stdbool.h> #include <gdk/gdk.h> #include <pango/pango.h> @@ -39,6 +40,15 @@ #define G_BUFFER_SEGMENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_BUFFER_SEGMENT, GBufferSegmentClass)) +/* Types de rendus */ +typedef enum _SegRenderingStyle +{ + SRS_CLASSIC, /* Comportement par défaut */ + SRS_HIGHLIGHT_SAME, /* Surlignage des identiques */ + + SRS_COUNT + +} SegRenderingStyle; /* Types d'exportation */ typedef enum _BufferExportType @@ -64,6 +74,9 @@ GType g_buffer_segment_get_type(void); /* Crée un nouveau fragment de texte avec des propriétés. */ GBufferSegment *g_buffer_segment_new(PangoContext *, PangoAttrList *, const char *, size_t); +/* Indique si les textes de deux segments sont identiques. */ +bool g_buffer_segment_compare(const GBufferSegment *, const GBufferSegment *); + /* Fournit le texte brut conservé dans le segment. */ const char *g_buffer_segment_get_text(const GBufferSegment *); @@ -73,6 +86,9 @@ gint g_buffer_segment_get_width(const GBufferSegment *); /* (Re)charge les couleurs à partir de la liste d'attributs. */ void g_buffer_segment_cache_colors(GBufferSegment *); +/* Module l'apparence finale du composant. */ +void g_buffer_segment_set_style(GBufferSegment *, SegRenderingStyle); + /* Imprime le fragment de texte représenté. */ void g_buffer_segment_draw(GBufferSegment *, GdkDrawable *, GdkGC *, gint *, gint); diff --git a/src/glibext/gcodebuffer.c b/src/glibext/gcodebuffer.c index ac63a87..573d07d 100644 --- a/src/glibext/gcodebuffer.c +++ b/src/glibext/gcodebuffer.c @@ -28,7 +28,8 @@ #include <string.h> -#include "../glibext/delayed-int.h" +#include "delayed-int.h" +#include "../gtkext/iodamarshal.h" @@ -143,6 +144,7 @@ struct _GBufferView buffer_line_draw_fc drawing_extra; /* Fonction d'accompagnement */ void *drawing_data; /* Donnée utilisateur */ + GSList *highlighted; /* Segments mis en évidence */ }; @@ -151,6 +153,10 @@ struct _GBufferViewClass { GObjectClass parent; /* A laisser en premier */ + /* Signaux */ + + void (* need_redraw) (GBufferView *); + }; @@ -567,6 +573,13 @@ G_DEFINE_TYPE(GBufferView, g_buffer_view, G_TYPE_OBJECT); static void g_buffer_view_class_init(GBufferViewClass *class) { + g_signal_new("need-redraw", + G_TYPE_BUFFER_VIEW, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(GBufferViewClass, need_redraw), + NULL, NULL, + g_cclosure_user_marshal_VOID__OBJECT, + G_TYPE_NONE, 0); } @@ -815,6 +828,111 @@ void g_buffer_view_get_size(GBufferView *view, gint *width, gint *height, bool a /****************************************************************************** * * +* Paramètres : view = vue de tampon à mettre à jour. * +* * +* Description : Supprime toute mise en évidence de segments. * +* * +* Retour : true si un besoin d'actualisation d'affichage se fait sentir.* +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_buffer_view_unhighlight_segments(GBufferView *view) +{ + GSList *iter; /* Boucle de parcours */ + GBufferSegment *segment; /* Segment visé par le pointeur*/ + + if (g_slist_length(view->highlighted) == 0) + return false; + + for (iter = view->highlighted; iter != NULL; iter = view->highlighted) + { + segment = G_BUFFER_SEGMENT(iter->data); + g_buffer_segment_set_style(segment, SRS_CLASSIC); + + g_object_unref(G_OBJECT(segment)); + + view->highlighted = g_slist_remove_link(view->highlighted, iter); + + } + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : view = vue de tampon à mettre à jour. * +* x = abscisse de la zone principale à traiter. * +* y = ordonnée de la zone principale à traiter. * +* * +* Description : Surligne tous les segments similaires à celui sous la souris.* +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_buffer_view_highlight_segments(GBufferView *view, gint x, gint y) +{ + GBufferLine *line; /* Ligne sous le pointeur */ + GBufferSegment *segment; /* Segment visé par le pointeur*/ + bool need_redraw; /* Besoin d'actualisation ? */ + size_t first; /* Première ligne intégrée */ + size_t last; /* Dernière ligne intégrée */ + size_t i; /* Boucle de parcours */ + + line = g_buffer_view_find_line_at(view, y); + if (line == NULL) return; + + + do + { + vmpa_t addr; + addr = g_buffer_line_get_address(line); + + printf(" ... x2 clic at 0x%08lx\n", addr); + + } + while (0); + + x -= view->left_text; + if (x < 0) return; + + segment = g_buffer_line_get_segment_at(line, view->max_widths, x); + printf(" ... seg @%d ? %p\n", x, segment); + if (segment == NULL) return; + + + printf("text :: '%s'\n", g_buffer_segment_get_text(segment)); + + + if (view->highlighted != NULL) + need_redraw = g_buffer_view_unhighlight_segments(view); + else + need_redraw = false; + + first = g_code_buffer_get_index_from_address(view->buffer, view->start); + last = g_code_buffer_get_index_from_address(view->buffer, view->end); + + for (i = first; i < last; i++) + view->highlighted = g_buffer_line_highlight_all_same_segments(view->buffer->lines[i], + view->highlighted, segment); + + if (g_slist_length(view->highlighted) > 0) + need_redraw = true; + + if (need_redraw) + g_signal_emit_by_name(view, "need-redraw"); + +} + + +/****************************************************************************** +* * * Paramètres : view = visualisation à mettre à jour. * * method = procédure à appeler à chaque dessin de ligne. * * data = donnée utilisateur à passer lors des appels. * diff --git a/src/glibext/gcodebuffer.h b/src/glibext/gcodebuffer.h index 2c8dbe9..b92f38b 100644 --- a/src/glibext/gcodebuffer.h +++ b/src/glibext/gcodebuffer.h @@ -118,6 +118,12 @@ gint g_buffer_view_get_line_height(GBufferView *); /* Fournit les dimensions requises par une visualisation. */ void g_buffer_view_get_size(GBufferView *, gint *, gint *, bool, bool); +/* Supprime toute mise en évidence de segments. */ +bool g_buffer_view_unhighlight_segments(GBufferView *); + +/* Surligne tous les segments similaires à celui sous la souris. */ +void g_buffer_view_highlight_segments(GBufferView *, gint, gint); + /* Définit à une procédure à appeler lors des dessins de ligne. */ void g_buffer_view_define_extra_drawing(GBufferView *, buffer_line_draw_fc, void *); diff --git a/src/gtkext/gtkblockview.c b/src/gtkext/gtkblockview.c index 398856f..e026cbe 100644 --- a/src/gtkext/gtkblockview.c +++ b/src/gtkext/gtkblockview.c @@ -52,6 +52,12 @@ static void gtk_block_view_class_init(GtkBlockViewClass *); /* Procède à l'initialisation de l'afficheur de bloc assembleur. */ static void gtk_block_view_init(GtkBlockView *); +/* Assure la gestion des clics de souris sur le composant. */ +static gboolean gtk_block_view_button_press_event(GtkBlockView *, GdkEventButton *, gpointer); + +/* Redessine l'affichage suite à un changement visuel. */ +static gboolean gtk_block_view_need_redraw(GBufferView *, GtkBlockView *); + /* Prend acte de l'association d'un binaire chargé. */ static void gtk_block_view_attach_binary(GtkBlockView *, GLoadedBinary *, bool *, bool *); @@ -104,6 +110,9 @@ static void gtk_block_view_init(GtkBlockView *view) panel->attach = (attach_binary_fc)gtk_block_view_attach_binary; + g_signal_connect(G_OBJECT(view), "button_press_event", + G_CALLBACK(gtk_block_view_button_press_event), NULL); + } @@ -132,6 +141,75 @@ GtkWidget *gtk_block_view_new(void) /****************************************************************************** * * +* Paramètres : view = composant GTK visé par l'opération. * +* event = informations liées à l'événement. * +* data = donnée non utilisée ici. * +* * +* Description : Assure la gestion des clics de souris sur le composant. * +* * +* Retour : FALSE pour poursuivre la propagation de l'événement. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static gboolean gtk_block_view_button_press_event(GtkBlockView *view, GdkEventButton *event, gpointer data) +{ + GtkBufferView *bview; /* Autre vision du composant */ + gint real_x; /* Abscisse absolue réelle */ + gint real_y; /* Ordonnée absolue réelle */ + + if (event->type == GDK_2BUTTON_PRESS) + { + + + + printf("I feel %s clicked with button %d\n", + event->type == GDK_2BUTTON_PRESS ? "double" : "triple", + event->button); + + bview = GTK_BUFFER_VIEW(view); + + real_x = event->x; + real_y = event->y; + + gtk_buffer_view_compute_real_coord(bview, &real_x, &real_y); + + g_buffer_view_highlight_segments(gtk_buffer_view_get_buffer(bview), real_x, real_y); + + + + } + + return FALSE; + +} + + +/****************************************************************************** +* * +* Paramètres : view = composant GLib interne. * +* block = composant GTK d'affichage. * +* * +* Description : Redessine l'affichage suite à un changement visuel. * +* * +* Retour : FALSE pour poursuivre la propagation de l'événement. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static gboolean gtk_block_view_need_redraw(GBufferView *view, GtkBlockView *block) +{ + gtk_widget_queue_draw(GTK_WIDGET(block)); + + return FALSE; + +} + + +/****************************************************************************** +* * * Paramètres : view = composant GTK à mettre à jour. * * binary = binaire associé à intégrer. * * addr = indique si les positions doivent être affichées. * @@ -148,9 +226,14 @@ GtkWidget *gtk_block_view_new(void) static void gtk_block_view_attach_binary(GtkBlockView *view, GLoadedBinary *binary, bool *addr, bool *code) { GCodeBuffer *buffer; /* Tampon par défaut */ + GBufferView *bview; /* Vue sur ce même tampon */ buffer = g_loaded_binary_get_disassembled_buffer(binary); + bview = g_buffer_view_new(buffer); + + gtk_buffer_view_attach_buffer(GTK_BUFFER_VIEW(view), bview, addr, code); - gtk_buffer_view_attach_buffer(GTK_BUFFER_VIEW(view), g_buffer_view_new(buffer), addr, code); + g_signal_connect(G_OBJECT(bview), "need-redraw", + G_CALLBACK(gtk_block_view_need_redraw), view); } diff --git a/src/gtkext/gtkbufferview-int.h b/src/gtkext/gtkbufferview-int.h index db27b9e..5d5a407 100644 --- a/src/gtkext/gtkbufferview-int.h +++ b/src/gtkext/gtkbufferview-int.h @@ -54,5 +54,12 @@ struct _GtkBufferViewClass }; +/* Transcrit les coordonnées à l'écran en coordonnées absolues. */ +void gtk_buffer_view_compute_fake_coord(GtkBufferView *, gint *, gint *); + +/* Transcrit les coordonnées absolues en coordonnées à l'écran. */ +void gtk_buffer_view_compute_real_coord(GtkBufferView *, gint *, gint *); + + #endif /* _GTK_BUFFERVIEW_INT_H */ diff --git a/src/gtkext/gtkbufferview.c b/src/gtkext/gtkbufferview.c index 99b67ab..e94d11a 100644 --- a/src/gtkext/gtkbufferview.c +++ b/src/gtkext/gtkbufferview.c @@ -34,12 +34,6 @@ static void gtk_buffer_view_class_init(GtkBufferViewClass *); /* Procède à l'initialisation de l'afficheur de tampons. */ static void gtk_buffer_view_init(GtkBufferView *); -/* Transcrit les coordonnées à l'écran en coordonnées absolues. */ -static void gtk_buffer_view_compute_fake_coord(GtkBufferView *, gint *, gint *); - -/* Transcrit les coordonnées absolues en coordonnées à l'écran. */ -static void gtk_buffer_view_compute_real_coord(GtkBufferView *, gint *, gint *); - /* Fournit la taille de composant requise pour un plein rendu. */ static void gtk_buffer_view_size_request(GtkWidget *, GtkRequisition *); @@ -128,7 +122,7 @@ static void gtk_buffer_view_init(GtkBufferView *view) * * ******************************************************************************/ -static void gtk_buffer_view_compute_fake_coord(GtkBufferView *view, gint *x, gint *y) +void gtk_buffer_view_compute_fake_coord(GtkBufferView *view, gint *x, gint *y) { if (GTK_VIEW_PANEL(view)->hadjustment != NULL) *x -= gtk_adjustment_get_value(GTK_VIEW_PANEL(view)->hadjustment); @@ -152,7 +146,7 @@ static void gtk_buffer_view_compute_fake_coord(GtkBufferView *view, gint *x, gin * * ******************************************************************************/ -static void gtk_buffer_view_compute_real_coord(GtkBufferView *view, gint *x, gint *y) +void gtk_buffer_view_compute_real_coord(GtkBufferView *view, gint *x, gint *y) { if (x != NULL && GTK_VIEW_PANEL(view)->hadjustment != NULL) *x += gtk_adjustment_get_value(GTK_VIEW_PANEL(view)->hadjustment); |