diff options
Diffstat (limited to 'src')
| -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 | 
12 files changed, 619 insertions, 30 deletions
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);  | 
