summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2024-05-13 21:34:56 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2024-05-14 10:27:57 (GMT)
commite9f10d8fe1c5e9f8a70801c1cd4d3d342e290f15 (patch)
tree42a1d8560e8772e76e4e57db82a441d4a8152f74
parent071572b0df281cfa04442a636e84fbabd2acfe57 (diff)
Introduce a template for the widget providing a hex view.
-rw-r--r--src/framework.c13
-rw-r--r--src/glibext/Makefile.am8
-rw-r--r--src/glibext/helpers.h166
-rw-r--r--src/gtkext/Makefile.am13
-rw-r--r--src/gtkext/area-int.h51
-rw-r--r--src/gtkext/area.c231
-rw-r--r--src/gtkext/area.h51
-rw-r--r--src/gtkext/gresource.xml5
-rw-r--r--src/gtkext/hexview.c351
-rw-r--r--src/gtkext/hexview.css30
-rw-r--r--src/gtkext/hexview.h33
-rw-r--r--src/gtkext/hexview.ui32
12 files changed, 795 insertions, 189 deletions
diff --git a/src/framework.c b/src/framework.c
index dfd0bfa..b7a1332 100644
--- a/src/framework.c
+++ b/src/framework.c
@@ -27,6 +27,7 @@
#include "framework.h"
+#include "glibext/helpers.h"
@@ -225,6 +226,7 @@ static void gtk_chrysalide_framework_activate(GApplication *app)
GtkChrysalideFramework *real_app; /* Version réelle de l'instance*/
GSettings *settings; /* Paramètres globaux */
GtkWindow *window; /* Fenêtre mise en place */
+ GtkCssProvider *css; /* Feuille de style maison */
real_app = GTK_CHRYSALIDE_FRAMEWORK(app);
@@ -247,6 +249,17 @@ static void gtk_chrysalide_framework_activate(GApplication *app)
gtk_window_set_title(window, "Chrysalide");
gtk_window_present(window);
+ /* Chargement des extensions de thème */
+
+ css = gtk_css_provider_new();
+
+ gtk_css_provider_load_from_resource(css, "/re/chrysalide/framework/gtkext/hexview.css");
+
+ gtk_style_context_add_provider_for_display(gtk_widget_get_display(GTK_WIDGET(window)),
+ GTK_STYLE_PROVIDER(css), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+
+ unref_object(css);
+
}
diff --git a/src/glibext/Makefile.am b/src/glibext/Makefile.am
index 986bbd1..58ddb93 100644
--- a/src/glibext/Makefile.am
+++ b/src/glibext/Makefile.am
@@ -1,7 +1,7 @@
BUILT_SOURCES = chrysamarshal.h chrysamarshal.c
-noinst_LTLIBRARIES = libglibext.la
+noinst_LTLIBRARIES = libglibext4.la # libglibext.la
libglibext_la_SOURCES = \
buffercache-int.h \
@@ -52,6 +52,12 @@ libglibext_la_LIBADD = \
generators/libglibextgenerators.la
+libglibext4_la_SOURCES = \
+ helpers.h
+
+libglibext4_la_CFLAGS = $(TOOLKIT_CFLAGS)
+
+
devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%)
dev_HEADERS = $(libglibext_la_SOURCES:%c=)
diff --git a/src/glibext/helpers.h b/src/glibext/helpers.h
new file mode 100644
index 0000000..752eb07
--- /dev/null
+++ b/src/glibext/helpers.h
@@ -0,0 +1,166 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * helpers.h - prototypes pour la simplification des interactions de base avec GLib
+ *
+ * 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_HELPERS_H
+#define _GLIBEXT_HELPERS_H
+
+
+#include <assert.h>
+#include <glib-object.h>
+
+
+
+/**
+ * Les définitions issues de <glib-2.80>/gobject/gtype.h fournissent des macros
+ * facilitant la déclaration de types pour entêtes. Cependant :
+ *
+ * - G_DECLARE_FINAL_TYPE impose une structure de classe fixe ;
+ * - G_DECLARE_DERIVABLE_TYPE impose une structure d'objet fixe.
+ *
+ * Ces deux macros ne peuvent donc pas être employées en l'état dans Chrysalide.
+ *
+ * Par ailleurs, la fonctionnalité g_autoptr() n'offre pas une séduction totale :
+ * elle conduit à un code inconsistant, avec parfois des libérations explicites,
+ * parfois des libérations invisible gérées par le compilateur. Cet aspect
+ * fonctionnel offert par les macros GLib est donc inutile pour Chrysalide.
+ *
+ * Une nouvelle macro de déclaration est ainsi constituée ici.
+ *
+ * De fait de l'absence d'argument, l'inclusion de la définition suivante n'est
+ * pas possible :
+ *
+ * MOD##_TYPE_##NAME t_n##_get_type()
+ *
+ * La macro traditionnelle doit ainsi être fournie en parallèle à la déclaration
+ * condensée ici. Elle y est d'ailleurs référencée, forçant une déclaration
+ * préalable de manière globale et cohérente dans l'ensemble du code d'emploi.
+ */
+
+#define DECLARE_GTYPE(TN, t_n, MOD, NAME) \
+ \
+ GType t_n##_get_type(void); \
+ \
+ typedef struct _##TN TN; \
+ typedef struct _##TN##Class TN##Class; \
+ \
+ G_GNUC_UNUSED static inline TN *MOD##_##NAME(gpointer obj) \
+ { \
+ return G_TYPE_CHECK_INSTANCE_CAST(obj, MOD##_TYPE_##NAME, TN); \
+ } \
+ \
+ G_GNUC_UNUSED static inline TN##Class *MOD##_##NAME##_CLASS(gpointer klass) \
+ { \
+ return G_TYPE_CHECK_CLASS_CAST(klass, MOD##_TYPE_##NAME, TN##Class); \
+ } \
+ \
+ G_GNUC_UNUSED static inline gboolean MOD##_IS_##NAME(gpointer obj) \
+ { \
+ return G_TYPE_CHECK_INSTANCE_TYPE(obj, MOD##_TYPE_##NAME); \
+ } \
+ \
+ G_GNUC_UNUSED static inline gboolean MOD##_IS_##NAME##_CLASS(gpointer klass) \
+ { \
+ return G_TYPE_CHECK_CLASS_TYPE(klass, MOD##_TYPE_##NAME); \
+ } \
+ \
+ G_GNUC_UNUSED static inline TN##Class *MOD##_##NAME##_GET_CLASS(gpointer obj) \
+ { \
+ return G_TYPE_INSTANCE_GET_CLASS(obj, MOD##_TYPE_##NAME, TN##Class); \
+ }
+
+
+/**
+ * Les principales fonctions incrémentant ou réduisant le nombre de références
+ * attachées à un objet acceptent de simples pointeurs génériques (cf. définitions
+ * du fichier <glib-2.80>/gobject/gobject.h :
+ *
+ * [...]
+ * void g_object_notify_by_pspec (GObject *object,
+ * GParamSpec *pspec);
+ * void g_object_thaw_notify (GObject *object);
+ * gboolean g_object_is_floating (gpointer object);
+ * gpointer g_object_ref_sink (gpointer object);
+ * gpointer g_object_take_ref (gpointer object);
+ * gpointer g_object_ref (gpointer object);
+ * void g_object_unref (gpointer object);
+ * void g_object_weak_ref (GObject *object,
+ * GWeakNotify notify,
+ * gpointer data);
+ * [...]
+ *
+ * La fonction g_object_unref() débute bien par exemple par une validation
+ * de l'instance, avec un appel à : g_return_if_fail (G_IS_OBJECT (object)).
+ *
+ * Cependant, cette vérification est désactivée en cas de compilation de GLib
+ * avec G_DISABLE_CHECKS.
+ *
+ * Une conversion vers un type donné (par exemple avec G_OBJECT()) est par
+ * ailleurs dépendante d'autres paramètres de compilation, comme le révèle
+ * le fichier <glib-2.80>/gobject/gtype.h :
+ *
+ * #if defined(G_DISABLE_CAST_CHECKS) || defined(__OPTIMIZE__)
+ * # define _G_TYPE_CIC(ip, gt, ct) ((ct*) (void *) ip)
+ * # define _G_TYPE_CCC(cp, gt, ct) ((ct*) (void *) cp)
+ * #else
+ * # define _G_TYPE_CIC(ip, gt, ct) \
+ * ((ct*) (void *) g_type_check_instance_cast ((GTypeInstance*) ip, gt))
+ * # define _G_TYPE_CCC(cp, gt, ct) \
+ * ((ct*) (void *) g_type_check_class_cast ((GTypeClass*) cp, gt))
+ * #endif
+ *
+ * Afin d'assurer des conditions de débogage/fuzzing optimales dans tous les
+ * cas de figure, les fonctions de manipulation des références font l'objet
+ * ici d'une couche intermédiaire pour les appels.
+ */
+
+#ifndef NDEBUG
+
+# define ref_object(ip) \
+ do \
+ { \
+ GTypeInstance *__inst; \
+ __inst = g_type_check_instance_cast((GTypeInstance *)ip, G_TYPE_OBJECT); \
+ assert(__inst != NULL); \
+ g_object_ref(ip); \
+ } \
+ while (0);
+
+# define unref_object(ip) \
+ do \
+ { \
+ GTypeInstance *__inst; \
+ __inst = g_type_check_instance_cast((GTypeInstance *)ip, G_TYPE_OBJECT); \
+ assert(__inst != NULL); \
+ g_object_unref(ip); \
+ } \
+ while (0);
+
+#else
+
+# define ref_object(p) g_object_ref(p)
+# define unref_object(p) g_object_unref(p)
+
+#endif
+
+
+#endif /* _GLIBEXT_HELPERS_H */
diff --git a/src/gtkext/Makefile.am b/src/gtkext/Makefile.am
index a037fb8..45c9a1c 100644
--- a/src/gtkext/Makefile.am
+++ b/src/gtkext/Makefile.am
@@ -35,8 +35,15 @@ libgtkext_la_LIBADD = \
libgtkext_la_CFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS)
+UI_FILES_4_ = \
+ hexview.css \
+ hexview.ui
+
libgtkext4_la_SOURCES = \
- hexview.h hexview.c
+ area-int.h \
+ area.h area.c \
+ hexview.h hexview.c \
+ resources.h resources.c
libgtkext4_la_CFLAGS = $(LIBGTK4_CFLAGS)
@@ -49,7 +56,7 @@ dev_HEADERS = $(libgtkext_la_SOURCES:%c=)
SUBDIRS = graph
-resources.c: gresource.xml $(UI_FILES)
+resources.c: gresource.xml $(UI_FILES_4_)
glib-compile-resources --target=$@ --sourcedir=$(srcdir) --generate-source --c-name gtkext gresource.xml
resources.h: gresource.xml
@@ -58,4 +65,4 @@ resources.h: gresource.xml
CLEANFILES = resources.h resources.c
-EXTRA_DIST = gresource.xml $(UI_FILES)
+EXTRA_DIST = gresource.xml $(UI_FILES_4_)
diff --git a/src/gtkext/area-int.h b/src/gtkext/area-int.h
new file mode 100644
index 0000000..0bb7bd7
--- /dev/null
+++ b/src/gtkext/area-int.h
@@ -0,0 +1,51 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * area-int.h - définitions internes propres à la définition d'un sous-composant de rendu
+ *
+ * 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 _GTKEXT_AREA_INT_H
+#define _GTKEXT_AREA_INT_H
+
+
+#include "area.h"
+
+
+
+/* Sous-composant de composition à dessiner (instance) */
+struct _GtkComposingArea
+{
+ GtkWidget parent; /* A laisser en premier */
+
+ snapshot_composing_area_cb snapshot; /* Procédure de sous-traitance */
+ GtkWidget *snapshot_wgt; /* Composant GTK à associer */
+
+};
+
+/* Sous-composant de composition à dessiner (classe) */
+struct _GtkComposingAreaClass
+{
+ GtkWidgetClass parent; /* A laisser en premier */
+
+};
+
+
+
+#endif /* _GTKEXT_AREA_INT_H */
diff --git a/src/gtkext/area.c b/src/gtkext/area.c
new file mode 100644
index 0000000..087a726
--- /dev/null
+++ b/src/gtkext/area.c
@@ -0,0 +1,231 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * area.c - définition d'un sous-composant de rendu
+ *
+ * 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/>.
+ */
+
+
+#include "area.h"
+
+
+#include "area-int.h"
+#include "../glibext/helpers.h"
+
+
+
+/* ------------------------ BASES D'UN NOUVEAU COMPOSANT GTK ------------------------ */
+
+
+/* Procède à l'initialisation de l'afficheur générique. */
+static void gtk_composing_area_class_init(GtkComposingAreaClass *);
+
+/* Procède à l'initialisation de l'afficheur générique. */
+static void gtk_composing_area_init(GtkComposingArea *);
+
+/* Supprime toutes les références externes. */
+static void gtk_composing_area_dispose(GtkComposingArea *);
+
+/* Procède à la libération totale de la mémoire. */
+static void gtk_composing_area_finalize(GtkComposingArea *);
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Procède à l'actualisation de l'affichage d'un composant. */
+static void gtk_composing_area_snapshot(GtkWidget *, GtkSnapshot *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* BASES D'UN NOUVEAU COMPOSANT GTK */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Détermine le type du composant d'affichage générique. */
+G_DEFINE_TYPE(GtkComposingArea, gtk_composing_area, GTK_TYPE_WIDGET);
+
+
+/******************************************************************************
+* *
+* Paramètres : class = classe GTK à initialiser. *
+* *
+* Description : Procède à l'initialisation de l'afficheur générique. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_composing_area_class_init(GtkComposingAreaClass *class)
+{
+ GObjectClass *object; /* Plus haut niveau équivalent */
+ GtkWidgetClass *widget; /* Classe de haut niveau */
+
+ object = G_OBJECT_CLASS(class);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)gtk_composing_area_dispose;
+ object->finalize = (GObjectFinalizeFunc)gtk_composing_area_finalize;
+
+ widget = GTK_WIDGET_CLASS(class);
+
+ widget->snapshot = gtk_composing_area_snapshot;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : area = composant GTK à initialiser. *
+* *
+* Description : Procède à l'initialisation de l'afficheur générique. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_composing_area_init(GtkComposingArea *area)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : area = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_composing_area_dispose(GtkComposingArea *area)
+{
+ g_clear_object(&area->snapshot_wgt);
+
+ G_OBJECT_CLASS(gtk_composing_area_parent_class)->dispose(G_OBJECT(area));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : area = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_composing_area_finalize(GtkComposingArea *area)
+{
+ G_OBJECT_CLASS(gtk_composing_area_parent_class)->finalize(G_OBJECT(area));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Crée un composant de composition pour rendu principalement. *
+* *
+* Retour : Composant graphique pour GTK créé. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GtkComposingArea *g_raw_scan_cache_builder_new(void)
+{
+ GtkComposingArea *result; /* Nouvelle instance à renvoyer*/
+
+ result = g_object_new(GTK_TYPE_COMPOSING_AREA, NULL);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : area = sous-composant dont la définition est à compléter. *
+* cb = procédure de sous-traitance à enregistrer. *
+* wgt = contexte d'appel. *
+* *
+* Description : Enregistre une fonction de rappel pour le rendu du composant.*
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_raw_scan_cache_register_snapshot(GtkComposingArea *area, snapshot_composing_area_cb cb, GtkWidget *wgt)
+{
+ g_clear_object(&area->snapshot_wgt);
+
+ area->snapshot = cb;
+
+ if (wgt != NULL)
+ ref_object(wgt);
+
+ area->snapshot_wgt = wgt;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : widget = composant graphique visé par la procédure. *
+* snapshot = gestionnaire de noeuds de rendu à solliciter. *
+* *
+* Description : Procède à l'actualisation de l'affichage d'un composant. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_composing_area_snapshot(GtkWidget *widget, GtkSnapshot *snapshot)
+{
+ GtkComposingArea *area; /* Véritable instance en jeu */
+
+ area = GTK_COMPOSING_AREA(widget);
+
+ if (area->snapshot != NULL)
+ area->snapshot(widget, snapshot, area->snapshot_wgt);
+
+}
diff --git a/src/gtkext/area.h b/src/gtkext/area.h
new file mode 100644
index 0000000..fa063e3
--- /dev/null
+++ b/src/gtkext/area.h
@@ -0,0 +1,51 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * area.h - prototypes pour la définition d'un sous-composant de rendu
+ *
+ * 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 _GTKEXT_AREA_H
+#define _GTKEXT_AREA_H
+
+
+#include <gtk/gtk.h>
+
+
+#include "../glibext/helpers.h"
+
+
+
+#define GTK_TYPE_COMPOSING_AREA (gtk_composing_area_get_type())
+
+DECLARE_GTYPE(GtkComposingArea, gtk_composing_area, GTK, COMPOSING_AREA);
+
+
+/* Crée un composant de composition pour rendu principalement. */
+GtkComposingArea *g_raw_scan_cache_builder_new(void);
+
+/* Procède à l'actualisation de l'affichage d'un composant. */
+typedef void (* snapshot_composing_area_cb) (GtkWidget *, GtkSnapshot *, GtkWidget *);
+
+/* Enregistre une fonction de rappel pour le rendu du composant. */
+void g_raw_scan_cache_register_snapshot(GtkComposingArea *, snapshot_composing_area_cb, GtkWidget *);
+
+
+
+#endif /* _GTKEXT_AREA_H */
diff --git a/src/gtkext/gresource.xml b/src/gtkext/gresource.xml
index 0250484..2ee8977 100644
--- a/src/gtkext/gresource.xml
+++ b/src/gtkext/gresource.xml
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
- <gresource prefix="/org/chrysalide/gtkext">
- <file compressed="true">blockbar.ui</file>
+ <gresource prefix="/re/chrysalide/framework/gtkext">
+ <file compressed="true">hexview.ui</file>
+ <file compressed="true">hexview.css</file>
</gresource>
</gresources>
diff --git a/src/gtkext/hexview.c b/src/gtkext/hexview.c
index 32bd69b..56a167d 100644
--- a/src/gtkext/hexview.c
+++ b/src/gtkext/hexview.c
@@ -1,8 +1,8 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * hexdisplay.c - affichage d'un contenu binaire sous forme hexadécimale
+ * hexview.c - affichage de contenus de binaire
*
- * Copyright (C) 2019 Cyrille Bagard
+ * Copyright (C) 2016-2024 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -17,71 +17,74 @@
* 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/>.
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "hexdisplay.h"
+#include "hexview.h"
-#include "gtkbufferdisplay-int.h"
-#include "../core/columns.h"
-#include "../core/params.h"
-#include "../format/format.h"
-#include "../glibext/generators/hex.h"
+#include "area.h"
-/* Composant d'affichage de contenu sous forme hexadécimale (instance) */
-struct _GtkHexDisplay
+
+
+/* Composant d'affichage générique (instance) */
+struct _GtkHexView
{
- GtkBufferDisplay parent; /* A laisser en premier */
+ GtkWidget parent; /* A laisser en premier */
- GBufferCache *cache; /* Cache pour l'affichage */
- GHexGenerator *generator; /* Générateur à la volée */
+ GtkWidget *offsets; /* Affichage des positions */
+ GtkWidget *hex; /* Affichage des octets brut */
+ GtkWidget *ascii; /* Affichage des imprimables */
};
-/* Composant d'affichage de contenu sous forme hexadécimale (classe) */
-struct _GtkHexDisplayClass
+/* Composant d'affichage générique (classe) */
+struct _GtkHexViewClass
{
- GtkBufferDisplayClass parent; /* A laisser en premier */
+ GtkWidgetClass parent; /* A laisser en premier */
};
-/* Procède à l'initialisation des afficheurs sous forme hexa. */
-static void gtk_hex_display_class_init(GtkHexDisplayClass *);
+/* Procède à l'initialisation de l'afficheur générique. */
+static void gtk_hex_view_class_init(GtkHexViewClass *);
-/* Procède à l'initialisation de l'afficheur sous forme hexa. */
-static void gtk_hex_display_init(GtkHexDisplay *);
+/* Procède à l'initialisation de l'afficheur générique. */
+static void gtk_hex_view_init(GtkHexView *);
/* Supprime toutes les références externes. */
-static void g_hex_display_dispose(GtkHexDisplay *);
+static void gtk_hex_view_dispose(GtkHexView *);
/* Procède à la libération totale de la mémoire. */
-static void g_hex_display_finalize(GtkHexDisplay *);
+static void gtk_hex_view_finalize(GtkHexView *);
+
-/* S'adapte à la surface concédée par le composant parent. */
-static void gtk_hex_display_size_allocate(GtkWidget *, GtkAllocation *);
-/* Indique les dimensions de travail du composant d'affichage. */
-static void gtk_hex_display_compute_requested_size(GtkHexDisplay *, gint *, gint *);
+void demo_snapshot (GtkWidget *widget, GtkSnapshot *snapshot);
-/* Adapte le cache de lignes hexadécimales à la taille courante. */
-static void gtk_hex_display_populate_cache(GtkHexDisplay *);
+void demo_measure (GtkWidget *widget,
+ GtkOrientation orientation,
+ int for_size,
+ int *minimum_size,
+ int *natural_size,
+ int *minimum_baseline,
+ int *natural_baseline);
-/* Détermine le type du composant d'affichage sous forme hexadécimale. */
-G_DEFINE_TYPE(GtkHexDisplay, gtk_hex_display, GTK_TYPE_BUFFER_DISPLAY)
+
+/* Détermine le type du composant d'affichage générique. */
+G_DEFINE_TYPE(GtkHexView, gtk_hex_view, GTK_TYPE_WIDGET);
/******************************************************************************
* *
* Paramètres : class = classe GTK à initialiser. *
* *
-* Description : Procède à l'initialisation des afficheurs sous forme hexa. *
+* Description : Procède à l'initialisation de l'afficheur générique. *
* *
* Retour : - *
* *
@@ -89,24 +92,54 @@ G_DEFINE_TYPE(GtkHexDisplay, gtk_hex_display, GTK_TYPE_BUFFER_DISPLAY)
* *
******************************************************************************/
-static void gtk_hex_display_class_init(GtkHexDisplayClass *class)
+static void gtk_hex_view_class_init(GtkHexViewClass *class)
{
- GObjectClass *object; /* Autre version de la classe */
- GtkWidgetClass *widget_class; /* Classe de haut niveau */
- GtkDisplayPanelClass *panel_class; /* Classe parente */
+ GObjectClass *object; /* Plus haut niveau équivalent */
+ GtkWidgetClass *widget; /* Classe de haut niveau */
object = G_OBJECT_CLASS(class);
- object->dispose = (GObjectFinalizeFunc/* ! */)g_hex_display_dispose;
- object->finalize = (GObjectFinalizeFunc)g_hex_display_finalize;
+ object->dispose = (GObjectFinalizeFunc/* ! */)gtk_hex_view_dispose;
+ object->finalize = (GObjectFinalizeFunc)gtk_hex_view_finalize;
+
+ widget = GTK_WIDGET_CLASS(class);
+
+ gtk_widget_class_set_css_name(widget, "GtkHexView");
+
+ gtk_widget_class_set_layout_manager_type(widget, GTK_TYPE_BOX_LAYOUT);
+
+ g_type_ensure(GTK_TYPE_COMPOSING_AREA);
+
+ gtk_widget_class_set_template_from_resource(widget, "/re/chrysalide/framework/gtkext/hexview.ui");
- widget_class = GTK_WIDGET_CLASS(class);
+ gtk_widget_class_bind_template_child(widget, GtkHexView, offsets);
+ gtk_widget_class_bind_template_child(widget, GtkHexView, hex);
+ gtk_widget_class_bind_template_child(widget, GtkHexView, ascii);
- widget_class->size_allocate = gtk_hex_display_size_allocate;
- panel_class = GTK_DISPLAY_PANEL_CLASS(class);
- panel_class->compute_size = (compute_requested_size_fc)gtk_hex_display_compute_requested_size;
+ //widget->snapshot = demo_snapshot;
+
+ //widget->measure = demo_measure;
+
+
+ /*
+
+
+
+
+
+
+ */
+
+
+ /*
+ widget->destroy = gtk_hex_view_destroy;
+ widget->realize = gtk_hex_view_realize;
+ widget->size_allocate = gtk_hex_view_size_allocate;
+ widget->get_preferred_height = gtk_hex_view_get_preferred_height;
+ widget->get_preferred_width = gtk_hex_view_get_preferred_width;
+ */
}
@@ -115,7 +148,7 @@ static void gtk_hex_display_class_init(GtkHexDisplayClass *class)
* *
* Paramètres : view = composant GTK à initialiser. *
* *
-* Description : Procède à l'initialisation de l'afficheur sous forme hexa. *
+* Description : Procède à l'initialisation de l'afficheur générique. *
* *
* Retour : - *
* *
@@ -123,40 +156,37 @@ static void gtk_hex_display_class_init(GtkHexDisplayClass *class)
* *
******************************************************************************/
-static void gtk_hex_display_init(GtkHexDisplay *view)
+static void gtk_hex_view_init(GtkHexView *view)
{
+ gtk_widget_init_template(GTK_WIDGET(view));
-}
-/******************************************************************************
-* *
-* Paramètres : display = instance d'objet GLib à traiter. *
-* *
-* Description : Supprime toutes les références externes. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-static void g_hex_display_dispose(GtkHexDisplay *display)
-{
- g_clear_object(&display->cache);
- g_clear_object(&display->generator);
+ g_object_set(G_OBJECT(view->offsets), "width-request", 30, NULL);
+
+ g_object_set(G_OBJECT(view->ascii), "width-request", 230, NULL);
+
+
+ g_raw_scan_cache_register_snapshot(GTK_COMPOSING_AREA(view->offsets), demo_snapshot, GTK_WIDGET(view));
+
+ g_raw_scan_cache_register_snapshot(GTK_COMPOSING_AREA(view->hex), demo_snapshot, GTK_WIDGET(view));
+
+ g_raw_scan_cache_register_snapshot(GTK_COMPOSING_AREA(view->ascii), demo_snapshot, GTK_WIDGET(view));
+
+
+
- G_OBJECT_CLASS(gtk_hex_display_parent_class)->dispose(G_OBJECT(display));
}
/******************************************************************************
* *
-* Paramètres : display = instance d'objet GLib à traiter. *
+* Paramètres : view = instance d'objet GLib à traiter. *
* *
-* Description : Procède à la libération totale de la mémoire. *
+* Description : Supprime toutes les références externes. *
* *
* Retour : - *
* *
@@ -164,113 +194,100 @@ static void g_hex_display_dispose(GtkHexDisplay *display)
* *
******************************************************************************/
-static void g_hex_display_finalize(GtkHexDisplay *display)
+static void gtk_hex_view_dispose(GtkHexView *view)
{
- G_OBJECT_CLASS(gtk_hex_display_parent_class)->finalize(G_OBJECT(display));
+ gtk_widget_dispose_template(GTK_WIDGET(view), GTK_TYPE_HEX_VIEW);
+
+ G_OBJECT_CLASS(gtk_hex_view_parent_class)->dispose(G_OBJECT(view));
}
/******************************************************************************
* *
-* Paramètres : content = contenu brut à représenter. *
+* Paramètres : view = instance d'objet GLib à traiter. *
* *
-* Description : Crée un nouveau composant pour l'affichage sous forme hexa. *
+* Description : Procède à la libération totale de la mémoire. *
* *
-* Retour : Composant GTK créé. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-GtkWidget *gtk_hex_display_new(GBinContent *content)
+static void gtk_hex_view_finalize(GtkHexView *view)
{
- GtkHexDisplay *result; /* Composant à retourner */
- GBufferView *view; /* Vue pointée sur un tampon */
- int padding; /* Bourrage entre colonnes */
- GWidthTracker *tracker; /* Gestionnaire de largeurs */
+ G_OBJECT_CLASS(gtk_hex_view_parent_class)->finalize(G_OBJECT(view));
- result = g_object_new(GTK_TYPE_HEX_DISPLAY, NULL);
+}
- result->cache = g_buffer_cache_new(content, HLC_COUNT, HLC_BINARY);
- g_object_ref_sink(G_OBJECT(result->cache));
- g_generic_config_get_value(get_main_configuration(), MPK_HEX_PADDING, &padding);
- tracker = g_buffer_cache_get_width_tracker(result->cache);
- g_width_tracker_set_column_min_width(tracker, HLC_PADDING, padding);
- g_object_unref(G_OBJECT(tracker));
- result->generator = g_hex_generator_new(content);
- gtk_hex_display_populate_cache(result);
+void demo_measure (GtkWidget *widget,
+ GtkOrientation orientation,
+ int for_size,
+ int *minimum_size,
+ int *natural_size,
+ int *minimum_baseline,
+ int *natural_baseline)
+{
+ printf("set size\n");
- view = g_buffer_view_new(result->cache, NULL);
+ *minimum_size = 100;
+ *natural_size = 200;
+}
- GTK_BUFFER_DISPLAY(result)->view = view;
- return GTK_WIDGET(result);
-}
-/******************************************************************************
-* *
-* Paramètres : widget = composant GTK à mettre à jour. *
-* allocation = étendue accordée à la vue. *
-* *
-* Description : S'adapte à la surface concédée par le composant parent. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void gtk_hex_display_size_allocate(GtkWidget *widget, GtkAllocation *allocation)
+void demo_snapshot (GtkWidget *widget, GtkSnapshot *snapshot)
{
- GtkHexDisplay *display; /* Autre version du composant */
- GBufferCache *cache; /* Contenu représenté */
- gint text_pos; /* Abscisse minimale du texte */
- bool show_pos; /* Affichage des positions ? */
- GWidthTracker *tracker; /* Gestionnaire de largeurs */
- gint padding; /* Bourrage supplémentaire */
- bool changed; /* Note toute variation */
+ GdkRGBA red, green, yellow, blue;
+ float w, h;
- display = GTK_HEX_DISPLAY(widget);
+ gdk_rgba_parse (&red, "red");
+ gdk_rgba_parse (&green, "green");
+ gdk_rgba_parse (&yellow, "yellow");
+ gdk_rgba_parse (&blue, "blue");
- cache = g_buffer_view_get_cache(GTK_BUFFER_DISPLAY(display)->view);
- text_pos = g_buffer_cache_get_text_position(cache);
- g_object_unref(G_OBJECT(cache));
+ w = gtk_widget_get_width (widget) / 2.0;
+ h = gtk_widget_get_height (widget) / 2.0;
- show_pos = g_display_options_get(GTK_DISPLAY_PANEL(widget)->options, 0);
+ gtk_snapshot_append_color (snapshot, &red,
+ &GRAPHENE_RECT_INIT(0, 0, w, h));
+ gtk_snapshot_append_color (snapshot, &green,
+ &GRAPHENE_RECT_INIT(w, 0, w, h));
+ gtk_snapshot_append_color (snapshot, &yellow,
+ &GRAPHENE_RECT_INIT(0, h, w, h));
+ gtk_snapshot_append_color (snapshot, &blue,
+ &GRAPHENE_RECT_INIT(w, h, w, h));
- tracker = g_buffer_cache_get_width_tracker(display->cache);
- padding = g_width_tracker_get_column_min_width(tracker, HLC_PADDING);
- g_object_unref(G_OBJECT(tracker));
+ /*
+ printf("[widget] CSS name: %s\n", gtk_widget_get_css_name(widget));
- changed = g_hex_generator_auto_fit(display->generator, text_pos, show_pos, padding, allocation->width);
+ char **iter;
- if (changed)
- gtk_hex_display_populate_cache(display);
-
- /**
- * On fait appel au parent en dernier pour bénéficier des besoins
- * en espace actualisés avec les nouvelles dispositions.
- */
+ iter = gtk_widget_get_css_classes(widget);
- GTK_WIDGET_CLASS(gtk_hex_display_parent_class)->size_allocate(widget, allocation);
+ while (*iter)
+ printf("[widget] CSS classes: %s\n", *iter);
+ */
}
+
+#if 0
/******************************************************************************
* *
-* Paramètres : display = composant GTK à consulter. *
-* width = largeur requise à renseigner ou NULL. [OUT] *
-* height = hauteur requise à renseigner ou NULL. [OUT] *
+* Paramètres : widget = composant GTK à examiner. *
+* minimum = largeur minimale à préciser ou NULL. [OUT] *
+* natural = largeur idéale à préciser ou NULL. [OUT] *
* *
-* Description : Indique les dimensions de travail du composant d'affichage. *
+* Description : Fournit la largeur idéale pour le composant d'affichage. *
* *
* Retour : - *
* *
@@ -278,25 +295,31 @@ static void gtk_hex_display_size_allocate(GtkWidget *widget, GtkAllocation *allo
* *
******************************************************************************/
-static void gtk_hex_display_compute_requested_size(GtkHexDisplay *display, gint *width, gint *height)
+static void gtk_hex_view_get_preferred_width(GtkWidget *widget, gint *minimum, gint *natural)
{
- GtkDisplayPanel *pdisplay; /* Version parente */
+ GtkHexView *panel; /* Autre version du composant */
+ gint req; /* Dimension requise */
+
+ panel = GTK_HEX_VIEW(widget);
- pdisplay = GTK_DISPLAY_PANEL(display);
+ GTK_HEX_VIEW_GET_CLASS(widget)->compute_size(panel, &req, NULL);
- GTK_DISPLAY_PANEL_CLASS(gtk_hex_display_parent_class)->compute_size(pdisplay, width, height);
+ req *= panel->scale;
- if (width != NULL && *width != 0)
- *width = 1;
+ if (minimum != NULL) *minimum = req;
+ if (natural != NULL) *natural = req;
}
+
+
/******************************************************************************
* *
-* Paramètres : display = composant GTK à mettre à jour. *
+* Paramètres : panel = composant GTK à venir consulter. *
+* cr = contexte graphique associé à l'événement. *
* *
-* Description : Adapte le cache de lignes hexadécimales à la taille courante.*
+* Description : Dessine si besoin est une bordure autour du composant. *
* *
* Retour : - *
* *
@@ -304,44 +327,50 @@ static void gtk_hex_display_compute_requested_size(GtkHexDisplay *display, gint
* *
******************************************************************************/
-static void gtk_hex_display_populate_cache(GtkHexDisplay *display)
+void gtk_hex_view_draw_border(GtkHexView *panel, cairo_t *cr)
{
- GBinContent *content; /* Contenu binaire affiché */
- phys_t full; /* Taille totale à représenter */
- phys_t line; /* Taille représentée par ligne*/
- size_t needed; /* Nombre de lignes nécessaires*/
- size_t count; /* Nombre actuel de lignes */
+ GtkWidget *widget; /* Autre version du composant */
+ GtkStyleContext *context; /* Contexte du thème actuel */
+ GdkRGBA color; /* Couleur de thème récupérée */
+ GtkRequisition req; /* Taille allouée à l'élément */
+ GtkAllocation area; /* Emplacement à considérer */
- /* Détermination du besoin */
+ if (panel->show_border)
+ {
+ widget = GTK_WIDGET(panel);
- content = g_hex_generator_get_content(display->generator);
+ gtk_widget_get_preferred_size(widget, NULL, &req);
- full = g_binary_content_compute_size(content);
+ context = gtk_widget_get_style_context(widget);
- g_object_unref(G_OBJECT(content));
+ gtk_style_context_save(context);
- line = g_hex_generator_get_bytes_per_line(display->generator);
+ gtk_style_context_add_class(context, GTK_STYLE_CLASS_FRAME);
- needed = full / line;
+ gtk_style_context_get(gtk_widget_get_style_context(widget),
+ gtk_widget_get_state_flags(widget),
+ GTK_STYLE_PROPERTY_COLOR, &color, NULL);
- if (full % line > 0)
- needed++;
+ cairo_set_source_rgba(cr, color.red, color.green, color.blue, color.alpha);
- /* Adaptation du tampon interne */
+ cairo_set_line_width(cr, 1.0);
- g_buffer_cache_wlock(display->cache);
+ gtk_widget_get_preferred_size(GTK_WIDGET(panel), NULL, &req);
- count = g_buffer_cache_count_lines(display->cache);
+ area.x = 0;
+ area.y = 0;
+ area.width = req.width;
+ area.height = req.height;
- if (needed < count)
- g_buffer_cache_truncate(display->cache, needed);
+ gtk_hex_view_define_border_path(panel, cr, &area);
+ cairo_stroke(cr);
- else if (needed > count)
- g_buffer_cache_extend_with(display->cache, needed, G_LINE_GENERATOR(display->generator));
+ gtk_style_context_restore(context);
- g_buffer_cache_wunlock(display->cache);
-
- if (needed != count)
- gtk_widget_queue_resize(GTK_WIDGET(display));
+ }
}
+
+
+
+#endif
diff --git a/src/gtkext/hexview.css b/src/gtkext/hexview.css
new file mode 100644
index 0000000..fdde1cc
--- /dev/null
+++ b/src/gtkext/hexview.css
@@ -0,0 +1,30 @@
+
+.gutter {
+
+ background-color: @theme_bg_color;
+
+}
+
+.custom-view {
+
+ background-color: @theme_base_color;
+
+}
+
+GtkHexView > :not(scrollbar) {
+
+ padding-left: 8px;
+
+}
+
+GtkHexView > :nth-last-child(2) {
+
+ padding-right: 4px;
+
+}
+
+GtkHexView > :nth-last-child(4) {
+
+ border-right: 1px solid @borders;
+
+}
diff --git a/src/gtkext/hexview.h b/src/gtkext/hexview.h
index 9190548..8d3129d 100644
--- a/src/gtkext/hexview.h
+++ b/src/gtkext/hexview.h
@@ -1,8 +1,8 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * hexdisplay.h - prototypes pour l'affichage d'un contenu binaire sous forme hexadécimale
+ * hexview.h - prototypes pour l'affichage de contenus de binaire
*
- * Copyright (C) 2019 Cyrille Bagard
+ * Copyright (C) 2016-2024 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -17,43 +17,32 @@
* 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/>.
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef _GTKEXT_HEXDISPLAY_H
-#define _GTKEXT_HEXDISPLAY_H
+#ifndef _GTKEXT_HEXVIEW_H
+#define _GTKEXT_HEXVIEW_H
-#include <glib-object.h>
#include <gtk/gtk.h>
-#include "../analysis/content.h"
+#include "../glibext/helpers.h"
-#define GTK_TYPE_HEX_DISPLAY (gtk_hex_display_get_type())
-#define GTK_HEX_DISPLAY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_HEX_DISPLAY, GtkHexDisplay))
-#define GTK_HEX_DISPLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GTK_TYPE_HEX_DISPLAY, GtkHexDisplayClass))
-#define GTK_IS_HEX_DISPLAY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_HEX_DISPLAY))
-#define GTK_IS_HEX_DISPLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GTK_TYPE_HEX_DISPLAY))
-#define GTK_HEX_DISPLAY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_HEX_DISPLAY, GtkHexDisplayClass))
+#define GTK_TYPE_HEX_VIEW (gtk_hex_view_get_type())
+DECLARE_GTYPE(GtkHexView, gtk_hex_view, GTK, HEX_VIEW);
-/* Composant d'affichage de contenu sous forme hexadécimale (instance) */
-typedef struct _GtkHexDisplay GtkHexDisplay;
-/* Composant d'affichage de contenu sous forme hexadécimale (classe) */
-typedef struct _GtkHexDisplayClass GtkHexDisplayClass;
-/* Détermine le type du composant d'affichage sous forme hexadécimale. */
-GType gtk_hex_display_get_type(void);
-/* Crée un nouveau composant pour l'affichage sous forme hexa. */
-GtkWidget *gtk_hex_display_new(GBinContent *);
-#endif /* _GTKEXT_HEXDISPLAY_H */
+
+
+#endif /* _GTKEXT_HEXVIEW_H */
diff --git a/src/gtkext/hexview.ui b/src/gtkext/hexview.ui
new file mode 100644
index 0000000..f0dd8b0
--- /dev/null
+++ b/src/gtkext/hexview.ui
@@ -0,0 +1,32 @@
+<interface>
+ <template class="GtkHexView" parent="GtkWidget">
+ <property name="css-name">GtkHexView</property>
+ <child>
+ <object class="GtkComposingArea" id="offsets">
+ <style>
+ <class name="gutter"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkComposingArea" id="hex">
+ <property name="hexpand">true</property>
+ <style>
+ <class name="custom-view"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkComposingArea" id="ascii">
+ <style>
+ <class name="custom-view"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkScrollbar" id="vscroll">
+ <property name="orientation">1</property>
+ </object>
+ </child>
+ </template>
+</interface>