From e9f10d8fe1c5e9f8a70801c1cd4d3d342e290f15 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Mon, 13 May 2024 23:34:56 +0200
Subject: Introduce a template for the widget providing a hex view.

---
 src/framework.c          |  13 ++
 src/glibext/Makefile.am  |   8 +-
 src/glibext/helpers.h    | 166 ++++++++++++++++++++++
 src/gtkext/Makefile.am   |  13 +-
 src/gtkext/area-int.h    |  51 +++++++
 src/gtkext/area.c        | 231 +++++++++++++++++++++++++++++++
 src/gtkext/area.h        |  51 +++++++
 src/gtkext/gresource.xml |   5 +-
 src/gtkext/hexview.c     | 351 +++++++++++++++++++++++++----------------------
 src/gtkext/hexview.css   |  30 ++++
 src/gtkext/hexview.h     |  33 ++---
 src/gtkext/hexview.ui    |  32 +++++
 12 files changed, 795 insertions(+), 189 deletions(-)
 create mode 100644 src/glibext/helpers.h
 create mode 100644 src/gtkext/area-int.h
 create mode 100644 src/gtkext/area.c
 create mode 100644 src/gtkext/area.h
 create mode 100644 src/gtkext/hexview.css
 create mode 100644 src/gtkext/hexview.ui

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>
-- 
cgit v0.11.2-87-g4458