diff options
Diffstat (limited to 'src/glibext/gbuffersegment.c')
-rw-r--r-- | src/glibext/gbuffersegment.c | 1333 |
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, "<", "<"); - valid = strrpl(valid, "&", "&"); - - 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; - -} |