summaryrefslogtreecommitdiff
path: root/src/glibext/gbuffersegment.c
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2016-10-23 16:22:50 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2016-10-23 18:53:25 (GMT)
commit56f7524c4fd0fc14a509be7689f4820b31564dbc (patch)
tree9c84e11279cd5711a4e0af907ca6160b62317528 /src/glibext/gbuffersegment.c
parent3f05bacd4fec23824489b51d964a7ce3565bb85b (diff)
Deleted a level of data to reduce the memory fingerprint.
Diffstat (limited to 'src/glibext/gbuffersegment.c')
-rw-r--r--src/glibext/gbuffersegment.c1333
1 files changed, 0 insertions, 1333 deletions
diff --git a/src/glibext/gbuffersegment.c b/src/glibext/gbuffersegment.c
deleted file mode 100644
index dfa8c41..0000000
--- a/src/glibext/gbuffersegment.c
+++ /dev/null
@@ -1,1333 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * gbuffersegment.c - concentration d'un fragment de caractères aux propriétés communes
- *
- * Copyright (C) 2010-2014 Cyrille Bagard
- *
- * This file is part of Chrysalide.
- *
- * OpenIDA is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * OpenIDA is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#include "gbuffersegment.h"
-
-
-#include <assert.h>
-#include <limits.h>
-#include <malloc.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include <string.h>
-
-
-#include "../common/extstr.h"
-#include "../common/fnv1a.h"
-#include "../gtkext/gtkblockview.h"
-#include "../gtkext/support.h"
-
-
-
-/* ----------------------- ISOLATION DE CONTENUS PARTAGEABLES ----------------------- */
-
-
-/* Propriétés de rendu */
-
-typedef struct _rendering_color_t
-{
- GdkRGBA color; /* Couleur de rendu */
- bool has_color; /* Définition en place ? */
-
-} rendering_color_t;
-
-typedef struct _rendering_pattern_t
-{
- rendering_color_t foreground; /* Couleur d'impression */
- rendering_color_t inverted; /* Couleur inversée pour sél. */
-
- cairo_font_slant_t slant; /* Style d'impression */
- cairo_font_weight_t weight; /* Poids de la police */
-
-} rendering_pattern_t;
-
-/* Contenu brut pour segment, potentiellement commun */
-typedef struct _seg_content
-{
- unsigned int ref_count; /* Compteur de références */
-
- rendering_pattern_t *pattern; /* Propriétés du rendu */
-
- fnv64_t hash; /* Empreinte pour comparaisons */
- char text[0]; /* Texte brut conservé */
-
-} seg_content;
-
-
-/* Conservation de toutes les créations partagées */
-static GHashTable *_segcnt_htable;
-
-
-/* Fournit l'empreinte d'un contenu pour segments. */
-static guint get_seg_content_hash(const seg_content *);
-
-/* Détermine si deux contenus pour segments sont identiques. */
-static bool is_seg_content_equal(const seg_content *, const seg_content *);
-
-/* Détermine si deux contenus pour segments sont identiques. */
-static seg_content *get_shared_content(const seg_content *);
-
-/* Abandonne un contenu pour segments. */
-static void release_shared_content(seg_content *);
-
-
-
-/* -------------------- NATURE DE BASE POUR UN FRAGMENT DE TEXTE -------------------- */
-
-
-/* Nom des éléments CSS */
-
-#define SEGMENT_NAME(s) "segment-" s
-
-static const char *_segment_names[RTT_COUNT] = {
-
- [RTT_RAW] = SEGMENT_NAME("raw"),
- [RTT_COMMENT] = SEGMENT_NAME("comment"),
- [RTT_INDICATION] = SEGMENT_NAME("indication"),
- [RTT_PHYS_ADDR_PAD] = SEGMENT_NAME("phys-addr-padding"),
- [RTT_PHYS_ADDR] = SEGMENT_NAME("phys-addr"),
- [RTT_VIRT_ADDR_PAD] = SEGMENT_NAME("virt-addr-padding"),
- [RTT_VIRT_ADDR] = SEGMENT_NAME("virt-addr"),
- [RTT_RAW_CODE] = SEGMENT_NAME("raw-code"),
- [RTT_LABEL] = SEGMENT_NAME("label"),
- [RTT_INSTRUCTION] = SEGMENT_NAME("instruction"),
- [RTT_IMMEDIATE] = SEGMENT_NAME("immediate"),
- [RTT_REGISTER] = SEGMENT_NAME("register"),
- [RTT_PUNCT] = SEGMENT_NAME("punct"),
- [RTT_HOOK] = SEGMENT_NAME("hooks"),
- [RTT_SIGNS] = SEGMENT_NAME("signs"),
- [RTT_LTGT] = SEGMENT_NAME("ltgt"),
- [RTT_SECTION] = SEGMENT_NAME("section"),
- [RTT_SEGMENT] = SEGMENT_NAME("segment"),
- [RTT_STRING] = SEGMENT_NAME("string"),
- [RTT_VAR_NAME] = SEGMENT_NAME("var-name"),
- [RTT_KEY_WORD] = SEGMENT_NAME("keyword"),
- [RTT_ERROR] = SEGMENT_NAME("error"),
-
-};
-
-/* Compléments à Cairo */
-
-#define CAIRO_FONT_SLANT_COUNT 3
-#define CAIRO_FONT_WEIGHT_COUNT 2
-
-#define CAIRO_FONTS_COUNT (CAIRO_FONT_SLANT_COUNT * CAIRO_FONT_WEIGHT_COUNT)
-#define CAIRO_FONT_INDEX(s, w) ((s) + (w) * CAIRO_FONT_WEIGHT_COUNT)
-
-/* Fragment de caractères aux propriétés communes (instance) */
-struct _GBufferSegment
-{
- GObject parent; /* A laisser en premier */
-
- seg_content *content; /* Contenu, partagé ou non */
-
-};
-
-/* Fragment de caractères aux propriétés communes (classe) */
-struct _GBufferSegmentClass
-{
- GObjectClass parent; /* A laisser en premier */
-
- rendering_color_t selection_bg; /* Fond d'impression */
-
- cairo_t *font_ctxts[CAIRO_FONTS_COUNT]; /* Contextes de police */
- double x_advances[CAIRO_FONTS_COUNT]; /* Largeurs par caractère */
- rendering_pattern_t patterns[RTT_COUNT];/* Modèles d'impression */
-
- /* Signaux */
-
- void (* content_changed) (GBufferSegment *);
-
-};
-
-
-/* Procède à l'initialisation d'une classe de fragment de texte. */
-static void g_buffer_segment_class_init(GBufferSegmentClass *);
-
-/* Procède à l'initialisation d'un fragment de texte. */
-static void g_buffer_segment_init(GBufferSegment *);
-
-/* Supprime toutes les références externes. */
-static void g_buffer_segment_dispose(GBufferSegment *);
-
-/* Procède à la libération totale de la mémoire. */
-static void g_buffer_segment_finalize(GBufferSegment *);
-
-/* Met à jour le contenu d'un fragment de texte. */
-void g_buffer_segment_set_text(GBufferSegment *, rendering_pattern_t *, const char *, 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 */
-
-};
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* ISOLATION DE CONTENUS PARTAGEABLES */
-/* ---------------------------------------------------------------------------------- */
-
-
-/******************************************************************************
-* *
-* Paramètres : - *
-* *
-* Description : Initialise la table mémorisant les contenus pour segments. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-bool init_segment_content_hash_table(void)
-{
- _segcnt_htable = g_hash_table_new_full((GHashFunc)get_seg_content_hash,
- (GEqualFunc)is_seg_content_equal,
- free, NULL);
-
- return (_segcnt_htable != NULL);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : - *
-* *
-* Description : Organise la sortie de la table des contenus pour segments. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void exit_segment_content_hash_table(void)
-{
- assert(g_hash_table_size(_segcnt_htable) == 0);
-
- g_hash_table_unref(_segcnt_htable);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : content = contenu pour segment à consulter. *
-* *
-* Description : Fournit l'empreinte d'un contenu pour segments. *
-* *
-* Retour : Empreinte de lu contenu représenté. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static guint get_seg_content_hash(const seg_content *content)
-{
- return content->hash;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : content = premier contenu pour segment à analyser. *
-* other = second contenu pour segment à analyser. *
-* *
-* Description : Détermine si deux contenus pour segments sont identiques. *
-* *
-* Retour : Bilan de la comparaison. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static bool is_seg_content_equal(const seg_content *content, const seg_content *other)
-{
- bool result; /* Résultat à retourner */
-
- result = (content->pattern == other->pattern);
-
- result &= (cmp_fnv_64a(content->hash, other->hash) == 0);
-
- result &= (strcmp(content->text, other->text) == 0);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : content = premier contenu pour segment à analyser. *
-* other = second contenu pour segment à analyser. *
-* *
-* Description : Détermine si deux contenus pour segments sont identiques. *
-* *
-* Retour : Bilan de la comparaison. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static seg_content *get_shared_content(const seg_content *content)
-{
- seg_content *result; /* Contenu partagé à renvoyer */
- gboolean found; /* Le contenu existe déjà ? */
- size_t allocated; /* Besoin complet en mémoire */
-#ifndef NDEBUG
- gboolean created; /* Validation de mise en place */
-#endif
-
- /**
- * On considère qu'il n'y a pas besoin de mutex ici, puisque toutes les
- * opérations se réalisent à priori dans le seul thread principal pour l'affichage.
- */
-
- found = g_hash_table_lookup_extended(_segcnt_htable, content, (gpointer *)&result, NULL);
-
- if (!found)
- {
- allocated = sizeof(seg_content) + strlen(content->text) + 1;
-
- result = (seg_content *)malloc(allocated);
-
- memcpy(result, content, allocated);
-
- result->ref_count = 1;
-
-#ifndef NDEBUG
- created = g_hash_table_insert(_segcnt_htable, result, result);
- assert(created);
-#else
- g_hash_table_insert(_segcnt_htable, result, result);
-#endif
-
- }
-
- else
- {
- assert(result->ref_count < UINT_MAX);
-
- result->ref_count++;
-
- }
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : content = contenu pour segments à délaisser. *
-* *
-* Description : Abandonne un contenu pour segments. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void release_shared_content(seg_content *content)
-{
-#ifndef NDEBUG
- gboolean deleted; /* Validation de suppression */
-#endif
-
- /**
- * On considère qu'il n'y a pas besoin de mutex ici, puisque toutes les
- * opérations se réalisent à priori dans le seul thread principal pour l'affichage.
- */
-
- if (--content->ref_count == 0)
- {
-#ifndef NDEBUG
- deleted = g_hash_table_remove(_segcnt_htable, content);
- assert(deleted);
-#else
- g_hash_table_remove(_segcnt_htable, content);
-#endif
- }
-
-}
-
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* 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);
-
-
-/******************************************************************************
-* *
-* Paramètres : class = classe de composant GTK à initialiser. *
-* *
-* Description : Procède à l'initialisation d'une classe de fragment de texte.*
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_buffer_segment_class_init(GBufferSegmentClass *class)
-{
- GObjectClass *object; /* Autre version de la classe */
- GtkStyleContext *context; /* Contexte pour les styles */
- GtkWidgetPath *path; /* Chemin d'accès aux thèmes */
- gchar *filename; /* Accès à une image 1x1 */
- cairo_font_slant_t s; /* Boucle de parcours #1 */
- cairo_font_weight_t w; /* Boucle de parcours #2 */
- cairo_t **cr; /* Contexte à créer */
- cairo_surface_t *surface; /* Surface pour dessin Cairo */
- cairo_text_extents_t extents; /* Couverture des caractères */
- RenderingTagType i; /* Boucle de parcours */
-
- object = G_OBJECT_CLASS(class);
-
- object->dispose = (GObjectFinalizeFunc/* ! */)g_buffer_segment_dispose;
- object->finalize = (GObjectFinalizeFunc)g_buffer_segment_finalize;
-
- /* Création d'un contexte d'accès */
-
- path = gtk_widget_path_new();
- gtk_widget_path_append_type(path, G_TYPE_OBJECT);
-
- context = gtk_style_context_new();
- gtk_style_context_set_path(context, path);
- gtk_style_context_set_screen(context, gdk_screen_get_default());
-
- /* Contextes pour les mesures initiales */
-
- filename = find_pixmap_file("nil.png");
- if (filename == NULL) abort();
-
- for (s = CAIRO_FONT_SLANT_NORMAL; s < CAIRO_FONT_SLANT_COUNT; s++)
- for (w = CAIRO_FONT_WEIGHT_NORMAL; w < CAIRO_FONT_WEIGHT_COUNT; w++)
- {
- cr = &class->font_ctxts[CAIRO_FONT_INDEX(s, w)];
-
- surface = cairo_image_surface_create_from_png(filename);
- *cr = cairo_create(surface);
- cairo_surface_destroy(surface);
-
- cairo_select_font_face(*cr, "mono", s, w);
- cairo_set_font_size(*cr, 13);
-
- cairo_text_extents(*cr, "A", &extents);
- class->x_advances[CAIRO_FONT_INDEX(s, w)] = extents.x_advance;
-
- }
-
- g_free(filename);
-
- /* Fond d'impression */
-
- class->selection_bg.has_color = true;
- class->selection_bg.color.red = 0.5;
- class->selection_bg.color.green = 0.5;
- class->selection_bg.color.blue = 0.5;
- class->selection_bg.color.alpha = 1.0;
-
- /* Chargement des définitions utiles */
-
- void define_rendering_pattern(GtkStyleContext *ctx, const char *name, rendering_pattern_t *pattern)
- {
- GdkRGBA *tmp_color; /* Description d'une couleur */
- PangoFontDescription *font_desc; /* Description d'une police */
-
- gtk_style_context_save(ctx);
-
- gtk_style_context_add_class(context, name);
-
- gtk_style_context_get(ctx, GTK_STATE_NORMAL, GTK_STYLE_PROPERTY_COLOR, &tmp_color, NULL);
-
- pattern->foreground.has_color = true;
- pattern->foreground.color = *tmp_color;
-
- pattern->inverted.has_color = true;
- pattern->inverted.color.red = 1.0 - tmp_color->red;
- pattern->inverted.color.green = 1.0 - tmp_color->green;
- pattern->inverted.color.blue = 1.0 - tmp_color->blue;
- pattern->inverted.color.alpha = tmp_color->alpha;
-
- gdk_rgba_free(tmp_color);
-
- gtk_style_context_get(context, GTK_STATE_FLAG_NORMAL, GTK_STYLE_PROPERTY_FONT, &font_desc, NULL);
-
- switch (pango_font_description_get_style(font_desc))
- {
- case PANGO_STYLE_NORMAL:
- pattern->slant = CAIRO_FONT_SLANT_NORMAL;
- break;
- case PANGO_STYLE_ITALIC:
- pattern->slant = CAIRO_FONT_SLANT_ITALIC;
- break;
- case PANGO_STYLE_OBLIQUE:
- pattern->slant = CAIRO_FONT_SLANT_OBLIQUE;
- break;
- }
-
- switch (pango_font_description_get_weight(font_desc))
- {
- case PANGO_WEIGHT_THIN:
- case PANGO_WEIGHT_ULTRALIGHT:
- case PANGO_WEIGHT_LIGHT:
- case PANGO_WEIGHT_SEMILIGHT:
- case PANGO_WEIGHT_BOOK:
- case PANGO_WEIGHT_NORMAL:
- case PANGO_WEIGHT_MEDIUM:
- pattern->weight = CAIRO_FONT_WEIGHT_NORMAL;
- break;
- case PANGO_WEIGHT_SEMIBOLD:
- case PANGO_WEIGHT_BOLD:
- case PANGO_WEIGHT_ULTRABOLD:
- case PANGO_WEIGHT_HEAVY:
- case PANGO_WEIGHT_ULTRAHEAVY:
- pattern->weight = CAIRO_FONT_WEIGHT_BOLD;
- break;
- }
-
- pango_font_description_free(font_desc);
-
- gtk_style_context_restore(context);
-
- }
-
- for (i = 0; i < RTT_COUNT; i++)
- define_rendering_pattern(context, _segment_names[i], &class->patterns[i]);
-
- /* Nettoyages finaux... */
-
- gtk_widget_path_free(path);
- g_object_unref(context);
-
- /* Signaux */
-
- g_signal_new("content-changed",
- G_TYPE_BUFFER_SEGMENT,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET(GBufferSegmentClass, content_changed),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : segment = composant GTK à initialiser. *
-* *
-* Description : Procède à l'initialisation d'un fragment de texte. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_buffer_segment_init(GBufferSegment *segment)
-{
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : segment = instance d'objet GLib à traiter. *
-* *
-* Description : Supprime toutes les références externes. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_buffer_segment_dispose(GBufferSegment *segment)
-{
- release_shared_content(segment->content);
-
- G_OBJECT_CLASS(g_buffer_segment_parent_class)->dispose(G_OBJECT(segment));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : segment = instance d'objet GLib à traiter. *
-* *
-* Description : Procède à la libération totale de la mémoire. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_buffer_segment_finalize(GBufferSegment *segment)
-{
- G_OBJECT_CLASS(g_buffer_segment_parent_class)->finalize(G_OBJECT(segment));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : type = propriétés de la zone de texte. *
-* text = chaîne de caractères à traiter. *
-* length = quantité de ces caractères. *
-* *
-* Description : Crée un nouveau fragment de texte avec des propriétés. *
-* *
-* Retour : Composant GTK créé. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GBufferSegment *g_buffer_segment_new(RenderingTagType type, const char *text, size_t length)
-{
- GBufferSegment *result; /* Composant à retourner */
- GBufferSegmentClass *class; /* Stockage de styles préparés */
-
- result = g_object_new(G_TYPE_BUFFER_SEGMENT, NULL);
-
- class = G_BUFFER_SEGMENT_GET_CLASS(result);
-
- g_buffer_segment_set_text(result, &class->patterns[type], text, length);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : segment = fragment de texte à mettre à jour. *
-* pattern = paramètres d'impression du texte. *
-* text = chaîne de caractères à traiter. *
-* length = quantité de ces caractères. *
-* *
-* Description : Met à jour le contenu d'un fragment de texte. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_buffer_segment_set_text(GBufferSegment *segment, rendering_pattern_t *pattern, const char *text, size_t length)
-{
- char atmp[sizeof(seg_content) + 128]; /* Allocation static facile */
- seg_content *content; /* Contenu à mettre en place ? */
-
- if (length < (sizeof(atmp) - sizeof(seg_content)))
- content = (seg_content *)atmp;
- else
- content = (seg_content *)malloc(sizeof(seg_content) + length + 1);
-
- content->pattern = pattern;
-
- content->hash = fnv_64a_hash(text);
-
- memcpy(content->text, text, length);
- content->text[length] = '\0';
-
- segment->content = get_shared_content(content);
-
- if (content != (seg_content *)atmp)
- free(content);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : segment = fragment de texte à mettre à jour. *
-* text = chaîne de caractères à traiter. *
-* length = quantité de ces caractères. *
-* *
-* Description : Met à jour le contenu d'un fragment de texte. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_buffer_segment_update_text(GBufferSegment *segment, const char *text, size_t length)
-{
- rendering_pattern_t *pattern; /* Conservation des paramètres */
-
- /* Destruction */
-
- pattern = segment->content->pattern;
-
- release_shared_content(segment->content);
-
- /* Création */
-
- g_buffer_segment_set_text(segment, pattern, text, length);
-
- g_signal_emit_by_name(segment, "content-changed");
-
-}
-
-
-/******************************************************************************
-* *
-* 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 = is_seg_content_equal(segment->content, ref->content);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : segment = fragment de texte à consulter. *
-* markup = indique si le texte doit être décoré ou non. *
-* *
-* Description : Fournit le texte brut conservé dans le segment. *
-* *
-* Retour : Texte conservé en interne. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-char *g_buffer_segment_get_text(const GBufferSegment *segment, bool markup)
-{
- char *result; /* Description à renvoyer */
- const seg_content *content; /* Accès au contenu */
- char color[7]; /* Couleur hexadécimale */
- char *valid;
-
- content = segment->content;
-
- /* Résolution du cas simple */
- if (!markup)
- return strdup(content->text);
-
- result = strdup("<span ");
-
- /* Couleur */
-
- result = stradd(result, "foreground=\"#");
-
- snprintf(color, sizeof(color), "%02hhx%02hhx%02hhx",
- (unsigned char)(content->pattern->foreground.color.red * 255),
- (unsigned char)(content->pattern->foreground.color.green * 255),
- (unsigned char)(content->pattern->foreground.color.blue * 255));
-
- result = stradd(result, color);
-
- result = stradd(result, "\"");
-
- /* Style */
-
- result = stradd(result, "style=\"");
-
- switch (content->pattern->slant)
- {
- case CAIRO_FONT_SLANT_NORMAL:
- result = stradd(result, "normal");
- break;
-
- case CAIRO_FONT_SLANT_ITALIC:
- result = stradd(result, "italic");
- break;
-
- case CAIRO_FONT_SLANT_OBLIQUE:
- result = stradd(result, "oblique");
- break;
-
- }
-
- result = stradd(result, "\"");
-
- /* Epaisseur */
-
- result = stradd(result, "weight=\"");
-
- switch (content->pattern->weight)
- {
- case CAIRO_FONT_WEIGHT_NORMAL:
- result = stradd(result, "normal");
- break;
-
- case CAIRO_FONT_WEIGHT_BOLD:
- result = stradd(result, "bold");
- break;
-
- }
-
- result = stradd(result, "\"");
-
- /* Conclusion */
-
- result = stradd(result, ">");
-
- valid = strdup(content->text);
- valid = strrpl(valid, "<", "&lt;");
- valid = strrpl(valid, "&", "&amp;");
-
- result = stradd(result, valid);
-
- free(valid);
-
- result = stradd(result, "</span>");
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : segment = fragment de texte à consulter. *
-* *
-* Description : Fournit la quantité de pixels requise pour l'impression. *
-* *
-* Retour : Largeur requise par la colonne, en pixel. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-gint g_buffer_segment_get_width(const GBufferSegment *segment)
-{
- gint result; /* Largeur à retourner */
- GBufferSegmentClass *class; /* Classe associée à l'instance*/
- const seg_content *content; /* Accès au contenu */
- cairo_font_slant_t slant; /* Style d'impression */
- cairo_font_weight_t weight; /* Poids de la police */
-
- class = G_BUFFER_SEGMENT_GET_CLASS(segment);
-
- content = segment->content;
-
- slant = content->pattern->slant;
- weight = content->pattern->weight;
-
- result = class->x_advances[CAIRO_FONT_INDEX(slant, weight)] * strlen(content->text);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : segment = fragment de texte à consulter. *
-* x = position horizontale au niveau du segment. *
-* *
-* Description : Fournit la position idéale pour un marqueur. *
-* *
-* Retour : Position dans le segment donné. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-gint g_buffer_segment_get_caret_position(const GBufferSegment *segment, gint x)
-{
- gint result; /* Position à retourner */
- gint width; /* Largeur du segment */
- gint char_width; /* Largeur de police fixe */
-
- width = g_buffer_segment_get_width(segment);
-
- if (x <= 0)
- result = 0;
-
- else if (x >= width)
- result = width;
-
- else
- {
- char_width = width / strlen(segment->content->text);
-
- result = (x / char_width) * char_width;
- if ((x % char_width) > (char_width / 2))
- result += char_width;
-
- }
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : segment = fragment de texte à manipuler. *
-* x = position du curseur à faire évoluer. [OUT] *
-* ctrl = indique la demande d'un parcours rapide. *
-* dir = direction du parcours. *
-* *
-* Description : Déplace le curseur au sein d'un segment de tampon. *
-* *
-* Retour : true si un déplacement a été effectué, false sinon. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-bool g_buffer_segment_move_caret(const GBufferSegment *segment, gint *x, bool ctrl, GdkScrollDirection dir)
-{
- bool result; /* Bilan d'opération à renvoyer*/
- gint width; /* Largeur du segment */
- gint char_width; /* Largeur de police fixe */
-
- result = false;
-
- width = g_buffer_segment_get_width(segment);
- char_width = width / strlen(segment->content->text);
-
- if (dir == GDK_SCROLL_LEFT)
- {
- printf(">>>>> left ::: x=%d width=%d char=%d\n", *x, width, char_width);
-
- if (*x > width) *x = width + char_width;
-
- if (*x == 0) goto gbsmc_done;
-
- if (ctrl) *x = 0;
- else *x = MAX(0, *x - char_width);
-
- result = true;
-
- }
-
- else if (dir == GDK_SCROLL_RIGHT)
- {
-
- printf(">>>>> right ::: x=%d width=%d char=%d\n", *x, width, char_width);
-
- if (*x == width) goto gbsmc_done;
-
- if (ctrl) *x = width;
- else *x = MIN(width, *x + char_width);
-
- result = true;
-
- }
-
- gbsmc_done:
-
- printf(">>>>> result ::: %d\n", result);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : segment = fragment de texte à manipuler. *
-* cr = 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 : Imprime le fragment de texte représenté. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_buffer_segment_draw(GBufferSegment *segment, cairo_t *cr, gint *x, gint y, const segcnt_list *list)
-{
- bool selected; /* Marquer une sélection ? */
- gint width; /* Largeur du segment */
- GBufferSegmentClass *class; /* Accès aux infos globales */
- cairo_operator_t old; /* Sauvegarde avant changement */
- const seg_content *content; /* Accès au contenu */
- const rendering_color_t *used_fg; /* Couleur d'impression utile */
-
- selected = selection_list_has_segment_content(list, segment);
-
- width = g_buffer_segment_get_width(segment);
-
- /* Fond du texte */
- if (selected)
- {
- class = G_BUFFER_SEGMENT_GET_CLASS(segment);
-
- cairo_set_source_rgba(cr,
- class->selection_bg.color.red,
- class->selection_bg.color.green,
- class->selection_bg.color.blue,
- class->selection_bg.color.alpha);
-
- cairo_rectangle(cr, *x, y, width, 17);
-
- old = cairo_get_operator(cr);
- cairo_set_operator(cr, CAIRO_OPERATOR_DIFFERENCE);
- cairo_fill(cr);
- cairo_set_operator(cr, old);
-
- }
-
- /* Couleur d'impression */
-
- content = segment->content;
-
- if (selected)
- used_fg = &content->pattern->inverted;
- else
- used_fg = &content->pattern->foreground;
-
- if (used_fg->has_color)
- cairo_set_source_rgba(cr,
- used_fg->color.red,
- used_fg->color.green,
- used_fg->color.blue,
- used_fg->color.alpha);
- else
- cairo_set_source_rgb(cr, 0, 0, 0);
-
- /* Impression du texte */
-
- cairo_select_font_face(cr, "mono", content->pattern->slant, content->pattern->weight);
- cairo_set_font_size(cr, 13);
-
- cairo_move_to(cr, *x, y + 17 - 3); /* 3 = font extents.descent */
-
- cairo_show_text(cr, content->text);
-
- *x += width;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : ctx = éléments à disposition pour l'exportation. *
-* type = type d'exportation attendue. *
-* *
-* Description : Exporte tous les styles utilisés par des segments. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_buffer_segment_export_style(buffer_export_context *ctx, BufferExportType type)
-{
- GBufferSegment *dummy; /* Segment servant de sujet */
- GBufferSegmentClass *class; /* Classe des segments */
- size_t i; /* Boucle de parcours */
- const rendering_pattern_t *pattern; /* Modèle à transcrire */
-
- dummy = g_object_new(G_TYPE_BUFFER_SEGMENT, NULL);
- class = G_BUFFER_SEGMENT_GET_CLASS(dummy);
-
- for (i = 0; i < RTT_COUNT; i++)
- {
- pattern = &class->patterns[i];
-
- switch (type)
- {
- case BET_HTML:
-
- dprintf(ctx->fd, ".%s {\n", _segment_names[i]);
-
- if (pattern->foreground.has_color)
- dprintf(ctx->fd, "\tcolor: #%02hhx%02hhx%02hhx;\n",
- (unsigned char)(pattern->foreground.color.red * 255),
- (unsigned char)(pattern->foreground.color.green * 255),
- (unsigned char)(pattern->foreground.color.blue * 255));
-
- switch (pattern->slant)
- {
- case CAIRO_FONT_SLANT_ITALIC:
- dprintf(ctx->fd, "\tfont-style: italic;\n");
- break;
- case CAIRO_FONT_SLANT_OBLIQUE:
- dprintf(ctx->fd, "\tfont-style: oblique;\n");
- break;
- default:
- dprintf(ctx->fd, "\tfont-style: normal;\n");
- break;
- }
-
- switch (pattern->weight)
- {
- case CAIRO_FONT_WEIGHT_BOLD:
- dprintf(ctx->fd, "\tfont-weight: bold;\n");
- break;
- default:
- dprintf(ctx->fd, "\tfont-weight: normal;\n");
- break;
- }
-
- dprintf(ctx->fd, "}\n");
-
- break;
-
- default:
- break;
-
- }
-
- }
-
- g_object_unref(G_OBJECT(dummy));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : segment = fragment de texte à manipuler. *
-* ctx = éléments à disposition pour l'exportation. *
-* type = type d'exportation attendue. *
-* *
-* Description : Exporte le fragment de texte représenté. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_buffer_segment_export(const GBufferSegment *segment, buffer_export_context *ctx, BufferExportType type)
-{
- const seg_content *content; /* Accès au contenu */
- GBufferSegmentClass *class; /* Classe des segments */
- size_t index; /* Indice du modèle de rendu */
-
- content = segment->content;
-
- switch (type)
- {
- case BET_HTML:
- class = G_BUFFER_SEGMENT_GET_CLASS(segment);
- index = (content->pattern - class->patterns);
- dprintf(ctx->fd, "<SPAN class=\"%s\">", _segment_names[index]);
- break;
- default:
- break;
- }
-
- dprintf(ctx->fd, "%s", content->text);
-
- switch (type)
- {
- case BET_HTML:
- dprintf(ctx->fd, "</SPAN>");
- break;
- default:
- break;
- }
-
-}
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* 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 */
- const seg_content *content; /* Accès au contenu */
- size_t i; /* Boucle de parcours */
-
- static const char white_list[] = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
-
- result = false;
-
- content = segment->content;
-
- for (i = 0; i < (sizeof(white_list) - 1) && !result; i++)
- result = (strchr(content->text, white_list[i]) != NULL);
-
- if (result)
- {
- list->hashes = (fnv64_t *)realloc(list->hashes, ++list->count * sizeof(fnv64_t));
-
- list->hashes[list->count - 1] = content->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->content->hash) == 0);
-
- return result;
-
-}