summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2015-04-12 22:07:56 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2015-04-12 22:07:56 (GMT)
commit90923fccb863075722d2ed17360e2c330b262e04 (patch)
treeb7588517a6437efa2d4cd885984e0b87ef8307fe
parent054d2d76f1951c20822286bce0128e60c26c4b9b (diff)
Highlighted the current segment on caret location changes.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@511 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
-rw-r--r--ChangeLog21
-rw-r--r--src/glibext/gbufferline.c214
-rw-r--r--src/glibext/gbufferline.h5
-rw-r--r--src/glibext/gbuffersegment.c222
-rw-r--r--src/glibext/gbuffersegment.h42
-rw-r--r--src/glibext/gcodebuffer.c124
-rw-r--r--src/glibext/gcodebuffer.h2
-rw-r--r--src/gtkext/gtkblockview.c36
-rw-r--r--src/gtkext/gtkbufferview-int.h6
-rw-r--r--src/gtkext/gtkbufferview.c81
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 <nocbos@gmail.com>
+ * 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 <nocbos@gmail.com>
+
* 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);