diff options
Diffstat (limited to 'src/glibext')
-rw-r--r-- | src/glibext/Makefile.am | 26 | ||||
-rw-r--r-- | src/glibext/gresource.xml | 6 | ||||
-rw-r--r-- | src/glibext/linetoken.h | 48 | ||||
-rw-r--r-- | src/glibext/tokenstyle-int.h | 94 | ||||
-rw-r--r-- | src/glibext/tokenstyle.c | 769 | ||||
-rw-r--r-- | src/glibext/tokenstyle.css | 26 | ||||
-rw-r--r-- | src/glibext/tokenstyle.h | 90 |
7 files changed, 900 insertions, 159 deletions
diff --git a/src/glibext/Makefile.am b/src/glibext/Makefile.am index ac8668c..336c121 100644 --- a/src/glibext/Makefile.am +++ b/src/glibext/Makefile.am @@ -1,7 +1,7 @@ -BUILT_SOURCES = chrysamarshal.h chrysamarshal.c +BUILT_SOURCES = chrysamarshal.h chrysamarshal.c resources.h resources.c -noinst_LTLIBRARIES = libglibext4.la # libglibext.la +noinst_LTLIBRARIES = libglibext4.la libglibextui.la # libglibext.la libglibext_la_SOURCES = \ buffercache-int.h \ @@ -58,6 +58,17 @@ libglibext4_la_SOURCES = \ libglibext4_la_CFLAGS = $(TOOLKIT_CFLAGS) +RES_FILES = \ + tokenstyle.css + +libglibextui_la_SOURCES = \ + tokenstyle-int.h \ + tokenstyle.h tokenstyle.c \ + resources.h resources.c + +libglibextui_la_CFLAGS = $(LIBGTK4_CFLAGS) + + devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%) dev_HEADERS = $(libglibext_la_SOURCES:%c=) @@ -72,3 +83,14 @@ chrysamarshal.h: chrysamarshal.list chrysamarshal.c: chrysamarshal.list echo "#include <$(subst .c,.h,$@)>" > $@ glib-genmarshal --body $< >> $@ + +resources.c: gresource.xml $(RES_FILES) + glib-compile-resources --target=$@ --sourcedir=$(srcdir) --generate-source --c-name glibext gresource.xml + +resources.h: gresource.xml + glib-compile-resources --target=$@ --sourcedir=$(srcdir) --generate-header --c-name glibext gresource.xml + + +CLEANFILES = resources.h resources.c + +EXTRA_DIST = gresource.xml $(RES_FILES) diff --git a/src/glibext/gresource.xml b/src/glibext/gresource.xml new file mode 100644 index 0000000..0a88e4c --- /dev/null +++ b/src/glibext/gresource.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8"?> +<gresources> + <gresource prefix="/re/chrysalide/framework/glibext"> + <file compressed="true">tokenstyle.css</file> + </gresource> +</gresources> diff --git a/src/glibext/linetoken.h b/src/glibext/linetoken.h index 4859fbb..4e06f8c 100644 --- a/src/glibext/linetoken.h +++ b/src/glibext/linetoken.h @@ -72,54 +72,6 @@ void exit_segment_content_hash_table(void); /* -------------------- NATURE DE BASE POUR UN FRAGMENT DE TEXTE -------------------- */ -/* Types de partie de rendu */ -typedef enum _RenderingTagType -{ - RTT_NONE, /* Espace ou tabulation */ - - RTT_RAW, /* Contenu brut */ - RTT_RAW_FULL, /* Contenu brut et complet */ - RTT_RAW_NULL, /* Contenu brut et nul */ - RTT_PRINTABLE, /* Caractère imprimable */ - RTT_NOT_PRINTABLE, /* Caractère non imprimable */ - - RTT_COMMENT, /* Commentaire */ - RTT_INDICATION, /* Aide à la lecture */ - - RTT_PHYS_ADDR_PAD, /* Position physique (début) */ - RTT_PHYS_ADDR, /* Position physique */ - RTT_VIRT_ADDR_PAD, /* Adresse virtuelle (début) */ - RTT_VIRT_ADDR, /* Adresse virtuelle */ - RTT_RAW_CODE, /* Code binaire brut */ - RTT_RAW_CODE_NULL, /* Code binaire brut et nul */ - - RTT_LABEL, /* Etiquette sur une adresse */ - - RTT_INSTRUCTION, /* Code binaire brut */ - - RTT_IMMEDIATE, /* Valeur immédiate */ - - RTT_REGISTER, /* Registre */ - - RTT_PUNCT, /* Signes de ponctuation */ - RTT_HOOK, /* Crochets '[' et ']' */ - RTT_SIGNS, /* Signes '+', '-' et '*' */ - RTT_LTGT, /* Caractères '<' et '>' */ - - RTT_SECTION, /* Identifiant de section */ - RTT_SEGMENT, /* Indication de segment */ - RTT_STRING, /* Chaîne de caractères avec " */ - - RTT_VAR_NAME, /* Nom de variable */ - - RTT_KEY_WORD, /* Mot clef de langage */ - - RTT_ERROR, /* Erreur "interne" */ - - RTT_COUNT - -} RenderingTagType; - /* Crée un nouveau fragment de texte avec des propriétés. */ line_segment *get_new_line_segment(RenderingTagType, const char *, size_t); diff --git a/src/glibext/tokenstyle-int.h b/src/glibext/tokenstyle-int.h new file mode 100644 index 0000000..9cf4df2 --- /dev/null +++ b/src/glibext/tokenstyle-int.h @@ -0,0 +1,94 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * tokenstyle-int.h - définitions internes propres à la centralisation des paramètres de rendu de bribes textuelles + * + * Copyright (C) 2024 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide 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. + * + * Chrysalide 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _GLIBEXT_TOKENSTYLE_INT_H +#define _GLIBEXT_TOKENSTYLE_INT_H + + +#include "tokenstyle.h" + + +#include <stdbool.h> + + + +/* Valeurs principales par défaut */ + +#define DEFAULT_FONT_FAMILY "cairo:monospace" +#define DEFAULT_FONT_SIZE 14 + + +/* Condensé de propriétés de 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) + + +/* Restitution d'un élément de thème pour bribe de texte */ +typedef struct _rendering_property_t +{ + GdkRGBA foreground; /* Couleur d'impression */ + GdkRGBA 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_property_t; + + +/* Centralisation de paramètres de rendu (instance) */ +struct _GTokenStyle +{ + GObject parent; /* A laisser en premier */ + + GtkWidget *target; /* Composant ciblé */ + + bool loaded; /* Validité des paramètres */ + + char *font_family; /* Désignation de la police */ + int font_size; /* Taille de police choisie */ + cairo_font_extents_t font_extents; /* Dimensions de la police */ + + double x_advances[CAIRO_FONTS_COUNT]; /* Largeurs par caractère */ + + rendering_property_t properties[TRT_COUNT]; /* Modèles d'impression */ + +}; + +/* Centralisation de paramètres de rendu (classe) */ +struct _GTokenStyleClass +{ + GObjectClass parent; /* A laisser en premier */ + +}; + + +/* Met en place un nouveau gestionnaire de rendu des lignes. */ +bool g_token_style_create(GTokenStyle *, GtkWidget *); + + + +#endif /* _GLIBEXT_TOKENSTYLE_INT_H */ diff --git a/src/glibext/tokenstyle.c b/src/glibext/tokenstyle.c index 8badf21..e797856 100644 --- a/src/glibext/tokenstyle.c +++ b/src/glibext/tokenstyle.c @@ -1,8 +1,8 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * rendering.h - prototypes pour la transformation de paramètres du thème GTK courant + * tokenstyle.c - centralisation des paramètres de rendu de bribes textuelles * - * Copyright (C) 2018 Cyrille Bagard + * Copyright (C) 2018-2024 Cyrille Bagard * * This file is part of Chrysalide. * @@ -22,25 +22,104 @@ */ -#include "rendering.h" +#include "tokenstyle.h" -#include <malloc.h> -#include <stdio.h> #include <string.h> -#include <gtk/gtk.h> +#include "tokenstyle-int.h" +#include "../core/logs.h" #include "../common/extstr.h" +/* -------------------------- DEFINITION D'UN NOUVEL OBJET -------------------------- */ + + +/* Procède à l'initialisation des gestionnaires de paramètres. */ +static void g_token_style_class_init(GTokenStyleClass *); + +/* Procède à l'initialisation d'un gestionnaire de paramètres. */ +static void g_token_style_init(GTokenStyle *); + +/* Supprime toutes les références externes. */ +static void g_token_style_dispose(GTokenStyle *); + +/* Procède à la libération totale de la mémoire. */ +static void g_token_style_finalize(GTokenStyle *); + + + +/* ------------------------ RECEPTACLES DE SIGNAUX CONNECTES ------------------------ */ + + +/* Nom des éléments CSS */ + +#define SEGMENT_NAME(s) "token-" s + +static const char *_token_names[TRT_COUNT] = { + + [TRT_NONE] = SEGMENT_NAME("none"), + [TRT_RAW] = SEGMENT_NAME("raw"), + [TRT_RAW_FULL] = SEGMENT_NAME("raw-full"), + [TRT_RAW_NULL] = SEGMENT_NAME("raw-null"), + [TRT_PRINTABLE] = SEGMENT_NAME("printable"), + [TRT_NOT_PRINTABLE] = SEGMENT_NAME("not-printable"), + [TRT_COMMENT] = SEGMENT_NAME("comment"), + [TRT_INDICATION] = SEGMENT_NAME("indication"), + [TRT_PHYS_ADDR_PAD] = SEGMENT_NAME("phys-addr-padding"), + [TRT_PHYS_ADDR] = SEGMENT_NAME("phys-addr"), + [TRT_VIRT_ADDR_PAD] = SEGMENT_NAME("virt-addr-padding"), + [TRT_VIRT_ADDR] = SEGMENT_NAME("virt-addr"), + [TRT_RAW_CODE] = SEGMENT_NAME("raw-code"), + [TRT_RAW_CODE_NULL] = SEGMENT_NAME("raw-code-null"), + [TRT_LABEL] = SEGMENT_NAME("label"), + [TRT_INSTRUCTION] = SEGMENT_NAME("instruction"), + [TRT_IMMEDIATE] = SEGMENT_NAME("immediate"), + [TRT_REGISTER] = SEGMENT_NAME("register"), + [TRT_PUNCT] = SEGMENT_NAME("punct"), + [TRT_HOOK] = SEGMENT_NAME("hooks"), + [TRT_SIGNS] = SEGMENT_NAME("signs"), + [TRT_LTGT] = SEGMENT_NAME("ltgt"), + [TRT_SECTION] = SEGMENT_NAME("section"), + [TRT_SEGMENT] = SEGMENT_NAME("segment"), + [TRT_STRING] = SEGMENT_NAME("string"), + [TRT_VAR_NAME] = SEGMENT_NAME("var-name"), + [TRT_KEY_WORD] = SEGMENT_NAME("keyword"), + [TRT_ERROR] = SEGMENT_NAME("error"), + +}; + + +/* Réagit à un changement de racine pour le composant suivi. */ +static void on_root_change(GtkWidget *, GParamSpec *, GTokenStyle *); + +/* Charge toutes les indications liées aux polices. */ +static bool g_token_style_retrieve_font(GTokenStyle *); + +/* Détermine les tailles d'impression possibles pour les rendus. */ +static bool g_token_style_retrieve_advances(GTokenStyle *); + +/* Charge les définitions complémentaires spécifiques. */ +static bool g_token_style_retrieve_rendering_properties(GTokenStyle *, TokenRenderingTag ); + + + +/* ---------------------------------------------------------------------------------- */ +/* DEFINITION D'UN NOUVEL OBJET */ +/* ---------------------------------------------------------------------------------- */ + + +/* Détermine le type du composant d'affichage générique. */ +G_DEFINE_TYPE(GTokenStyle, g_token_style, G_TYPE_OBJECT); + + /****************************************************************************** * * -* Paramètres : name = désignation d'un élément dans une feuille de style.* -* pattern = paramètres restitués en interne. |OUT] * +* Paramètres : class = classe des objets à initialiser. * * * -* Description : Récupère les informations de rendus d'un élément de thème. * +* Description : Procède à l'initialisation des gestionnaires de paramètres. * * * * Retour : - * * * @@ -48,84 +127,267 @@ * * ******************************************************************************/ -void load_rendering_pattern(const char *name, rendering_pattern_t *pattern) +static void g_token_style_class_init(GTokenStyleClass *class) { - GtkStyleContext *context; /* Contexte pour les styles */ - GtkWidgetPath *path; /* Chemin d'accès aux thèmes */ - GdkRGBA *tmp_color; /* Description d'une couleur */ - PangoFontDescription *font_desc; /* Description d'une police */ + GObjectClass *object; /* Plus haut niveau équivalent */ - /* Création d'un contexte d'accès */ + object = G_OBJECT_CLASS(class); - path = gtk_widget_path_new(); - gtk_widget_path_append_type(path, G_TYPE_OBJECT); + object->dispose = (GObjectFinalizeFunc/* ! */)g_token_style_dispose; + object->finalize = (GObjectFinalizeFunc)g_token_style_finalize; - context = gtk_style_context_new(); - gtk_style_context_set_path(context, path); - gtk_style_context_set_screen(context, gdk_screen_get_default()); +} - gtk_style_context_add_class(context, name); - gtk_style_context_get(context, GTK_STATE_FLAG_NORMAL, GTK_STYLE_PROPERTY_COLOR, &tmp_color, NULL); +/****************************************************************************** +* * +* Paramètres : style = centralisation de paramètres de rendu à initialiser. * +* * +* Description : Procède à l'initialisation d'un gestionnaire de paramètres. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ - pattern->foreground.has_color = true; - pattern->foreground.color = *tmp_color; +static void g_token_style_init(GTokenStyle *style) +{ + style->target = NULL; - 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; + style->loaded = false; - gdk_rgba_free(tmp_color); + style->font_family = NULL; + style->font_size = 0; - 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)) +/****************************************************************************** +* * +* Paramètres : style = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_token_style_dispose(GTokenStyle *style) +{ + g_clear_object(&style->target); + + G_OBJECT_CLASS(g_token_style_parent_class)->dispose(G_OBJECT(style)); + +} + + +/****************************************************************************** +* * +* Paramètres : style = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_token_style_finalize(GTokenStyle *style) +{ + if (style->font_family != NULL) + free(style->font_family); + + G_OBJECT_CLASS(g_token_style_parent_class)->finalize(G_OBJECT(style)); + +} + + +/****************************************************************************** +* * +* Paramètres : target = composant GTK à dédier au futur gestionnaire. * +* * +* Description : Crée un gestionnaire de style pour le rendu des lignes. * +* * +* Retour : Centralisateur mis en place pour un composant GTK donné. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GTokenStyle *g_token_style_new(GtkWidget *target) +{ + GTokenStyle *result; /* Nouvelle instance à renvoyer*/ + + result = g_object_new(G_TYPE_TOKEN_STYLE, NULL); + + if (!g_token_style_create(result, target)) + g_clear_object(&result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : style = gestionnaire à initialiser. * +* target = composant GTK à dédier au gestionnaire préparé. * +* * +* Description : Met en place un nouveau gestionnaire de rendu des lignes. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_token_style_create(GTokenStyle *style, GtkWidget *target) +{ + bool result; /* Bilan à retourner */ + + result = true; + + style->target = target; + ref_object(target); + + /** + * Si le composant est déjà affiché, l'actualisation des paramètres est + * forcée ! Dans le cas contraire, la surveillance des changements + * déclenchera l'opération. + */ + if (gtk_widget_get_root(target) != NULL) + on_root_change(target, NULL, style); + + g_signal_connect(target, "notify::root", G_CALLBACK(on_root_change), style); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : style = gestionnaire de paramètres de rendu à consulter. * +* tag = type de rendu sollicité. * +* length = nombre de caractères à mesurer. * +* * +* Description : Fournit la quantité de pixels requise pour l'impression. * +* * +* Retour : Largeur requise par la colonne, en pixel. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int g_token_style_measure_width(const GTokenStyle *style, TokenRenderingTag tag, size_t length) +{ + int result; /* Largeur à retourner */ + const rendering_property_t *prop; /* Motif de rendu visé */ + size_t index; /* Indice de config. adaptée */ + + prop = &style->properties[tag]; + + index = CAIRO_FONT_INDEX(prop->slant, prop->weight); + + result = style->x_advances[index] * length; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : style = gestionnaire de paramètres de rendu à consulter. * +* tag = type de rendu sollicité. * +* cr = contexte graphique à utiliser pour les pinceaux. * +* x = abscisse du point d'impression (à maj). [OUT] * +* y = ordonnée du point d'impression. * +* text = texte UTF-8 à faire appraître. * +* length = taille de ce texte à imprimer. * +* * +* Description : Imprime le fragment de texte transmis. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_token_style_draw_text(const GTokenStyle *style, TokenRenderingTag tag, cairo_t *cr, int *x, int y, const char *text, size_t length) +{ + bool selected; /* Marquer une sélection ? */ + gint width; /* Largeur du segment */ + cairo_operator_t old; /* Sauvegarde avant changement */ + const rendering_property_t *prop; /* Motif de rendu visé */ + + selected = false;//selection_list_has_segment_content(list, segment); + + width = g_token_style_measure_width(style, tag, length); + + /* Fond du texte */ + if (selected) { - 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; +#if 0 + + cairo_set_source_rgba(cr, + _seg_params.selection_bg.color.red, + _seg_params.selection_bg.color.green, + _seg_params.selection_bg.color.blue, + _seg_params.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); + +#endif + } - pango_font_description_free(font_desc); + /* Couleur d'impression */ + + prop = &style->properties[tag]; + + if (selected) + cairo_set_source_rgba(cr, + prop->inverted.red, + prop->inverted.green, + prop->inverted.blue, + prop->inverted.alpha); + + else + cairo_set_source_rgba(cr, + prop->foreground.red, + prop->foreground.green, + prop->foreground.blue, + prop->foreground.alpha); + + /* Impression du texte */ + + cairo_select_font_face(cr, style->font_family, prop->slant, prop->weight); + cairo_set_font_size(cr, style->font_size); - gtk_widget_path_free(path); - g_object_unref(context); + cairo_move_to(cr, *x, y + style->font_extents.ascent); + + cairo_show_text(cr, text); + + *x += width; } /****************************************************************************** * * -* Paramètres : text = texte à encadrer par des balises Pango. * -* pattern = paramètres restitués en interne. * +* Paramètres : style = gestionnaire de paramètres de rendu à consulter. * +* tag = type de rendu sollicité. * +* text = texte à encadrer par des balises Pango. * * * * Description : Enjolive du texte selon les paramètres d'un élément de thème.* * * @@ -135,36 +397,35 @@ void load_rendering_pattern(const char *name, rendering_pattern_t *pattern) * * ******************************************************************************/ -char *build_pango_markup_for(const char *text, const rendering_pattern_t *pattern) +char *g_token_style_build_markup(const GTokenStyle *style, TokenRenderingTag tag, const char *text) { char *result; /* Construction à retourner */ + const rendering_property_t *prop; /* Motif de rendu visé */ char color[10]; /* Définition hexa de couleur */ result = strdup(text); - if (pattern->foreground.has_color) - { - snprintf(color, sizeof(color), "#%02hhx%02hhx%02hhx%02hhx", - (unsigned char)(255 * pattern->foreground.color.red), - (unsigned char)(255 * pattern->foreground.color.green), - (unsigned char)(255 * pattern->foreground.color.blue), - (unsigned char)(255 * pattern->foreground.color.alpha)); + prop = &style->properties[tag]; - result = strprep(result, "\">"); - result = strprep(result, color); - result = strprep(result, "<span color=\""); + snprintf(color, sizeof(color), "#%02hhx%02hhx%02hhx%02hhx", + (unsigned char)(255 * prop->foreground.red), + (unsigned char)(255 * prop->foreground.green), + (unsigned char)(255 * prop->foreground.blue), + (unsigned char)(255 * prop->foreground.alpha)); - result = stradd(result, "</span>"); + result = strprep(result, "\">"); + result = strprep(result, color); + result = strprep(result, "<span color=\""); - } + result = stradd(result, "</span>"); - if (pattern->slant == CAIRO_FONT_SLANT_ITALIC || pattern->slant == CAIRO_FONT_SLANT_OBLIQUE) + if (prop->slant == CAIRO_FONT_SLANT_ITALIC || prop->slant == CAIRO_FONT_SLANT_OBLIQUE) { result = strprep(result, "<i>"); result = stradd(result, "</i>"); } - if (pattern->weight == CAIRO_FONT_WEIGHT_BOLD) + if (prop->weight == CAIRO_FONT_WEIGHT_BOLD) { result = strprep(result, "<b>"); result = stradd(result, "</b>"); @@ -177,9 +438,10 @@ char *build_pango_markup_for(const char *text, const rendering_pattern_t *patter /****************************************************************************** * * -* Paramètres : base = base de texte à compléter. * -* text = texte à encadrer par des balises Pango. * -* pattern = paramètres restitués en interne. * +* Paramètres : style = gestionnaire de paramètres de rendu à consulter. * +* base = base de texte à compléter. * +* tag = type de rendu sollicité. * +* text = texte à encadrer par des balises Pango. * * * * Description : Ajoute du texte enjolivé selon un élément de thème. * * * @@ -189,12 +451,12 @@ char *build_pango_markup_for(const char *text, const rendering_pattern_t *patter * * ******************************************************************************/ -char *append_pango_markup_with(char *base, const char *text, const rendering_pattern_t *pattern) +char *g_token_style_append_markup(const GTokenStyle *style, char *base, TokenRenderingTag tag, const char *text) { char *result; /* Construction à retourner */ char *tmp; /* Stockage temporaire */ - tmp = build_pango_markup_for(text, pattern); + tmp = g_token_style_build_markup(style, tag, text); result = stradd(base, tmp); @@ -203,3 +465,340 @@ char *append_pango_markup_with(char *base, const char *text, const rendering_pat return result; } + + + +/* ---------------------------------------------------------------------------------- */ +/* RECEPTACLES DE SIGNAUX CONNECTES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : widget = composant graphique de GTK changeant d'affichage. * +* pspec = détails de la propriété ayant évolué. * +* style = concentration de paramètres de rendu à actualiser. * +* * +* Description : Réagit à un changement de racine pour le composant suivi. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void on_root_change(GtkWidget *widget, GParamSpec *pspec, GTokenStyle *style) +{ + GtkCssProvider *css; /* Feuille de style maison */ + GdkDisplay *display; /* Zone d'affichage courante */ + TokenRenderingTag i; /* Boucle de parcours */ + + /** + * Si on fermeture n'est pas en court... + */ + if (gtk_widget_get_root(widget) != NULL) + { + /* Chargement des définitions dédiées */ + + css = gtk_css_provider_new(); + + gtk_css_provider_load_from_resource(css, "/re/chrysalide/framework/glibext/tokenstyle.css"); + + display = gtk_widget_get_display(widget); + + gtk_style_context_add_provider_for_display(display, GTK_STYLE_PROVIDER(css), + GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); + + /* Relecture des paramètres */ + + gtk_widget_add_css_class(widget, "token-generic"); + + style->loaded = g_token_style_retrieve_font(style); + + if (style->loaded) + style->loaded = g_token_style_retrieve_advances(style); + + for (i = 0; i < TRT_COUNT && style->loaded; i++) + { + gtk_widget_add_css_class(widget, _token_names[i]); + + style->loaded = g_token_style_retrieve_rendering_properties(style, i); + + gtk_widget_remove_css_class(widget, _token_names[i]); + + } + + gtk_widget_remove_css_class(widget, "token-generic"); + + /* Déchargement des définitions prises en compte */ + + gtk_style_context_remove_provider_for_display(display, GTK_STYLE_PROVIDER(css)); + + unref_object(css); + + } + +} + + +/****************************************************************************** +* * +* Paramètres : style = gestionnaire de paramètres de rendu à actualiser. * +* * +* Description : Charge toutes les indications liées aux polices. * +* * +* Retour : Bilan de l'opération : true pour un chargement sans encombre.* +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_token_style_retrieve_font(GTokenStyle *style) +{ + bool result; /* Bilan à faire remonter */ + PangoContext *context; /* Contexte Pango du composant */ + PangoFontDescription *desc; /* Détails de la police liée */ + const char *family; /* Eventuelle désignation */ + bool is_mono; /* Propriété attendue de chasse*/ + PangoFontFamily **pango_families; /* Liste des familles connues */ + int pango_families_count; /* Taille de cette liste */ + int k; /* Boucle de parcours */ + const char *other; /* Autre nom à comparer */ + + result = true; + + /* Réinitialisation */ + + if (style->font_family != NULL) + { + free(style->font_family); + style->font_family = NULL; + } + + style->font_size = 0; + + /* Chargement */ + + context = gtk_widget_create_pango_context(style->target); + + desc = pango_context_get_font_description(context); + + if (desc != NULL) + { + family = pango_font_description_get_family(desc); + + if (family != NULL) + { + is_mono = false; + + pango_context_list_families(context, &pango_families, &pango_families_count); + + for (k = 0; k < pango_families_count && !is_mono; k++) + { + if (!pango_font_family_is_monospace(pango_families[k])) + continue; + + other = pango_font_family_get_name(pango_families[k]); + + is_mono = (strcmp(family, other) == 0); + + } + + g_free(pango_families); + + if (is_mono) + style->font_family = strdup(family); + else + log_variadic_message(LMT_WARNING, + _("Selected font '%s' does not seem to be a monospace font; skipping it..."), + family); + + } + + style->font_size = pango_font_description_get_size(desc); + + if (pango_font_description_get_size_is_absolute(desc)) + style->font_size /= PANGO_SCALE; + + } + + /* Application de valeurs par défaut au besoin */ + + if (style->font_family == NULL) + { + style->font_family = strdup(DEFAULT_FONT_FAMILY); + + log_variadic_message(LMT_WARNING, + _("No font family defined; switching to '%s' as default"), + DEFAULT_FONT_FAMILY); + + } + + if (style->font_size == 0) + { + style->font_size = DEFAULT_FONT_SIZE; + + log_variadic_message(LMT_WARNING, + _("No font size defined; switching to '%s' as default"), + DEFAULT_FONT_SIZE); + + } + + log_variadic_message(LMT_INFO, + _("Using '%s' as font family for buffer rendering (size: %d)"), + style->font_family, style->font_size); + + unref_object(context); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : style = gestionnaire de paramètres de rendu à actualiser. * +* * +* Description : Détermine les tailles d'impression possibles pour les rendus.* +* * +* Retour : Bilan de l'opération : true pour un chargement sans encombre.* +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_token_style_retrieve_advances(GTokenStyle *style) +{ + bool result; /* Bilan à faire remonter */ + cairo_font_slant_t s; /* Boucle de parcours #1 */ + cairo_font_weight_t w; /* Boucle de parcours #2 */ + cairo_t *cr; /* Contexte à usage unique */ + cairo_surface_t *surface; /* Surface pour dessin Cairo */ + cairo_text_extents_t extents; /* Couverture des caractères */ + + result = true; + + for (s = CAIRO_FONT_SLANT_NORMAL; s < CAIRO_FONT_SLANT_COUNT; s++) + for (w = CAIRO_FONT_WEIGHT_NORMAL; w < CAIRO_FONT_WEIGHT_COUNT; w++) + { + surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 100, 100); + cr = cairo_create(surface); + + cairo_select_font_face(cr, style->font_family, s, w); + cairo_set_font_size(cr, style->font_size); + + if (s == CAIRO_FONT_SLANT_NORMAL && w == CAIRO_FONT_WEIGHT_NORMAL) + { + cairo_font_extents(cr, &style->font_extents); + } + + cairo_text_extents(cr, "A", &extents); + style->x_advances[CAIRO_FONT_INDEX(s, w)] = extents.x_advance; + + cairo_destroy(cr); + cairo_surface_destroy(surface); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : style = gestionnaire de paramètres de rendu à actualiser. * +* tag = désignation du style de rendu à traiter. * +* * +* Description : Charge les définitions complémentaires spécifiques. * +* * +* Retour : Bilan de l'opération : true pour un chargement sans encombre.* +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_token_style_retrieve_rendering_properties(GTokenStyle *style, TokenRenderingTag tag) +{ + bool result; /* Bilan à faire remonter */ + rendering_property_t *prop; /* Motif de rendu visé */ + GtkStyleContext *s_context; /* Contexte voué à disparaître */ + PangoContext *context; /* Contexte Pango du composant */ + PangoFontDescription *desc; /* Détails de la police liée */ + + result = true; + + prop = &style->properties[tag]; + + /* Couleur d'impression */ + + /** + * En attendant la disponibilité de GTK 4.10 et l'appel + * gtk_widget_get_color(widget, &color); + */ + + s_context = gtk_widget_get_style_context(style->target); + + gtk_style_context_get_color(s_context, &prop->foreground); + + /* Couleur inversée */ + + prop->inverted.red = 1.0 - prop->foreground.red; + prop->inverted.green = 1.0 - prop->foreground.green; + prop->inverted.blue = 1.0 - prop->foreground.blue; + prop->inverted.alpha = prop->foreground.alpha; + + /* Style d'impression */ + + context = gtk_widget_create_pango_context(style->target); + + desc = pango_context_get_font_description(context); + + if (desc == NULL) + { + prop->slant = CAIRO_FONT_SLANT_NORMAL; + prop->weight = CAIRO_FONT_WEIGHT_NORMAL; + } + + else + { + switch (pango_font_description_get_style(desc)) + { + case PANGO_STYLE_NORMAL: + prop->slant = CAIRO_FONT_SLANT_NORMAL; + break; + case PANGO_STYLE_ITALIC: + prop->slant = CAIRO_FONT_SLANT_ITALIC; + break; + case PANGO_STYLE_OBLIQUE: + prop->slant = CAIRO_FONT_SLANT_OBLIQUE; + break; + } + + switch (pango_font_description_get_weight(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: + prop->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: + prop->weight = CAIRO_FONT_WEIGHT_BOLD; + break; + } + + } + + unref_object(context); + + return result; + +} diff --git a/src/glibext/tokenstyle.css b/src/glibext/tokenstyle.css new file mode 100644 index 0000000..0cf9f37 --- /dev/null +++ b/src/glibext/tokenstyle.css @@ -0,0 +1,26 @@ + +.token-generic { + + font-family: Cousine; + +} + + + + +.token-raw-full { + + color: white; + + font-style: italic; + font-weight: bold; + +} + +.token-raw-null { + + color: black; + + background-color: pink; + +} diff --git a/src/glibext/tokenstyle.h b/src/glibext/tokenstyle.h index 9adfe1a..923b725 100644 --- a/src/glibext/tokenstyle.h +++ b/src/glibext/tokenstyle.h @@ -1,8 +1,8 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * rendering.h - prototypes pour la transformation de paramètres du thème GTK courant + * tokenstyle.h - prototypes pour la centralisation des paramètres de rendu de bribes textuelles * - * Copyright (C) 2018 Cyrille Bagard + * Copyright (C) 2018-2024 Cyrille Bagard * * This file is part of Chrysalide. * @@ -22,44 +22,86 @@ */ -#ifndef _GTKEXT_RENDERING_H -#define _GTKEXT_RENDERING_H +#ifndef _GLIBEXT_TOKENSTYLE_H +#define _GLIBEXT_TOKENSTYLE_H -#include <stdbool.h> -#include <gdk/gdk.h> +#include <gtk/gtk.h> +#include "helpers.h" -/* Restitution d'une couleur */ -typedef struct _rendering_color_t -{ - GdkRGBA color; /* Couleur de rendu */ - bool has_color; /* Définition en place ? */ -} rendering_color_t; -/* Restitution d'un élément de thème */ -typedef struct _rendering_pattern_t +/* Types de partie de rendu */ +typedef enum _TokenRenderingTag { - rendering_color_t foreground; /* Couleur d'impression */ - rendering_color_t inverted; /* Couleur inversée pour sél. */ + TRT_NONE, /* Espace ou tabulation */ + + TRT_RAW, /* Contenu brut */ + TRT_RAW_FULL, /* Contenu brut et complet */ + TRT_RAW_NULL, /* Contenu brut et nul */ + TRT_PRINTABLE, /* Caractère imprimable */ + TRT_NOT_PRINTABLE, /* Caractère non imprimable */ + + TRT_COMMENT, /* Commentaire */ + TRT_INDICATION, /* Aide à la lecture */ + + TRT_PHYS_ADDR_PAD, /* Position physique (début) */ + TRT_PHYS_ADDR, /* Position physique */ + TRT_VIRT_ADDR_PAD, /* Adresse virtuelle (début) */ + TRT_VIRT_ADDR, /* Adresse virtuelle */ + TRT_RAW_CODE, /* Code binaire brut */ + TRT_RAW_CODE_NULL, /* Code binaire brut et nul */ + + TRT_LABEL, /* Etiquette sur une adresse */ + + TRT_INSTRUCTION, /* Code binaire brut */ + + TRT_IMMEDIATE, /* Valeur immédiate */ + + TRT_REGISTER, /* Registre */ + + TRT_PUNCT, /* Signes de ponctuation */ + TRT_HOOK, /* Crochets '[' et ']' */ + TRT_SIGNS, /* Signes '+', '-' et '*' */ + TRT_LTGT, /* Caractères '<' et '>' */ + + TRT_SECTION, /* Identifiant de section */ + TRT_SEGMENT, /* Indication de segment */ + TRT_STRING, /* Chaîne de caractères avec " */ + + TRT_VAR_NAME, /* Nom de variable */ + + TRT_KEY_WORD, /* Mot clef de langage */ + + TRT_ERROR, /* Erreur "interne" */ + + TRT_COUNT + +} TokenRenderingTag; + + +#define G_TYPE_TOKEN_STYLE (g_token_style_get_type()) + +DECLARE_GTYPE(GTokenStyle, g_token_style, G, TOKEN_STYLE); - cairo_font_slant_t slant; /* Style d'impression */ - cairo_font_weight_t weight; /* Poids de la police */ -} rendering_pattern_t; +/* Crée un gestionnaire de style pour le rendu des lignes. */ +GTokenStyle *g_token_style_new(GtkWidget *); +/* Fournit la quantité de pixels requise pour l'impression. */ +int g_token_style_measure_width(const GTokenStyle *, TokenRenderingTag, size_t); -/* Récupère les informations de rendus d'un élément de thème. */ -void load_rendering_pattern(const char *, rendering_pattern_t *); +/* Imprime le fragment de texte transmis. */ +void g_token_style_draw_text(const GTokenStyle *, TokenRenderingTag, cairo_t *, int *, int, const char *, size_t); /* Enjolive du texte selon les paramètres d'un élément de thème. */ -char *build_pango_markup_for(const char *, const rendering_pattern_t *); +char *g_token_style_build_markup(const GTokenStyle *, TokenRenderingTag, const char *); /* Ajoute du texte enjolivé selon un élément de thème. */ -char *append_pango_markup_with(char *, const char *, const rendering_pattern_t *); +char *g_token_style_append_markup(const GTokenStyle *, char *, TokenRenderingTag, const char *); -#endif /* _GTKEXT_RENDERING_H */ +#endif /* _GLIBEXT_TOKENSTYLE_H */ |