From 90923fccb863075722d2ed17360e2c330b262e04 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Sun, 12 Apr 2015 22:07:56 +0000 Subject: Highlighted the current segment on caret location changes. git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@511 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a --- ChangeLog | 21 ++++ src/glibext/gbufferline.c | 214 ++------------------------------------- src/glibext/gbufferline.h | 5 +- src/glibext/gbuffersegment.c | 222 +++++++++++++++++++++++++++++++++++------ src/glibext/gbuffersegment.h | 42 +++++--- src/glibext/gcodebuffer.c | 124 +++++++++++++---------- src/glibext/gcodebuffer.h | 2 +- src/gtkext/gtkblockview.c | 36 ++++++- src/gtkext/gtkbufferview-int.h | 6 ++ src/gtkext/gtkbufferview.c | 81 +++++++++++++-- 10 files changed, 438 insertions(+), 315 deletions(-) diff --git a/ChangeLog b/ChangeLog index d08796b..05c70ad 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,26 @@ 15-04-12 Cyrille Bagard + * src/glibext/gbufferline.c: + * src/glibext/gbufferline.h: + Update code. + + * src/glibext/gbuffersegment.c: + * src/glibext/gbuffersegment.h: + Fix a bug when computing the segment hash: use the final text. + Create a list structure to identify segment contents by their hash. + Draw the segments according to this kind of list. + + * src/glibext/gcodebuffer.c: + * src/glibext/gcodebuffer.h: + Keep track of each highlighted segment. + + * src/gtkext/gtkblockview.c: + * src/gtkext/gtkbufferview.c: + * src/gtkext/gtkbufferview-int.h: + Highlight the current segment on caret location changes. + +15-04-12 Cyrille Bagard + * src/core/params.c: * src/core/params.h: Allow to configure the drawing of the selection line. diff --git a/src/glibext/gbufferline.c b/src/glibext/gbufferline.c index d763e9d..238bfb3 100644 --- a/src/glibext/gbufferline.c +++ b/src/glibext/gbufferline.c @@ -74,11 +74,8 @@ static GBufferSegment *get_segment_at(const buffer_line_column *, gint *, GdkScr /* Fournit le segment voisin d'un autre segment identifié. */ static GBufferSegment *find_near_segment(const buffer_line_column *, GBufferSegment *, GdkScrollDirection); -/* Met en surbrillance des segments similaires. */ -static 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 *, cairo_t *, gint, gint); +static void draw_segments_of_column(buffer_line_column *, cairo_t *, gint, gint, const segcnt_list *); /* Exporte la ligne de texte représentée. */ static void export_segments_of_column(buffer_line_column *, buffer_export_context *, BufferExportType, int); @@ -351,41 +348,11 @@ static GBufferSegment *find_near_segment(const buffer_line_column *column, GBuff /****************************************************************************** * * -* 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 : - * -* * -******************************************************************************/ - -static 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. * * cairo = contexte graphique à utiliser pour les pinceaux. * * x_init = abscisse du point d'impression de départ. * * y = ordonnée du point d'impression. * +* list = liste de contenus à mettre en évidence. * * * * Description : Imprime le contenu d'une colonne de ligne de texte. * * * @@ -395,7 +362,7 @@ static GSList *highlight_all_same_segments(const buffer_line_column *column, GSL * * ******************************************************************************/ -static void draw_segments_of_column(buffer_line_column *column, cairo_t *cairo, gint x_init, gint y) +static void draw_segments_of_column(buffer_line_column *column, cairo_t *cairo, gint x_init, gint y, const segcnt_list *list) { gint x; /* Abscisse d'impression */ size_t i; /* Boucle de parcours */ @@ -403,7 +370,7 @@ static void draw_segments_of_column(buffer_line_column *column, cairo_t *cairo, x = x_init; for (i = 0; i < column->count; i++) - g_buffer_segment_draw(column->segments[i], cairo, &x, y); + g_buffer_segment_draw(column->segments[i], cairo, &x, y, list); } @@ -933,148 +900,6 @@ GBufferSegment *g_buffer_line_get_segment_at(const GBufferLine *line, const gint } -#if 0 -GBufferSegment *g_buffer_line_get_segment_at(const GBufferLine *line, const gint max_widths[BLC_COUNT], const bool *display, gint *base, gint *offset, GdkScrollDirection dir, bool force) -{ - GBufferSegment *result; /* Trouvaille à retourner */ - gint old; /* Valeur d'origine de position*/ - BufferLineColumn last; /* Dernière colonne remplie */ - gint last_x; /* Dernière abscisse associée */ - gint sum; /* Somme de toutes les largeurs*/ - BufferLineColumn i; /* Boucle de parcours */ - gint width; /* Largeur d'une colonne donnée*/ - gint consumed; /* Distance vers le segment */ - - result = NULL; - - old = *x; - last = BLC_COUNT; - last_x = *x; /* Pour GCC */ - - sum = 0; - - printf("---------------\n"); - - /* On cible déjà la colonne idéale */ - - for (i = 0; i < BLC_COUNT; i++) - { - printf(" @ (%d) x=%d width=%d max=%d display ? %d\n", - i, *x, get_column_width(&line->columns[i]), max_widths[i], i < BLC_DISPLAY ? display[i] : true); - - - if (i < BLC_DISPLAY && !display[i]) continue; - - /* Mémorisation de la dernière colonne contenant quelque chose... */ - if (get_column_width(&line->columns[i]) > 0) - { - last = i; - last_x = sum; - } - - if (i < line->merge_start) - { - width = max_widths[i]; - if ((i + 1) < BLC_COUNT) width += COL_MARGIN; - - if (*x <= width) break; - else - { - *x -= width; - sum += width; - } - - } - else - { - width = get_column_width(&line->columns[i]); - - if (*x <= width) break; - else - { - *x -= width; - sum += width; - } - - } - - - } - - printf(" -- get segment at -- found index %u (max=%u)\n", i, BLC_COUNT); - - - printf(" last seen = %u\n", last); - - - - - - if (i < BLC_COUNT) - { - - printf(" -- width @ %u : %d\n", i, get_column_width(&line->columns[i])); - - if (get_column_width(&line->columns[i]) > 0) - { - result = get_segment_at(&line->columns[i], x, dir, &consumed); - *x += sum + consumed; - } - - /* La position fournie tombe dans une colonne vide ! */ - else - { - if (force || get_column_width(&line->columns[i]) == 0) - { - result = NULL; - *x = sum; - - for (i++; i < BLC_COUNT && result == NULL; i++) - { - printf(" -- update to col %u -- x = %d\n", i, *x); - - if ((i - 1) < line->merge_start) - *x += (max_widths[i - 1] + COL_MARGIN); - else - *x += get_column_width(&line->columns[i - 1]); - - result = get_first_segment(&line->columns[i]); - - } - - printf(" -- final x = %d (result=%p)\n", *x, result); - - if (result == NULL) - goto use_right_border; - - } - - } - - } - - else /* if (i == BLC_COUNT) */ - { - if (force && last != BLC_COUNT) - { - use_right_border: - - result = get_last_segment(&line->columns[last]); - *x = last_x + get_column_width(&line->columns[last]); - - } - else - result = NULL; - - } - - return result; - -} -#endif - - - /****************************************************************************** * * * Paramètres : line = ligne à venir consulter. * @@ -1195,32 +1020,6 @@ GBufferSegment *g_buffer_line_find_near_segment(const GBufferLine *line, GBuffer /****************************************************************************** * * -* 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 = 0; 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. * @@ -1470,6 +1269,7 @@ void g_buffer_line_remove_flag(GBufferLine *line, BufferLineFlags flag) * x_init = abscisse du point d'impression de départ. * * y = ordonnée du point d'impression. * * display = règles d'affichage des colonnes modulables. * +* list = liste de contenus à mettre en évidence. * * * * Description : Imprime la ligne de texte représentée. * * * @@ -1479,7 +1279,7 @@ void g_buffer_line_remove_flag(GBufferLine *line, BufferLineFlags flag) * * ******************************************************************************/ -void g_buffer_line_draw(GBufferLine *line, cairo_t *cairo, const gint max_widths[BLC_COUNT], gint x_init, gint y, const bool *display) +void g_buffer_line_draw(GBufferLine *line, cairo_t *cairo, const gint max_widths[BLC_COUNT], gint x_init, gint y, const bool *display, const segcnt_list *list) { GBufferLineClass *class; /* Stockage de briques de base */ gint x; /* Point de départ d'impression*/ @@ -1504,7 +1304,7 @@ void g_buffer_line_draw(GBufferLine *line, cairo_t *cairo, const gint max_widths { if (i < BLC_DISPLAY && !display[i]) continue; - draw_segments_of_column(&line->columns[i], cairo, x, y); + draw_segments_of_column(&line->columns[i], cairo, x, y, list); if (i < line->merge_start) x += max_widths[i] + COL_MARGIN; diff --git a/src/glibext/gbufferline.h b/src/glibext/gbufferline.h index e8916ac..6da36af 100644 --- a/src/glibext/gbufferline.h +++ b/src/glibext/gbufferline.h @@ -118,9 +118,6 @@ GBufferSegment *g_buffer_line_get_segment_at(const GBufferLine *, const gint [BL /* Fournit le segment voisin d'un autre segment identifié. */ GBufferSegment *g_buffer_line_find_near_segment(const GBufferLine *, GBufferSegment *, const gint [BLC_COUNT], const bool *, GdkScrollDirection, 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. */ GBufferSegment *g_buffer_line_insert_text(GBufferLine *, BufferLineColumn, const char *, size_t, RenderingTagType); @@ -146,7 +143,7 @@ BufferLineFlags g_buffer_line_get_flags(const GBufferLine *); void g_buffer_line_remove_flag(GBufferLine *, BufferLineFlags); /* Imprime la ligne de texte représentée. */ -void g_buffer_line_draw(GBufferLine *, cairo_t *, const gint [BLC_COUNT], gint, gint, const bool *); +void g_buffer_line_draw(GBufferLine *, cairo_t *, const gint [BLC_COUNT], gint, gint, const bool *, const segcnt_list *); /* Exporte la ligne de texte représentée. */ void g_buffer_line_export(GBufferLine *, buffer_export_context *, BufferExportType, const bool *); diff --git a/src/glibext/gbuffersegment.c b/src/glibext/gbuffersegment.c index d25d728..8e7613f 100644 --- a/src/glibext/gbuffersegment.c +++ b/src/glibext/gbuffersegment.c @@ -36,6 +36,9 @@ +/* -------------------- NATURE DE BASE POUR UN FRAGMENT DE TEXTE -------------------- */ + + /* Propriétés de rendu */ typedef struct _rendering_color_t @@ -105,8 +108,6 @@ struct _GBufferSegment rendering_pattern_t *pattern; /* Propriétés du rendu */ - SegRenderingStyle style; /* Apparence du segment */ - rendering_color_t cache_bg; /* Fond d'impression */ rendering_color_t alt_fg; /* Couleur d'impression bis */ const rendering_color_t *used_fg; /* Couleur d'impression utile */ @@ -144,6 +145,25 @@ static void g_buffer_segment_prepare(GBufferSegment *, size_t); + +/* -------------------- GESTION OPTIMALE D'UNE LISTE DE CONTENUS -------------------- */ + + +/* Liste identifiant un ensemble de segments */ +struct _segcnt_list +{ + fnv64_t *hashes; /* Empreinte pour comparaisons */ + size_t count; /* Nommbre de ces empreintes */ + +}; + + + +/* ---------------------------------------------------------------------------------- */ +/* NATURE DE BASE POUR UN FRAGMENT DE TEXTE */ +/* ---------------------------------------------------------------------------------- */ + + /* Détermine le type du fragment de caractères aux propriétés communes. */ G_DEFINE_TYPE(GBufferSegment, g_buffer_segment, G_TYPE_OBJECT); @@ -360,15 +380,13 @@ GBufferSegment *g_buffer_segment_new(RenderingTagType type, const char *text, si result = g_object_new(G_TYPE_BUFFER_SEGMENT, NULL); result->text = strndup(text, length); - result->hash = fnv_64a_hash(text); + result->hash = fnv_64a_hash(result->text); class = G_BUFFER_SEGMENT_GET_CLASS(result); result->pattern = &class->patterns[type]; g_buffer_segment_prepare(result, length); - g_buffer_segment_set_style(result, SRS_CLASSIC); - return result; } @@ -702,9 +720,12 @@ bool g_buffer_segment_move_caret(const GBufferSegment *segment, gint *x, bool ct /****************************************************************************** * * * Paramètres : segment = fragment de texte à manipuler. * -* style = style de rendu pour le segment. * +* cairo = contexte graphique à utiliser pour les pinceaux. * +* x = abscisse du point d'impression (à maj). [OUT] * +* y = ordonnée du point d'impression. * +* list = liste de contenus à mettre en évidence. * * * -* Description : Module l'apparence finale du composant. * +* Description : Imprime le fragment de texte représenté. * * * * Retour : - * * * @@ -712,10 +733,14 @@ bool g_buffer_segment_move_caret(const GBufferSegment *segment, gint *x, bool ct * * ******************************************************************************/ -void g_buffer_segment_set_style(GBufferSegment *segment, SegRenderingStyle style) +void g_buffer_segment_draw(GBufferSegment *segment, cairo_t *cairo, gint *x, gint y, const segcnt_list *list) { - segment->style = style; + bool selected; /* Marquer une sélection ? */ + cairo_font_extents_t extents; + + + /* switch (style) { default: @@ -734,34 +759,28 @@ void g_buffer_segment_set_style(GBufferSegment *segment, SegRenderingStyle style break; } + */ -} + segment->used_fg = &segment->pattern->foreground; -/****************************************************************************** -* * -* Paramètres : segment = fragment de texte à manipuler. * -* cairo = contexte graphique à utiliser pour les pinceaux. * -* x = abscisse du point d'impression (à maj). [OUT] * -* y = ordonnée du point d'impression. * -* * -* Description : Imprime le fragment de texte représenté. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ -void g_buffer_segment_draw(GBufferSegment *segment, cairo_t *cairo, gint *x, gint y) -{ + selected = selection_list_has_segment_content(list, segment); - cairo_font_extents_t extents; + if (selected) + { + segment->cache_bg.color.red = 0.5; + segment->cache_bg.color.green = 0.5; + segment->cache_bg.color.blue = 0.5; + + segment->used_fg = &segment->alt_fg; + + } /* Fond du texte */ - if (segment->style != SRS_CLASSIC) + if (selected) { cairo_set_source_rgb(cairo, segment->cache_bg.color.red, @@ -935,3 +954,150 @@ void g_buffer_segment_export(const GBufferSegment *segment, buffer_export_contex } } + + + +/* ---------------------------------------------------------------------------------- */ +/* GESTION OPTIMALE D'UNE LISTE DE CONTENUS */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Initilise une liste de contenus de segments. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +segcnt_list *init_segment_content_list(void) +{ + segcnt_list *result; /* Structure à retourner */ + + result = (segcnt_list *)calloc(1, sizeof(segcnt_list)); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : list = ensemble de références de contenus à traiter. * +* * +* Description : Libère la mémoire occupée par une liste de contenus. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void exit_segment_content_list(segcnt_list *list) +{ + reset_segment_content_list(list); + + free(list); + +} + + +/****************************************************************************** +* * +* Paramètres : list = ensemble de références de contenus à manipuler. * +* * +* Description : Vide, si besoin est, une liste de contenus de segments. * +* * +* Retour : true si des éléments ont été purgés, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool reset_segment_content_list(segcnt_list *list) +{ + bool result; /* Bilan d'action à renvoyer */ + + result = (list->count > 0); + + if (list->hashes != NULL) + { + free(list->hashes); + list->hashes = NULL; + } + + list->count = 0; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : list = ensemble de références de contenus à manipuler. * +* segment = fragment de texte à conservr. * +* * +* Description : Marque le contenu d'un segment comme remarquable. * +* * +* Retour : true si la liste a été complétée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool add_segment_content_to_selection_list(segcnt_list *list, const GBufferSegment *segment) +{ + bool result; /* Bilan à retourner */ + size_t i; /* Boucle de parcours */ + + static const char white_list[] = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + + result = false; + + for (i = 0; i < (sizeof(white_list) - 1) && !result; i++) + result = (strchr(segment->text, white_list[i]) != NULL); + + if (result) + { + list->hashes = (fnv64_t *)realloc(list->hashes, ++list->count * sizeof(fnv64_t)); + + list->hashes[list->count - 1] = segment->hash; + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : list = ensemble de références de contenus à consulter. * +* segment = fragment de texte à comparer. * +* * +* Description : Indique si le contenu d'un segment est notable ou non. * +* * +* Retour : true si le segment a un contenu présent dans la sélection. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool selection_list_has_segment_content(const segcnt_list *list, const GBufferSegment *segment) +{ + bool result; /* Bilan à retourner */ + size_t i; /* Boucle de parcours */ + + result = false; + + for (i = 0; i < list->count && !result; i++) + result = (cmp_fnv_64a(list->hashes[i], segment->hash) == 0); + + return result; + +} diff --git a/src/glibext/gbuffersegment.h b/src/glibext/gbuffersegment.h index 51bfb2a..67091fb 100644 --- a/src/glibext/gbuffersegment.h +++ b/src/glibext/gbuffersegment.h @@ -32,6 +32,13 @@ +/* Liste identifiant un ensemble de segments */ +typedef struct _segcnt_list segcnt_list; + + +/* -------------------- NATURE DE BASE POUR UN FRAGMENT DE TEXTE -------------------- */ + + #define G_TYPE_BUFFER_SEGMENT (g_buffer_segment_get_type()) #define G_BUFFER_SEGMENT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_BUFFER_SEGMENT, GBufferSegment)) #define G_BUFFER_SEGMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_BUFFER_SEGMENT, GBufferSegmentClass)) @@ -81,16 +88,6 @@ typedef enum _RenderingTagType } RenderingTagType; -/* Types de rendus */ -typedef enum _SegRenderingStyle -{ - SRS_CLASSIC, /* Comportement par défaut */ - SRS_HIGHLIGHT_SAME, /* Surlignage des identiques */ - - SRS_COUNT - -} SegRenderingStyle; - /* Fragment de caractères aux propriétés communes (instance) */ typedef struct _GBufferSegment GBufferSegment; @@ -127,11 +124,8 @@ gint g_buffer_segment_get_caret_position(const GBufferSegment *, gint); /* Déplace le curseur au sein d'un segment de tampon. */ bool g_buffer_segment_move_caret(const GBufferSegment *, gint *, bool, GdkScrollDirection); -/* 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 *, cairo_t *, gint *, gint); +void g_buffer_segment_draw(GBufferSegment *, cairo_t *, gint *, gint, const segcnt_list *); /* Types d'exportation */ typedef enum _BufferExportType @@ -177,4 +171,24 @@ void g_buffer_segment_export(const GBufferSegment *, buffer_export_context *, Bu +/* -------------------- GESTION OPTIMALE D'UNE LISTE DE CONTENUS -------------------- */ + + +/* Initilise une liste de contenus de segments. */ +segcnt_list *init_segment_content_list(void); + +/* Libère la mémoire occupée par une liste de contenus. */ +void exit_segment_content_list(segcnt_list *); + +/* Vide, si besoin est, une liste de contenus de segments. */ +bool reset_segment_content_list(segcnt_list *); + +/* Marque le contenu d'un segment comme remarquable. */ +bool add_segment_content_to_selection_list(segcnt_list *, const GBufferSegment *); + +/* Indique si le contenu d'un segment est notable ou non. */ +bool selection_list_has_segment_content(const segcnt_list *, const GBufferSegment *); + + + #endif /* _GLIBEXT_GBUFFERSEGMENT_H */ diff --git a/src/glibext/gcodebuffer.c b/src/glibext/gcodebuffer.c index fd1330b..171ba09 100644 --- a/src/glibext/gcodebuffer.c +++ b/src/glibext/gcodebuffer.c @@ -154,7 +154,7 @@ struct _GBufferView gint last_width; /* Plus grande col. de fusion */ BufferLineColumn last_merge; /* Colonne de fusion extrême */ - GSList *highlighted; /* Segments mis en évidence */ + segcnt_list *highlighted; /* Segments mis en évidence */ }; @@ -180,6 +180,12 @@ static void g_buffer_view_class_init(GBufferViewClass *); /* Procède à l'initialisation d'une vue d'un tampon pour code. */ static void g_buffer_view_init(GBufferView *); +/* Supprime toutes les références externes. */ +static void g_buffer_view_dispose(GBufferView *); + +/* Procède à la libération totale de la mémoire. */ +static void g_buffer_view_finalize(GBufferView *); + /* Réinitialise le cache de la hauteur des lignes. */ static void g_buffer_view_reset_required_height(GBufferView *); @@ -892,6 +898,13 @@ G_DEFINE_TYPE(GBufferView, g_buffer_view, G_TYPE_OBJECT); static void g_buffer_view_class_init(GBufferViewClass *class) { + GObjectClass *object; /* Autre version de la classe */ + + object = G_OBJECT_CLASS(class); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_buffer_view_dispose; + object->finalize = (GObjectFinalizeFunc)g_buffer_view_finalize; + g_signal_new("need-redraw", G_TYPE_BUFFER_VIEW, G_SIGNAL_RUN_LAST, @@ -922,6 +935,48 @@ static void g_buffer_view_init(GBufferView *buffer) g_buffer_view_reset_required_height(buffer); g_buffer_view_reset_required_widths(buffer); + buffer->highlighted = init_segment_content_list(); + +} + + +/****************************************************************************** +* * +* Paramètres : view = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_buffer_view_dispose(GBufferView *view) +{ + G_OBJECT_CLASS(g_buffer_view_parent_class)->dispose(G_OBJECT(view)); + +} + + +/****************************************************************************** +* * +* Paramètres : view = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_buffer_view_finalize(GBufferView *view) +{ + exit_segment_content_list(view->highlighted); + + G_OBJECT_CLASS(g_buffer_view_parent_class)->finalize(G_OBJECT(view)); + } @@ -1689,84 +1744,49 @@ const vmpa2t *g_buffer_view_move_caret(GBufferView *view, GdkRectangle *caret, b bool g_buffer_view_unhighlight_segments(GBufferView *view) { - GSList *iter; /* Boucle de parcours */ - GBufferSegment *segment; /* Segment visé par le pointeur*/ + bool result; /* Bilan d'action à renvoyer */ - if (g_slist_length(view->highlighted) == 0) - return false; + result = reset_segment_content_list(view->highlighted); - 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; + return result; } /****************************************************************************** * * -* Paramètres : view = vue de tampon à mettre à jour. * -* x = abscisse de la zone principale à traiter. * -* y = ordonnée de la zone principale à traiter. * +* Paramètres : view = vue de tampon à mettre à jour. * +* x = abscisse de la zone principale à traiter. * +* y = ordonnée de la zone principale à traiter. * +* display = règles d'affichage des colonnes modulables. * * * * Description : Surligne tous les segments similaires à celui sous la souris.* * * -* Retour : - * +* Retour : true si un besoin d'actualisation d'affichage se fait sentir.* * * * Remarques : - * * * ******************************************************************************/ -void g_buffer_view_highlight_segments(GBufferView *view, gint x, gint y) +bool g_buffer_view_highlight_segments(GBufferView *view, gint x, gint y, const bool *display) { -#if 0 /* FIXME : inclusion des champs adresses/code */ - 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, NULL); - if (line == NULL) return; - - x -= view->left_text; - if (x < 0) return; - - segment = g_buffer_line_get_segment_at(line, view->max_widths, &x, GDK_SCROLL_LEFT, false); - printf(" ... seg @%d ? %p\n", x, segment); - if (segment == NULL) return; - - - printf("text :: '%s'\n", g_buffer_segment_get_text(segment, false)); - + GBufferLine *line; /* Ligne ciblée */ + GBufferSegment *segment; /* Segment sélectionnable */ 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, true); - last = g_code_buffer_get_index_from_address(view->buffer, view->end, false); - - for (i = first; i <= last; i++) - view->highlighted = g_buffer_line_highlight_all_same_segments(view->buffer->lines[i], - view->highlighted, segment); + line = g_buffer_view_find_line_and_segment_at(view, &x, y, NULL, display, &segment); - if (g_slist_length(view->highlighted) > 0) - need_redraw = true; + if (segment) + need_redraw |= add_segment_content_to_selection_list(view->highlighted, segment); if (need_redraw) g_signal_emit_by_name(view, "need-redraw"); -#endif + } @@ -1837,7 +1857,7 @@ void g_buffer_view_draw(const GBufferView *view, cairo_t *cr, gint fake_x, gint } - g_buffer_line_draw(lines[i], cr, view->max_widths, real_x, y, display); + g_buffer_line_draw(lines[i], cr, view->max_widths, real_x, y, display, view->highlighted); y += view->line_height; diff --git a/src/glibext/gcodebuffer.h b/src/glibext/gcodebuffer.h index 339e0a0..846da64 100644 --- a/src/glibext/gcodebuffer.h +++ b/src/glibext/gcodebuffer.h @@ -144,7 +144,7 @@ const vmpa2t *g_buffer_view_move_caret(GBufferView *, GdkRectangle *, bool, GdkS 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); +bool g_buffer_view_highlight_segments(GBufferView *, gint, gint, const bool *); /* Imprime la visualisation du tampon de code désassemblé. */ void g_buffer_view_draw(const GBufferView *, cairo_t *, gint, gint, const cairo_rectangle_int_t *, const bool *, const gint *); diff --git a/src/gtkext/gtkblockview.c b/src/gtkext/gtkblockview.c index 2584405..1c7ba43 100644 --- a/src/gtkext/gtkblockview.c +++ b/src/gtkext/gtkblockview.c @@ -52,6 +52,9 @@ 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 *); +/* Réagit à un déplacement de curseur. */ +static bool gtk_block_view_notify_caret_relocation(GtkBlockView *, const GdkRectangle *, const vmpa2t *); + /* Assure la gestion des clics de souris sur le composant. */ static gboolean gtk_block_view_button_press_event(GtkBlockView *, GdkEventButton *, gpointer); @@ -87,11 +90,15 @@ G_DEFINE_TYPE(GtkBlockView, gtk_block_view, GTK_TYPE_BUFFER_VIEW) static void gtk_block_view_class_init(GtkBlockViewClass *class) { GtkViewPanelClass *panel_class; /* Classe parente */ + GtkBufferViewClass *buffer_class; /* Classe supérieure */ panel_class = GTK_VIEW_PANEL_CLASS(class); + buffer_class = GTK_BUFFER_VIEW_CLASS(class); panel_class->attach = (attach_binary_fc)gtk_block_view_attach_binary; + buffer_class->notify_caret = (notify_caret_relocation_fc)gtk_block_view_notify_caret_relocation; + } @@ -109,8 +116,35 @@ static void gtk_block_view_class_init(GtkBlockViewClass *class) static void gtk_block_view_init(GtkBlockView *view) { + + + /* g_signal_connect(G_OBJECT(view), "button_press_event", G_CALLBACK(gtk_block_view_button_press_event), NULL); + */ + + +} + + +/****************************************************************************** +* * +* Paramètres : view = composant GTK à manipuler. * +* area = emplacement pour le dessin d'un curseur. * +* addr = position dans la mémoire représentée du curseur. * +* * +* Description : Réagit à un déplacement de curseur. * +* * +* Retour : true si un changement a été opéré. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool gtk_block_view_notify_caret_relocation(GtkBlockView *view, const GdkRectangle *area, const vmpa2t *addr) +{ + return g_buffer_view_highlight_segments(GTK_BUFFER_VIEW(view)->buffer_view, area->x, area->y, + GTK_VIEW_PANEL(view)->display); } @@ -174,7 +208,7 @@ static gboolean gtk_block_view_button_press_event(GtkBlockView *view, GdkEventBu 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); + g_buffer_view_highlight_segments(gtk_buffer_view_get_buffer(bview), real_x, real_y, NULL); diff --git a/src/gtkext/gtkbufferview-int.h b/src/gtkext/gtkbufferview-int.h index a6d937b..e8e11a0 100644 --- a/src/gtkext/gtkbufferview-int.h +++ b/src/gtkext/gtkbufferview-int.h @@ -32,6 +32,10 @@ +/* Réagit à un déplacement de curseur. */ +typedef bool (* notify_caret_relocation_fc) (GtkBufferView *, const GdkRectangle *, const vmpa2t *); + + /* Composant d'affichage de tampon de lignes (instance) */ struct _GtkBufferView { @@ -56,6 +60,8 @@ struct _GtkBufferViewClass { GtkViewPanelClass parent; /* A laisser en premier */ + notify_caret_relocation_fc notify_caret;/* Accompagne un déplacement */ + /* Signaux */ void (* caret_moved) (GtkBufferView *, const vmpa2t *); diff --git a/src/gtkext/gtkbufferview.c b/src/gtkext/gtkbufferview.c index 1c2c7a9..1a1f6f1 100644 --- a/src/gtkext/gtkbufferview.c +++ b/src/gtkext/gtkbufferview.c @@ -41,6 +41,12 @@ static void gtk_buffer_view_class_init(GtkBufferViewClass *); /* Procède à l'initialisation de l'afficheur de tampons. */ static void gtk_buffer_view_init(GtkBufferView *); +/* Supprime toutes les références externes. */ +static void gtk_buffer_view_dispose(GtkBufferView *); + +/* Procède à la libération totale de la mémoire. */ +static void gtk_buffer_view_finalize(GtkBufferView *); + /* Intègre le focus dans le rendu du composant. */ static gboolean gtk_buffer_view_focus(GtkWidget *, GtkDirectionType); @@ -110,12 +116,17 @@ G_DEFINE_TYPE(GtkBufferView, gtk_buffer_view, GTK_TYPE_VIEW_PANEL) static void gtk_buffer_view_class_init(GtkBufferViewClass *class) { + GObjectClass *object; /* Autre version de la classe */ GtkWidgetClass *widget_class; /* Classe version Widget */ GtkViewPanelClass *panel_class; /* Classe parente */ + object = G_OBJECT_CLASS(class); widget_class = GTK_WIDGET_CLASS(class); panel_class = GTK_VIEW_PANEL_CLASS(class); + object->dispose = (GObjectFinalizeFunc/* ! */)gtk_buffer_view_dispose; + object->finalize = (GObjectFinalizeFunc)gtk_buffer_view_finalize; + widget_class->focus = gtk_buffer_view_focus; widget_class->button_press_event = gtk_buffer_view_button_press; widget_class->draw = gtk_buffer_view_draw; @@ -163,6 +174,44 @@ static void gtk_buffer_view_init(GtkBufferView *view) /****************************************************************************** * * +* Paramètres : view = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_buffer_view_dispose(GtkBufferView *view) +{ + G_OBJECT_CLASS(gtk_buffer_view_parent_class)->dispose(G_OBJECT(view)); + +} + + +/****************************************************************************** +* * +* Paramètres : view = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_buffer_view_finalize(GtkBufferView *view) +{ + G_OBJECT_CLASS(gtk_buffer_view_parent_class)->finalize(G_OBJECT(view)); + +} + + +/****************************************************************************** +* * * Paramètres : widget = composant GTK visé par l'opération. * * dir = sens de l'opération : perte ou gain de focus. * * * @@ -826,21 +875,37 @@ void gtk_buffer_view_compute_relative_coords(GtkBufferView *view, gint *x, gint static void gtk_buffer_view_relocate_caret(GtkBufferView *view, const GdkRectangle *area, const vmpa2t *addr) { + bool clear_old; /* Effacement chirurgical */ + GdkRectangle old_area; /* Mémorisation de l'ancien */ + bool need_redraw; /* Besoin de rafraîchissement ?*/ + if (view->caret_addr != NULL) { - gtk_buffer_view_compute_relative_coords(view, &view->caret.x, &view->caret.y); + clear_old = true; + old_area = view->caret; + } + else + clear_old = false; + + view->caret = *area; + view->caret_addr = addr; - /* - gtk_widget_queue_draw_area(GTK_WIDGET(view), view->caret.x, view->caret.y, - view->caret.width, view->caret.height); - */ + if (GTK_BUFFER_VIEW_GET_CLASS(view)->notify_caret != NULL) + need_redraw = GTK_BUFFER_VIEW_GET_CLASS(view)->notify_caret(view, area, addr); + else + need_redraw = false; + if (need_redraw) gtk_widget_queue_draw(GTK_WIDGET(view)); - } + else if (clear_old) + { + gtk_buffer_view_compute_relative_coords(view, &old_area.x, &old_area.y); - view->caret = *area; - view->caret_addr = addr; + gtk_widget_queue_draw_area(GTK_WIDGET(view), old_area.x, old_area.y, + old_area.width, old_area.height); + + } restart_caret_blinking(view); -- cgit v0.11.2-87-g4458