diff options
Diffstat (limited to 'src/glibext')
-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 |
6 files changed, 391 insertions, 21 deletions
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 *); |