From 53edb30496d1065019406de16f9f9d96ba61cd3c Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Tue, 18 Jun 2024 08:31:42 +0200 Subject: Rebuild hex views for large contents. --- src/Makefile.am | 5 +- src/common/Makefile.am | 2 +- src/core/core.c | 4 +- src/framework.c | 63 +++ src/glibext/Makefile.am | 33 +- src/glibext/buffercache-int.h | 38 +- src/glibext/buffercache.c | 937 ++++++++++++++++++++----------------- src/glibext/buffercache.h | 72 ++- src/glibext/bufferline-int.h | 94 ++++ src/glibext/bufferline.c | 248 ++++++++-- src/glibext/bufferline.h | 50 +- src/glibext/bufferview-int.h | 83 ++++ src/glibext/bufferview.c | 380 +++++++++++---- src/glibext/bufferview.h | 53 ++- src/glibext/generator-int.h | 51 +- src/glibext/generator.c | 135 +++--- src/glibext/generator.h | 53 +-- src/glibext/generators/Makefile.am | 11 +- src/glibext/generators/hex.c | 469 ++++++++++++++++--- src/glibext/generators/hex.h | 30 +- src/glibext/helpers.h | 34 +- src/glibext/linecolumn.c | 140 ++++-- src/glibext/linecolumn.h | 58 ++- src/glibext/linetoken.c | 627 +++++++++++++++---------- src/glibext/linetoken.h | 74 ++- src/glibext/options/hex.c | 2 +- src/glibext/options/hex.h | 10 + src/glibext/tokenstyle.c | 142 ++++-- src/glibext/tokenstyle.css | 17 +- src/glibext/tokenstyle.h | 19 +- src/glibext/widthtracker-int.h | 80 ++++ src/glibext/widthtracker.c | 556 +++++++++++++--------- src/glibext/widthtracker.h | 39 +- src/gtkext/Makefile.am | 5 +- src/gtkext/bufferview-int.h | 49 +- src/gtkext/bufferview.c | 449 ++++++++++++++++-- src/gtkext/bufferview.h | 38 +- src/gtkext/contentview-int.h | 52 +- src/gtkext/contentview.c | 532 +++++++++++---------- src/gtkext/hexview-int.h | 71 +++ src/gtkext/hexview.c | 437 ++++++++++------- src/gtkext/hexview.h | 8 +- src/gtkext/hexview.ui | 7 +- src/gui/core/Makefile.am | 4 +- src/gui/core/core.c | 76 +++ src/gui/core/core.h | 29 +- 46 files changed, 4456 insertions(+), 1910 deletions(-) create mode 100644 src/glibext/bufferline-int.h create mode 100644 src/glibext/bufferview-int.h create mode 100644 src/glibext/widthtracker-int.h create mode 100644 src/gtkext/hexview-int.h diff --git a/src/Makefile.am b/src/Makefile.am index a01ed63..1250b59 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -81,6 +81,7 @@ libchrysacore4_la_LIBADD = \ arch/libarch4.la \ common/libcommon4.la \ core/libcore4.la \ + glibext/libglibext4.la \ plugins/libplugins.la libchrysacore4_la_LDFLAGS = \ @@ -98,8 +99,10 @@ libchrysacoreui_la_LIBADD = \ gtkext/libgtkext4.la \ gui/libgui4.la +# -lm: log() libchrysacoreui_la_LDFLAGS = \ - $(LIBGTK4_CFLAGS) -L.libs -lchrysacore4 + $(LIBGTK4_CFLAGS) -L.libs -lchrysacore4 \ + -lm diff --git a/src/common/Makefile.am b/src/common/Makefile.am index a57868d..8161f8e 100644 --- a/src/common/Makefile.am +++ b/src/common/Makefile.am @@ -17,7 +17,6 @@ libcommon_la_SOURCES = \ ibuf.h ibuf.c \ io.h io.c \ itoa.h itoa.c \ - fnv1a.h fnv1a.c \ leb128.h leb128.c \ macros.h \ net.h net.c \ @@ -58,6 +57,7 @@ libcommon4_la_SOURCES = \ datatypes.h \ environment.h environment.c \ extstr.h extstr.c \ + fnv1a.h fnv1a.c \ io.h io.c \ leb128.h leb128.c \ packed.h packed.c \ diff --git a/src/core/core.c b/src/core/core.c index addd58c..f67e23d 100644 --- a/src/core/core.c +++ b/src/core/core.c @@ -183,7 +183,7 @@ void unload_all_core_components(bool cs) /****************************************************************************** * * -* Paramètres : selected = liste d'éléments à décharger. * +* Paramètres : flags = liste d'éléments à charger. * * * * Description : Charge une sélection d'éléments de base du programme. * * * @@ -231,7 +231,7 @@ bool load_core_components(AvailableCoreComponent flags) /****************************************************************************** * * -* Paramètres : selected = liste d'éléments à décharger. * +* Paramètres : flags = liste d'éléments à décharger. * * * * Description : Décharge une sélection d'éléments de base du programme. * * * diff --git a/src/framework.c b/src/framework.c index b7a1332..96c97c3 100644 --- a/src/framework.c +++ b/src/framework.c @@ -28,6 +28,9 @@ #include "framework.h" #include "glibext/helpers.h" +#include "gui/core/core.h" +#include "analysis/contents/file.h" // REMME +#include "gtkext/hexview.h" // REMME @@ -249,8 +252,63 @@ static void gtk_chrysalide_framework_activate(GApplication *app) gtk_window_set_title(window, "Chrysalide"); gtk_window_present(window); + + do + { + GBinContent *cnt; + + GtkWidget *parent; + GtkHexView *wgt; + + +#if 0 + + cnt = g_file_content_new("tmp.bin"); + + parent = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5); + gtk_box_set_homogeneous(GTK_BOX(parent), FALSE); + gtk_window_set_child(window, parent); + + wgt = gtk_hex_view_new(cnt); + gtk_box_append(GTK_BOX(parent), GTK_WIDGET(wgt)); + + wgt = gtk_hex_view_new(cnt); + gtk_box_append(GTK_BOX(parent), GTK_WIDGET(wgt)); + +#else + + cnt = g_file_content_new("/bin/id"); + //cnt = g_file_content_new("tmp.bin"); + + + parent = gtk_scrolled_window_new(); + gtk_window_set_child(window, parent); + + wgt = gtk_hex_view_new(cnt); + gtk_scrolled_window_set_child(GTK_SCROLLED_WINDOW(parent), GTK_WIDGET(wgt)); + +#endif + + + + + } + while (0); + + /* Chargement des extensions de thème */ + /* + css = gtk_css_provider_new(); + + gtk_css_provider_load_from_resource(css, "/re/chrysalide/framework/glibext/linestyle.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); + */ + css = gtk_css_provider_new(); gtk_css_provider_load_from_resource(css, "/re/chrysalide/framework/gtkext/hexview.css"); @@ -287,12 +345,17 @@ int main(int argc, char **argv) int result; /* Bilan de l'exécution */ GtkChrysalideFramework *app; /* Gestion d'application GTK */ + if (!load_gui_components(AGC_BUFFER_FEATURES)) + return EXIT_FAILURE; + app = gtk_chrysalide_framework_new(); result = g_application_run(G_APPLICATION(app), argc, argv); g_object_unref(G_OBJECT(app)); + unload_gui_components(AGC_BUFFER_FEATURES); + return result; } diff --git a/src/glibext/Makefile.am b/src/glibext/Makefile.am index ba4e3fa..e2c9d69 100644 --- a/src/glibext/Makefile.am +++ b/src/glibext/Makefile.am @@ -4,10 +4,6 @@ BUILT_SOURCES = chrysamarshal.h chrysamarshal.c resources.h resources.c noinst_LTLIBRARIES = libglibext4.la libglibextui.la # libglibext.la libglibext_la_SOURCES = \ - buffercache-int.h \ - buffercache.h buffercache.c \ - bufferline.h bufferline.c \ - chrysamarshal.h chrysamarshal.c \ comparison-int.h \ comparison.h comparison.c \ configuration-int.h \ @@ -17,11 +13,9 @@ libglibext_la_SOURCES = \ gbinarycursor.h gbinarycursor.c \ gbinportion-int.h \ gbinportion.h gbinportion.c \ - displayoptions.h displayoptions.c \ glinecursor-int.h \ glinecursor.h glinecursor.c \ gnhash.h gnhash.c \ - linecolumn.h linecolumn.c \ notifier.h \ objhole.h \ proto.h \ @@ -35,12 +29,10 @@ libglibext_la_SOURCES = \ if BUILD_GTK_SUPPORT libglibext_la_SOURCES += \ - bufferview.h bufferview.c \ gloadedpanel-int.h \ gloadedpanel.h gloadedpanel.c \ named-int.h \ - named.h named.c \ - widthtracker.h widthtracker.c + named.h named.c endif @@ -51,6 +43,7 @@ libglibext_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) libglibext4_la_SOURCES = \ + chrysamarshal.h chrysamarshal.c \ helpers.h libglibext4_la_CFLAGS = $(TOOLKIT_CFLAGS) @@ -60,19 +53,37 @@ RES_FILES = \ tokenstyle.css libglibextui_la_SOURCES = \ + buffercache-int.h \ + buffercache.h buffercache.c \ + bufferline-int.h \ + bufferline.h bufferline.c \ + bufferview-int.h \ + bufferview.h bufferview.c \ + generator-int.h \ + generator.h generator.c \ + linecolumn.h linecolumn.c \ + linetoken.h linetoken.c \ + options-int.h \ + options.h options.c \ tokenstyle-int.h \ tokenstyle.h tokenstyle.c \ - resources.h resources.c + resources.h resources.c \ + widthtracker-int.h \ + widthtracker.h widthtracker.c libglibextui_la_CFLAGS = $(LIBGTK4_CFLAGS) +libglibextui_la_LIBADD = \ + generators/libglibextgenerators.la \ + options/libglibextoptions.la + devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%) dev_HEADERS = $(libglibext_la_SOURCES:%c=) -#SUBDIRS = generators +SUBDIRS = generators options chrysamarshal.h: chrysamarshal.list diff --git a/src/glibext/buffercache-int.h b/src/glibext/buffercache-int.h index 0e831a2..59d273b 100644 --- a/src/glibext/buffercache-int.h +++ b/src/glibext/buffercache-int.h @@ -33,20 +33,20 @@ /* Informations rattachées à la génération d'une ligne */ -typedef struct _generator_link +typedef struct _generator_link_t { - GLineGenerator *instance; /* Fournisseur de contenu */ + GTokenGenerator *instance; /* Fournisseur de contenu */ size_t repeat; /* Compteur de successions */ -} generator_link; +} generator_link_t; /* Suivi interne de l'état d'une ligne */ -typedef struct _cache_info +typedef struct _cache_info_t { union { - generator_link generator; /* Générateur unique */ - generator_link *generators; /* Liste de générateurs */ + generator_link_t generator; /* Générateur unique */ + generator_link_t *generators; /* Liste de générateurs */ }; size_t count; /* Taille de cette liste */ @@ -54,7 +54,7 @@ typedef struct _cache_info BufferLineFlags extra_flags; /* Propriétés supplémentaires */ -} cache_info; +} cache_info_t; @@ -66,13 +66,25 @@ struct _GBufferCache { GObject parent; /* A laisser en premier */ + size_t opt_count; /* Qté de colonnes en option */ + size_t reg_count; /* Nombre de colonnes normales */ +#ifndef NDEBUG + size_t col_count; /* Nombre maximum de colonnes */ +#endif + + + +#if 0 GBinContent *content; /* Contenu binaire global */ #ifdef INCLUDE_GTK_SUPPORT GWidthTracker *tracker; /* Suivi des largeurs */ #endif +#endif + - cache_info *lines; /* Liste des lignes intégrées */ + + cache_info_t *lines; /* Liste des lignes intégrées */ size_t count; /* Quantité en cache */ size_t used; /* Quantité utilisée */ GRWLock access; /* Verrou de protection */ @@ -84,18 +96,20 @@ struct _GBufferCacheClass { GObjectClass parent; /* A laisser en premier */ - gint line_height; /* Hauteur maximale des lignes */ - gint left_margin; /* Marge gauche + espace */ - gint text_pos; /* Début d'impression du code */ - /* Signaux */ void (* size_changed) (GBufferCache *, bool, size_t, size_t); +#if 0 void (* line_updated) (GBufferCache *, size_t); +#endif }; +/* Met en place un nouveau tampon pour lignes quelconques. */ +bool g_buffer_cache_create(GBufferCache *, size_t, size_t); + + #endif /* _GLIBEXT_BUFFERCACHE_INT_H */ diff --git a/src/glibext/buffercache.c b/src/glibext/buffercache.c index 78c7479..7856ff2 100644 --- a/src/glibext/buffercache.c +++ b/src/glibext/buffercache.c @@ -37,40 +37,45 @@ /* --------------------- FONCTIONS AUXILIAIRES DE MANIPULATIONS --------------------- */ -/* Gros verrou global pour alléger les structures... */ -G_LOCK_DEFINE_STATIC(_line_update); - - /* Met en place un nouvel ensemble d'information sur une ligne. */ -static void init_cache_info(cache_info *, GLineGenerator *, size_t, BufferLineFlags); +static void init_cache_info(cache_info_t *, GTokenGenerator *, size_t, BufferLineFlags); /* Libère la mémoire occupée par des informations sur une ligne. */ -static void release_cache_info(cache_info *); +static void release_cache_info(cache_info_t *); + +/* Force la réinitialisation d'une éventuelle ligne cachée. */ +static void reset_cache_info_line(cache_info_t *); + +/* Suivit les variations du compteur de références d'une ligne. */ +static void on_line_ref_toggle(cache_info_t *, GBufferLine *, gboolean); + +/* Fournit la ligne de tampon correspondant aux générateurs. */ +static GBufferLine *get_cache_info_line(cache_info_t *, size_t, size_t, void *); + +/* Calcule l'indice d'apparition d'un générateur. */ +static size_t compute_cache_info_repetition(const cache_info_t *, GTokenGenerator *); + + + +#if 0 +/* Gros verrou global pour alléger les structures... */ +G_LOCK_DEFINE_STATIC(_line_update); + /* Ajoute un générateur aux informations sur une ligne. */ -static void extend_cache_info(cache_info *, GLineGenerator *, BufferLineFlags); +static void extend_cache_info(cache_info_t *, GLineGenerator *, BufferLineFlags); /* Retire un générateur aux informations d'une ligne. */ -static void remove_from_cache_info(cache_info *, GLineGenerator *); +static void remove_from_cache_info(cache_info_t *, GLineGenerator *); /* Retrouve l'emplacement correspondant à une position de ligne. */ -static void get_cache_info_cursor(const cache_info *, size_t, gint, GLineCursor **); - -/* Suivit les variations du compteur de références d'une ligne. */ -static void on_line_ref_toggle(cache_info *, GBufferLine *, gboolean); +static void get_cache_info_cursor(const cache_info_t *, size_t, gint, GLineCursor **); #ifdef INCLUDE_GTK_SUPPORT -/* Fournit la ligne de tampon correspondant aux générateurs. */ -static GBufferLine *get_cache_info_line(cache_info *, const GWidthTracker *, size_t, const GBinContent *); - #endif -/* Force la réinitialisation d'une éventuelle ligne cachée. */ -static void _reset_cache_info_line_unlocked(cache_info *); - -/* Force la réinitialisation d'une éventuelle ligne cachée. */ -static void reset_cache_info_line(cache_info *); +#endif @@ -78,7 +83,7 @@ static void reset_cache_info_line(cache_info *); /* Taille des allocations de masse */ -#define LINE_ALLOC_BULK 1000 +//#define LINE_ALLOC_BULK 1000 /* Procède à l'initialisation d'une classe de tampon de lignes. */ @@ -93,9 +98,6 @@ static void g_buffer_cache_dispose(GBufferCache *); /* Procède à la libération totale de la mémoire. */ static void g_buffer_cache_finalize(GBufferCache *); -/* Calcule l'indice d'apparition d'un générateur dans le tampon. */ -static size_t g_buffer_cache_compute_repetition(GBufferCache *, size_t, GLineGenerator *); - /* ---------------------------------------------------------------------------------- */ @@ -118,12 +120,12 @@ static size_t g_buffer_cache_compute_repetition(GBufferCache *, size_t, GLineGen * * ******************************************************************************/ -static void init_cache_info(cache_info *info, GLineGenerator *generator, size_t repeat, BufferLineFlags flags) +static void init_cache_info(cache_info_t *info, GTokenGenerator *generator, size_t repeat, BufferLineFlags flags) { info->generator.instance = generator; info->generator.repeat = repeat; - g_object_ref(G_OBJECT(generator)); + ref_object(generator); info->count = 1; @@ -146,16 +148,16 @@ static void init_cache_info(cache_info *info, GLineGenerator *generator, size_t * * ******************************************************************************/ -static void release_cache_info(cache_info *info) +static void release_cache_info(cache_info_t *info) { size_t i; /* Boucle de parcours */ if (info->count == 1) - g_object_unref(G_OBJECT(info->generator.instance)); + unref_object(info->generator.instance); else for (i = 0; i < info->count; i++) - g_object_unref(G_OBJECT(info->generators[i].instance)); + unref_object(info->generators[i].instance); reset_cache_info_line(info); @@ -164,6 +166,155 @@ static void release_cache_info(cache_info *info) /****************************************************************************** * * +* Paramètres : info = informations sur une ligne à venir manipuler. * +* * +* Description : Force la réinitialisation d'une éventuelle ligne cachée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void reset_cache_info_line(cache_info_t *info) +{ + if (info->line != NULL) + { + g_object_remove_toggle_ref(G_OBJECT(info->line), (GToggleNotify)on_line_ref_toggle, info); + + info->line = NULL; + + } + +} + + +/****************************************************************************** +* * +* Paramètres : info = informations sur une ligne à venir manipuler. * +* line = tampon de lignes à venir supprimer au besoin. * +* last = indication sur la valeur du compteur de références. * +* * +* Description : Suivit les variations du compteur de références d'une ligne. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void on_line_ref_toggle(cache_info_t *info, GBufferLine *line, gboolean last) +{ + if (last) + { + assert(info->line != NULL); + + reset_cache_info_line(info); + + } + +} + + +/****************************************************************************** +* * +* Paramètres : info = informations sur une ligne à venir manipuler. * +* index = indice de la ligne à constituer. * +* col_count = quantité de colonnes à considérer. * +* data = éventuelle donnée complémentaire fournie. * +* * +* Description : Fournit la ligne de tampon correspondant aux générateurs. * +* * +* Retour : Ligne déjà en place ou créée pour le besoin. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GBufferLine *get_cache_info_line(cache_info_t *info, size_t index, size_t col_count, void *data) +{ + GBufferLine *result; /* Construction à retourner */ + size_t i; /* Boucle de parcours */ + + result = info->line; + + if (result != NULL) + ref_object(result); + + else + { + result = g_buffer_line_new(col_count); + + //g_buffer_line_add_flag(result, info->extra_flags); + + g_object_add_toggle_ref(G_OBJECT(result), (GToggleNotify)on_line_ref_toggle, info); + + if (info->count == 1) + g_token_generator_populate_line(info->generator.instance, + index, info->generator.repeat, + result, data); + + else + for (i = 0; i < info->count; i++) + g_token_generator_populate_line(info->generators[i].instance, + index, info->generators[i].repeat, + result, data); + + info->line = result; + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : info = informations sur une ligne à consulter. * +* generator = générateur associé à au moins une ligne. * +* * +* Description : Calcule l'indice d'apparition d'un générateur. * +* * +* Retour : Indice de répétition, 0 si aucune. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static size_t compute_cache_info_repetition(const cache_info_t *info, GTokenGenerator *generator) +{ + size_t result; /* Compteur à retourner */ + size_t i; /* Boucle de parcours */ + + result = 0; + + if (info->count == 1) + { + if (info->generator.instance == generator) + result = info->generator.repeat + 1; + + } + + else + for (i = 0; i < info->count; i++) + if (info->generators[i].instance == generator) + { + result = info->generators[i].repeat + 1; + break; + } + + return result; + +} + + + + + +#if 0 +/****************************************************************************** +* * * Paramètres : info = informations concernant une ligne à actualiser. * * generator = générateur à associer à toutes les lignes. * * flags = propriétés supplémentaires à associer à la ligne.* @@ -176,7 +327,7 @@ static void release_cache_info(cache_info *info) * * ******************************************************************************/ -static void extend_cache_info(cache_info *info, GLineGenerator *generator, BufferLineFlags flags) +static void extend_cache_info(cache_info_t *info, GLineGenerator *generator, BufferLineFlags flags) { generator_link first; /* Générateur déjà en place */ generator_link *new; /* Nouveau générateur placé */ @@ -235,7 +386,7 @@ static void extend_cache_info(cache_info *info, GLineGenerator *generator, Buffe * * ******************************************************************************/ -static void remove_from_cache_info(cache_info *info, GLineGenerator *generator) +static void remove_from_cache_info(cache_info_t *info, GLineGenerator *generator) { generator_link *link; /* Accès simplifié */ size_t i; /* Boucle de parcours */ @@ -326,7 +477,7 @@ static void remove_from_cache_info(cache_info *info, GLineGenerator *generator) * * ******************************************************************************/ -static void get_cache_info_cursor(const cache_info *info, size_t index, gint x, GLineCursor **cursor) +static void get_cache_info_cursor(const cache_info_t *info, size_t index, gint x, GLineCursor **cursor) { const generator_link *generator; /* Générateur retenu */ @@ -340,13 +491,34 @@ static void get_cache_info_cursor(const cache_info *info, size_t index, gint x, } + +#ifdef INCLUDE_GTK_SUPPORT + + + + +#endif + + + + +#endif + + +/* ---------------------------------------------------------------------------------- */ +/* TAMPON POUR CODE DESASSEMBLE */ +/* ---------------------------------------------------------------------------------- */ + + +/* Détermine le type du composant de tampon pour gestion de lignes optimisée. */ +G_DEFINE_TYPE(GBufferCache, g_buffer_cache, G_TYPE_OBJECT); + + /****************************************************************************** * * -* Paramètres : info = informations sur une ligne à venir manipuler. * -* line = tampon de lignes à venir supprimer au besoin. * -* last = indication sur la valeur du compteur de références. * +* Paramètres : class = classe de composant GLib à initialiser. * * * -* Description : Suivit les variations du compteur de références d'une ligne. * +* Description : Procède à l'initialisation d'une classe de tampon de lignes. * * * * Retour : - * * * @@ -354,89 +526,124 @@ static void get_cache_info_cursor(const cache_info *info, size_t index, gint x, * * ******************************************************************************/ -static void on_line_ref_toggle(cache_info *info, GBufferLine *line, gboolean last) +static void g_buffer_cache_class_init(GBufferCacheClass *class) { - if (last) - { - G_LOCK(_line_update); + GObjectClass *object; /* Autre version de la classe */ - assert(info->line != NULL); + object = G_OBJECT_CLASS(class); - _reset_cache_info_line_unlocked(info); + object->dispose = (GObjectFinalizeFunc/* ! */)g_buffer_cache_dispose; + object->finalize = (GObjectFinalizeFunc)g_buffer_cache_finalize; - G_UNLOCK(_line_update); + /* Signaux */ - } + g_signal_new("size-changed", + G_TYPE_BUFFER_CACHE, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(GBufferCacheClass, size_changed), + NULL, NULL, + g_cclosure_user_marshal_VOID__BOOLEAN_ULONG_ULONG, + G_TYPE_NONE, 3, G_TYPE_BOOLEAN, G_TYPE_ULONG, G_TYPE_ULONG); -} +#if 0 + g_signal_new("line-updated", + G_TYPE_BUFFER_CACHE, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(GBufferCacheClass, line_updated), + NULL, NULL, + g_cclosure_marshal_VOID__ULONG, + G_TYPE_NONE, 1, G_TYPE_ULONG); -#ifdef INCLUDE_GTK_SUPPORT +#endif + +} /****************************************************************************** * * -* Paramètres : info = informations sur une ligne à venir manipuler. * -* tracker = gestionnaire de largeurs à consulter si besoin est.* -* index = indice de la ligne à constituer. * -* content = éventuel contenu binaire brut à imprimer. * +* Paramètres : cache = composant GLib à initialiser. * * * -* Description : Fournit la ligne de tampon correspondant aux générateurs. * +* Description : Procède à l'initialisation d'un tampon de gestion de lignes. * * * -* Retour : Ligne déjà en place ou créée pour le besoin. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -static GBufferLine *get_cache_info_line(cache_info *info, const GWidthTracker *tracker, size_t index, const GBinContent *content) +static void g_buffer_cache_init(GBufferCache *cache) { - GBufferLine *result; /* Construction à retourner */ - size_t i; /* Boucle de parcours */ +#if 0 - G_LOCK(_line_update); + cache->content = NULL; - result = info->line; + cache->lines = NULL; + cache->count = 0; + cache->used = 0; + g_rw_lock_init(&cache->access); - if (result == NULL) - { - result = g_buffer_line_new(g_width_tracker_count_columns(tracker)); +#ifdef INCLUDE_GTK_SUPPORT + cache->tracker = NULL; +#endif + +#endif - g_buffer_line_add_flag(result, info->extra_flags); +} - g_object_add_toggle_ref(G_OBJECT(result), (GToggleNotify)on_line_ref_toggle, info); + +/****************************************************************************** +* * +* Paramètres : cache = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_buffer_cache_dispose(GBufferCache *cache) +{ +#if 0 + size_t i; /* Boucle de parcours #1 */ + cache_info_t *info; /* Accès direct à une ligne */ + size_t j; /* Boucle de parcours #2 */ + + g_clear_object(&cache->content); + + for (i = 0; i < cache->used; i++) + { + info = &cache->lines[i]; if (info->count == 1) - g_line_generator_print(info->generator.instance, result, index, - info->generator.repeat, content); + g_clear_object(&info->generator.instance); else - for (i = 0; i < info->count; i++) - g_line_generator_print(info->generators[i].instance, result, index, - info->generators[i].repeat, content); + for (j = 0; j < info->count; j++) + g_clear_object(&info->generators[j].instance); - info->line = result; + g_clear_object(&info->line); } - else - g_object_ref(G_OBJECT(result)); +#ifdef INCLUDE_GTK_SUPPORT + g_clear_object(&cache->tracker); +#endif - G_UNLOCK(_line_update); +#endif - return result; + G_OBJECT_CLASS(g_buffer_cache_parent_class)->dispose(G_OBJECT(cache)); } -#endif - - /****************************************************************************** * * -* Paramètres : info = informations sur une ligne à venir manipuler. * +* Paramètres : cache = instance d'objet GLib à traiter. * * * -* Description : Force la réinitialisation d'une éventuelle ligne cachée. * +* Description : Procède à la libération totale de la mémoire. * * * * Retour : - * * * @@ -444,57 +651,100 @@ static GBufferLine *get_cache_info_line(cache_info *info, const GWidthTracker *t * * ******************************************************************************/ -static void _reset_cache_info_line_unlocked(cache_info *info) +static void g_buffer_cache_finalize(GBufferCache *cache) { - if (info->line != NULL) + +#if 0 + size_t i; /* Boucle de parcours */ + cache_info_t *info; /* Accès direct à une ligne */ + + for (i = 0; i < cache->used; i++) { - g_object_remove_toggle_ref(G_OBJECT(info->line), (GToggleNotify)on_line_ref_toggle, info); + info = &cache->lines[i]; - info->line = NULL; + if (info->count > 1) + free(info->generators); } + if (cache->lines != NULL) + free(cache->lines); + + g_rw_lock_clear(&cache->access); + +#endif + + G_OBJECT_CLASS(g_buffer_cache_parent_class)->finalize(G_OBJECT(cache)); + } /****************************************************************************** * * -* Paramètres : info = informations sur une ligne à venir manipuler. * +* Paramètres : opt_count = quantité de colonnes optionnelles. * +* reg_count = quantité de colonnes normales à considérer. * * * -* Description : Force la réinitialisation d'une éventuelle ligne cachée. * +* Description : Crée un nouveau tampon pour lignes quelconques. * * * -* Retour : - * +* Retour : Composant GLib créé. * * * * Remarques : - * * * ******************************************************************************/ -static void reset_cache_info_line(cache_info *info) +GBufferCache *g_buffer_cache_new(size_t opt_count, size_t reg_count) { - G_LOCK(_line_update); + GBufferCache *result; /* Composant à retourner */ - _reset_cache_info_line_unlocked(info); + result = g_object_new(G_TYPE_BUFFER_CACHE, NULL); - G_UNLOCK(_line_update); + if (!g_buffer_cache_create(result, opt_count, reg_count)) + g_clear_object(&result); + + return result; } +/****************************************************************************** +* * +* Paramètres : cache = cache de lignes à initialiser. * +* opt_count = quantité de colonnes optionnelles. * +* reg_count = quantité de colonnes normales à considérer. * +* * +* Description : Met en place un nouveau tampon pour lignes quelconques. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_buffer_cache_create(GBufferCache *cache, size_t opt_count, size_t reg_count) +{ + bool result; /* Bilen à retourner */ + + result = true; -/* ---------------------------------------------------------------------------------- */ -/* TAMPON POUR CODE DESASSEMBLE */ -/* ---------------------------------------------------------------------------------- */ + cache->opt_count = opt_count; + cache->reg_count = reg_count; +#ifndef NDEBUG + cache->col_count = opt_count + reg_count; +#endif -/* Détermine le type du composant de tampon pour gestion de lignes optimisée. */ -G_DEFINE_TYPE(GBufferCache, g_buffer_cache, G_TYPE_OBJECT); + return result; + +} /****************************************************************************** * * -* Paramètres : class = classe de composant GLib à initialiser. * +* Paramètres : cache = tampon de lignes à consulter. * +* opt_count = quantité de colonnes optionnelles. [OUT] * +* reg_count = quantité de colonnes normales à considérer. [OUT]* * * -* Description : Procède à l'initialisation d'une classe de tampon de lignes. * +* Description : Fournit le nombre de colonnes supportées par un tampon. * * * * Retour : - * * * @@ -502,45 +752,76 @@ G_DEFINE_TYPE(GBufferCache, g_buffer_cache, G_TYPE_OBJECT); * * ******************************************************************************/ -static void g_buffer_cache_class_init(GBufferCacheClass *class) +void g_buffer_cache_count_columns(const GBufferCache *cache, size_t *opt_count, size_t *reg_count) { - GObjectClass *object; /* Autre version de la classe */ + *opt_count = cache->opt_count; + *reg_count = cache->reg_count; - object = G_OBJECT_CLASS(class); +} - object->dispose = (GObjectFinalizeFunc/* ! */)g_buffer_cache_dispose; - object->finalize = (GObjectFinalizeFunc)g_buffer_cache_finalize; - class->line_height = 17; - class->left_margin = 2 * class->line_height; - class->text_pos = 2.5 * class->line_height; +/****************************************************************************** +* * +* Paramètres : cache = cache de lignes à mettre à jour. * +* write = précise le type d'accès prévu (lecture/écriture). * +* lock = indique le sens du verrouillage à mener. * +* * +* Description : Met à disposition un encadrement des accès aux lignes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ - /* Signaux */ +void g_buffer_cache_lock_unlock(GBufferCache *cache, bool write, bool lock) +{ + if (write) + { + if (lock) g_rw_lock_writer_lock(&cache->access); + else g_rw_lock_writer_unlock(&cache->access); + } + else + { + if (lock) g_rw_lock_reader_lock(&cache->access); + else g_rw_lock_reader_unlock(&cache->access); + } - g_signal_new("size-changed", - G_TYPE_BUFFER_CACHE, - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET(GBufferCacheClass, size_changed), - NULL, NULL, - g_cclosure_user_marshal_VOID__BOOLEAN_ULONG_ULONG, - G_TYPE_NONE, 3, G_TYPE_BOOLEAN, G_TYPE_ULONG, G_TYPE_ULONG); +} - g_signal_new("line-updated", - G_TYPE_BUFFER_CACHE, - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET(GBufferCacheClass, line_updated), - NULL, NULL, - g_cclosure_marshal_VOID__ULONG, - G_TYPE_NONE, 1, G_TYPE_ULONG); + +/****************************************************************************** +* * +* Paramètres : cache = instance GLib à consulter. * +* * +* Description : Compte le nombre de lignes rassemblées dans un tampon. * +* * +* Retour : Nombre de lignes constituant le tampon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +size_t g_buffer_cache_count_lines(GBufferCache *cache) +{ + size_t result; /* Quantité à retourner */ + + assert(!g_rw_lock_writer_trylock(&cache->access)); + + result = cache->used; + + return result; } /****************************************************************************** * * -* Paramètres : cache = composant GLib à initialiser. * +* Paramètres : cache = instance GLib à modifier. * +* count = quantité totale de lignes à avoir à disposition. * +* generator = générateur à associer à toutes les lignes. * * * -* Description : Procède à l'initialisation d'un tampon de gestion de lignes. * +* Description : Etend un tampon avec un générateur de lignes unique. * * * * Retour : - * * * @@ -548,27 +829,54 @@ static void g_buffer_cache_class_init(GBufferCacheClass *class) * * ******************************************************************************/ -static void g_buffer_cache_init(GBufferCache *cache) +void g_buffer_cache_extend_with(GBufferCache *cache, size_t count, GTokenGenerator *generator) { - cache->content = NULL; + size_t index; /* Point d'insertion */ + size_t repeat; /* Compteur de répétition */ + size_t i; /* Boucle de parcours */ + size_t added; /* Nombre d'ajouts effectués */ - cache->lines = NULL; - cache->count = 0; - cache->used = 0; - g_rw_lock_init(&cache->access); + assert(!g_rw_lock_writer_trylock(&cache->access)); -#ifdef INCLUDE_GTK_SUPPORT - cache->tracker = NULL; -#endif + assert(count >= cache->used); + + if (count > cache->count) + { + cache->lines = realloc(cache->lines, count * sizeof(cache_info_t)); + cache->count = count; + } + + index = cache->used; + + if (index == 0) + repeat = 0; + else + repeat = compute_cache_info_repetition(&cache->lines[index - 1], generator); + + for (i = index; i < count; i++) + init_cache_info(&cache->lines[i], generator, repeat++, BLF_NONE); + + added = count - cache->used; + + cache->used = count; + + if (added > 0) + { + //g_width_tracker_update_added(cache->tracker, index, added); + + g_signal_emit_by_name(cache, "size-changed", true, index, added); + + } } /****************************************************************************** * * -* Paramètres : cache = instance d'objet GLib à traiter. * +* Paramètres : cache = instance GLib à modifier. * +* max = nombre maximal de lignes à conserver. * * * -* Description : Supprime toutes les références externes. * +* Description : Réduit le tampon à une quantité de lignes précise. * * * * Retour : - * * * @@ -576,43 +884,47 @@ static void g_buffer_cache_init(GBufferCache *cache) * * ******************************************************************************/ -static void g_buffer_cache_dispose(GBufferCache *cache) +void g_buffer_cache_truncate(GBufferCache *cache, size_t max) { - size_t i; /* Boucle de parcours #1 */ - cache_info *info; /* Accès direct à une ligne */ - size_t j; /* Boucle de parcours #2 */ + size_t i; /* Boucle de parcours */ + size_t removed; /* Nombre de retraits effectués*/ - g_clear_object(&cache->content); + assert(!g_rw_lock_writer_trylock(&cache->access)); - for (i = 0; i < cache->used; i++) + for (i = max; i < cache->used; i++) + release_cache_info(&cache->lines[i]); + + if (max < cache->used) { - info = &cache->lines[i]; + removed = cache->used - max; - if (info->count == 1) - g_clear_object(&info->generator.instance); + cache->used = max; - else - for (j = 0; j < info->count; j++) - g_clear_object(&info->generators[j].instance); + //g_width_tracker_update_deleted(cache->tracker, max, max + removed - 1); + + g_signal_emit_by_name(cache, "size-changed", false, max, removed); + + } + +} - g_clear_object(&info->line); - } -#ifdef INCLUDE_GTK_SUPPORT - g_clear_object(&cache->tracker); -#endif - G_OBJECT_CLASS(g_buffer_cache_parent_class)->dispose(G_OBJECT(cache)); -} /****************************************************************************** * * -* Paramètres : cache = instance d'objet GLib à traiter. * +* Paramètres : cache = visualisation à représenter. * +* cr = contexte graphique dédié à la procédure. * +* column = (première) colonne à traiter. * +* top = ordonnée attribuée à la première ligne. * +* first = première ligne à dessiner. * +* last = dernière ligne à dessiner. * +* style = style de rendu pour les bribes de texte. * * * -* Description : Procède à la libération totale de la mémoire. * +* Description : Imprime une partie choisie du tampon contenant des lignes. * * * * Retour : - * * * @@ -620,65 +932,47 @@ static void g_buffer_cache_dispose(GBufferCache *cache) * * ******************************************************************************/ -static void g_buffer_cache_finalize(GBufferCache *cache) +void g_buffer_cache_draw(GBufferCache *cache, cairo_t *cr, size_t column, int top, size_t first, size_t last, const GTokenStyle *style) { + int y; /* Point de départ en ordonnée */ + int lheight; /* Hauteur d'une ligne */ size_t i; /* Boucle de parcours */ - cache_info *info; /* Accès direct à une ligne */ + GBufferLine *line; /* Ligne à venir dessiner */ - for (i = 0; i < cache->used; i++) + if (cache->used > 0) { - info = &cache->lines[i]; + y = top; - if (info->count > 1) - free(info->generators); + lheight = g_token_style_get_line_height(style); - } + g_buffer_cache_rlock(cache); - if (cache->lines != NULL) - free(cache->lines); + for (i = first; i <= last; i++) + { + line = get_cache_info_line(&cache->lines[i], i, cache->opt_count + cache->reg_count, NULL); - g_rw_lock_clear(&cache->access); + g_buffer_line_draw(line, cr, column, y, style); - G_OBJECT_CLASS(g_buffer_cache_parent_class)->finalize(G_OBJECT(cache)); + unref_object(line); -} + y += lheight; + } -/****************************************************************************** -* * -* Paramètres : content = éventuel contenu binaire brut à référencer. * -* col_count = quantité maximale de colonnes à considérer. * -* opt_count = quantité de colonnes optionnelles. * -* * -* Description : Crée un nouveau composant de tampon pour code désassemblé. * -* * -* Retour : Composant GLib créé. * -* * -* Remarques : - * -* * -******************************************************************************/ + g_buffer_cache_runlock(cache); -GBufferCache *g_buffer_cache_new(GBinContent *content, size_t col_count, size_t opt_count) -{ - GBufferCache *result; /* Composant à retourner */ + } + +} - result = g_object_new(G_TYPE_BUFFER_CACHE, NULL); - if (content != NULL) - { - result->content = content; - g_object_ref(G_OBJECT(content)); - } -#ifdef INCLUDE_GTK_SUPPORT - result->tracker = g_width_tracker_new(result, col_count, opt_count); -#endif - return result; -} + +#if 0 /****************************************************************************** * * * Paramètres : cache = tampon de lignes à consulter. * @@ -805,107 +1099,10 @@ GWidthTracker *g_buffer_cache_get_width_tracker(const GBufferCache *cache) #endif -/****************************************************************************** -* * -* Paramètres : cache = cache de lignes à mettre à jour. * -* write = précise le type d'accès prévu (lecture/écriture). * -* lock = indique le sens du verrouillage à mener. * -* * -* Description : Met à disposition un encadrement des accès aux lignes. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_buffer_cache_lock_unlock(GBufferCache *cache, bool write, bool lock) -{ - if (write) - { - if (lock) g_rw_lock_writer_lock(&cache->access); - else g_rw_lock_writer_unlock(&cache->access); - } - else - { - if (lock) g_rw_lock_reader_lock(&cache->access); - else g_rw_lock_reader_unlock(&cache->access); - } - -} - - -/****************************************************************************** -* * -* Paramètres : cache = instance GLib à consulter. * -* * -* Description : Compte le nombre de lignes rassemblées dans un tampon. * -* * -* Retour : Nombre de lignes constituant le tampon. * -* * -* Remarques : - * -* * -******************************************************************************/ - -size_t g_buffer_cache_count_lines(GBufferCache *cache) -{ - size_t result; /* Quantité à retourner */ - - assert(!g_rw_lock_writer_trylock(&cache->access)); - - result = cache->used; - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : cache = instance GLib à consulter. * -* index = indice de la ligne où se trouve le générateur. * -* generator = générateur associé à au moins une ligne. * -* * -* Description : Calcule l'indice d'apparition d'un générateur dans le tampon.* -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static size_t g_buffer_cache_compute_repetition(GBufferCache *cache, size_t index, GLineGenerator *generator) -{ - size_t result; /* Compteur à retourner */ - cache_info *info; /* Accès direct à une ligne */ - size_t i; /* Boucle de parcours */ - - result = 0; - - if (index > 0) - { - info = &cache->lines[index - 1]; - - if (info->count == 1) - { - if (info->generator.instance == generator) - result = info->generator.repeat + 1; - - } - else - for (i = 0; i < info->count; i++) - if (info->generators[i].instance == generator) - { - result = info->generators[i].repeat + 1; - break; - } - } - return result; -} /****************************************************************************** @@ -1063,7 +1260,7 @@ void g_buffer_cache_insert_at(GBufferCache *cache, size_t index, GLineGenerator void g_buffer_cache_delete_at(GBufferCache *cache, size_t index) { - cache_info *info; /* Accès direct à une ligne */ + cache_info_t *info; /* Accès direct à une ligne */ assert(!g_rw_lock_writer_trylock(&cache->access)); @@ -1107,7 +1304,7 @@ void g_buffer_cache_delete_at(GBufferCache *cache, size_t index) GLineGenerator *g_buffer_cache_delete_type_at(GBufferCache *cache, size_t index, GType type, bool before, bool after) { GLineGenerator *result; /* Prédécesseur à retourner */ - cache_info *info; /* Accès direct à une ligne */ + cache_info_t *info; /* Accès direct à une ligne */ generator_link *link; /* Accès simplifié */ size_t i; /* Boucle de parcours */ size_t count; /* Emplacements occupés */ @@ -1236,7 +1433,7 @@ void g_buffer_cache_append(GBufferCache *cache, GLineGenerator *generator, Buffe size_t count; /* Nombre de lignes générées */ size_t index; /* Point d'insertion */ size_t i; /* Boucle de parcours */ - cache_info *info; /* Accès direct à une ligne */ + cache_info_t *info; /* Accès direct à une ligne */ size_t repeat; /* Compteur de répétition */ assert(!g_rw_lock_writer_trylock(&cache->access)); @@ -1255,146 +1452,37 @@ void g_buffer_cache_append(GBufferCache *cache, GLineGenerator *generator, Buffe index = cache->used; - for (i = 0; i < count; i++) - { - info = &cache->lines[index + i]; - - repeat = g_buffer_cache_compute_repetition(cache, index + i, generator); - - init_cache_info(info, generator, repeat, flags); - - } - - cache->used += count; - -#ifdef INCLUDE_GTK_SUPPORT - g_width_tracker_update_added(cache->tracker, index, count); -#endif - - g_signal_emit_by_name(cache, "size-changed", true, index, count); - -} - - -/****************************************************************************** -* * -* Paramètres : cache = instance GLib à modifier. * -* count = quantité totale de lignes à avoir à disposition. * -* generator = générateur à associer à toutes les lignes. * -* * -* Description : Etend un tampon avec un générateur de lignes unique. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_buffer_cache_extend_with(GBufferCache *cache, size_t count, GLineGenerator *generator) -{ - size_t index; /* Point d'insertion */ - size_t i; /* Boucle de parcours */ - cache_info *info; /* Accès direct à une ligne */ - size_t repeat; /* Compteur de répétition */ - size_t added; /* Nombre d'ajouts effectués */ - - assert(!g_rw_lock_writer_trylock(&cache->access)); - assert(count >= cache->used); + if (index == 0) + repeat = 0; - if (count > cache->count) + else { - cache->lines = realloc(cache->lines, count * sizeof(cache_info)); - cache->count = count; + info = &cache->lines[index - 1]; + repeat = compute_cache_info_repetition(info, generator); } - index = cache->used; - - for (i = index; i < count; i++) + for (i = 0; i < count; i++) { - info = &cache->lines[i]; - - repeat = g_buffer_cache_compute_repetition(cache, i, generator); - - init_cache_info(info, generator, repeat, BLF_NONE); - + info = &cache->lines[index + i]; + init_cache_info(info, generator, repeat++, flags); } - added = count - cache->used; + cache->used += count; - cache->used = count; + /* - if (added > 0) - { #ifdef INCLUDE_GTK_SUPPORT - g_width_tracker_update_added(cache->tracker, index, added); + g_width_tracker_update_added(cache->tracker, index, count); #endif - g_signal_emit_by_name(cache, "size-changed", true, index, added); + g_signal_emit_by_name(cache, "size-changed", true, index, count); - } + */ } -/****************************************************************************** -* * -* Paramètres : cache = instance GLib à modifier. * -* max = nombre maximal de lignes à conserver. * -* * -* Description : Réduit le tampon à une quantité de lignes précise. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_buffer_cache_truncate(GBufferCache *cache, size_t max) -{ - size_t i; /* Boucle de parcours #1 */ - cache_info *info; /* Accès direct à une ligne */ - size_t j; /* Boucle de parcours #2 */ - size_t removed; /* Nombre de retraits effectués*/ - - assert(!g_rw_lock_writer_trylock(&cache->access)); - - for (i = max; i < cache->used; i++) - { - info = &cache->lines[i]; - - if (info->count == 1) - g_object_unref(G_OBJECT(info->generator.instance)); - - else - { - for (j = 0; j < info->count; j++) - g_object_unref(G_OBJECT(info->generators[j].instance)); - - free(info->generators); - - } - - reset_cache_info_line(info); - - } - - if (max < cache->used) - { - removed = cache->used - max; - - cache->used = max; - -#ifdef INCLUDE_GTK_SUPPORT - g_width_tracker_update_deleted(cache->tracker, max, max + removed - 1); -#endif - - g_signal_emit_by_name(cache, "size-changed", false, max, removed); - - } - -} - #ifdef INCLUDE_GTK_SUPPORT @@ -1444,7 +1532,7 @@ void g_buffer_cache_get_line_cursor(GBufferCache *cache, size_t index, gint x, G void g_buffer_cache_add_line_flag(GBufferCache *cache, size_t index, BufferLineFlags flag) { - cache_info *info; /* Accès direct à une ligne */ + cache_info_t *info; /* Accès direct à une ligne */ assert(!g_rw_lock_writer_trylock(&cache->access)); @@ -1482,7 +1570,7 @@ void g_buffer_cache_add_line_flag(GBufferCache *cache, size_t index, BufferLineF BufferLineFlags g_buffer_cache_get_line_flags(GBufferCache *cache, size_t index) { BufferLineFlags result; /* Somme à renvoyer */ - cache_info *info; /* Accès direct à une ligne */ + cache_info_t *info; /* Accès direct à une ligne */ const generator_link *generator; /* Générateur retenu */ size_t i; /* Boucle de parcours */ @@ -1528,7 +1616,7 @@ BufferLineFlags g_buffer_cache_get_line_flags(GBufferCache *cache, size_t index) void g_buffer_cache_remove_line_flag(GBufferCache *cache, size_t index, BufferLineFlags flag) { - cache_info *info; /* Accès direct à une ligne */ + cache_info_t *info; /* Accès direct à une ligne */ assert(!g_rw_lock_writer_trylock(&cache->access)); @@ -1621,7 +1709,7 @@ size_t g_buffer_cache_look_for_flag(GBufferCache *cache, size_t start, BufferLin void g_buffer_cache_refresh_line(GBufferCache *cache, size_t index) { - cache_info *info; /* Accès direct à une ligne */ + cache_info_t *info; /* Accès direct à une ligne */ assert(!g_rw_lock_writer_trylock(&cache->access)); @@ -1689,6 +1777,8 @@ void g_buffer_cache_collect_widths(GBufferCache *cache, size_t index, size_t col { GBufferLine *line; /* Ligne éphémère à mesurer */ + // Need lock + line = get_cache_info_line(&cache->lines[index], cache->tracker, index, cache->content); g_buffer_line_collect_widths(line, col_count, opt_count, widths, merged); @@ -1723,7 +1813,7 @@ void g_buffer_cache_draw(const GBufferCache *cache, cairo_t *cr, size_t first, s gint y; /* Point de départ en ordonnée */ bool wait_selection; /* Sélection déjà passée ? */ size_t i; /* Boucle de parcours */ - cache_info *info; /* Accès direct à une ligne */ + cache_info_t *info; /* Accès direct à une ligne */ GBufferLine *line; /* Ligne à venir dessiner */ class = G_BUFFER_CACHE_GET_CLASS(cache); @@ -1749,6 +1839,8 @@ void g_buffer_cache_draw(const GBufferCache *cache, cairo_t *cr, size_t first, s info = &cache->lines[i]; + // Need lock + line = get_cache_info_line(info, cache->tracker, i, cache->content); g_buffer_line_draw(line, i, cr, class->text_pos, y, cache->tracker, options, list); @@ -1784,11 +1876,11 @@ void g_buffer_cache_draw(const GBufferCache *cache, cairo_t *cr, size_t first, s size_t _g_buffer_cache_find_index_by_cursor(GBufferCache *cache, const GLineCursor *cursor, bool first, size_t start, size_t end) { size_t result; /* Indice à retourner */ - cache_info *found; /* Eventuel élément trouvé */ + cache_info_t *found; /* Eventuel élément trouvé */ assert(!g_rw_lock_writer_trylock(&cache->access)); - int find_containing_generator(const GLineCursor *c, const cache_info *i) + int find_containing_generator(const GLineCursor *c, const cache_info_t *i) { const generator_link *generator; /* Générateur retenu */ @@ -1802,7 +1894,7 @@ size_t _g_buffer_cache_find_index_by_cursor(GBufferCache *cache, const GLineCurs } - found = (cache_info *)bsearch(cursor, &cache->lines[start], end - start + 1, + found = (cache_info_t *)bsearch(cursor, &cache->lines[start], end - start + 1, sizeof(cache_info), (__compar_fn_t)find_containing_generator); if (found == NULL) @@ -1898,7 +1990,7 @@ bool g_buffer_cache_get_cursor_coordinates(GBufferCache *cache, const GLineCurso bool result; /* Bilan à retourner */ size_t index; /* Indice de correspondance */ gint lheight; /* Hauteur d'une ligne */ - const cache_info *info; /* Infos sur une ligne donnée */ + const cache_info_t *info; /* Infos sur une ligne donnée */ const generator_link *generator; /* Générateur retenu */ assert(!g_rw_lock_writer_trylock(&cache->access)); @@ -1944,3 +2036,4 @@ bool g_buffer_cache_get_cursor_coordinates(GBufferCache *cache, const GLineCurso #endif +#endif diff --git a/src/glibext/buffercache.h b/src/glibext/buffercache.h index 68941c5..87aae4e 100644 --- a/src/glibext/buffercache.h +++ b/src/glibext/buffercache.h @@ -25,6 +25,57 @@ #define _GLIBEXT_BUFFERCACHE_H +#include + + +#include "helpers.h" +#include "generator.h" + + + +#define G_TYPE_BUFFER_CACHE (g_buffer_cache_get_type()) + +DECLARE_GTYPE(GBufferCache, g_buffer_cache, G, BUFFER_CACHE); + + +/* Crée un nouveau tampon pour lignes quelconques. */ +GBufferCache *g_buffer_cache_new(size_t, size_t); + +/* Fournit le nombre de colonnes supportées par un tampon. */ +void g_buffer_cache_count_columns(const GBufferCache *, size_t *, size_t *); + +/* Met à disposition un encadrement des accès aux lignes. */ +void g_buffer_cache_lock_unlock(GBufferCache *, bool, bool); + +#define g_buffer_cache_wlock(cache) g_buffer_cache_lock_unlock(cache, true, true); +#define g_buffer_cache_wunlock(cache) g_buffer_cache_lock_unlock(cache, true, false); + +#define g_buffer_cache_rlock(cache) g_buffer_cache_lock_unlock(cache, false, true); +#define g_buffer_cache_runlock(cache) g_buffer_cache_lock_unlock(cache, false, false); + +/* Compte le nombre de lignes rassemblées dans un tampon. */ +size_t g_buffer_cache_count_lines(GBufferCache *); + +/* Etend un tampon avec un générateur de lignes unique. */ +void g_buffer_cache_extend_with(GBufferCache *, size_t, GTokenGenerator *); + +/* Réduit le tampon à une quantité de lignes précise. */ +void g_buffer_cache_truncate(GBufferCache *, size_t); + + + + +/* Imprime une partie choisie du tampon contenant des lignes. */ +void g_buffer_cache_draw(GBufferCache *, cairo_t *, size_t, int, size_t, size_t, const GTokenStyle *); + + + + + + + +#if 0 + #include #include #ifdef INCLUDE_GTK_SUPPORT @@ -84,18 +135,18 @@ GWidthTracker *g_buffer_cache_get_width_tracker(const GBufferCache *); #endif /* Met à disposition un encadrement des accès aux lignes. */ -void g_buffer_cache_lock_unlock(GBufferCache *, bool, bool); +//void g_buffer_cache_lock_unlock(GBufferCache *, bool, bool); -#define g_buffer_cache_wlock(cache) g_buffer_cache_lock_unlock(cache, true, true); -#define g_buffer_cache_wunlock(cache) g_buffer_cache_lock_unlock(cache, true, false); +//#define g_buffer_cache_wlock(cache) g_buffer_cache_lock_unlock(cache, true, true); +//#define g_buffer_cache_wunlock(cache) g_buffer_cache_lock_unlock(cache, true, false); -#define g_buffer_cache_rlock(cache) g_buffer_cache_lock_unlock(cache, false, true); -#define g_buffer_cache_runlock(cache) g_buffer_cache_lock_unlock(cache, false, false); +//#define g_buffer_cache_rlock(cache) g_buffer_cache_lock_unlock(cache, false, true); +//#define g_buffer_cache_runlock(cache) g_buffer_cache_lock_unlock(cache, false, false); /* Compte le nombre de lignes rassemblées dans un tampon. */ -size_t g_buffer_cache_count_lines(GBufferCache *); +//size_t g_buffer_cache_count_lines(GBufferCache *); /* Insère un générateur dans des lignes à une position donnée. */ void g_buffer_cache_insert_at(GBufferCache *, size_t, GLineGenerator *, BufferLineFlags, bool, bool); @@ -110,10 +161,10 @@ GLineGenerator *g_buffer_cache_delete_type_at(GBufferCache *, size_t, GType, boo void g_buffer_cache_append(GBufferCache *, GLineGenerator *, BufferLineFlags); /* Etend un tampon avec un générateur de lignes unique. */ -void g_buffer_cache_extend_with(GBufferCache *, size_t, GLineGenerator *); +//void g_buffer_cache_extend_with(GBufferCache *, size_t, GLineGenerator *); /* Réduit le tampon à une quantité de lignes précise. */ -void g_buffer_cache_truncate(GBufferCache *, size_t); +//void g_buffer_cache_truncate(GBufferCache *, size_t); #ifdef INCLUDE_GTK_SUPPORT @@ -146,7 +197,7 @@ GBufferLine *g_buffer_cache_find_line_by_index(GBufferCache *, size_t); void g_buffer_cache_collect_widths(GBufferCache *, size_t, size_t, size_t, gint *, gint *); /* Imprime une partie choisie du tampon contenant des lignes. */ -void g_buffer_cache_draw(const GBufferCache *, cairo_t *, size_t, size_t, const cairo_rectangle_int_t *, const GDisplayOptions *, const gint *, const segcnt_list *); +//void g_buffer_cache_draw(const GBufferCache *, cairo_t *, size_t, size_t, const cairo_rectangle_int_t *, const GDisplayOptions *, const gint *, const segcnt_list *); #endif @@ -164,5 +215,8 @@ bool g_buffer_cache_get_cursor_coordinates(GBufferCache *, const GLineCursor *, #endif +#endif + + #endif /* _GLIBEXT_BUFFERCACHE_H */ diff --git a/src/glibext/bufferline-int.h b/src/glibext/bufferline-int.h new file mode 100644 index 0000000..8bee3c2 --- /dev/null +++ b/src/glibext/bufferline-int.h @@ -0,0 +1,94 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * bufferline-int.h - prototypes pour la définition interne d'une représentation de fragments de texte en ligne + * + * 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 . + */ + + +#ifndef _GLIBEXT_BUFFERLINE_INT_H +#define _GLIBEXT_BUFFERLINE_INT_H + + +#include "bufferline.h" +#include "linecolumn.h" + + + +#if 0 +/* Mémorisation des origines de texte */ +typedef struct _content_origin +{ + col_coord_t coord; /* Localisation d'attachement */ + + GObject *creator; /* Origine de la création */ + +} content_origin; +#endif + + +/* Représentation de fragments de texte en ligne (instance) */ +struct _GBufferLine +{ + GObject parent; /* A laisser en premier */ + + line_column_t *columns; /* Répartition du texte */ + size_t col_count; /* Nombre de colonnes présentes*/ + size_t merge_start; /* Début de la zone globale */ + + BufferLineFlags flags; /* Drapeaux particuliers */ + +#if 0 + + content_origin *origins; /* Mémorisation des origines */ + size_t ocount; /* Nombre de ces mémorisations */ + +#endif + +}; + +/* Représentation de fragments de texte en ligne (classe) */ +struct _GBufferLineClass +{ + GObjectClass parent; /* A laisser en premier */ + +#if 0 + +#ifdef INCLUDE_GTK_SUPPORT + cairo_surface_t *entrypoint_img; /* Image pour les entrées */ + cairo_surface_t *bookmark_img; /* Image pour les signets */ +#endif + + /* Signaux */ + + void (* content_changed) (GBufferLine *, line_segment *); + + void (* flip_flag) (GBufferLine *, BufferLineFlags, BufferLineFlags); + +#endif + +}; + + + +/* Met en place une nouvelle représentation de bribes de texte. */ +bool g_buffer_line_create(GBufferLine *, size_t); + + + +#endif /* _GLIBEXT_BUFFERLINE_INT_H */ diff --git a/src/glibext/bufferline.c b/src/glibext/bufferline.c index 2bdfebc..4862e9f 100644 --- a/src/glibext/bufferline.c +++ b/src/glibext/bufferline.c @@ -24,63 +24,27 @@ #include "bufferline.h" +#include "bufferline-int.h" + + + +#if 0 + #include #include #include #include "chrysamarshal.h" -#include "linecolumn.h" +//#include "linecolumn.h" #include "../common/extstr.h" #include "../core/paths.h" - - -/* ---------------------------- GESTION DE LINE COMPLETE ---------------------------- */ - - -/* Mémorisation des origines de texte */ -typedef struct _content_origin -{ - col_coord_t coord; /* Localisation d'attachement */ - - GObject *creator; /* Origine de la création */ - -} content_origin; - -/* Représentation de fragments de texte en ligne (instance) */ -struct _GBufferLine -{ - GObject parent; /* A laisser en premier */ - - line_column *columns; /* Répartition du texte */ - size_t col_count; /* Nombre de colonnes présentes*/ - size_t merge_start; /* Début de la zone globale */ - - BufferLineFlags flags; /* Drapeaux particuliers */ - - content_origin *origins; /* Mémorisation des origines */ - size_t ocount; /* Nombre de ces mémorisations */ - -}; - -/* Représentation de fragments de texte en ligne (classe) */ -struct _GBufferLineClass -{ - GObjectClass parent; /* A laisser en premier */ - -#ifdef INCLUDE_GTK_SUPPORT - cairo_surface_t *entrypoint_img; /* Image pour les entrées */ - cairo_surface_t *bookmark_img; /* Image pour les signets */ #endif - /* Signaux */ - void (* content_changed) (GBufferLine *, line_segment *); - void (* flip_flag) (GBufferLine *, BufferLineFlags, BufferLineFlags); - -}; +/* ---------------------------- GESTION DE LINE COMPLETE ---------------------------- */ /* Procède à l'initialisation d'une classe de représentation. */ @@ -106,7 +70,6 @@ static void g_buffer_line_finalize(GBufferLine *); G_DEFINE_TYPE(GBufferLine, g_buffer_line, G_TYPE_OBJECT); - /****************************************************************************** * * * Paramètres : class = classe de composant GTK à initialiser. * @@ -131,6 +94,9 @@ static void g_buffer_line_class_init(GBufferLineClass *class) object->dispose = (GObjectFinalizeFunc/* ! */)g_buffer_line_dispose; object->finalize = (GObjectFinalizeFunc)g_buffer_line_finalize; + +#if 0 + #ifdef INCLUDE_GTK_SUPPORT filename = find_pixmap_file("entrypoint.png"); @@ -165,12 +131,14 @@ static void g_buffer_line_class_init(GBufferLineClass *class) g_cclosure_user_marshal_VOID__ENUM_ENUM, G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT); +#endif + } /****************************************************************************** * * -* Paramètres : line = composant GTK à initialiser. * +* Paramètres : line = composant GLib à initialiser. * * * * Description : Procède à l'initialisation d'une représentation de fragments.* * * @@ -203,10 +171,12 @@ static void g_buffer_line_init(GBufferLine *line) static void g_buffer_line_dispose(GBufferLine *line) { +#if 0 size_t i; /* Boucle de parcours */ for (i = 0; i < line->ocount; i++) g_object_unref(G_OBJECT(line->origins[i].creator)); +#endif G_OBJECT_CLASS(g_buffer_line_parent_class)->dispose(G_OBJECT(line)); @@ -235,8 +205,10 @@ static void g_buffer_line_finalize(GBufferLine *line) if (line->columns != NULL) free(line->columns); +#if 0 if (line->origins != NULL) free(line->origins); +#endif G_OBJECT_CLASS(g_buffer_line_parent_class)->finalize(G_OBJECT(line)); @@ -258,22 +230,195 @@ static void g_buffer_line_finalize(GBufferLine *line) GBufferLine *g_buffer_line_new(size_t col_count) { GBufferLine *result; /* Composant à retourner */ - size_t i; /* Boucle de parcours */ result = g_object_new(G_TYPE_BUFFER_LINE, NULL); - result->columns = malloc(col_count * sizeof(line_column)); + if (!g_buffer_line_create(result, col_count)) + g_clear_object(&result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : line = ligne de représentation à initialiser. * +* col_count = quantité de colonnes à considérer. * +* * +* Description : Met en place une nouvelle représentation de bribes de texte. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_buffer_line_create(GBufferLine *line, size_t col_count) +{ + bool result; /* Bilen à retourner */ + size_t i; /* Boucle de parcours */ + + result = true; + + line->columns = malloc(col_count * sizeof(line_column_t)); for (i = 0; i < col_count; i++) - init_line_column(&result->columns[i]); + init_line_column(&line->columns[i]); - result->col_count = col_count; + line->col_count = col_count; return result; } + + + + + + + +/****************************************************************************** +* * +* Paramètres : line = ligne à venir compléter. * +* column = colonne de la ligne visée par l'insertion. * +* tag = type de décorateur à utiliser. * +* text = texte à insérer dans l'existant. * +* length = taille du texte à traiter. * +* style = gestionnaire de paramètres de rendu à consulter. * +* creator = instance GLib quelconque à associer. * +* * +* Description : Ajoute du texte à formater dans une ligne donnée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_buffer_line_append_text(GBufferLine *line, size_t column, TokenRenderingTag tag, const char *text, size_t length, const GTokenStyle *style, GObject *creator) +{ + size_t index; /* Indice d'insertion */ + //content_origin *origin; /* Définition d'une origine */ + + assert(column < line->col_count); + assert(length > 0); + + index = append_text_to_line_column(&line->columns[column], tag, text, length, style); + + /* + if (creator != NULL) + { + line->origins = realloc(line->origins, ++line->ocount * sizeof(content_origin)); + + origin = &line->origins[line->ocount - 1]; + + origin->coord.column = column; + origin->coord.index = index; + + origin->creator = creator; + g_object_ref(G_OBJECT(creator)); + + } + */ + +} + + + + + + + + + + + +/****************************************************************************** +* * +* Paramètres : line = ligne de texte à manipuler. * +* cr = contexte graphique dédié à la procédure. * +* column = (première) colonne à traiter. * +* y = ordonnée du point d'impression. * +* style = style de rendu pour les bribes de texte. * +* * +* Description : Imprime la ligne de texte représentée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_buffer_line_draw(const GBufferLine *line, cairo_t *cr, size_t column, int y, const GTokenStyle *style) +{ +#if 0 + GBufferLineClass *class; /* Stockage de briques de base */ + bool has_src_surface; /* Note une présence définie */ +#endif + size_t max_column; /* Borne de fin des colonnes */ + int x; /* Point de départ d'impression*/ + size_t i; /* Boucle de parcours */ + + /* + if (line->flags != BLF_NONE) + { + class = G_BUFFER_LINE_GET_CLASS(line); + + if (line->flags & BLF_ENTRYPOINT) + { + cairo_set_source_surface(cairo, class->entrypoint_img, 5, y); + has_src_surface = true; + } + else if (line->flags & BLF_BOOKMARK) + { + cairo_set_source_surface(cairo, class->bookmark_img, 5, y); + has_src_surface = true; + } + else + has_src_surface = false; + + if (has_src_surface) + cairo_paint(cairo); + + } + */ + + + /* Détermination de l'éventail des colonnes à traiter */ + + if (column == line->merge_start) + max_column = line->col_count; + + else if (column > line->merge_start) + max_column = 0; + + else + max_column = column + 1; + + /* Dessin du contenu de ces colonnes */ + + x = 0; + + for (i = column; i < max_column; i++) + draw_line_column(&line->columns[i], cr, &x, y, style); + +} + + + + + + + + + + +#if 0 + + /****************************************************************************** * * * Paramètres : line = ligne à venir compléter. * @@ -1492,3 +1637,6 @@ void g_buffer_line_draw(GBufferLine *line, size_t index, cairo_t *cairo, gint x_ #endif + + +#endif diff --git a/src/glibext/bufferline.h b/src/glibext/bufferline.h index f5f25d0..d6a2e2d 100644 --- a/src/glibext/bufferline.h +++ b/src/glibext/bufferline.h @@ -25,10 +25,21 @@ #define _GLIBEXT_BUFFERLINE_H -#include #include +#include "helpers.h" +#include "tokenstyle.h" + + + + + +#if 0 + +#include + + #include "gdisplayoptions.h" #include "linesegment.h" #ifdef INCLUDE_GTK_SUPPORT @@ -60,6 +71,14 @@ typedef struct _GBufferLineClass GBufferLineClass; /* Espace entre les colonnes */ #define COL_MARGIN 23 +#endif + + + +#define G_TYPE_BUFFER_LINE (g_buffer_line_get_type()) + +DECLARE_GTYPE(GBufferLine, g_buffer_line, G, BUFFER_LINE); + /* Propriétés particulières supplémentaires */ typedef enum _BufferLineFlags @@ -76,12 +95,28 @@ typedef enum _BufferLineFlags } BufferLineFlags; -/* Détermine le type de la représentation de fragments de texte en ligne. */ -GType g_buffer_line_get_type(void); - /* Crée une nouvelle représentation de fragments de texte. */ GBufferLine *g_buffer_line_new(size_t); + + +/* Ajoute du texte à formater dans une ligne donnée. */ +void g_buffer_line_append_text(GBufferLine *, size_t, TokenRenderingTag, const char *, size_t, const GTokenStyle *, GObject *); + + + +/* Imprime la ligne de texte représentée. */ +void g_buffer_line_draw(const GBufferLine *, cairo_t *, size_t, int, const GTokenStyle *); + + + + + +#if 0 + +/* Détermine le type de la représentation de fragments de texte en ligne. */ +GType g_buffer_line_get_type(void); + /* Construit le tronc commun d'une ligne autour de sa position. */ void g_buffer_line_fill_phys(GBufferLine *, size_t, MemoryDataSize, const vmpa2t *); @@ -95,7 +130,7 @@ void g_buffer_line_fill_content(GBufferLine *, size_t, const GBinContent *, cons GObject *g_buffer_line_find_first_segment_creator(const GBufferLine *, size_t); /* Ajoute du texte à formater dans une ligne donnée. */ -void g_buffer_line_append_text(GBufferLine *, size_t, const char *, size_t, RenderingTagType, GObject *); +//void g_buffer_line_append_text(GBufferLine *, size_t, const char *, size_t, RenderingTagType, GObject *); /* Remplace du texte dans une ligne donnée. */ bool g_buffer_line_replace_text(GBufferLine *, const GObject *, const char *, size_t); @@ -162,7 +197,10 @@ GObject *g_buffer_line_get_creator_at(const GBufferLine *, size_t, GWidthTracker bool g_buffer_line_find_near_coord(const GBufferLine *, size_t, col_coord_t *, GWidthTracker *, const GDisplayOptions *, GdkScrollDirection, gint *); /* Imprime la ligne de texte représentée. */ -void g_buffer_line_draw(GBufferLine *, size_t, cairo_t *, gint, gint, GWidthTracker *, const GDisplayOptions *, const segcnt_list *); +//void g_buffer_line_draw(GBufferLine *, size_t, cairo_t *, gint, gint, GWidthTracker *, const GDisplayOptions *, const segcnt_list *); + +#endif + #endif diff --git a/src/glibext/bufferview-int.h b/src/glibext/bufferview-int.h new file mode 100644 index 0000000..7751c1e --- /dev/null +++ b/src/glibext/bufferview-int.h @@ -0,0 +1,83 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * bufferview.h - prototypes pour l'affichage d'une vue particulière d'un tampon de lignes + * + * Copyright (C) 2016-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 . + */ + + +#ifndef _GLIBEXT_BUFFERVIEW_INT_H +#define _GLIBEXT_BUFFERVIEW_INT_H + + +#include "bufferview.h" + + +/* Vue d'un tampon pour code désassemblé (instance) */ +struct _GBufferView +{ + GObject parent; /* A laisser en premier */ + + GBufferCache *cache; /* Tampon du contenu visualisé */ + GWidthTracker *tracker; /* Collecteur de largeurs */ + GTokenStyle *style; /* Style dédié aux rendus */ + + + + bool unrestricted; /* Validité des informations */ + + + size_t first; /* Indice de la première ligne */ + size_t last; /* Indice de la dernière ligne */ + + +#if 0 + + segcnt_list *highlighted; /* Segments mis en évidence */ + + //bool unrestricted; /* Validité des informations */ + GLineCursor *start; /* Première ligne intégrée */ + GLineCursor *end; /* Dernière ligne intégrée */ + + //size_t first; /* Indice de la première ligne */ + //size_t last; /* Indice de la dernière ligne */ + + GWidthTracker *tracker; /* Suivi des largeurs */ + +#endif + +}; + +/* Vue d'un tampon pour code désassemblé (classe) */ +struct _GBufferViewClass +{ + GObjectClass parent; /* A laisser en premier */ + + /* Signaux */ + + void (* need_redraw) (GBufferView *); + +}; + + +/* Met en place une nouvelle vue pour un tampon de texte. */ +bool g_buffer_view_create(GBufferView *, GBufferCache *, GTokenStyle *); + + + +#endif /* _GLIBEXT_BUFFERVIEW_INT_H */ diff --git a/src/glibext/bufferview.c b/src/glibext/bufferview.c index 72740b1..3747e2c 100644 --- a/src/glibext/bufferview.c +++ b/src/glibext/bufferview.c @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * bufferview.c - affichage d'une vue particulière d'un tampon de lignes * - * Copyright (C) 2016-2019 Cyrille Bagard + * Copyright (C) 2016-2024 Cyrille Bagard * * This file is part of Chrysalide. * @@ -24,46 +24,17 @@ #include "bufferview.h" -#include - +#include "bufferview-int.h" -/* Vue d'un tampon pour code désassemblé (instance) */ -struct _GBufferView -{ - GObject parent; /* A laisser en premier */ - GBufferCache *cache; /* Tampon du contenu visualisé */ - - segcnt_list *highlighted; /* Segments mis en évidence */ - - bool unrestricted; /* Validité des informations */ - GLineCursor *start; /* Première ligne intégrée */ - GLineCursor *end; /* Dernière ligne intégrée */ - - size_t first; /* Indice de la première ligne */ - size_t last; /* Indice de la dernière ligne */ - - GWidthTracker *tracker; /* Suivi des largeurs */ - -}; - -/* Vue d'un tampon pour code désassemblé (classe) */ -struct _GBufferViewClass -{ - GObjectClass parent; /* A laisser en premier */ - - /* Signaux */ - - void (* need_redraw) (GBufferView *); - -}; +/* -------------------------- DEFINITION D'UN NOUVEL OBJET -------------------------- */ /* Procède à l'initialisation d'une classe de vue de tampon. */ static void g_buffer_view_class_init(GBufferViewClass *); -/* Procède à l'initialisation d'une vue d'un tampon pour code. */ +/* Procède à l'initialisation d'une vue d'un tampon. */ static void g_buffer_view_init(GBufferView *); /* Supprime toutes les références externes. */ @@ -75,23 +46,15 @@ static void g_buffer_view_finalize(GBufferView *); /* Accompagne une variation de la quantité de lignes du tampon. */ static void on_buffer_cache_size_changed(const GBufferCache *, bool, size_t, size_t, GBufferView *); -/* Réagit à la modification d'une ligne du tampon. */ -static void on_buffer_cache_line_updated(const GBufferCache *, size_t, GBufferView *); - -/* Calcule la position idéale de curseur pour un point donné. */ -static bool _g_buffer_view_compute_caret_full(GBufferView *, gint, GBufferLine *, size_t, const GDisplayOptions *, cairo_rectangle_int_t *, GLineCursor **); - -/* Fournit la ligne présente à une ordonnée donnée. */ -static GBufferLine *g_buffer_view_find_line_at(GBufferView *, gint, size_t *); - -/* Déplace le curseur au sein d'une vue de tampon. */ -static bool _g_buffer_view_move_caret(GBufferView *, const GBufferLine *, size_t, cairo_rectangle_int_t *, bool, GdkScrollDirection, const GDisplayOptions *); +/* ---------------------------------------------------------------------------------- */ +/* DEFINITION D'UN NOUVEL OBJET */ +/* ---------------------------------------------------------------------------------- */ /* Détermine le type de la vue d'un tampon pour code désassemblé. */ @@ -100,7 +63,7 @@ G_DEFINE_TYPE(GBufferView, g_buffer_view, G_TYPE_OBJECT); /****************************************************************************** * * -* Paramètres : class = classe de composant GTK à initialiser. * +* Paramètres : class = classe de composant GLib à initialiser. * * * * Description : Procède à l'initialisation d'une classe de vue de tampon. * * * @@ -136,7 +99,7 @@ static void g_buffer_view_class_init(GBufferViewClass *class) * * * Paramètres : view = composant GLib à initialiser. * * * -* Description : Procède à l'initialisation d'une vue d'un tampon pour code. * +* Description : Procède à l'initialisation d'une vue d'un tampon. * * * * Retour : - * * * @@ -147,22 +110,26 @@ static void g_buffer_view_class_init(GBufferViewClass *class) static void g_buffer_view_init(GBufferView *view) { view->cache = NULL; - - view->highlighted = NULL; + view->tracker = NULL; + view->style = NULL; /** * Inversion du statut pour forcer l'actualisation lors de la création. */ view->unrestricted = false; +#if 0 + view->start = NULL; view->end = NULL; +#endif + + + view->first = 0; view->last = 0; - view->tracker = NULL; - } @@ -181,11 +148,13 @@ static void g_buffer_view_init(GBufferView *view) static void g_buffer_view_dispose(GBufferView *view) { g_clear_object(&view->cache); + g_clear_object(&view->tracker); + g_clear_object(&view->style); +#if 0 g_clear_object(&view->start); g_clear_object(&view->end); - - g_clear_object(&view->tracker); +#endif G_OBJECT_CLASS(g_buffer_view_parent_class)->dispose(G_OBJECT(view)); @@ -206,9 +175,6 @@ static void g_buffer_view_dispose(GBufferView *view) static void g_buffer_view_finalize(GBufferView *view) { - if (view->highlighted != NULL) - unref_segment_content_list(view->highlighted); - G_OBJECT_CLASS(g_buffer_view_parent_class)->finalize(G_OBJECT(view)); } @@ -216,38 +182,25 @@ static void g_buffer_view_finalize(GBufferView *view) /****************************************************************************** * * -* Paramètres : buffer = tampon à représenter à l'écran. * -* highlighted = gestionnaire de surbrillance pour segments. * +* Paramètres : cache = cache de lignes à présenter à la vue. * +* style = modèles de rendus pour tous les types de bribes. * * * -* Description : Crée une nouvelle vue d'un tampon pour code désassemblé. * +* Description : Crée une nouvelle vue d'un tampon de texte. * * * -* Retour : Composant GTK créé. * +* Retour : Vue de tampon mise en place ou NULL en cas d'erreur. * * * * Remarques : - * * * ******************************************************************************/ -GBufferView *g_buffer_view_new(GBufferCache *cache, segcnt_list *highlighted) +GBufferView *g_buffer_view_new(GBufferCache *cache, GTokenStyle *style) { GBufferView *result; /* Composant à retourner */ result = g_object_new(G_TYPE_BUFFER_VIEW, NULL); - result->cache = cache; - g_object_ref_sink(G_OBJECT(cache)); - - g_buffer_view_restrict(result, NULL, NULL); - - g_signal_connect(cache, "size-changed", G_CALLBACK(on_buffer_cache_size_changed), result); - g_signal_connect(cache, "line-updated", G_CALLBACK(on_buffer_cache_line_updated), result); - - if (highlighted != NULL) - { - ref_segment_content_list(highlighted); - result->highlighted = highlighted; - } - else - result->highlighted = init_segment_content_list(); + if (!g_buffer_view_create(result, cache, style)) + g_clear_object(&result); return result; @@ -256,21 +209,50 @@ GBufferView *g_buffer_view_new(GBufferCache *cache, segcnt_list *highlighted) /****************************************************************************** * * -* Paramètres : cache = tampon de lignes cohérentes à manipuler. * -* index = indice de la première ligne actualisée. * +* Paramètres : view = vue de tampon à initialiser. * +* cache = cache de lignes à présenter à la vue. * +* style = modèles de rendus pour tous les types de bribes. * * * -* Description : Réagit à la modification d'une ligne du tampon. * +* Description : Met en place une nouvelle vue pour un tampon de texte. * * * -* Retour : - * +* Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ -static void on_buffer_cache_line_updated(const GBufferCache *cache, size_t index, GBufferView *view) +bool g_buffer_view_create(GBufferView *view, GBufferCache *cache, GTokenStyle *style) { - if (view->first <= index && index <= view->last) - g_signal_emit_by_name(view, "need-redraw"); + bool result; /* Bilan à retourner */ + + result = true; + + view->cache = cache; + ref_object(cache); + + view->tracker = g_width_tracker_new(cache); + + view->style = style; + ref_object(style); + + g_buffer_view_restrict(view, NULL, NULL); + + g_signal_connect(cache, "size-changed", G_CALLBACK(on_buffer_cache_size_changed), view); + + +#if 0 + g_signal_connect(cache, "line-updated", G_CALLBACK(on_buffer_cache_line_updated), result); + + if (highlighted != NULL) + { + ref_segment_content_list(highlighted); + result->highlighted = highlighted; + } + else + result->highlighted = init_segment_content_list(); +#endif + + return result; } @@ -411,7 +393,32 @@ GBufferCache *g_buffer_view_get_cache(const GBufferView *view) result = view->cache; - g_object_ref(G_OBJECT(result)); + ref_object(result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : view = visualisateur à consulter. * +* * +* Description : Fournit le collecteur de largeurs associé au tampon lié. * +* * +* Retour : Collecteur de largeurs des lignes du tampon représenté. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GWidthTracker *g_buffer_view_get_tracker(const GBufferView *view) +{ + GWidthTracker *result; /* Instance à retourner */ + + result = view->tracker; + + ref_object(result); return result; @@ -432,10 +439,10 @@ GBufferCache *g_buffer_view_get_cache(const GBufferView *view) * * ******************************************************************************/ -void g_buffer_view_restrict(GBufferView *view, GLineCursor *start, GLineCursor *end) +void g_buffer_view_restrict(GBufferView *view, /*GLineCursor*/void *start, /*GLineCursor*/void *end) { bool state; /* Nouvel état à proclamer */ - GWidthTracker *template; /* Suivi déjà en place */ + //GWidthTracker *template; /* Suivi déjà en place */ state = (start == NULL || end == NULL); @@ -443,11 +450,11 @@ void g_buffer_view_restrict(GBufferView *view, GLineCursor *start, GLineCursor * { view->unrestricted = state; - template = g_buffer_cache_get_width_tracker(view->cache); + //template = g_buffer_cache_get_width_tracker(view->cache); /* Vérification pour le cas particulier du démarrage */ - if (view->tracker != NULL) - g_object_unref(G_OBJECT(view->tracker)); + //if (view->tracker != NULL) + // g_object_unref(G_OBJECT(view->tracker)); g_buffer_cache_rlock(view->cache); @@ -456,12 +463,14 @@ void g_buffer_view_restrict(GBufferView *view, GLineCursor *start, GLineCursor * view->first = 0; view->last = g_buffer_cache_count_lines(view->cache) - 1; - view->tracker = template; + //view->tracker = template; } else { + /* + g_object_ref_sink(G_OBJECT(start)); g_object_ref_sink(G_OBJECT(end)); @@ -475,6 +484,8 @@ void g_buffer_view_restrict(GBufferView *view, GLineCursor *start, GLineCursor * g_object_unref(G_OBJECT(template)); + */ + } g_buffer_cache_runlock(view->cache); @@ -484,6 +495,156 @@ void g_buffer_view_restrict(GBufferView *view, GLineCursor *start, GLineCursor * } + + + + + + +/****************************************************************************** +* * +* Paramètres : view = visualisation à consulter. * +* style = style de rendu pour les bribes de texte. * +* width = largeur requise pour un affichage complet. [OUT] * +* height = hauteur requise pour un affichage complet. [OUT] * +* * +* Description : Détermine la taille nécessaire à une représentation complète.* +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_buffer_view_compute_size(const GBufferView *view, int *width, int *height) +{ + size_t last; /* Dernière ligne à dessiner */ + + /* Largeur de l'ensemble des colonnes */ + + g_width_tracker_compute_width(view->tracker, width); + + /* Hauteur de l'ensemble des lignes */ + + *height = g_token_style_get_line_height(view->style) * (view->last + 1); + +} + + + + + +/****************************************************************************** +* * +* Paramètres : view = visualisation à représenter. * +* cr = contexte graphique dédié à la procédure. * +* column = (première) colonne à traiter. * +* virt_top = ordonnée présentée au point 0 à l'écran. * +* height = hauteur disponible pour les représentations. * +* * +* Description : Imprime la visualisation du tampon de lignes quelconques. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_buffer_view_draw(const GBufferView *view, cairo_t *cr, size_t column, int virt_top, int height) +{ + int line_height; /* Hauteur d'une ligne */ + gint cr_y; /* Ordonnée pour le dessin */ + size_t first; /* Première ligne visée */ + size_t last; /* Dernière ligne visée */ + + line_height = g_token_style_get_line_height(view->style); + + /* Indice et point de départ */ + + first = view->first; + first += (virt_top / line_height); + + cr_y = -(virt_top % line_height); + + /* Indice de d'arrivée */ + + last = first + (height / line_height); + if (height % line_height > 0) last++; + + last = MIN(last, view->last); + + /* Phase de dessin ! */ + + g_buffer_cache_draw(view->cache, cr, column, cr_y, first, last, view->style); + +} + + + + + + + + + + + + + +#if 0 + +#include + + + + +/* Accompagne une variation de la quantité de lignes du tampon. */ +//static void on_buffer_cache_size_changed(const GBufferCache *, bool, size_t, size_t, GBufferView *); + +/* Réagit à la modification d'une ligne du tampon. */ +static void on_buffer_cache_line_updated(const GBufferCache *, size_t, GBufferView *); + +/* Calcule la position idéale de curseur pour un point donné. */ +static bool _g_buffer_view_compute_caret_full(GBufferView *, gint, GBufferLine *, size_t, const GDisplayOptions *, cairo_rectangle_int_t *, GLineCursor **); + +/* Fournit la ligne présente à une ordonnée donnée. */ +static GBufferLine *g_buffer_view_find_line_at(GBufferView *, gint, size_t *); + +/* Déplace le curseur au sein d'une vue de tampon. */ +static bool _g_buffer_view_move_caret(GBufferView *, const GBufferLine *, size_t, cairo_rectangle_int_t *, bool, GdkScrollDirection, const GDisplayOptions *); + + + + + + + + + +/****************************************************************************** +* * +* Paramètres : cache = tampon de lignes cohérentes à manipuler. * +* index = indice de la première ligne actualisée. * +* * +* Description : Réagit à la modification d'une ligne du tampon. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void on_buffer_cache_line_updated(const GBufferCache *cache, size_t index, GBufferView *view) +{ + if (view->first <= index && index <= view->last) + g_signal_emit_by_name(view, "need-redraw"); + +} + + + + + /****************************************************************************** * * * Paramètres : view = visualisateur à consulter. * @@ -1313,3 +1474,44 @@ bool g_buffer_view_get_cursor_coordinates(GBufferView *view, const GLineCursor * return result; } + + + +#endif + + + + + +#if 0 + + +/****************************************************************************** +* * +* Paramètres : view = visualisation à consulter. * +* cursor = emplacement à présenter à l'écran. * +* code = s'arrête si possible à une ligne avec code. * +* x = position horizontale au sein du composant. [OUT] * +* y = position verticale au sein du composant. [OUT] * +* * +* Description : Indique la position d'affichage d'une adresse donnée. * +* * +* Retour : true si l'adresse fait partie du composant, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_buffer_view_allocate_widths(GBufferView *view, int width, int height, int fill, int *out) +{ + + + + + + +} + + + +#endif diff --git a/src/glibext/bufferview.h b/src/glibext/bufferview.h index 43e6293..d5af6d1 100644 --- a/src/glibext/bufferview.h +++ b/src/glibext/bufferview.h @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * bufferview.h - prototypes pour l'affichage d'une vue particulière d'un tampon de lignes * - * Copyright (C) 2016-2019 Cyrille Bagard + * Copyright (C) 2016-2024 Cyrille Bagard * * This file is part of Chrysalide. * @@ -25,6 +25,48 @@ #define _GLIBEXT_BUFFERVIEW_H +#include "buffercache.h" +#include "helpers.h" +#include "tokenstyle.h" +#include "widthtracker.h" + + + +#define G_TYPE_BUFFER_VIEW (g_buffer_view_get_type()) + +DECLARE_GTYPE(GBufferView, g_buffer_view, G, BUFFER_VIEW); + + +/* Crée une nouvelle vue d'un tampon de texte. */ +GBufferView *g_buffer_view_new(GBufferCache *, GTokenStyle *); + +/* Fournit le tampon de code lié à un visualisateur donné. */ +GBufferCache *g_buffer_view_get_cache(const GBufferView *); + +/* Fournit le collecteur de largeurs associé au tampon lié. */ +GWidthTracker *g_buffer_view_get_tracker(const GBufferView *); + +/* Restreint le champ d'application de l'affichage. */ +void g_buffer_view_restrict(GBufferView *, /*GLineCursor*/void *, /*GLineCursor*/void *); + + + +/* Détermine la taille nécessaire à une représentation complète. */ +void g_buffer_view_compute_size(const GBufferView *, int *, int *); + + + +/* Imprime la visualisation du tampon de lignes quelconques. */ +void g_buffer_view_draw(const GBufferView *, cairo_t *, size_t, int, int); + + + + + + + +#if 0 + #include @@ -52,13 +94,13 @@ typedef struct _GBufferViewClass GBufferViewClass; GType g_buffer_view_get_type(void); /* Crée une nouvelle vue d'un tampon pour lignes générées. */ -GBufferView *g_buffer_view_new(GBufferCache *, segcnt_list *); +//GBufferView *g_buffer_view_new(GBufferCache *, segcnt_list *); /* Fournit le tampon de code lié à un visualisateur donné. */ -GBufferCache *g_buffer_view_get_cache(const GBufferView *); +//GBufferCache *g_buffer_view_get_cache(const GBufferView *); /* Restreint le champ d'application de l'affichage. */ -void g_buffer_view_restrict(GBufferView *, GLineCursor *, GLineCursor *); +//void g_buffer_view_restrict(GBufferView *, GLineCursor *, GLineCursor *); /* Indique le champ d'application de l'affichage. */ bool g_buffer_view_get_restrictions(const GBufferView *, GLineCursor **, GLineCursor **); @@ -110,6 +152,9 @@ bool g_buffer_view_get_cursor_coordinates(GBufferView *, const GLineCursor *, bo +#endif + + #endif /* _GLIBEXT_BUFFERVIEW_H */ diff --git a/src/glibext/generator-int.h b/src/glibext/generator-int.h index 6952f69..8b7e28d 100644 --- a/src/glibext/generator-int.h +++ b/src/glibext/generator-int.h @@ -1,8 +1,8 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * linegen-int.h - définitions internes propres aux intermédiaires de génération de lignes + * generator-int.h - définitions internes propres aux intermédiaires de génération de lignes à partir de bribres de texte * - * Copyright (C) 2016-2018 Cyrille Bagard + * Copyright (C) 2016-2024 Cyrille Bagard * * This file is part of Chrysalide. * @@ -21,47 +21,52 @@ */ -#ifndef _GLIBEXT_LINEGEN_INT_H -#define _GLIBEXT_LINEGEN_INT_H +#ifndef _GLIBEXT_GENERATOR_INT_H +#define _GLIBEXT_GENERATOR_INT_H -#include "linegen.h" +#include "generator.h" /* Indique le nombre de ligne prêtes à être générées. */ -typedef size_t (* linegen_count_lines_fc) (const GLineGenerator *); +typedef size_t (* count_tokgen_lines_fc) (const GTokenGenerator *); + +/* Renseigne sur les propriétés liées à un générateur. */ +typedef BufferLineFlags (* get_tokgen_flags_fc) (const GTokenGenerator *, size_t, size_t); + +/* Imprime dans une ligne de rendu le contenu représenté. */ +typedef void (* populate_tokgen_line_fc) (const GTokenGenerator *, size_t, size_t, GBufferLine *, void *); + +#if 0 /* Retrouve l'emplacement correspondant à une position donnée. */ -typedef void (* linegen_compute_fc) (const GLineGenerator *, gint, size_t, size_t, GLineCursor **); +typedef void (* compute_tokgen_fc) (const GTokenGenerator *, gint, size_t, size_t, GLineCursor **); /* Détermine si le conteneur s'inscrit dans une plage donnée. */ -typedef int (* linegen_contain_fc) (const GLineGenerator *, size_t, size_t, const GLineCursor *); +typedef int (* contain_tokgen_fc) (const GTokenGenerator *, size_t, size_t, const GLineCursor *); -/* Renseigne sur les propriétés liées à un générateur. */ -typedef BufferLineFlags (* linegen_get_flags_fc) (const GLineGenerator *, size_t, size_t); - -/* Imprime dans une ligne de rendu le contenu représenté. */ -typedef void (* linegen_print_fc) (GLineGenerator *, GBufferLine *, size_t, size_t, const GBinContent *); +#endif /* Intermédiaire pour la génération de lignes (interface) */ -struct _GLineGeneratorIface +struct _GTokenGeneratorInterface { GTypeInterface base_iface; /* A laisser en premier */ - linegen_count_lines_fc count; /* Décompte des lignes */ - linegen_compute_fc compute; /* Calcul d'emplacement */ - linegen_contain_fc contain; /* Inclusion de positions */ - linegen_get_flags_fc get_flags; /* Récupération des drapeaux */ - linegen_print_fc print; /* Impression d'une ligne */ + count_tokgen_lines_fc count; /* Décompte des lignes */ + get_tokgen_flags_fc get_flags; /* Récupération des drapeaux */ + populate_tokgen_line_fc populate; /* Impression d'une ligne */ -}; +#if 0 + compute_tokgen_fc compute; /* Calcul d'emplacement */ + contain_tokgen_fc contain; /* Inclusion de positions */ -/* Redéfinition */ -typedef GLineGeneratorIface GLineGeneratorInterface; +#endif + +}; -#endif /* _GLIBEXT_LINEGEN_INT_H */ +#endif /* _GLIBEXT_GENERATOR_INT_H */ diff --git a/src/glibext/generator.c b/src/glibext/generator.c index c5291ab..2d3d349 100644 --- a/src/glibext/generator.c +++ b/src/glibext/generator.c @@ -1,8 +1,8 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * linegen.c - intermédiaires de génération de lignes + * generator.c - intermédiaires de génération de lignes à partir de bribres de texte * - * Copyright (C) 2016-2018 Cyrille Bagard + * Copyright (C) 2016-2024 Cyrille Bagard * * This file is part of Chrysalide. * @@ -21,23 +21,26 @@ */ -#include "linegen.h" +#include "generator.h" #include -#include "linegen-int.h" +#include "generator-int.h" /* Procède à l'initialisation de l'interface de génération. */ -static void g_line_generator_default_init(GLineGeneratorInterface *); +static void g_token_generator_default_init(GTokenGeneratorInterface *); + +/* Indique le nombre de ligne prêtes à être générées. */ +static size_t _g_token_generator_count_one_line(const GTokenGenerator *); /* Détermine le type d'une interface pour la mise en place de lignes. */ -G_DEFINE_INTERFACE(GLineGenerator, g_line_generator, G_TYPE_OBJECT) +G_DEFINE_INTERFACE(GTokenGenerator, g_token_generator, G_TYPE_OBJECT) /****************************************************************************** @@ -52,8 +55,32 @@ G_DEFINE_INTERFACE(GLineGenerator, g_line_generator, G_TYPE_OBJECT) * * ******************************************************************************/ -static void g_line_generator_default_init(GLineGeneratorInterface *iface) +static void g_token_generator_default_init(GTokenGeneratorInterface *iface) +{ + iface->count = _g_token_generator_count_one_line; + +} + + +/****************************************************************************** +* * +* Paramètres : generator = générateur à consulter. * +* * +* Description : Indique le nombre de ligne prêtes à être générées. * +* * +* Retour : Nombre de lignes devant apparaître au final. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static size_t _g_token_generator_count_one_line(const GTokenGenerator *generator) { + size_t result; /* Décompte à retourner */ + + result = 1; + + return result; } @@ -70,12 +97,12 @@ static void g_line_generator_default_init(GLineGeneratorInterface *iface) * * ******************************************************************************/ -size_t g_line_generator_count_lines(const GLineGenerator *generator) +size_t g_token_generator_count_lines(const GTokenGenerator *generator) { size_t result; /* Décompte à retourner */ - GLineGeneratorIface *iface; /* Interface utilisée */ + GTokenGeneratorInterface *iface; /* Interface utilisée */ - iface = G_LINE_GENERATOR_GET_IFACE(generator); + iface = G_TOKEN_GENERATOR_GET_IFACE(generator); result = iface->count(generator); @@ -87,31 +114,29 @@ size_t g_line_generator_count_lines(const GLineGenerator *generator) /****************************************************************************** * * * Paramètres : generator = générateur à consulter. * -* x = position géographique sur la ligne concernée. * * index = indice de cette même ligne dans le tampon global.* * repeat = indice d'utilisations successives du générateur. * * * -* Description : Retrouve l'emplacement correspondant à une position donnée. * +* Description : Renseigne sur les propriétés liées à un générateur. * * * -* Retour : Emplacement constitué. * +* Retour : Propriétés particulières associées. * * * * Remarques : - * * * ******************************************************************************/ -GLineCursor *g_line_generator_compute_cursor(const GLineGenerator *generator, gint x, size_t index, size_t repeat) +BufferLineFlags g_token_generator_get_flags(const GTokenGenerator *generator, size_t index, size_t repeat) { - GLineCursor *result; /* Emplacement à renvoyer */ - GLineGeneratorIface *iface; /* Interface utilisée */ + BufferLineFlags result; /* Fanions à retourner */ + GTokenGeneratorInterface *iface; /* Interface utilisée */ - iface = G_LINE_GENERATOR_GET_IFACE(generator); + iface = G_TOKEN_GENERATOR_GET_IFACE(generator); #ifndef NDEBUG - if (iface->count != NULL) - assert(repeat < g_line_generator_count_lines(generator)); + assert(repeat < g_token_generator_count_lines(generator)); #endif - iface->compute(generator, x, index, repeat, &result); + result = iface->get_flags(generator, index, repeat); return result; @@ -120,65 +145,65 @@ GLineCursor *g_line_generator_compute_cursor(const GLineGenerator *generator, gi /****************************************************************************** * * -* Paramètres : generator = générateur à consulter. * +* Paramètres : generator = générateur à utiliser pour l'impression. * * index = indice de cette même ligne dans le tampon global.* * repeat = indice d'utilisations successives du générateur. * -* cursor = emplacement à analyser. * +* line = ligne de rendu à compléter. * +* data = éventuelle donnée complémentaire fournie. * * * -* Description : Détermine si le conteneur s'inscrit dans une plage donnée. * +* Description : Etablit dans une ligne de rendu le contenu représenté. * * * -* Retour : Bilan de la détermination, utilisable en comparaisons. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -int g_line_generator_contain_cursor(const GLineGenerator *generator, size_t index, size_t repeat, const GLineCursor *cursor) +void g_token_generator_populate_line(const GTokenGenerator *generator, size_t index, size_t repeat, GBufferLine *line, void *data) { - int result; /* Bilan d'analyse à retourner */ - GLineGeneratorIface *iface; /* Interface utilisée */ + GTokenGeneratorInterface *iface; /* Interface utilisée */ - iface = G_LINE_GENERATOR_GET_IFACE(generator); + iface = G_TOKEN_GENERATOR_GET_IFACE(generator); #ifndef NDEBUG - if (iface->count != NULL) - assert(repeat < g_line_generator_count_lines(generator)); + assert(repeat < g_token_generator_count_lines(generator)); #endif - result = iface->contain(generator, index, repeat, cursor); - - return result; + iface->populate(generator, index, repeat, line, data); } +#if 0 + + /****************************************************************************** * * * Paramètres : generator = générateur à consulter. * +* x = position géographique sur la ligne concernée. * * index = indice de cette même ligne dans le tampon global.* * repeat = indice d'utilisations successives du générateur. * * * -* Description : Renseigne sur les propriétés liées à un générateur. * +* Description : Retrouve l'emplacement correspondant à une position donnée. * * * -* Retour : Propriétés particulières associées. * +* Retour : Emplacement constitué. * * * * Remarques : - * * * ******************************************************************************/ -BufferLineFlags g_line_generator_get_flags(const GLineGenerator *generator, size_t index, size_t repeat) +GLineCursor *g_token_generator_compute_cursor(const GTokenGenerator *generator, gint x, size_t index, size_t repeat) { - BufferLineFlags result; /* Fanions à retourner */ - GLineGeneratorIface *iface; /* Interface utilisée */ + GLineCursor *result; /* Emplacement à renvoyer */ + GTokenGeneratorInterface *iface; /* Interface utilisée */ - iface = G_LINE_GENERATOR_GET_IFACE(generator); + iface = G_TOKEN_GENERATOR_GET_IFACE(generator); #ifndef NDEBUG - if (iface->count != NULL) - assert(repeat < g_line_generator_count_lines(generator)); + assert(repeat < g_token_generator_count_lines(generator)); #endif - result = iface->get_flags(generator, index, repeat); + iface->compute(generator, x, index, repeat, &result); return result; @@ -187,31 +212,35 @@ BufferLineFlags g_line_generator_get_flags(const GLineGenerator *generator, size /****************************************************************************** * * -* Paramètres : generator = générateur à utiliser pour l'impression. * -* line = ligne de rendu à compléter. * +* Paramètres : generator = générateur à consulter. * * index = indice de cette même ligne dans le tampon global.* * repeat = indice d'utilisations successives du générateur. * -* content = éventuel contenu binaire brut à imprimer. * +* cursor = emplacement à analyser. * * * -* Description : Imprime dans une ligne de rendu le contenu représenté. * +* Description : Détermine si le conteneur s'inscrit dans une plage donnée. * * * -* Retour : - * +* Retour : Bilan de la détermination, utilisable en comparaisons. * * * * Remarques : - * * * ******************************************************************************/ -void g_line_generator_print(GLineGenerator *generator, GBufferLine *line, size_t index, size_t repeat, const GBinContent *content) +int g_token_generator_contain_cursor(const GTokenGenerator *generator, size_t index, size_t repeat, const GLineCursor *cursor) { - GLineGeneratorIface *iface; /* Interface utilisée */ + int result; /* Bilan d'analyse à retourner */ + GTokenGeneratorInterface *iface; /* Interface utilisée */ - iface = G_LINE_GENERATOR_GET_IFACE(generator); + iface = G_TOKEN_GENERATOR_GET_IFACE(generator); #ifndef NDEBUG - if (iface->count != NULL) - assert(repeat < g_line_generator_count_lines(generator)); + assert(repeat < g_token_generator_count_lines(generator)); #endif - iface->print(generator, line, index, repeat, content); + result = iface->contain(generator, index, repeat, cursor); + + return result; } + + +#endif diff --git a/src/glibext/generator.h b/src/glibext/generator.h index d40a598..c93e0a0 100644 --- a/src/glibext/generator.h +++ b/src/glibext/generator.h @@ -1,8 +1,8 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * linegen.h - prototypes pour les intermédiaires de génération de lignes + * generator.h - prototypes pour les intermédiaires de génération de lignes à partir de bribres de texte * - * Copyright (C) 2016-2018 Cyrille Bagard + * Copyright (C) 2016-2024 Cyrille Bagard * * This file is part of Chrysalide. * @@ -21,52 +21,43 @@ */ -#ifndef _GLIBEXT_LINEGEN_H -#define _GLIBEXT_LINEGEN_H - - -#include +#ifndef _GLIBEXT_GENERATOR_H +#define _GLIBEXT_GENERATOR_H #include "bufferline.h" +#include "helpers.h" +/* #include "glinecursor.h" -#include "../analysis/content.h" +*/ -#define G_TYPE_LINE_GENERATOR g_line_generator_get_type() -#define G_LINE_GENERATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_LINE_GENERATOR, GLineGenerator)) -#define G_LINE_GENERATOR_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST((vtable), G_TYPE_LINE_GENERATOR, GLineGeneratorIface)) -#define GTK_IS_LINE_GENERATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_LINE_GENERATOR)) -#define GTK_IS_LINE_GENERATOR_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE((vtable), G_TYPE_LINE_GENERATOR)) -#define G_LINE_GENERATOR_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), G_TYPE_LINE_GENERATOR, GLineGeneratorIface)) +#define G_TYPE_TOKEN_GENERATOR (g_token_generator_get_type()) +DECLARE_INTERFACE(GTokenGenerator, g_token_generator, G, TOKEN_GENERATOR); -/* Intermédiaire pour la génération de lignes (coquille vide) */ -typedef struct _GLineGenerator GLineGenerator; -/* Intermédiaire pour la génération de lignes (interface) */ -typedef struct _GLineGeneratorIface GLineGeneratorIface; +/* Indique le nombre de ligne prêtes à être générées. */ +size_t g_token_generator_count_lines(const GTokenGenerator *); -/* Détermine le type d'une interface pour la mise en place de lignes. */ -GType g_line_generator_get_type(void) G_GNUC_CONST; +/* Renseigne sur les propriétés liées à un générateur. */ +BufferLineFlags g_token_generator_get_flags(const GTokenGenerator *, size_t, size_t); -/* Indique le nombre de ligne prêtes à être générées. */ -size_t g_line_generator_count_lines(const GLineGenerator *); +/* Etablit dans une ligne de rendu le contenu représenté. */ +void g_token_generator_populate_line(const GTokenGenerator *, size_t, size_t, GBufferLine *, void *); -/* Retrouve l'emplacement correspondant à une position donnée. */ -GLineCursor *g_line_generator_compute_cursor(const GLineGenerator *, gint, size_t, size_t); -/* Détermine si le conteneur s'inscrit dans une plage donnée. */ -int g_line_generator_contain_cursor(const GLineGenerator *, size_t, size_t, const GLineCursor *); +#if 0 -/* Renseigne sur les propriétés liées à un générateur. */ -BufferLineFlags g_line_generator_get_flags(const GLineGenerator *, size_t, size_t); +/* Retrouve l'emplacement correspondant à une position donnée. */ +GLineCursor *g_token_generator_compute_cursor(const GTokenGenerator *, gint, size_t, size_t); -/* Imprime dans une ligne de rendu le contenu représenté. */ -void g_line_generator_print(GLineGenerator *, GBufferLine *, size_t, size_t, const GBinContent *); +/* Détermine si le conteneur s'inscrit dans une plage donnée. */ +int g_token_generator_contain_cursor(const GTokenGenerator *, size_t, size_t, const GLineCursor *); +#endif -#endif /* _GLIBEXT_LINEGEN_H */ +#endif /* _GLIBEXT_GENERATOR_H */ diff --git a/src/glibext/generators/Makefile.am b/src/glibext/generators/Makefile.am index a332498..e95618f 100644 --- a/src/glibext/generators/Makefile.am +++ b/src/glibext/generators/Makefile.am @@ -3,17 +3,14 @@ noinst_LTLIBRARIES = libglibextgenerators.la libglibextgenerators_la_SOURCES = \ - prologue.h prologue.c \ - rborder.h rborder.c + hex.h hex.c -if BUILD_GTK_SUPPORT -libglibextgenerators_la_SOURCES += \ - hex.h hex.c -endif +# prologue.h prologue.c \ +# rborder.h rborder.c -libglibextgenerators_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) +libglibextgenerators_la_CFLAGS = $(TOOLKIT_CFLAGS) devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%) diff --git a/src/glibext/generators/hex.c b/src/glibext/generators/hex.c index 668ebae..6058825 100644 --- a/src/glibext/generators/hex.c +++ b/src/glibext/generators/hex.c @@ -28,14 +28,26 @@ #include +#include "../generator-int.h" +#include "../options/hex.h" + + + + +#if 0 + +//#include + + #include "../bufferline.h" #include "../gbinarycursor.h" -#include "../linegen-int.h" #include "../linesegment.h" #include "../../core/columns.h" #include "../../core/params.h" #include "../../gtkext/hexdisplay.h" +#endif + /* --------------------------- RENDU AMIQUE D'HEXADECIMAL --------------------------- */ @@ -48,9 +60,13 @@ struct _GHexGenerator GBinContent *content; /* Contenu à représenter */ +#if 0 + gint left_start; /* Abscisse des impressions */ gint padding; /* Bourrage supplémentaire */ +#endif + phys_t bytes_per_line; /* Nombre d'octets par ligne */ }; @@ -60,11 +76,15 @@ struct _GHexGeneratorClass { GObjectClass parent; /* A laisser en premier */ +#if 0 + gint addr_width; /* Largeur des positions */ gint byte_width; /* Largeur d'un octet brut */ gint sep_width; /* Largeur de séparation */ gint char_width; /* Largeur d'un caractère */ +#endif + }; @@ -75,7 +95,7 @@ static void g_hex_generator_class_init(GHexGeneratorClass *); static void g_hex_generator_init(GHexGenerator *); /* Procède à l'initialisation de l'interface de génération. */ -static void g_hex_generator_interface_init(GLineGeneratorInterface *); +static void g_hex_generator_token_generator_iface_init(GTokenGeneratorInterface *); /* Supprime toutes les références externes. */ static void g_hex_generator_dispose(GHexGenerator *); @@ -91,6 +111,13 @@ static void g_hex_generator_finalize(GHexGenerator *); /* Indique le nombre de ligne prêtes à être générées. */ static size_t g_hex_generator_count_lines(const GHexGenerator *); +/* Etablit dans une ligne de rendu le contenu représenté. */ +static void g_hex_generator_populate_line(const GHexGenerator *, size_t, size_t, GBufferLine *, void *); + + + + +#if 0 #ifdef INCLUDE_GTK_SUPPORT /* Retrouve l'emplacement correspondant à une position donnée. */ @@ -106,6 +133,7 @@ static BufferLineFlags g_hex_generator_get_flags(const GHexGenerator *, size_t, /* Imprime dans une ligne de rendu le contenu représenté. */ static void g_hex_generator_print(GHexGenerator *, GBufferLine *, size_t, size_t); +#endif @@ -116,7 +144,7 @@ static void g_hex_generator_print(GHexGenerator *, GBufferLine *, size_t, size_t /* Détermine le type du générateur de lignes hexadécimales à la volée. */ G_DEFINE_TYPE_WITH_CODE(GHexGenerator, g_hex_generator, G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE(G_TYPE_LINE_GENERATOR, g_hex_generator_interface_init)); + G_IMPLEMENT_INTERFACE(G_TYPE_TOKEN_GENERATOR, g_hex_generator_token_generator_iface_init)); /****************************************************************************** @@ -134,13 +162,15 @@ G_DEFINE_TYPE_WITH_CODE(GHexGenerator, g_hex_generator, G_TYPE_OBJECT, static void g_hex_generator_class_init(GHexGeneratorClass *class) { GObjectClass *object; /* Autre version de la classe */ - line_segment *segment; /* Segment de test pour mesure */ + //line_segment *segment; /* Segment de test pour mesure */ object = G_OBJECT_CLASS(class); object->dispose = (GObjectFinalizeFunc/* ! */)g_hex_generator_dispose; object->finalize = (GObjectFinalizeFunc)g_hex_generator_finalize; +#if 0 + /* Mesure de quelques dimensions */ segment = get_new_line_segment(RTT_PHYS_ADDR, "0x00000000", 10); @@ -167,6 +197,8 @@ static void g_hex_generator_class_init(GHexGeneratorClass *class) release_line_segment(segment); +#endif + } @@ -184,7 +216,7 @@ static void g_hex_generator_class_init(GHexGeneratorClass *class) static void g_hex_generator_init(GHexGenerator *generator) { - generator->bytes_per_line = 4; + generator->bytes_per_line = 0; } @@ -201,15 +233,20 @@ static void g_hex_generator_init(GHexGenerator *generator) * * ******************************************************************************/ -static void g_hex_generator_interface_init(GLineGeneratorInterface *iface) +static void g_hex_generator_token_generator_iface_init(GTokenGeneratorInterface *iface) { - iface->count = (linegen_count_lines_fc)g_hex_generator_count_lines; + iface->count = (count_tokgen_lines_fc)g_hex_generator_count_lines; + + iface->populate = (populate_tokgen_line_fc)g_hex_generator_populate_line; + +#if 0 #ifdef INCLUDE_GTK_SUPPORT iface->compute = (linegen_compute_fc)g_hex_generator_compute_cursor; iface->contain = (linegen_contain_fc)g_hex_generator_contain_cursor; #endif iface->get_flags = (linegen_get_flags_fc)g_hex_generator_get_flags; iface->print = (linegen_print_fc)g_hex_generator_print; +#endif } @@ -228,8 +265,7 @@ static void g_hex_generator_interface_init(GLineGeneratorInterface *iface) static void g_hex_generator_dispose(GHexGenerator *generator) { - if (generator->content != NULL) - g_object_unref(G_OBJECT(generator->content)); + g_clear_object(&generator->content); G_OBJECT_CLASS(g_hex_generator_parent_class)->dispose(G_OBJECT(generator)); @@ -274,8 +310,239 @@ GHexGenerator *g_hex_generator_new(GBinContent *content) result = g_object_new(G_TYPE_HEX_GENERATOR, NULL); result->content = content; + ref_object(content); + + return result; + +} + + +// TODO create... + + +/****************************************************************************** +* * +* Paramètres : generator = générateur à consulter. * +* * +* Description : Fournit le contenu associé au générateur de lignes hexa. * +* * +* Retour : Contenu dans lequel puise le générateur pour les lignes. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBinContent *g_hex_generator_get_content(const GHexGenerator *generator) +{ + GBinContent *result; /* Référence à retourner */ + + result = generator->content; + + ref_object(result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : generator = générateur à ajuster. * +* options = options d'affichage des colonnes. * +* style = style de rendus des bribes de texte. * +* width = largeur disponible pour les différentes colonnes.* +* * +* Description : Détermine la hauteur idéale d'un contenu lié à une largeur. * +* * +* Retour : Hauteur nécessaire pour les lignes induites. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int g_hex_generator_mesure_height_for_width(GHexGenerator *generator, const GDisplayOptions *options, const GTokenStyle *style, int width) +{ + int result; /* Taille à retourner */ + vmpa2t end; /* Position terminale */ + bool status; /* Bilan d'une opération */ + int off_size; /* Taille des emplacements */ + int byte_width; /* Largeur d'un octet brut */ + int sep_width; /* Largeur de séparation */ + int char_width; /* Largeur d'un caractère */ + phys_t i; /* Boucle de parcours */ + phys_t block_count; /* Nombre de blocs d'octets */ + int requested; /* Espace requis pour X octets */ + phys_t size; /* Taille du contenu binaire */ + phys_t line_count; /* Nombre de lignes requises */ + + result = -1; + + /* Largeur des positions */ + + if (g_display_options_get(options, HCO_OFFSET)) + { + status = g_binary_content_compute_end_pos(generator->content, &end); + assert(status); + if (!status) goto done; + + off_size = g_token_style_compute_location_width(style, end.physical, false); + + width -= off_size; + + } + + /* Détermination des tailles basiques */ + + byte_width = g_token_style_measure_width(style, TRT_RAW_CODE, 2 /* 00 */); + + sep_width = g_token_style_measure_width(style, TRT_RAW_CODE, TAB_SIZE /* \t */); + + char_width = g_token_style_measure_width(style, TRT_RAW_CODE, 1 /* 0 */); + + for (i = 4; ; i += 4) + { + block_count = (i / 4); + + requested = i * byte_width + 3 * block_count * char_width; + requested += (block_count > 1 ? block_count - 1 : 0) * sep_width; + + requested += i * char_width; + + /* Limite atteinte ? */ + if (requested > width) + { + i -= 4; + break; + } + + } + + if (i == 0) + i = 4; + + /* Détermination de la taille pour un nombre de lignes donné */ + + size = g_binary_content_compute_size(generator->content); + + line_count = size / i; + + if (size % i > 0) + line_count++; + + result = line_count * g_token_style_get_line_height(style); + + done: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : generator = générateur à ajuster. * +* options = options d'affichage des colonnes. * +* style = style de rendus des bribes de texte. * +* width = largeur disponible pour les différentes colonnes.* +* columns = largeurs adaptées pour les colonnes. [OUT] * +* * +* Description : Détermine les différentes largeurs de colonnes requises. * +* * +* Retour : true si un changement de contenu a été déterminé. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_hex_generator_allocate(GHexGenerator *generator, const GDisplayOptions *options, const GTokenStyle *style, int width, int *columns) +{ + bool result; /* Variation d'état à remonter */ + vmpa2t end; /* Position terminale */ + bool status; /* Bilan d'une opération */ + int byte_width; /* Largeur d'un octet brut */ + int sep_width; /* Largeur de séparation */ + int char_width; /* Largeur d'un caractère */ + phys_t i; /* Boucle de parcours */ + phys_t block_count; /* Nombre de blocs d'octets */ + int requested; /* Espace requis pour X octets */ + + result = false; + + /* Largeur des positions */ + + status = g_binary_content_compute_end_pos(generator->content, &end); + assert(status); + if (!status) goto done; + + columns[HCO_OFFSET] = g_token_style_compute_location_width(style, end.physical, false); + + if (g_display_options_get(options, HCO_OFFSET)) + width -= columns[HCO_OFFSET]; + + /* Détermination des tailles basiques */ + + byte_width = g_token_style_measure_width(style, TRT_RAW_CODE, 2 /* 00 */); + + sep_width = g_token_style_measure_width(style, TRT_RAW_CODE, TAB_SIZE /* \t */); + + char_width = g_token_style_measure_width(style, TRT_RAW_CODE, 1 /* 0 */); + + for (i = 4; ; i += 4) + { + block_count = (i / 4); + + requested = i * byte_width + 3 * block_count * char_width; + requested += (block_count > 1 ? block_count - 1 : 0) * sep_width; + + requested += i * char_width; + + /* Limite atteinte ? */ + if (requested > width) + { + i -= 4; + break; + } + + } + + if (i == 0) + i = 4; + + /* Détermination des largeurs de colonnes principales */ + + columns[HCO_COUNT + 0] = i * byte_width + 3 * block_count * char_width; + columns[HCO_COUNT + 0] += (block_count > 1 ? block_count - 1 : 0) * sep_width; + + columns[HCO_COUNT + 1] = i * char_width; + + result = (generator->bytes_per_line != i); + + generator->bytes_per_line = i; + + done: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : generator = générateur à consulter. * +* * +* Description : Indique le nombre d'octets programmés constituer une ligne. * +* * +* Retour : Nombre d'octets représentés sur chaque ligne. * +* * +* Remarques : - * +* * +******************************************************************************/ - g_object_ref(G_OBJECT(result->content)); +phys_t g_hex_generator_get_bytes_per_line(const GHexGenerator *generator) +{ + phys_t result; /* Quantité d'octets à renvoyer*/ + + result = generator->bytes_per_line; return result; @@ -317,6 +584,136 @@ static size_t g_hex_generator_count_lines(const GHexGenerator *generator) } +/****************************************************************************** +* * +* Paramètres : generator = générateur à utiliser pour l'impression. * +* index = indice de cette même ligne dans le tampon global.* +* repeat = indice d'utilisations successives du générateur. * +* line = ligne de rendu à compléter. * +* data = éventuelle donnée complémentaire fournie. * +* * +* Description : Etablit dans une ligne de rendu le contenu représenté. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_hex_generator_populate_line(const GHexGenerator *generator, size_t index, size_t repeat, GBufferLine *line, void *data) +{ + + + //GGenConfig *config; /* Configuration à consulter */ + bool upper_case; /* Casse des données en hexa */ +#ifndef NDEBUG + bool status; /* Bilan de la consultation */ +#endif + const char *hexa; /* Chaîne à considérer #0 */ + const char *ff; /* Chaîne à considérer #1 */ + vmpa2t pos; /* Position définie à la volée */ + phys_t got; /* Quantité affichable */ + const bin_t *raw; /* Accès direct et brut */ + phys_t i; /* Boucle de parcours */ + bin_t byte; /* Copie pour confort */ + char tmp[2]; /* Représentation d'un octet */ + + static const char hexa_lower[] = "0123456789abcdef"; + static const char hexa_upper[] = "0123456789ABCDEF"; + static const char ff_lower[] = "ff"; + static const char ff_upper[] = "FF"; + + /* + config = get_main_configuration(); + +#ifndef NDEBUG + status = g_generic_config_get_value(config, MPK_HEX_UPPER_CASE, &upper_case); + assert(status); +#else + g_generic_config_get_value(config, MPK_HEX_UPPER_CASE, &upper_case); +#endif + */ + + upper_case = true; + + if (upper_case) + { + hexa = hexa_upper; + ff = ff_upper; + } + else + { + hexa = hexa_lower; + ff = ff_lower; + } + + /* Position physique */ + + init_vmpa(&pos, generator->bytes_per_line * index, VMPA_NO_VIRTUAL); + + //g_buffer_line_fill_phys(line, HLC_PHYSICAL, MDS_32_BITS_UNSIGNED, &pos); + + /* Contenu brut */ + + got = g_binary_content_compute_size(generator->content) - get_phy_addr(&pos); + + if (got > generator->bytes_per_line) + got = generator->bytes_per_line; + + raw = g_binary_content_get_raw_access(generator->content, &pos, got); + + for (i = 0; i < got; i++) + { + /* Séparation ? */ + + if (i > 0) + { + if (i % 4 == 0) + g_buffer_line_append_text(line, HCO_COUNT + 0, TRT_NONE, "\t", 1, NULL, NULL); + else + g_buffer_line_append_text(line, HCO_COUNT + 0, TRT_NONE, " ", 1, NULL, NULL); + } + + /* Binaire brut */ + + byte = raw[i]; + + if (byte == 0x00) + g_buffer_line_append_text(line, HCO_COUNT + 0, TRT_RAW_NULL, "00", 2, NULL, NULL); + + else if (byte == 0xff) + g_buffer_line_append_text(line, HCO_COUNT + 0, TRT_RAW_FULL, ff, 2, NULL, NULL); + + else + { + tmp[1] = hexa[byte & 0xf]; + tmp[0] = hexa[(byte >> 4) & 0xf]; + + if (isgraph(byte) || byte == ' ') + g_buffer_line_append_text(line, HCO_COUNT + 0, TRT_RAW_PRINTABLE, tmp, 2, NULL, NULL); + else + g_buffer_line_append_text(line, HCO_COUNT + 0, TRT_RAW_NOT_PRINTABLE, tmp, 2, NULL, NULL); + + } + + /* Représentation humaine ? */ + + if (isgraph(byte) || byte == ' ') + g_buffer_line_append_text(line, HCO_COUNT + 1, TRT_CHR_PRINTABLE, (char *)raw + i, 1, NULL, NULL); + else + g_buffer_line_append_text(line, HCO_COUNT + 1, TRT_CHR_NOT_PRINTABLE, ".", 1, NULL, NULL); + + } + +} + + + + + + + +#if 0 #ifdef INCLUDE_GTK_SUPPORT @@ -538,9 +935,9 @@ static void g_hex_generator_print(GHexGenerator *generator, GBufferLine *line, s if (i > 0) { if (i % 4 == 0) - g_buffer_line_append_text(line, HLC_BINARY, "\t", 1, RTT_RAW, NULL); + g_buffer_line_append_text(line, HCO_COUNT + 0, "\t", 1, RTT_RAW, NULL); else - g_buffer_line_append_text(line, HLC_BINARY, " ", 1, RTT_RAW, NULL); + g_buffer_line_append_text(line, HCO_COUNT + 0, " ", 1, RTT_RAW, NULL); } /* Binaire brut */ @@ -548,17 +945,17 @@ static void g_hex_generator_print(GHexGenerator *generator, GBufferLine *line, s byte = raw[i]; if (byte == 0x00) - g_buffer_line_append_text(line, HLC_BINARY, "00", 2, RTT_RAW_NULL, NULL); + g_buffer_line_append_text(line, HCO_COUNT + 0, "00", 2, RTT_RAW_NULL, NULL); else if (byte == 0xff) - g_buffer_line_append_text(line, HLC_BINARY, ff, 2, RTT_RAW_FULL, NULL); + g_buffer_line_append_text(line, HCO_COUNT + 0, ff, 2, RTT_RAW_FULL, NULL); else { tmp[1] = hexa[byte & 0xf]; tmp[0] = hexa[(byte >> 4) & 0xf]; - g_buffer_line_append_text(line, HLC_BINARY, tmp, 2, RTT_RAW, NULL); + g_buffer_line_append_text(line, HCO_COUNT + 0, tmp, 2, RTT_RAW, NULL); } @@ -574,30 +971,6 @@ static void g_hex_generator_print(GHexGenerator *generator, GBufferLine *line, s } -/****************************************************************************** -* * -* Paramètres : generator = générateur à consulter. * -* * -* Description : Fournit le contenu associé au générateur de lignes hexa. * -* * -* Retour : Contenu dans lequel puise le générateur pour les lignes. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GBinContent *g_hex_generator_get_content(const GHexGenerator *generator) -{ - GBinContent *result; /* Référence à retourner */ - - result = generator->content; - - g_object_ref(G_OBJECT(result)); - - return result; - -} - /****************************************************************************** * * @@ -665,20 +1038,4 @@ bool g_hex_generator_auto_fit(GHexGenerator *generator, gint left, bool show_pos } -/****************************************************************************** -* * -* Paramètres : generator = générateur à consulter. * -* * -* Description : Indique le nombre d'octets programmés constituer une ligne. * -* * -* Retour : Nombre d'octets représentés sur chaque ligne. * -* * -* Remarques : - * -* * -******************************************************************************/ - -phys_t g_hex_generator_get_bytes_per_line(const GHexGenerator *generator) -{ - return generator->bytes_per_line; - -} +#endif diff --git a/src/glibext/generators/hex.h b/src/glibext/generators/hex.h index f4aeb03..e404adf 100644 --- a/src/glibext/generators/hex.h +++ b/src/glibext/generators/hex.h @@ -25,30 +25,17 @@ #define _GLIBEXT_GENERATORS_HEX_H -#include - - +#include "../helpers.h" +#include "../options.h" +#include "../tokenstyle.h" #include "../../analysis/content.h" -#define G_TYPE_HEX_GENERATOR (g_hex_generator_get_type()) -#define G_HEX_GENERATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_HEX_GENERATOR, GHexGenerator)) -#define G_IS_HEX_GENERATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_HEX_GENERATOR)) -#define G_HEX_GENERATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_HEX_GENERATOR, GHexGeneratorClass)) -#define G_IS_HEX_GENERATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_HEX_GENERATOR)) -#define G_HEX_GENERATOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_HEX_GENERATOR, GHexGeneratorClass)) - +#define G_TYPE_HEX_GENERATOR (g_hex_generator_get_type()) -/* Tampon pour générateur de lignes hexadécimales (instance) */ -typedef struct _GHexGenerator GHexGenerator; +DECLARE_GTYPE(GHexGenerator, g_hex_generator, G, HEX_GENERATOR); -/* Tampon pour générateur de lignes hexadécimales (classe) */ -typedef struct _GHexGeneratorClass GHexGeneratorClass; - - -/* Détermine le type du générateur de lignes hexadécimales à la volée. */ -GType g_hex_generator_get_type(void); /* Crée un nouveau générateur de lignes hexadécimales. */ GHexGenerator *g_hex_generator_new(GBinContent *); @@ -56,8 +43,11 @@ GHexGenerator *g_hex_generator_new(GBinContent *); /* Fournit le contenu associé au générateur de lignes hexa. */ GBinContent *g_hex_generator_get_content(const GHexGenerator *); -/* Ajuste la génération à une nouvelle largeur de rendu. */ -bool g_hex_generator_auto_fit(GHexGenerator *, gint, bool, gint, gint); +/* Détermine la hauteur idéale d'un contenu lié à une largeur. */ +int g_hex_generator_mesure_height_for_width(GHexGenerator *, const GDisplayOptions *, const GTokenStyle *, int); + +/* Détermine les différentes largeurs de colonnes requises. */ +bool g_hex_generator_allocate(GHexGenerator *, const GDisplayOptions *, const GTokenStyle *, int, int *); /* Indique le nombre d'octets programmés constituer une ligne. */ phys_t g_hex_generator_get_bytes_per_line(const GHexGenerator *); diff --git a/src/glibext/helpers.h b/src/glibext/helpers.h index 71a7269..04e51ad 100644 --- a/src/glibext/helpers.h +++ b/src/glibext/helpers.h @@ -90,6 +90,36 @@ /** + * Bis repetita pour les interfaces... + */ + +#define DECLARE_INTERFACE(TN, t_n, MOD, NAME) \ + \ + GType t_n##_get_type(void) G_GNUC_CONST; \ + \ + /* Coquille vide */ \ + typedef struct _##TN TN; \ + /* Interface */ \ + typedef struct _##TN##Interface TN##Interface; \ + \ + G_GNUC_UNUSED static inline TN *MOD##_##NAME(gconstpointer obj) \ + { \ + return G_TYPE_CHECK_INSTANCE_CAST(obj, MOD##_TYPE_##NAME, TN); \ + } \ + \ + G_GNUC_UNUSED static inline gboolean MOD##_IS_##NAME(gconstpointer obj) \ + { \ + return G_TYPE_CHECK_INSTANCE_TYPE(obj, MOD##_TYPE_##NAME); \ + } \ + \ + G_GNUC_UNUSED static inline TN##Interface *MOD##_##NAME##_GET_IFACE(gconstpointer obj) \ + { \ + return G_TYPE_INSTANCE_GET_INTERFACE(obj, MOD##_TYPE_##NAME, TN##Interface); \ + } + + + +/** * 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 /gobject/gobject.h : @@ -143,7 +173,7 @@ assert(__inst != NULL); \ g_object_ref(ip); \ } \ - while (0); + while (0) # define unref_object(ip) \ do \ @@ -153,7 +183,7 @@ assert(__inst != NULL); \ g_object_unref(ip); \ } \ - while (0); + while (0) #else diff --git a/src/glibext/linecolumn.c b/src/glibext/linecolumn.c index 35f7698..22ff2a4 100644 --- a/src/glibext/linecolumn.c +++ b/src/glibext/linecolumn.c @@ -24,13 +24,9 @@ #include "linecolumn.h" -#include #include -#include "../common/extstr.h" - - /****************************************************************************** * * @@ -44,14 +40,12 @@ * * ******************************************************************************/ -void init_line_column(line_column *column) +void init_line_column(line_column_t *column) { - column->segments = NULL; + column->tokens = NULL; column->count = 0; -#ifdef INCLUDE_GTK_SUPPORT column->max_width = 0; -#endif } @@ -68,114 +62,162 @@ void init_line_column(line_column *column) * * ******************************************************************************/ -void reset_line_column(line_column *column) +void reset_line_column(line_column_t *column) { size_t i; /* Boucle de parcours */ for (i = 0; i < column->count; i++) - release_line_segment(column->segments[i]); + release_line_token(column->tokens[i]); - if (column->segments != NULL) + if (column->tokens != NULL) { - free(column->segments); - column->segments = NULL; + free(column->tokens); + column->tokens = NULL; } column->count = 0; -#ifdef INCLUDE_GTK_SUPPORT column->max_width = 0; -#endif } -#ifdef INCLUDE_GTK_SUPPORT + /****************************************************************************** * * -* Paramètres : column = colonne de ligne à mettre à jour. * +* Paramètres : column = colonne de ligne à venir compléter. * +* tag = propriétés de la zone de texte. * +* text = chaîne de caractères à traiter. * +* length = quantité de ces caractères. * +* style = gestionnaire de paramètres de rendu à consulter. * * * -* Description : Recalcule la largeur d'une colonne de segments. * +* Description : Ajoute un fragment de texte à une colonne de ligne. * * * -* Retour : - * +* Retour : Indice du point d'insertion. * * * * Remarques : - * * * ******************************************************************************/ -void refresh_line_column_width(line_column *column) +size_t append_text_to_line_column(line_column_t *column, TokenRenderingTag tag, const char *text, size_t length, const GTokenStyle *style) { - size_t i; /* Boucle de parcours */ + size_t result; /* Indice à retourner */ + line_token_t *token; /* Contenu à représenter */ - column->max_width = 0; + result = column->count; - for (i = 0; i < column->count; i++) - column->max_width += get_line_segment_width(column->segments[i]); + token = get_new_line_token(tag, text, length); + + column->tokens = realloc(column->tokens, ++column->count * sizeof(line_token_t *)); + + column->tokens[result] = token; + + //column->max_width += g_token_style_measure_width(style, tag, length); + + return result; } + + + + /****************************************************************************** * * -* Paramètres : column = colonne de ligne à consulter. * +* Paramètres : column = colonne de ligne de texte à manipuler. * +* cr = contexte graphique à utiliser pour les pinceaux. * +* x = abscisse du point d'impression (à maj). [OUT] * +* y = ordonnée du point d'impression. * +* style = style de rendu pour les bribes de texte. * * * -* Description : Fournit la quantité de pixels requise pour l'impression. * +* Description : Imprime le contenu d'une colonne de ligne de texte. * * * -* Retour : Largeur requise par la colonne, en pixel. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -gint get_column_width(const line_column *column) +void draw_line_column(const line_column_t *column, cairo_t *cr, int *x, int y, const GTokenStyle *style) { - return column->max_width; + size_t i; /* Boucle de parcours */ + + for (i = 0; i < column->count; i++) + draw_line_token(column->tokens[i], cr, x, y, style); } -#endif + + + + +#if 0 + +#include +#include + + +#include "../common/extstr.h" + + + + + +#ifdef INCLUDE_GTK_SUPPORT /****************************************************************************** * * -* Paramètres : column = colonne de ligne à venir compléter. * -* text = texte à insérer dans l'existant. * -* length = taille du texte à traiter. * -* type = type de décorateur à utiliser. * +* Paramètres : column = colonne de ligne à mettre à jour. * * * -* Description : Ajoute un fragment de texte à une colonne de ligne. * +* Description : Recalcule la largeur d'une colonne de segments. * * * -* Retour : Indice du point d'insertion. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -size_t append_text_to_line_column(line_column *column, const char *text, size_t length, RenderingTagType type) +void refresh_line_column_width(line_column *column) { - size_t result; /* Indice à retourner */ - line_segment *segment; /* Contenu à représenter */ + size_t i; /* Boucle de parcours */ - result = column->count; + column->max_width = 0; - segment = get_new_line_segment(type, text, length); + for (i = 0; i < column->count; i++) + column->max_width += get_line_segment_width(column->segments[i]); - column->segments = realloc(column->segments, ++column->count * sizeof(line_segment *)); +} - column->segments[result] = segment; -#ifdef INCLUDE_GTK_SUPPORT - column->max_width += get_line_segment_width(segment); -#endif +/****************************************************************************** +* * +* Paramètres : column = colonne de ligne à consulter. * +* * +* Description : Fournit la quantité de pixels requise pour l'impression. * +* * +* Retour : Largeur requise par la colonne, en pixel. * +* * +* Remarques : - * +* * +******************************************************************************/ - return result; +gint get_column_width(const line_column *column) +{ + return column->max_width; } +#endif + + + + /****************************************************************************** * * * Paramètres : column = colonne de ligne à venir compléter. * @@ -202,7 +244,7 @@ void replace_text_in_line_column(line_column *column, size_t index, const char * segment = column->segments[index]; - type = get_line_segment_type(segment); + type = get_line_token_type(segment); release_line_segment(segment); @@ -544,3 +586,5 @@ void export_line_column_segments(const line_column *column, buffer_export_contex } } + +#endif diff --git a/src/glibext/linecolumn.h b/src/glibext/linecolumn.h index 6dd50f6..a1757f9 100644 --- a/src/glibext/linecolumn.h +++ b/src/glibext/linecolumn.h @@ -25,39 +25,58 @@ #define _GLIBEXT_LINECOLUMN_H -#include -#include -#ifdef INCLUDE_GTK_SUPPORT -# include -#endif +#include -#include "linesegment.h" +#include "linetoken.h" /* Informations sur le contenu d'une colonne */ -typedef struct _line_column line_column; - - -/* Informations sur le contenu d'une colonne */ -struct _line_column +typedef struct _line_column_t { - line_segment **segments; /* Liste des segments contenus */ + line_token_t **tokens; /* Liste des segments contenus */ size_t count; /* Taille de cette liste */ -#ifdef INCLUDE_GTK_SUPPORT int max_width; /* Largeur max. de l'espace */ -#endif -}; +} line_column_t; + /* Initialise une colonne de ligne. */ -void init_line_column(line_column *); +void init_line_column(line_column_t *); /* Réinitialise une colonne de ligne. */ -void reset_line_column(line_column *); +void reset_line_column(line_column_t *); + +/* Ajoute un fragment de texte à une colonne de ligne. */ +size_t append_text_to_line_column(line_column_t *, TokenRenderingTag, const char *, size_t, const GTokenStyle *); + + + + +/* Imprime le contenu d'une colonne de ligne de texte. */ +void draw_line_column(const line_column_t *, cairo_t *, int *, int, const GTokenStyle *); + + + + +#if 0 + +#include +#include +#ifdef INCLUDE_GTK_SUPPORT +# include +#endif + + +#include "linesegment.h" + + + +/* Réinitialise une colonne de ligne. */ +//void reset_line_column(line_column *); #ifdef INCLUDE_GTK_SUPPORT @@ -70,7 +89,7 @@ gint get_column_width(const line_column *); #endif /* Ajoute un fragment de texte à une colonne de ligne. */ -size_t append_text_to_line_column(line_column *, const char *, size_t, RenderingTagType); +//size_t append_text_to_line_column(line_column *, const char *, size_t, RenderingTagType); /* Remplace un fragment de texte dans une colonne de ligne. */ void replace_text_in_line_column(line_column *, size_t, const char *, size_t); @@ -104,5 +123,8 @@ char *get_line_column_text(const line_column *, bool); void export_line_column_segments(const line_column *, buffer_export_context *, BufferExportType, int); +#endif + + #endif /* _GLIBEXT_LINECOLUMN_H */ diff --git a/src/glibext/linetoken.c b/src/glibext/linetoken.c index 192e030..6caa7df 100644 --- a/src/glibext/linetoken.c +++ b/src/glibext/linetoken.c @@ -1,6 +1,6 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * linesegment.c - concentration d'un fragment de caractères aux propriétés communes + * linetoken.c - concentration d'un fragment de caractères aux propriétés communes * * Copyright (C) 2016-2019 Cyrille Bagard * @@ -21,173 +21,137 @@ */ -#include "linesegment.h" +#include "linetoken.h" -#include -#include +#include #include -#include -#include #include -#include "../common/extstr.h" #include "../common/fnv1a.h" -#include "../core/paths.h" -#ifdef INCLUDE_GTK_SUPPORT -# include "../gtkext/rendering.h" -#endif -/* ------------------------ NATURE POUR UN FRAGMENT DE TEXTE ------------------------ */ +/* -------------------- NATURE DE BASE POUR UN FRAGMENT DE TEXTE -------------------- */ -/* Nom des éléments CSS */ +/* Fragment de caractères aux propriétés potentiellement partagées */ +struct _line_token_t +{ + gint ref_count; /* Compteur de références */ -#define SEGMENT_NAME(s) "token-" s + TokenRenderingTag tag; /* Type de rendu attendu */ -static const char *_segment_names[RTT_COUNT] = { + fnv64_t hash; /* Empreinte pour comparaisons */ - [RTT_NONE] = SEGMENT_NAME("none"), - [RTT_RAW] = SEGMENT_NAME("raw"), - [RTT_RAW_FULL] = SEGMENT_NAME("raw-full"), - [RTT_RAW_NULL] = SEGMENT_NAME("raw-null"), - [RTT_PRINTABLE] = SEGMENT_NAME("printable"), - [RTT_NOT_PRINTABLE] = SEGMENT_NAME("not-printable"), - [RTT_COMMENT] = SEGMENT_NAME("comment"), - [RTT_INDICATION] = SEGMENT_NAME("indication"), - [RTT_PHYS_ADDR_PAD] = SEGMENT_NAME("phys-addr-padding"), - [RTT_PHYS_ADDR] = SEGMENT_NAME("phys-addr"), - [RTT_VIRT_ADDR_PAD] = SEGMENT_NAME("virt-addr-padding"), - [RTT_VIRT_ADDR] = SEGMENT_NAME("virt-addr"), - [RTT_RAW_CODE] = SEGMENT_NAME("raw-code"), - [RTT_RAW_CODE_NULL] = SEGMENT_NAME("raw-code-null"), - [RTT_LABEL] = SEGMENT_NAME("label"), - [RTT_INSTRUCTION] = SEGMENT_NAME("instruction"), - [RTT_IMMEDIATE] = SEGMENT_NAME("immediate"), - [RTT_REGISTER] = SEGMENT_NAME("register"), - [RTT_PUNCT] = SEGMENT_NAME("punct"), - [RTT_HOOK] = SEGMENT_NAME("hooks"), - [RTT_SIGNS] = SEGMENT_NAME("signs"), - [RTT_LTGT] = SEGMENT_NAME("ltgt"), - [RTT_SECTION] = SEGMENT_NAME("section"), - [RTT_SEGMENT] = SEGMENT_NAME("segment"), - [RTT_STRING] = SEGMENT_NAME("string"), - [RTT_VAR_NAME] = SEGMENT_NAME("var-name"), - [RTT_KEY_WORD] = SEGMENT_NAME("keyword"), - [RTT_ERROR] = SEGMENT_NAME("error"), + size_t length; /* Taille du texte brut */ + char text[0]; /* Texte brut conservé */ }; +/* Fournit l'empreinte d'une bribe de texte pour rendu. */ +static guint hash_line_token(const line_token_t *); -#ifdef INCLUDE_GTK_SUPPORT - -/* Compléments à Cairo */ - -#define CAIRO_FONT_SLANT_COUNT 3 -#define CAIRO_FONT_WEIGHT_COUNT 2 +/* Détermine si deux fragments de texte sont identiques. */ +static bool is_line_token_equal(const line_token_t *, const line_token_t *); -#define CAIRO_FONTS_COUNT (CAIRO_FONT_SLANT_COUNT * CAIRO_FONT_WEIGHT_COUNT) -#define CAIRO_FONT_INDEX(s, w) ((s) + (w) * CAIRO_FONT_WEIGHT_COUNT) - - -/* Propriétés de rendu */ -typedef struct _segment_rendering -{ - rendering_color_t selection_bg; /* Fond d'impression */ - cairo_t *font_ctxts[CAIRO_FONTS_COUNT]; /* Contextes de police */ - double x_advances[CAIRO_FONTS_COUNT]; /* Largeurs par caractère */ - rendering_pattern_t patterns[RTT_COUNT];/* Modèles d'impression */ +/* ----------------------- ISOLATION DE CONTENUS PARTAGEABLES ----------------------- */ -} segment_rendering; +/* Conservation de toutes les créations partagées */ +static GHashTable *_token_htable; +G_LOCK_DEFINE_STATIC(_token_mutex); -/* Configuration globale des rendus */ -static segment_rendering _seg_params; +/* Fournit l'adresse d'un fragment de texte unique. */ +static line_token_t *get_shared_line_token(const line_token_t *); -#endif +/* Abandonne un contenu pour segments. */ +static void release_shared_line_token(line_token_t *); -/* ----------------------- ISOLATION DE CONTENUS PARTAGEABLES ----------------------- */ +/* ---------------------------------------------------------------------------------- */ +/* NATURE DE BASE POUR UN FRAGMENT DE TEXTE */ +/* ---------------------------------------------------------------------------------- */ +/****************************************************************************** +* * +* Paramètres : tag = propriétés de la zone de texte. * +* text = chaîne de caractères à traiter. * +* length = quantité de ces caractères. * +* * +* Description : Crée un nouveau fragment de texte avec des propriétés. * +* * +* Retour : Elément créé ou recyclé. * +* * +* Remarques : - * +* * +******************************************************************************/ -/* Fragment de caractères aux propriétés potentiellement partagées */ -struct _line_segment +line_token_t *get_new_line_token(TokenRenderingTag tag, const char *text, size_t length) { - gint ref_count; /* Compteur de références */ - -#ifdef INCLUDE_GTK_SUPPORT - rendering_pattern_t *pattern; /* Propriétés du rendu */ -#else - RenderingTagType type; /* Type de rendu attendu */ -#endif - - fnv64_t hash; /* Empreinte pour comparaisons */ - char text[0]; /* Texte brut conservé */ + line_token_t *result; /* Elément à retourner */ + char atmp[sizeof(line_token_t) + 128]; /* Allocation static facile */ + line_token_t *template; /* Contenu à mettre en place ? */ -}; + assert(length > 0); + /** + * L'octet nul final est attendu par la fonction cairo_show_text() + * pour le rendu. + */ -/* Conservation de toutes les créations partagées */ -static GHashTable *_segcnt_htable; -G_LOCK_DEFINE_STATIC(_segcnt_mutex); + if ((length + 1) < (sizeof(atmp) - sizeof(line_token_t))) + template = (line_token_t *)atmp; + else + template = malloc(sizeof(line_token_t) + length + 1); + template->tag = tag; -/* Fournit l'empreinte d'un contenu pour segments. */ -static guint get_line_segment_hash(const line_segment *); + template->hash = fnv_64a_hash(text); -/* Détermine si deux contenus pour segments sont identiques. */ -static bool is_line_segment_equal(const line_segment *, const line_segment *); + template->length = length; -/* Détermine si deux contenus pour segments sont identiques. */ -static line_segment *get_shared_segment_content(const line_segment *); + memcpy(template->text, text, length); + template->text[length] = '\0'; -/* Abandonne un contenu pour segments. */ -static void release_shared_segment_content(line_segment *); + result = get_shared_line_token(template); + if (template != (line_token_t *)atmp) + free(template); + return result; -/* -------------------- GESTION OPTIMALE D'UNE LISTE DE CONTENUS -------------------- */ +} -#ifdef INCLUDE_GTK_SUPPORT +/****************************************************************************** +* * +* Paramètres : token = fragment de texte à traiter. * +* * +* Description : Augmente le compteur de références d'un fragment de texte. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ -/* Liste identifiant un ensemble de segments */ -struct _segcnt_list +void ref_line_token(line_token_t *token) { - fnv64_t *hashes; /* Empreinte pour comparaisons */ - size_t count; /* Nommbre de ces empreintes */ - - unsigned int ref_count; /* Compteur de références */ - -}; - - -/* Indique si le contenu d'un segment est notable ou non. */ -bool selection_list_has_segment_content(const segcnt_list *, const line_segment *); - -#endif + g_atomic_int_inc(&token->ref_count); - - -/* ---------------------------------------------------------------------------------- */ -/* NATURE POUR UN FRAGMENT DE TEXTE */ -/* ---------------------------------------------------------------------------------- */ - - -#ifdef INCLUDE_GTK_SUPPORT +} /****************************************************************************** * * -* Paramètres : - * +* Paramètres : token = fragment de texte à libérer de la mémoire. * * * -* Description : Procède à l'initialisation des paramètres de rendu de texte. * +* Description : Retire une utilisation à un fragment de texte. * * * * Retour : - * * * @@ -195,164 +159,152 @@ bool selection_list_has_segment_content(const segcnt_list *, const line_segment * * ******************************************************************************/ -bool load_segment_rendering_parameters(void) +void release_line_token(line_token_t *token) { - cairo_font_slant_t s; /* Boucle de parcours #1 */ - cairo_font_weight_t w; /* Boucle de parcours #2 */ - cairo_t **cr; /* Contexte à créer */ - cairo_surface_t *surface; /* Surface pour dessin Cairo */ - cairo_text_extents_t extents; /* Couverture des caractères */ - RenderingTagType i; /* Boucle de parcours */ + release_shared_line_token(token); - /* Contextes pour les mesures initiales */ +} - for (s = CAIRO_FONT_SLANT_NORMAL; s < CAIRO_FONT_SLANT_COUNT; s++) - for (w = CAIRO_FONT_WEIGHT_NORMAL; w < CAIRO_FONT_WEIGHT_COUNT; w++) - { - cr = &_seg_params.font_ctxts[CAIRO_FONT_INDEX(s, w)]; +/****************************************************************************** +* * +* Paramètres : token = fragment de texte à consulter. * +* * +* Description : Fournit l'empreinte d'une bribe de texte pour rendu. * +* * +* Retour : Empreinte de lu contenu représenté. * +* * +* Remarques : - * +* * +******************************************************************************/ - surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 1, 1); - *cr = cairo_create(surface); - cairo_surface_destroy(surface); +static guint hash_line_token(const line_token_t *token) +{ + return token->hash; - cairo_select_font_face(*cr, "mono", s, w); - cairo_set_font_size(*cr, 13); +} - cairo_text_extents(*cr, "A", &extents); - _seg_params.x_advances[CAIRO_FONT_INDEX(s, w)] = extents.x_advance; - } +/****************************************************************************** +* * +* Paramètres : token = premier fragment de texte à analyser. * +* other = second fragment de texte à analyser. * +* * +* Description : Détermine si deux fragments de texte sont identiques. * +* * +* Retour : Bilan de la comparaison. * +* * +* Remarques : - * +* * +******************************************************************************/ - /* Fond d'impression */ +static bool is_line_token_equal(const line_token_t *token, const line_token_t *other) +{ + bool result; /* Résultat à retourner */ - _seg_params.selection_bg.has_color = true; - _seg_params.selection_bg.color.red = 0.5; - _seg_params.selection_bg.color.green = 0.5; - _seg_params.selection_bg.color.blue = 0.5; - _seg_params.selection_bg.color.alpha = 1.0; + result = (cmp_fnv_64a(token->hash, other->hash) == 0); - /* Chargement des définitions utiles */ + if (result) + result = (token->length == other->length); - for (i = 0; i < RTT_COUNT; i++) - load_rendering_pattern(_segment_names[i], &_seg_params.patterns[i]); + if (result) + result = (token->tag == other->tag); - return true; + if (result) + result = (strncmp(token->text, other->text, token->length) == 0); + + return result; } -#endif -/* ---------------------------------------------------------------------------------- */ -/* ISOLATION DE CONTENUS PARTAGEABLES */ -/* ---------------------------------------------------------------------------------- */ /****************************************************************************** * * -* Paramètres : - * +* Paramètres : token = fragment de texte à manipuler. * +* cr = contexte graphique à utiliser pour les pinceaux. * +* x = abscisse du point d'impression (à maj). [OUT] * +* y = ordonnée du point d'impression. * +* style = style de rendu pour les bribes de texte. * * * -* Description : Initialise la table mémorisant les contenus pour segments. * +* Description : Imprime le fragment de texte représenté. * * * -* Retour : Bilan de l'opération. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -bool init_segment_content_hash_table(void) +void draw_line_token(const line_token_t *token, cairo_t *cr, int *x, int y, const GTokenStyle *style) { - _segcnt_htable = g_hash_table_new_full((GHashFunc)get_line_segment_hash, - (GEqualFunc)is_line_segment_equal, - free, NULL); - - return (_segcnt_htable != NULL); + g_token_style_draw_text(style, token->tag, cr, x, y, token->text, token->length); } -/****************************************************************************** -* * -* Paramètres : - * -* * -* Description : Organise la sortie de la table des contenus pour segments. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ -void exit_segment_content_hash_table(void) -{ - assert(g_hash_table_size(_segcnt_htable) == 0); - g_hash_table_unref(_segcnt_htable); -} + + + +/* ---------------------------------------------------------------------------------- */ +/* ISOLATION DE CONTENUS PARTAGEABLES */ +/* ---------------------------------------------------------------------------------- */ /****************************************************************************** * * -* Paramètres : content = contenu pour segment à consulter. * +* Paramètres : - * * * -* Description : Fournit l'empreinte d'un contenu pour segments. * +* Description : Initialise la table mémorisant les contenus pour segments. * * * -* Retour : Empreinte de lu contenu représenté. * +* Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ -static guint get_line_segment_hash(const line_segment *content) +bool init_segment_content_hash_table(void) { - return content->hash; + _token_htable = g_hash_table_new_full((GHashFunc)hash_line_token, + (GEqualFunc)is_line_token_equal, + free, NULL); + + return (_token_htable != NULL); } /****************************************************************************** * * -* Paramètres : content = premier contenu pour segment à analyser. * -* other = second contenu pour segment à analyser. * +* Paramètres : - * * * -* Description : Détermine si deux contenus pour segments sont identiques. * +* Description : Organise la sortie de la table des contenus pour segments. * * * -* Retour : Bilan de la comparaison. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -static bool is_line_segment_equal(const line_segment *content, const line_segment *other) +void exit_segment_content_hash_table(void) { - bool result; /* Résultat à retourner */ - -#ifdef INCLUDE_GTK_SUPPORT - result = (content->pattern == other->pattern); -#else - result = (content->type == other->type); -#endif + assert(g_hash_table_size(_token_htable) == 0); - if (result) - result = (cmp_fnv_64a(content->hash, other->hash) == 0); - - if (result) - result = (strcmp(content->text, other->text) == 0); - - return result; + g_hash_table_unref(_token_htable); } /****************************************************************************** * * -* Paramètres : content = premier contenu pour segment à analyser. * -* other = second contenu pour segment à analyser. * +* Paramètres : template = premier contenu pour segment à rechercher. * * * -* Description : Détermine si deux contenus pour segments sont identiques. * +* Description : Fournit l'adresse d'un fragment de texte unique. * * * * Retour : Bilan de la comparaison. * * * @@ -360,34 +312,34 @@ static bool is_line_segment_equal(const line_segment *content, const line_segmen * * ******************************************************************************/ -static line_segment *get_shared_segment_content(const line_segment *content) +static line_token_t *get_shared_line_token(const line_token_t *template) { - line_segment *result; /* Contenu partagé à renvoyer */ + line_token_t *result; /* Contenu partagé à renvoyer */ gboolean found; /* Le contenu existe déjà ? */ size_t allocated; /* Besoin complet en mémoire */ #ifndef NDEBUG gboolean created; /* Validation de mise en place */ #endif - G_LOCK(_segcnt_mutex); + G_LOCK(_token_mutex); - found = g_hash_table_lookup_extended(_segcnt_htable, content, (gpointer *)&result, NULL); + found = g_hash_table_lookup_extended(_token_htable, template, (gpointer *)&result, NULL); if (!found) { - allocated = sizeof(line_segment) + strlen(content->text) + 1; + allocated = sizeof(line_token_t) + template->length + 1; - result = (line_segment *)malloc(allocated); + result = malloc(allocated); - memcpy(result, content, allocated); + memcpy(result, template, allocated); g_atomic_int_set(&result->ref_count, 1); #ifndef NDEBUG - created = g_hash_table_insert(_segcnt_htable, result, result); + created = g_hash_table_insert(_token_htable, result, result); assert(created); #else - g_hash_table_insert(_segcnt_htable, result, result); + g_hash_table_insert(_token_htable, result, result); #endif } @@ -400,7 +352,7 @@ static line_segment *get_shared_segment_content(const line_segment *content) } - G_UNLOCK(_segcnt_mutex); + G_UNLOCK(_token_mutex); return result; @@ -409,7 +361,7 @@ static line_segment *get_shared_segment_content(const line_segment *content) /****************************************************************************** * * -* Paramètres : content = contenu pour segments à délaisser. * +* Paramètres : token = fragment de texte à délaisser. * * * * Description : Abandonne un contenu pour segments. * * * @@ -419,24 +371,24 @@ static line_segment *get_shared_segment_content(const line_segment *content) * * ******************************************************************************/ -static void release_shared_segment_content(line_segment *content) +static void release_shared_line_token(line_token_t *token) { #ifndef NDEBUG gboolean deleted; /* Validation de suppression */ #endif - if (g_atomic_int_dec_and_test(&content->ref_count)) + if (g_atomic_int_dec_and_test(&token->ref_count)) { - G_LOCK(_segcnt_mutex); + G_LOCK(_token_mutex); #ifndef NDEBUG - deleted = g_hash_table_remove(_segcnt_htable, content); + deleted = g_hash_table_remove(_token_htable, token); assert(deleted); #else - g_hash_table_remove(_segcnt_htable, content); + g_hash_table_remove(_token_htable, token); #endif - G_UNLOCK(_segcnt_mutex); + G_UNLOCK(_token_mutex); } @@ -445,59 +397,240 @@ static void release_shared_segment_content(line_segment *content) + + + + + + + + + + +#if 0 + +#include +#include +#include +#include +#include +#include + + +#include "../common/extstr.h" +//#include "../common/fnv1a.h" +#include "../core/paths.h" +#ifdef INCLUDE_GTK_SUPPORT +# include "../gtkext/rendering.h" +#endif + + + +/* ------------------------ NATURE POUR UN FRAGMENT DE TEXTE ------------------------ */ + + +/* Nom des éléments CSS */ + +#define SEGMENT_NAME(s) "token-" s + +static const char *_segment_names[RTT_COUNT] = { + + [RTT_NONE] = SEGMENT_NAME("none"), + [RTT_RAW] = SEGMENT_NAME("raw"), + [RTT_RAW_FULL] = SEGMENT_NAME("raw-full"), + [RTT_RAW_NULL] = SEGMENT_NAME("raw-null"), + [RTT_PRINTABLE] = SEGMENT_NAME("printable"), + [RTT_NOT_PRINTABLE] = SEGMENT_NAME("not-printable"), + [RTT_COMMENT] = SEGMENT_NAME("comment"), + [RTT_INDICATION] = SEGMENT_NAME("indication"), + [RTT_PHYS_ADDR_PAD] = SEGMENT_NAME("phys-addr-padding"), + [RTT_PHYS_ADDR] = SEGMENT_NAME("phys-addr"), + [RTT_VIRT_ADDR_PAD] = SEGMENT_NAME("virt-addr-padding"), + [RTT_VIRT_ADDR] = SEGMENT_NAME("virt-addr"), + [RTT_RAW_CODE] = SEGMENT_NAME("raw-code"), + [RTT_RAW_CODE_NULL] = SEGMENT_NAME("raw-code-null"), + [RTT_LABEL] = SEGMENT_NAME("label"), + [RTT_INSTRUCTION] = SEGMENT_NAME("instruction"), + [RTT_IMMEDIATE] = SEGMENT_NAME("immediate"), + [RTT_REGISTER] = SEGMENT_NAME("register"), + [RTT_PUNCT] = SEGMENT_NAME("punct"), + [RTT_HOOK] = SEGMENT_NAME("hooks"), + [RTT_SIGNS] = SEGMENT_NAME("signs"), + [RTT_LTGT] = SEGMENT_NAME("ltgt"), + [RTT_SECTION] = SEGMENT_NAME("section"), + [RTT_SEGMENT] = SEGMENT_NAME("segment"), + [RTT_STRING] = SEGMENT_NAME("string"), + [RTT_VAR_NAME] = SEGMENT_NAME("var-name"), + [RTT_KEY_WORD] = SEGMENT_NAME("keyword"), + [RTT_ERROR] = SEGMENT_NAME("error"), + +}; + + +#ifdef INCLUDE_GTK_SUPPORT + +/* Compléments à Cairo */ + +#define CAIRO_FONT_SLANT_COUNT 3 +#define CAIRO_FONT_WEIGHT_COUNT 2 + +#define CAIRO_FONTS_COUNT (CAIRO_FONT_SLANT_COUNT * CAIRO_FONT_WEIGHT_COUNT) +#define CAIRO_FONT_INDEX(s, w) ((s) + (w) * CAIRO_FONT_WEIGHT_COUNT) + + +/* Propriétés de rendu */ +typedef struct _segment_rendering +{ + rendering_color_t selection_bg; /* Fond d'impression */ + + cairo_t *font_ctxts[CAIRO_FONTS_COUNT]; /* Contextes de police */ + double x_advances[CAIRO_FONTS_COUNT]; /* Largeurs par caractère */ + + rendering_pattern_t patterns[RTT_COUNT];/* Modèles d'impression */ + +} segment_rendering; + + +/* Configuration globale des rendus */ +static segment_rendering _seg_params; + +#endif + + + +/* ----------------------- ISOLATION DE CONTENUS PARTAGEABLES ----------------------- */ + + +/* Fragment de caractères aux propriétés potentiellement partagées */ +struct _line_segment +{ + gint ref_count; /* Compteur de références */ + +#ifdef INCLUDE_GTK_SUPPORT + rendering_pattern_t *pattern; /* Propriétés du rendu */ +#else + RenderingTagType type; /* Type de rendu attendu */ +#endif + + fnv64_t hash; /* Empreinte pour comparaisons */ + char text[0]; /* Texte brut conservé */ + +}; + + + +/* Détermine si deux contenus pour segments sont identiques. */ +static line_segment *get_shared_segment_content(const line_segment *); + +/* Abandonne un contenu pour segments. */ +static void release_shared_segment_content(line_segment *); + + + +/* -------------------- GESTION OPTIMALE D'UNE LISTE DE CONTENUS -------------------- */ + + +#ifdef INCLUDE_GTK_SUPPORT + +/* Liste identifiant un ensemble de segments */ +struct _segcnt_list +{ + fnv64_t *hashes; /* Empreinte pour comparaisons */ + size_t count; /* Nommbre de ces empreintes */ + + unsigned int ref_count; /* Compteur de références */ + +}; + + +/* Indique si le contenu d'un segment est notable ou non. */ +bool selection_list_has_segment_content(const segcnt_list *, const line_segment *); + +#endif + + + /* ---------------------------------------------------------------------------------- */ -/* NATURE DE BASE POUR UN FRAGMENT DE TEXTE */ +/* NATURE POUR UN FRAGMENT DE TEXTE */ /* ---------------------------------------------------------------------------------- */ +#ifdef INCLUDE_GTK_SUPPORT + + /****************************************************************************** * * -* Paramètres : type = propriétés de la zone de texte. * -* text = chaîne de caractères à traiter. * -* length = quantité de ces caractères. * +* Paramètres : - * * * -* Description : Crée un nouveau fragment de texte avec des propriétés. * +* Description : Procède à l'initialisation des paramètres de rendu de texte. * * * -* Retour : Elément créé ou recyclé. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -line_segment *get_new_line_segment(RenderingTagType type, const char *text, size_t length) +bool load_segment_rendering_parameters(void) { - line_segment *result; /* Elément à retourner */ - char atmp[sizeof(line_segment) + 128]; /* Allocation static facile */ - line_segment *content; /* Contenu à mettre en place ? */ + cairo_font_slant_t s; /* Boucle de parcours #1 */ + cairo_font_weight_t w; /* Boucle de parcours #2 */ + cairo_t **cr; /* Contexte à créer */ + cairo_surface_t *surface; /* Surface pour dessin Cairo */ + cairo_text_extents_t extents; /* Couverture des caractères */ + RenderingTagType i; /* Boucle de parcours */ - assert(length > 0); + /* Contextes pour les mesures initiales */ - if (length < (sizeof(atmp) - sizeof(line_segment))) - content = (line_segment *)atmp; - else - content = (line_segment *)malloc(sizeof(line_segment) + length + 1); + for (s = CAIRO_FONT_SLANT_NORMAL; s < CAIRO_FONT_SLANT_COUNT; s++) + for (w = CAIRO_FONT_WEIGHT_NORMAL; w < CAIRO_FONT_WEIGHT_COUNT; w++) + { + cr = &_seg_params.font_ctxts[CAIRO_FONT_INDEX(s, w)]; -#ifdef INCLUDE_GTK_SUPPORT - content->pattern = &_seg_params.patterns[type]; -#else - content->type = type; -#endif + surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 1, 1); + *cr = cairo_create(surface); + cairo_surface_destroy(surface); - content->hash = fnv_64a_hash(text); + cairo_select_font_face(*cr, "mono", s, w); + cairo_set_font_size(*cr, 13); - memcpy(content->text, text, length); - content->text[length] = '\0'; + cairo_text_extents(*cr, "A", &extents); + _seg_params.x_advances[CAIRO_FONT_INDEX(s, w)] = extents.x_advance; - result = get_shared_segment_content(content); + } - if (content != (line_segment *)atmp) - free(content); + /* Fond d'impression */ - return result; + _seg_params.selection_bg.has_color = true; + _seg_params.selection_bg.color.red = 0.5; + _seg_params.selection_bg.color.green = 0.5; + _seg_params.selection_bg.color.blue = 0.5; + _seg_params.selection_bg.color.alpha = 1.0; + + /* Chargement des définitions utiles */ + + for (i = 0; i < RTT_COUNT; i++) + load_rendering_pattern(_segment_names[i], &_seg_params.patterns[i]); + + return true; } +#endif + + + + + + + +/* ---------------------------------------------------------------------------------- */ +/* NATURE DE BASE POUR UN FRAGMENT DE TEXTE */ +/* ---------------------------------------------------------------------------------- */ + + + + /****************************************************************************** * * * Paramètres : segment = fragment de texte à traiter. * @@ -555,7 +688,7 @@ RenderingTagType get_line_segment_type(const line_segment *segment) #ifdef INCLUDE_GTK_SUPPORT result = (RenderingTagType)(segment->pattern - _seg_params.patterns); #else - result = segment->type; + result = segment->tag; #endif return result; @@ -1204,3 +1337,5 @@ bool selection_list_has_segment_content(const segcnt_list *list, const line_segm #endif + +#endif diff --git a/src/glibext/linetoken.h b/src/glibext/linetoken.h index 4e06f8c..25c93ed 100644 --- a/src/glibext/linetoken.h +++ b/src/glibext/linetoken.h @@ -1,6 +1,6 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * linesegment.h - prototypes pour la concentration d'un fragment de caractères aux propriétés communes + * linetoken.h - prototypes pour la concentration d'un fragment de caractères aux propriétés communes * * Copyright (C) 2016-2019 Cyrille Bagard * @@ -21,12 +21,61 @@ */ -#ifndef _GLIBEXT_LINESEGMENT_H -#define _GLIBEXT_LINESEGMENT_H +#ifndef _GLIBEXT_LINETOKEN_H +#define _GLIBEXT_LINETOKEN_H -#include #include + + +#include "tokenstyle.h" + + + +/* -------------------- NATURE DE BASE POUR UN FRAGMENT DE TEXTE -------------------- */ + + +/* Fragment de caractères aux propriétés potentiellement partagées */ +typedef struct _line_token_t line_token_t; + + +/* Crée un nouveau fragment de texte avec des propriétés. */ +line_token_t *get_new_line_token(TokenRenderingTag, const char *, size_t); + +/* Augmente le compteur de références d'un fragment de texte. */ +void ref_line_token(line_token_t *); + +/* Retire une utilisation à un fragment de texte. */ +void release_line_token(line_token_t *); + + + + + + + +/* ----------------------- ISOLATION DE CONTENUS PARTAGEABLES ----------------------- */ + + +/* Initialise la table mémorisant les contenus pour segments. */ +bool init_segment_content_hash_table(void); + +/* Organise la sortie de la table des contenus pour segments. */ +void exit_segment_content_hash_table(void); + + + +/* Imprime le fragment de texte représenté. */ +void draw_line_token(const line_token_t *, cairo_t *, int *, int, const GTokenStyle *); + + + + + + +#if 0 + +#include #ifdef INCLUDE_GTK_SUPPORT # include # include @@ -58,14 +107,14 @@ bool load_segment_rendering_parameters(void); /* Fragment de caractères aux propriétés potentiellement partagées */ -typedef struct _line_segment line_segment; +//typedef struct _line_segment line_segment; /* Initialise la table mémorisant les contenus pour segments. */ -bool init_segment_content_hash_table(void); +//bool init_segment_content_hash_table(void); /* Organise la sortie de la table des contenus pour segments. */ -void exit_segment_content_hash_table(void); +//void exit_segment_content_hash_table(void); @@ -74,13 +123,13 @@ void exit_segment_content_hash_table(void); /* Crée un nouveau fragment de texte avec des propriétés. */ -line_segment *get_new_line_segment(RenderingTagType, const char *, size_t); +//line_segment *get_new_line_segment(RenderingTagType, const char *, size_t); /* Augmente le compteur de références d'un fragment de texte. */ -void ref_line_segment(line_segment *); +//void ref_line_segment(line_segment *); /* Retire une utilisation à un fragment de texte. */ -void release_line_segment(line_segment *); +//void release_line_segment(line_segment *); /* Indique le type de rendu associé à un segment de ligne. */ RenderingTagType get_line_segment_type(const line_segment *); @@ -100,7 +149,7 @@ gint get_caret_position_from_line_segment(const line_segment *, gint); bool move_caret_on_line_segment(const line_segment *, gint *, bool, GdkScrollDirection); /* Imprime le fragment de texte représenté. */ -void draw_line_segment(const line_segment *, cairo_t *, gint *, gint, const segcnt_list *); +//void draw_line_segment(const line_segment *, cairo_t *, gint *, gint, const segcnt_list *); #endif @@ -174,6 +223,7 @@ bool add_segment_content_to_selection_list(segcnt_list *, const line_segment *); #endif +#endif -#endif /* _GLIBEXT_LINESEGMENT_H */ +#endif /* _GLIBEXT_LINETOKEN_H */ diff --git a/src/glibext/options/hex.c b/src/glibext/options/hex.c index 5804a57..ab461a7 100644 --- a/src/glibext/options/hex.c +++ b/src/glibext/options/hex.c @@ -101,7 +101,7 @@ static void g_hex_options_init(GHexOptions *options) #endif (const char *[]) { _("Offset") }, (const bool []) { true }, - 1); + HCO_COUNT); assert(status); diff --git a/src/glibext/options/hex.h b/src/glibext/options/hex.h index 48ce942..0d187dc 100644 --- a/src/glibext/options/hex.h +++ b/src/glibext/options/hex.h @@ -29,6 +29,16 @@ +/* Liste des colonnes en options */ +typedef enum _HexColumnOptions +{ + HCO_OFFSET, /* Position */ + + HCO_COUNT + +} HexColumnOptions; + + #define G_TYPE_HEX_OPTIONS (g_hex_options_get_type()) DECLARE_GTYPE(GHexOptions, g_hex_options, G, HEX_OPTIONS); diff --git a/src/glibext/tokenstyle.c b/src/glibext/tokenstyle.c index e797856..df1d42a 100644 --- a/src/glibext/tokenstyle.c +++ b/src/glibext/tokenstyle.c @@ -25,6 +25,7 @@ #include "tokenstyle.h" +#include #include @@ -60,34 +61,35 @@ static void g_token_style_finalize(GTokenStyle *); static const char *_token_names[TRT_COUNT] = { - [TRT_NONE] = SEGMENT_NAME("none"), - [TRT_RAW] = SEGMENT_NAME("raw"), - [TRT_RAW_FULL] = SEGMENT_NAME("raw-full"), - [TRT_RAW_NULL] = SEGMENT_NAME("raw-null"), - [TRT_PRINTABLE] = SEGMENT_NAME("printable"), - [TRT_NOT_PRINTABLE] = SEGMENT_NAME("not-printable"), - [TRT_COMMENT] = SEGMENT_NAME("comment"), - [TRT_INDICATION] = SEGMENT_NAME("indication"), - [TRT_PHYS_ADDR_PAD] = SEGMENT_NAME("phys-addr-padding"), - [TRT_PHYS_ADDR] = SEGMENT_NAME("phys-addr"), - [TRT_VIRT_ADDR_PAD] = SEGMENT_NAME("virt-addr-padding"), - [TRT_VIRT_ADDR] = SEGMENT_NAME("virt-addr"), - [TRT_RAW_CODE] = SEGMENT_NAME("raw-code"), - [TRT_RAW_CODE_NULL] = SEGMENT_NAME("raw-code-null"), - [TRT_LABEL] = SEGMENT_NAME("label"), - [TRT_INSTRUCTION] = SEGMENT_NAME("instruction"), - [TRT_IMMEDIATE] = SEGMENT_NAME("immediate"), - [TRT_REGISTER] = SEGMENT_NAME("register"), - [TRT_PUNCT] = SEGMENT_NAME("punct"), - [TRT_HOOK] = SEGMENT_NAME("hooks"), - [TRT_SIGNS] = SEGMENT_NAME("signs"), - [TRT_LTGT] = SEGMENT_NAME("ltgt"), - [TRT_SECTION] = SEGMENT_NAME("section"), - [TRT_SEGMENT] = SEGMENT_NAME("segment"), - [TRT_STRING] = SEGMENT_NAME("string"), - [TRT_VAR_NAME] = SEGMENT_NAME("var-name"), - [TRT_KEY_WORD] = SEGMENT_NAME("keyword"), - [TRT_ERROR] = SEGMENT_NAME("error"), + [TRT_NONE] = SEGMENT_NAME("none"), + [TRT_RAW_PRINTABLE] = SEGMENT_NAME("raw-printable"), + [TRT_RAW_NOT_PRINTABLE] = SEGMENT_NAME("raw-not-printable"), + [TRT_RAW_FULL] = SEGMENT_NAME("raw-full"), + [TRT_RAW_NULL] = SEGMENT_NAME("raw-null"), + [TRT_CHR_PRINTABLE] = SEGMENT_NAME("chr-printable"), + [TRT_CHR_NOT_PRINTABLE] = SEGMENT_NAME("chr-not-printable"), + [TRT_COMMENT] = SEGMENT_NAME("comment"), + [TRT_INDICATION] = SEGMENT_NAME("indication"), + [TRT_PHYS_ADDR_PAD] = SEGMENT_NAME("phys-addr-padding"), + [TRT_PHYS_ADDR] = SEGMENT_NAME("phys-addr"), + [TRT_VIRT_ADDR_PAD] = SEGMENT_NAME("virt-addr-padding"), + [TRT_VIRT_ADDR] = SEGMENT_NAME("virt-addr"), + [TRT_RAW_CODE] = SEGMENT_NAME("raw-code"), + [TRT_RAW_CODE_NULL] = SEGMENT_NAME("raw-code-null"), + [TRT_LABEL] = SEGMENT_NAME("label"), + [TRT_INSTRUCTION] = SEGMENT_NAME("instruction"), + [TRT_IMMEDIATE] = SEGMENT_NAME("immediate"), + [TRT_REGISTER] = SEGMENT_NAME("register"), + [TRT_PUNCT] = SEGMENT_NAME("punct"), + [TRT_HOOK] = SEGMENT_NAME("hooks"), + [TRT_SIGNS] = SEGMENT_NAME("signs"), + [TRT_LTGT] = SEGMENT_NAME("ltgt"), + [TRT_SECTION] = SEGMENT_NAME("section"), + [TRT_SEGMENT] = SEGMENT_NAME("segment"), + [TRT_STRING] = SEGMENT_NAME("string"), + [TRT_VAR_NAME] = SEGMENT_NAME("var-name"), + [TRT_KEY_WORD] = SEGMENT_NAME("keyword"), + [TRT_ERROR] = SEGMENT_NAME("error"), }; @@ -272,12 +274,35 @@ bool g_token_style_create(GTokenStyle *style, GtkWidget *target) /****************************************************************************** * * * Paramètres : style = gestionnaire de paramètres de rendu à consulter. * +* * +* Description : Fournit la quantité de pixels requise pour une ligne. * +* * +* Retour : Hauteur de chaque ligne de rendu, en pixels. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int g_token_style_get_line_height(const GTokenStyle *style) +{ + int result; /* Hauteur à retourner */ + + result = style->font_extents.height; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : style = gestionnaire de paramètres de rendu à consulter. * * tag = type de rendu sollicité. * * length = nombre de caractères à mesurer. * * * * Description : Fournit la quantité de pixels requise pour l'impression. * * * -* Retour : Largeur requise par la colonne, en pixel. * +* Retour : Largeur requise par la colonne, en pixels. * * * * Remarques : - * * * @@ -325,6 +350,13 @@ void g_token_style_draw_text(const GTokenStyle *style, TokenRenderingTag tag, ca cairo_operator_t old; /* Sauvegarde avant changement */ const rendering_property_t *prop; /* Motif de rendu visé */ + /* Cas particulier d'une tabulation */ + if (length == 1 && (text[0] == '\t' || text[0] == ' ')) + { + width = g_token_style_measure_width(style, tag, text[0] == '\t' ? TAB_SIZE : 1); + goto small_sep; + } + selected = false;//selection_list_has_segment_content(list, segment); width = g_token_style_measure_width(style, tag, length); @@ -378,6 +410,8 @@ void g_token_style_draw_text(const GTokenStyle *style, TokenRenderingTag tag, ca cairo_show_text(cr, text); + small_sep: + *x += width; } @@ -467,6 +501,56 @@ char *g_token_style_append_markup(const GTokenStyle *style, char *base, TokenRen } +/****************************************************************************** +* * +* Paramètres : style = gestionnaire de paramètres de rendu à consulter. * +* max = valeur maximale atteignable. * +* virt = indique une position virtuelle et non physique. * +* * +* Description : Détermine une taille de localisation, physique ou virtuelle. * +* * +* Retour : Largeur minimale à observer en pixels. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int g_token_style_compute_location_width(const GTokenStyle *style, uint64_t max, bool virt) +{ + int result; /* Taille à retourner */ + double n; /* Nombre de chiffres hexa */ + double c; /* Valeur ajustée */ + TokenRenderingTag tag; /* Type de représentation */ + + /** + * Les situations suivantes ont été évaluées : + * + * max | n | c + * ----------------------------------- + * 0 | 0 | 0 + * 1 | 0,25 | 1 + * f | 1 | 1 + * 10 | 1,02187 | 2 + * 11 | 1,04248 | 2 + * ff | 2 | 2 + * 100 | 2,00141 | 3 + * ffffffff | 8 | 8 + * ffffffffffffffff | 16 | 16 + */ + + n = log1p(max) / log(16); + + c = ceil(n); + + tag = virt ? TRT_VIRT_ADDR : TRT_PHYS_ADDR; + + result = g_token_style_measure_width(style, tag, c); + + return result; + +} + + /* ---------------------------------------------------------------------------------- */ /* RECEPTACLES DE SIGNAUX CONNECTES */ diff --git a/src/glibext/tokenstyle.css b/src/glibext/tokenstyle.css index 0cf9f37..6fb78aa 100644 --- a/src/glibext/tokenstyle.css +++ b/src/glibext/tokenstyle.css @@ -6,21 +6,30 @@ } +.token-raw-printable, +.token-chr-printable { + color: white; + +} + +.token-raw-not-printable, +.token-chr-not-printable { + + color: #bbbbbb; + +} .token-raw-full { color: white; - font-style: italic; font-weight: bold; } .token-raw-null { - color: black; - - background-color: pink; + color: #666666; } diff --git a/src/glibext/tokenstyle.h b/src/glibext/tokenstyle.h index 923b725..2e19b51 100644 --- a/src/glibext/tokenstyle.h +++ b/src/glibext/tokenstyle.h @@ -26,6 +26,8 @@ #define _GLIBEXT_TOKENSTYLE_H +#include +#include #include @@ -38,11 +40,12 @@ typedef enum _TokenRenderingTag { TRT_NONE, /* Espace ou tabulation */ - TRT_RAW, /* Contenu brut */ + TRT_RAW_PRINTABLE, /* Contenu brut */ + TRT_RAW_NOT_PRINTABLE, /* Contenu brut */ TRT_RAW_FULL, /* Contenu brut et complet */ TRT_RAW_NULL, /* Contenu brut et nul */ - TRT_PRINTABLE, /* Caractère imprimable */ - TRT_NOT_PRINTABLE, /* Caractère non imprimable */ + TRT_CHR_PRINTABLE, /* Caractère imprimable */ + TRT_CHR_NOT_PRINTABLE, /* Caractère non imprimable */ TRT_COMMENT, /* Commentaire */ TRT_INDICATION, /* Aide à la lecture */ @@ -82,6 +85,10 @@ typedef enum _TokenRenderingTag } TokenRenderingTag; +/* Caractères par tabulation */ +#define TAB_SIZE 2 + + #define G_TYPE_TOKEN_STYLE (g_token_style_get_type()) DECLARE_GTYPE(GTokenStyle, g_token_style, G, TOKEN_STYLE); @@ -90,6 +97,9 @@ DECLARE_GTYPE(GTokenStyle, g_token_style, G, TOKEN_STYLE); /* Crée un gestionnaire de style pour le rendu des lignes. */ GTokenStyle *g_token_style_new(GtkWidget *); +/* Fournit la quantité de pixels requise pour une ligne. */ +int g_token_style_get_line_height(const GTokenStyle *); + /* Fournit la quantité de pixels requise pour l'impression. */ int g_token_style_measure_width(const GTokenStyle *, TokenRenderingTag, size_t); @@ -102,6 +112,9 @@ char *g_token_style_build_markup(const GTokenStyle *, TokenRenderingTag, const c /* Ajoute du texte enjolivé selon un élément de thème. */ char *g_token_style_append_markup(const GTokenStyle *, char *, TokenRenderingTag, const char *); +/* Détermine une taille de localisation, physique ou virtuelle. */ +int g_token_style_compute_location_width(const GTokenStyle *, uint64_t, bool); + #endif /* _GLIBEXT_TOKENSTYLE_H */ diff --git a/src/glibext/widthtracker-int.h b/src/glibext/widthtracker-int.h new file mode 100644 index 0000000..50f5757 --- /dev/null +++ b/src/glibext/widthtracker-int.h @@ -0,0 +1,80 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * widthtracker-int.h - prototypes internes pour le suivi des largeurs associées à un ensemble de lignes + * + * Copyright (C) 2016-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 . + */ + + +#ifndef _GLIBEXT_WIDTHTRACKER_INT_H +#define _GLIBEXT_WIDTHTRACKER_INT_H + + +#include "widthtracker.h" + + + +/* Portions de largeurs communes */ +typedef struct _common_metrics_t +{ + size_t first; /* Premier indice de portion */ + size_t last; /* Dernier indice de portion */ + + size_t merging_index; /* Indice de colonne de fusion */ + + int *summary; /* Compilation de largeurs */ + bool cached; /* Mise en cache des calculs */ + +} common_metrics_t; + + +/* Gestionnaire de largeurs associées aux lignes (instance) */ +struct _GWidthTracker +{ + GObject parent; /* A laisser en premier */ + + GBufferCache *cache; /* Ensemble complet de lignes */ + size_t opt_count; /* Qté de colonnes en option */ + size_t reg_count; /* Nombre de colonnes normales */ +#ifndef NDEBUG + size_t col_count; /* Nombre maximum de colonnes */ +#endif + + common_metrics_t *locals; /* Portions représentées */ + size_t count; /* Quantité de ces portions */ + + int *min_widths; /* Largeurs requises suivies */ + bool *fixed; /* Indication d'impositions */ + bool cached; /* Mise en cache des calculs */ + +}; + +/* Gestionnaire de largeurs associées aux lignes (classe) */ +struct _GWidthTrackerClass +{ + GObjectClass parent; /* A laisser en premier */ + +}; + + +/* Met en place un nouveau suivi de largeurs au sein de lignes. */ +bool g_width_tracker_create(GWidthTracker *, GBufferCache *); + + + +#endif /* _GLIBEXT_WIDTHTRACKER_INT_H */ diff --git a/src/glibext/widthtracker.c b/src/glibext/widthtracker.c index bfeb32c..7e06578 100644 --- a/src/glibext/widthtracker.c +++ b/src/glibext/widthtracker.c @@ -26,6 +26,331 @@ #include #include + + +#include "widthtracker-int.h" + + + +/* ---------------------------- PRISE DE MESURES LOCALES ---------------------------- */ + + +/* Supprime de la mémoire une collecte de mesures locales. */ +static void delete_common_metrics(common_metrics_t *); + + + +/* ---------------------------- RASSEMBLEMENT DE MESURES ---------------------------- */ + + +/* Procède à l'initialisation d'une classe de suivi de largeurs. */ +static void g_width_tracker_class_init(GWidthTrackerClass *); + +/* Procède à l'initialisation d'un suivi de largeurs de lignes. */ +static void g_width_tracker_init(GWidthTracker *); + +/* Supprime toutes les références externes. */ +static void g_width_tracker_dispose(GWidthTracker *); + +/* Procède à la libération totale de la mémoire. */ +static void g_width_tracker_finalize(GWidthTracker *); + + + +/* ---------------------------------------------------------------------------------- */ +/* PRISE DE MESURES LOCALES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : metrics = mesures locales conservées. * +* * +* Description : Supprime de la mémoire une collecte de mesures locales. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void delete_common_metrics(common_metrics_t *metrics) +{ + free(metrics->summary); + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* RASSEMBLEMENT DE MESURES */ +/* ---------------------------------------------------------------------------------- */ + + +/* Détermine le type du gestionnaire de largeurs associées aux lignes. */ +G_DEFINE_TYPE(GWidthTracker, g_width_tracker, G_TYPE_OBJECT); + + +/****************************************************************************** +* * +* Paramètres : class = classe de composant GLib à initialiser. * +* * +* Description : Procède à l'initialisation d'une classe de suivi de largeurs.* +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_width_tracker_class_init(GWidthTrackerClass *class) +{ + GObjectClass *object; /* Autre version de la classe */ + + object = G_OBJECT_CLASS(class); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_width_tracker_dispose; + object->finalize = (GObjectFinalizeFunc)g_width_tracker_finalize; + +} + + +/****************************************************************************** +* * +* Paramètres : tracker = composant GLib à initialiser. * +* * +* Description : Procède à l'initialisation d'un suivi de largeurs de lignes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_width_tracker_init(GWidthTracker *tracker) +{ + tracker->cache = NULL; + tracker->opt_count = 0; + tracker->reg_count = 0; + + tracker->locals = NULL; + tracker->count = 0; + + tracker->min_widths = NULL; + tracker->fixed = NULL; + tracker->cached = false; + +} + + +/****************************************************************************** +* * +* Paramètres : tracker = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_width_tracker_dispose(GWidthTracker *tracker) +{ + g_clear_object(&tracker->cache); + + G_OBJECT_CLASS(g_width_tracker_parent_class)->dispose(G_OBJECT(tracker)); + +} + + +/****************************************************************************** +* * +* Paramètres : tracker = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_width_tracker_finalize(GWidthTracker *tracker) +{ + size_t i; /* Boucle de parcours */ + + for (i = 0; i < tracker->count; i++) + delete_common_metrics(&tracker->locals[i]); + + if (tracker->locals != NULL) + free(tracker->locals); + + if (tracker->min_widths != NULL) + free(tracker->min_widths); + + if (tracker->fixed != NULL) + free(tracker->fixed); + + G_OBJECT_CLASS(g_width_tracker_parent_class)->finalize(G_OBJECT(tracker)); + +} + + +/****************************************************************************** +* * +* Paramètres : cache = tampon de lignes à lier au futur collecteur. * +* * +* Description : Crée un nouveau suivi de largeurs au sein de lignes. * +* * +* Retour : Composant GLib créé. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GWidthTracker *g_width_tracker_new(GBufferCache *cache) +{ + GWidthTracker *result; /* Composant à retourner */ + + result = g_object_new(G_TYPE_WIDTH_TRACKER, NULL); + + if (!g_width_tracker_create(result, cache)) + g_clear_object(&result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : tracker = collecteur de largeur à initialiser pleinement. * +* cache = tampon de lignes à lier au futur élément. * +* * +* Description : Met en place un nouveau suivi de largeurs au sein de lignes. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_width_tracker_create(GWidthTracker *tracker, GBufferCache *cache) +{ + bool result; /* Bilen à retourner */ + size_t col_count; /* Nombre maximum de colonnes */ + + result = true; + + tracker->cache = cache; + ref_object(cache); + + g_buffer_cache_count_columns(cache, &tracker->opt_count, &tracker->reg_count); + + col_count = tracker->opt_count + tracker->reg_count; + +#ifndef NDEBUG + tracker->col_count = col_count; +#endif + + tracker->min_widths = malloc(col_count * sizeof(int)); + tracker->fixed = calloc(col_count, sizeof(bool)); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : tracker = gestionnaire de largeurs de lignes à mettre jour. * +* col = indice de colonne visée. * +* * +* Description : Indique la largeur minimale pour une colonne donnée. * +* * +* Retour : Largeur minimale à imposée, nulle ou positive. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int g_width_tracker_get_column_min_width(const GWidthTracker *tracker, size_t col) +{ + int result; /* Largeur à renvoyer */ + + assert(col < tracker->col_count); + + result = tracker->min_widths[col]; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : tracker = gestionnaire de largeurs de lignes à mettre jour. * +* col = indice de colonne visée. * +* width = largeur minimale à imposer. * +* * +* Description : Impose une largeur minimale pour une colonne donnée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_width_tracker_set_column_min_width(GWidthTracker *tracker, size_t col, int width) +{ + assert(col < tracker->col_count); + + if (width < 0) + width = 0; + + tracker->min_widths[col] = width; + tracker->fixed[col] = true; + +} + + +/****************************************************************************** +* * +* Paramètres : tracker = gestionnaire de largeurs de lignes à consulter. * +* width = largeur requise pour un affichage complet. [OUT] * +* * +* Description : Détermine la largeur nécessaire à une pleine représentation. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_width_tracker_compute_width(const GWidthTracker *tracker, int *width) +{ + size_t i; /* Boucle de parcours */ + + *width = 0; + + // FIX access to col_count + + for (i = 0; i < tracker->col_count; i++) + *width += tracker->min_widths[i]; + +} + + + + + + +#if 0 + + +//#include +//#include #include #include @@ -33,7 +358,7 @@ #include -#include "buffercache.h" +//#include "buffercache.h" #include "delayed-int.h" #include "../core/global.h" #include "../core/nproc.h" @@ -104,56 +429,7 @@ static void g_width_update_collect(GWidthUpdate *, line_width_summary *); /* ---------------------------- RASSEMBLEMENT DE MESURES ---------------------------- */ -/* Portions de largeurs communes */ -typedef struct _common_metrics -{ - size_t first; /* Premier indice de portion */ - size_t last; /* Dernier indice de portion */ - - line_width_summary summary; /* Compilation de largeurs */ - bool cached; /* Mise en cache des calculs */ - -} common_metrics; - - -/* Gestionnaire de largeurs associées aux lignes (instance) */ -struct _GWidthTracker -{ - GObject parent; /* A laisser en premier */ - - GBufferCache *cache; /* Ensemble complet de lignes */ - size_t col_count; /* Nombre maximum de colonnes */ - size_t opt_count; /* Qté de colonnes en option */ - - common_metrics *portions; /* Portions représentées */ - size_t count; /* Quantité de ces portions */ - - gint *min_widths; /* Largeurs min. à respecter */ - - line_width_summary summary; /* Largeurs requises suivies */ - bool cached; /* Mise en cache des calculs */ - -}; - -/* Gestionnaire de largeurs associées aux lignes (classe) */ -struct _GWidthTrackerClass -{ - GObjectClass parent; /* A laisser en premier */ - -}; - - -/* Procède à l'initialisation d'une classe de suivi de largeurs. */ -static void g_width_tracker_class_init(GWidthTrackerClass *); - -/* Procède à l'initialisation d'un suivi de largeurs de lignes. */ -static void g_width_tracker_init(GWidthTracker *); -/* Supprime toutes les références externes. */ -static void g_width_tracker_dispose(GWidthTracker *); - -/* Procède à la libération totale de la mémoire. */ -static void g_width_tracker_finalize(GWidthTracker *); /* Recherche la portion contenant un indice de ligne donné. */ static size_t g_width_tracker_find_metrics(const GWidthTracker *, size_t); @@ -375,131 +651,6 @@ static void g_width_update_collect(GWidthUpdate *update, line_width_summary *glo /* ---------------------------------------------------------------------------------- */ -/* Détermine le type du gestionnaire de largeurs associées aux lignes. */ -G_DEFINE_TYPE(GWidthTracker, g_width_tracker, G_TYPE_OBJECT); - - -/****************************************************************************** -* * -* Paramètres : class = classe de composant GTK à initialiser. * -* * -* Description : Procède à l'initialisation d'une classe de suivi de largeurs.* -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_width_tracker_class_init(GWidthTrackerClass *class) -{ - GObjectClass *object; /* Autre version de la classe */ - - object = G_OBJECT_CLASS(class); - - object->dispose = (GObjectFinalizeFunc/* ! */)g_width_tracker_dispose; - object->finalize = (GObjectFinalizeFunc)g_width_tracker_finalize; - -} - - -/****************************************************************************** -* * -* Paramètres : tracker = composant GLib à initialiser. * -* * -* Description : Procède à l'initialisation d'un suivi de largeurs de lignes. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_width_tracker_init(GWidthTracker *tracker) -{ - tracker->portions = NULL; - tracker->count = 0; - - memset(&tracker->summary, 0, sizeof(line_width_summary)); - tracker->cached = false; - -} - - -/****************************************************************************** -* * -* Paramètres : tracker = instance d'objet GLib à traiter. * -* * -* Description : Supprime toutes les références externes. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_width_tracker_dispose(GWidthTracker *tracker) -{ - g_object_unref(G_OBJECT(tracker->cache)); - - G_OBJECT_CLASS(g_width_tracker_parent_class)->dispose(G_OBJECT(tracker)); - -} - - -/****************************************************************************** -* * -* Paramètres : tracker = instance d'objet GLib à traiter. * -* * -* Description : Procède à la libération totale de la mémoire. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_width_tracker_finalize(GWidthTracker *tracker) -{ - if (tracker->min_widths != NULL) - free(tracker->min_widths); - - G_OBJECT_CLASS(g_width_tracker_parent_class)->finalize(G_OBJECT(tracker)); - -} - - -/****************************************************************************** -* * -* Paramètres : cache = tampon de lignes à lier au futur élément. * -* col_count = quantité maximale de colonnes à considérer. * -* opt_count = quantité de colonnes optionnelles. * -* * -* Description : Crée un nouveau suivi de largeurs au sein de lignes. * -* * -* Retour : Composant GLib créé. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GWidthTracker *g_width_tracker_new(GBufferCache *cache, size_t col_count, size_t opt_count) -{ - GWidthTracker *result; /* Composant à retourner */ - - result = g_object_new(G_TYPE_WIDTH_TRACKER, NULL); - - g_object_ref(G_OBJECT(cache)); - result->cache = cache; - - result->col_count = col_count; - result->opt_count = opt_count; - - result->min_widths = calloc(col_count, sizeof(gint)); - - return result; - -} /****************************************************************************** @@ -588,57 +739,6 @@ size_t g_width_tracker_count_columns(const GWidthTracker *tracker) } -/****************************************************************************** -* * -* Paramètres : tracker = gestionnaire de largeurs de lignes à mettre jour. * -* col = indice de colonne visée. * -* * -* Description : Indique la largeur minimale pour une colonne donnée. * -* * -* Retour : Largeur minimale à imposée, nulle ou positive. * -* * -* Remarques : - * -* * -******************************************************************************/ - -gint g_width_tracker_get_column_min_width(GWidthTracker *tracker, size_t col) -{ - gint result; /* Largeur à renvoyer */ - - assert(col < tracker->col_count); - - result = tracker->min_widths[col]; - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : tracker = gestionnaire de largeurs de lignes à mettre jour. * -* col = indice de colonne visée. * -* width = largeur minimale à imposer. * -* * -* Description : Impose une largeur minimale pour une colonne donnée. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_width_tracker_set_column_min_width(GWidthTracker *tracker, size_t col, gint width) -{ - assert(col < tracker->col_count); - - if (width < 0) - width = 0; - - tracker->min_widths[col] = width; - -} - /****************************************************************************** * * @@ -1367,3 +1467,7 @@ gint g_width_tracker_get_local_column_width(GWidthTracker *tracker, size_t index return result; } + + +#endif + diff --git a/src/glibext/widthtracker.h b/src/glibext/widthtracker.h index ce0aa93..c67e335 100644 --- a/src/glibext/widthtracker.h +++ b/src/glibext/widthtracker.h @@ -25,6 +25,34 @@ #define _GLIBEXT_WIDTHTRACKER_H +#include "buffercache.h" +#include "helpers.h" + + + +#define G_TYPE_WIDTH_TRACKER (g_width_tracker_get_type()) + +DECLARE_GTYPE(GWidthTracker, g_width_tracker, G, WIDTH_TRACKER); + + +/* Crée un nouveau suivi de largeurs au sein de lignes. */ +GWidthTracker *g_width_tracker_new(GBufferCache *); + +/* Indique la largeur minimale pour une colonne donnée. */ +int g_width_tracker_get_column_min_width(const GWidthTracker *, size_t); + +/* Impose une largeur minimale pour une colonne donnée. */ +void g_width_tracker_set_column_min_width(GWidthTracker *, size_t, int); + +/* Détermine la largeur nécessaire à une pleine représentation. */ +void g_width_tracker_compute_width(const GWidthTracker *, int *); + + + + +#if 0 + + #include #include @@ -74,7 +102,7 @@ typedef struct _GWidthTrackerClass GWidthTrackerClass; GType g_width_tracker_get_type(void); /* Crée un nouveau suivi de largeurs au sein de lignes. */ -GWidthTracker *g_width_tracker_new(GBufferCache *, size_t, size_t); +//GWidthTracker *g_width_tracker_new(GBufferCache *, size_t, size_t); /* Crée un nouveau suivi de largeurs au sein de lignes. */ GWidthTracker *g_width_tracker_new_restricted(const GWidthTracker *, size_t, size_t); @@ -82,12 +110,6 @@ GWidthTracker *g_width_tracker_new_restricted(const GWidthTracker *, size_t, siz /* Indique le nombre de colonnes prises en compte. */ size_t g_width_tracker_count_columns(const GWidthTracker *); -/* Indique la largeur minimale pour une colonne donnée. */ -gint g_width_tracker_get_column_min_width(GWidthTracker *, size_t); - -/* Impose une largeur minimale pour une colonne donnée. */ -void g_width_tracker_set_column_min_width(GWidthTracker *, size_t, gint); - /* Prend acte d'un changement sur une ligne pour les largeurs. */ void g_width_tracker_update(GWidthTracker *, size_t); @@ -110,5 +132,8 @@ gint g_width_tracker_get_margin(GWidthTracker *, const GDisplayOptions *); gint g_width_tracker_get_local_column_width(GWidthTracker *, size_t, size_t, size_t); +#endif + + #endif /* _GLIBEXT_WIDTHTRACKER_H */ diff --git a/src/gtkext/Makefile.am b/src/gtkext/Makefile.am index e33e09e..c9445e6 100644 --- a/src/gtkext/Makefile.am +++ b/src/gtkext/Makefile.am @@ -11,8 +11,6 @@ libgtkext_la_SOURCES = \ easygtk.h easygtk.c \ gtkbinarystrip.h gtkbinarystrip.c \ gtkblockdisplay.h gtkblockdisplay.c \ - gtkbufferdisplay-int.h \ - gtkbufferdisplay.h gtkbufferdisplay.c \ gtkdockable-int.h \ gtkdockable.h gtkdockable.c \ gtkdockstation.h gtkdockstation.c \ @@ -39,8 +37,11 @@ RES_FILES = \ libgtkext4_la_SOURCES = \ area-int.h \ area.h area.c \ + bufferview-int.h \ + bufferview.h bufferview.c \ contentview-int.h \ contentview.h contentview.c \ + hexview-int.h \ hexview.h hexview.c \ resources.h resources.c diff --git a/src/gtkext/bufferview-int.h b/src/gtkext/bufferview-int.h index d02aa37..7c9c8e1 100644 --- a/src/gtkext/bufferview-int.h +++ b/src/gtkext/bufferview-int.h @@ -1,8 +1,8 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * gtkbufferdisplay-int.h - prototypes internes pour l'affichage de tampons de lignes + * bufferview-int.h - prototypes internes pour l'affichage de tampons de lignes * - * Copyright (C) 2016-2019 Cyrille Bagard + * Copyright (C) 2016-2024 Cyrille Bagard * * This file is part of Chrysalide. * @@ -21,27 +21,38 @@ */ -#ifndef _GTK_BUFFERDISPLAY_INT_H -#define _GTK_BUFFERDISPLAY_INT_H +#ifndef _GTKEXT_BUFFERVIEW_INT_H +#define _GTKEXT_BUFFERVIEW_INT_H -#include "gtkbufferdisplay.h" +#include "bufferview.h" +#include "contentview-int.h" -#include "gtkdisplaypanel-int.h" - +#if 0 /* Réagit à un déplacement de curseur. */ -typedef bool (* notify_caret_relocation_fc) (GtkBufferDisplay *, const GdkRectangle *); +typedef bool (* notify_caret_relocation_fc) (GtkBufferView *, const GdkRectangle *); +#endif + + /* Composant d'affichage de tampon de lignes (instance) */ -struct _GtkBufferDisplay +struct _GtkBufferView { - GtkDisplayPanel parent; /* A laisser en premier */ + GtkContentView parent; /* A laisser en premier */ + + GBufferView *view; /* Vue choisie sur un tampon */ + GTokenStyle *style; /* Centralisation des styles */ + + int virt_top; /* Première ordonnée affichée */ + - GBufferView *view; /* Vue sur le contenu affiché */ + + +#if 0 cairo_rectangle_int_t caret; /* Emplacement du curseur #1 */ GLineCursor *cursor; /* Emplacement du curseur #2 */ @@ -51,23 +62,29 @@ struct _GtkBufferDisplay GtkBuilder *builder; /* Constructeur à manipuler */ GtkWidget *bar; /* Barre d'outils intégrée */ +#endif + }; /* Composant d'affichage de tampon de lignes (classe) */ -struct _GtkBufferDisplayClass +struct _GtkBufferViewClass { - GtkDisplayPanelClass parent; /* A laisser en premier */ + GtkContentViewClass parent; /* A laisser en premier */ + +#if 0 notify_caret_relocation_fc notify_caret;/* Accompagne un déplacement */ /* Signaux */ - void (* reach_limit) (GtkBufferDisplay *, GdkScrollDirection); + void (* reach_limit) (GtkBufferView *, GdkScrollDirection); + + void (* prepare_collapsing) (GtkBufferView *, gboolean); - void (* prepare_collapsing) (GtkBufferDisplay *, gboolean); +#endif }; -#endif /* _GTK_BUFFERDISPLAY_INT_H */ +#endif /* _GTKEXT_BUFFERVIEW_INT_H */ diff --git a/src/gtkext/bufferview.c b/src/gtkext/bufferview.c index 4566cc5..4a700c3 100644 --- a/src/gtkext/bufferview.c +++ b/src/gtkext/bufferview.c @@ -1,8 +1,8 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * gtkbufferdisplay.c - affichage de tampons de lignes + * bufferview.c - affichage de tampons de lignes * - * Copyright (C) 2016-2019 Cyrille Bagard + * Copyright (C) 2016-2024 Cyrille Bagard * * This file is part of Chrysalide. * @@ -21,9 +21,418 @@ */ -#include "gtkbufferdisplay.h" +#include "bufferview.h" +#include "bufferview-int.h" + + + + + +/* ------------------------- BASES D'UN COMPOSANT GRAPHIQUE ------------------------- */ + + +/* Procède à l'initialisation de l'afficheur de tampons. */ +static void gtk_buffer_view_class_init(GtkBufferViewClass *); + +/* Procède à l'initialisation de l'afficheur de tampons. */ +static void gtk_buffer_view_init(GtkBufferView *); + +/* Supprime toutes les références externes. */ +static void gtk_buffer_view_dispose(GtkBufferView *); + +/* Procède à la libération totale de la mémoire. */ +static void gtk_buffer_view_finalize(GtkBufferView *); + + + + +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + +/* Prend acte de la taille allouée au composant d'affichage. */ +static void gtk_buffer_view_size_allocate(GtkWidget *, int, int, int); + +/* Réagit à un défilement chez une barre associée au composant. */ +static void gtk_buffer_view_adjust_scroll_value(GtkBufferView *, GtkOrientation, GtkAdjustment *); + + + +/* ---------------------------------------------------------------------------------- */ +/* BASES D'UN COMPOSANT GRAPHIQUE */ +/* ---------------------------------------------------------------------------------- */ + + +/* Détermine le type du composant d'affichage générique. */ +G_DEFINE_TYPE(GtkBufferView, gtk_buffer_view, GTK_TYPE_CONTENT_VIEW); + + +/****************************************************************************** +* * +* Paramètres : class = classe GTK à initialiser. * +* * +* Description : Procède à l'initialisation de l'afficheur de tampons. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_buffer_view_class_init(GtkBufferViewClass *class) +{ + GObjectClass *object; /* Autre version de la classe */ + GtkWidgetClass *widget; /* Classe version Widget */ + GtkContentViewClass *content; /* Base d'affichage */ + + object = G_OBJECT_CLASS(class); + + object->dispose = (GObjectFinalizeFunc/* ! */)gtk_buffer_view_dispose; + object->finalize = (GObjectFinalizeFunc)gtk_buffer_view_finalize; + + widget = GTK_WIDGET_CLASS(class); + + widget->size_allocate = gtk_buffer_view_size_allocate; + + content = GTK_CONTENT_VIEW_CLASS(class); + + content->adjust = (adjust_scroll_value_fc)gtk_buffer_view_adjust_scroll_value; + + + +#if 0 + + widget_class->focus_in_event = gtk_buffer_view_focus; + widget_class->focus_out_event = gtk_buffer_view_focus; + widget_class->button_press_event = gtk_buffer_view_button_press; + widget_class->draw = gtk_buffer_view_draw; + widget_class->key_press_event = gtk_buffer_view_key_press; + + panel_class = GTK_DISPLAY_PANEL_CLASS(class); + + panel_class->compute_size = (compute_requested_size_fc)gtk_buffer_view_compute_requested_size; + panel_class->compute_inc = (compute_scroll_inc_fc)gtk_buffer_view_compute_scroll_inc; + panel_class->adjust = (adjust_scroll_value_fc)gtk_buffer_view_adjust_scroll_value; + panel_class->get_coordinates = (get_coordinates_fc)gtk_buffer_view_get_cursor_coordinates; + panel_class->get_active = (get_active_object_fc)gtk_buffer_view_get_active_object; + panel_class->move_caret_to = (move_caret_to_fc)_gtk_buffer_view_move_caret_to; + panel_class->cache_glance = (cache_glance_fc)gtk_buffer_view_cache_glance; + + panel_class->get_cursor = (get_cursor_fc)gtk_buffer_view_get_cursor; + + /* Signaux */ + + g_signal_new("reach-limit", + GTK_TYPE_BUFFER_DISPLAY, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(GtkBufferViewClass, reach_limit), + NULL, NULL, + g_cclosure_marshal_VOID__ENUM, + G_TYPE_NONE, 1, GTK_TYPE_SCROLL_TYPE); + + g_signal_new("prepare-collapsing", + GTK_TYPE_BUFFER_DISPLAY, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(GtkBufferViewClass, prepare_collapsing), + NULL, NULL, + g_cclosure_marshal_VOID__BOOLEAN, + G_TYPE_NONE, 1, G_TYPE_BOOLEAN); + +#endif + +} + + +/****************************************************************************** +* * +* Paramètres : display = composant GTK à initialiser. * +* * +* Description : Procède à l'initialisation de l'afficheur de tampons. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_buffer_view_init(GtkBufferView *view) +{ + view->view = NULL; + view->style = g_token_style_new(GTK_WIDGET(view)); + + view->virt_top = 0; + +} + + +/****************************************************************************** +* * +* Paramètres : display = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_buffer_view_dispose(GtkBufferView *view) +{ +#if 0 + + if (display->caret_timer != 0) + { + g_source_remove(display->caret_timer); + display->caret_timer = 0; + } + + g_clear_object(&display->cursor); + + g_clear_object(&display->builder); + g_clear_object(&display->bar); + +#endif + + + + + g_clear_object(&view->view); + g_clear_object(&view->style); + + G_OBJECT_CLASS(gtk_buffer_view_parent_class)->dispose(G_OBJECT(view)); + +} + + +/****************************************************************************** +* * +* Paramètres : display = instance d'objet Gtk à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_buffer_view_finalize(GtkBufferView *view) +{ + G_OBJECT_CLASS(gtk_buffer_view_parent_class)->finalize(G_OBJECT(view)); + +} + + +/****************************************************************************** +* * +* Paramètres : view = composant GTK à consulter. * +* * +* Description : Fournit la vue associée au tampon de lignes courant. * +* * +* Retour : Vue mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBufferView *gtk_buffer_view_get_view(const GtkBufferView *view) +{ + GBufferView *result; /* Instance à retourner */ + + result = view->view; + + ref_object(result); + + return result; + +} + + + + + + + + + + + + + + + + + + + + + + + + +/* ---------------------------------------------------------------------------------- */ +/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : widget = composant GTK à examiner. * +* width = largeur affectée au composant graphique. * +* height = hauteur affectée au composant graphique. * +* baseline = ligne de base affectée au composant graphique. * +* * +* Description : Prend acte de la taille allouée au composant d'affichage. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_buffer_view_size_allocate(GtkWidget *widget, int width, int height, int baseline) +{ + GtkContentView *base; /* Version de base */ + GtkBufferView *view; /* Version spécialisée */ + int full_width; /* Largeur idéale complète */ + int full_height; /* Hauteur idéale complète */ + int *min_widths; /* Largeurs minimales imposées */ + int *min_heights; /* Hauteurs minimales imposées */ + size_t i; /* Boucle de parcours */ + int upper; /* Valeur maximale retenue */ + GtkAdjustment *adj; /* Ajustement à mettre à jour */ + int line_height; /* Hauteur d'une ligne unique */ + int lines_per_page; /* Nombre de lignes sur l'écran*/ + GtkAllocation allocated; /* Zone allouée */ + GWidthTracker *tracker; /* Collecteur de largeurs */ + + base = GTK_CONTENT_VIEW(widget); + view = GTK_BUFFER_VIEW(widget); + + /* Détermination de la surface idéale à afficher */ + + g_buffer_view_compute_size(view->view, &full_width, &full_height); + + min_widths = alloca(base->sub_count * sizeof(int)); + min_heights = alloca(base->sub_count * sizeof(int)); + + for (i = 0; i < base->sub_count; i++) + { + gtk_widget_measure(base->sub_children[i], GTK_ORIENTATION_HORIZONTAL, -1, + &min_widths[i], NULL, NULL, NULL); + full_width += min_widths[i]; + + gtk_widget_measure(base->sub_children[i], GTK_ORIENTATION_VERTICAL, -1, + &min_heights[i], NULL, NULL, NULL); + full_height += min_heights[i]; + + } + + /* Définition des besoins en défilement */ + + upper = MAX(width, full_width); + + adj = base->adjustments[GTK_ORIENTATION_HORIZONTAL]; + + gtk_adjustment_configure(adj, + gtk_adjustment_get_value(adj), + 0, upper, + 0.1 * width, + 0.9 * width, + width); + + upper = MAX(height, full_height); + + line_height = g_token_style_get_line_height(view->style); + + lines_per_page = height / line_height; + if (lines_per_page == 0) lines_per_page = 1; + + adj = base->adjustments[GTK_ORIENTATION_VERTICAL]; + + gtk_adjustment_configure(adj, + gtk_adjustment_get_value(adj), + 0, upper, + line_height * lines_per_page, + line_height * lines_per_page * 10, + height); + + /* Placement des composants d'affichage */ + + tracker = g_buffer_view_get_tracker(view->view); + + allocated.x = 0; + allocated.y = 0; + allocated.height = height; + + for (i = 0; i < base->sub_count; i++) + { + allocated.width = g_width_tracker_get_column_min_width(tracker, i); + + if ((i + 1) == base->sub_count && allocated.width < (width - allocated.x)) + allocated.width = width - allocated.x; + + gtk_widget_size_allocate(base->sub_children[i], &allocated, baseline); + + allocated.x += allocated.width; + + } + + unref_object(tracker); + + /* Mise à jour des éléments plus internes */ + + GTK_WIDGET_CLASS(gtk_buffer_view_parent_class)->size_allocate(widget, width, height, baseline); + +} + + +/****************************************************************************** +* * +* Paramètres : view = panneau d'affichage concerné. * +* orientation = indication sur le défilement à traiter. * +* adj = nouvel ajustement à prendre en compte. * +* * +* Description : Réagit à un défilement chez une barre associée au composant. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_buffer_view_adjust_scroll_value(GtkBufferView *view, GtkOrientation orientation, GtkAdjustment *adj) +{ + GtkContentView *base; /* Version de base */ + size_t i; /* Boucle de parcours */ + + base = GTK_CONTENT_VIEW(view); + + if (orientation == GTK_ORIENTATION_HORIZONTAL) + printf("TODO...\n"); + + else + { + view->virt_top = gtk_adjustment_get_value(adj); + + for (i = 0; i < base->sub_count; i++) + gtk_widget_queue_draw(base->sub_children[i]); + + } + +} + + + + + + + + +#if 0 + #include @@ -38,16 +447,16 @@ /* Procède à l'initialisation de l'afficheur de tampons. */ -static void gtk_buffer_display_class_init(GtkBufferDisplayClass *); +//static void gtk_buffer_display_class_init(GtkBufferDisplayClass *); /* Procède à l'initialisation de l'afficheur de tampons. */ -static void gtk_buffer_display_init(GtkBufferDisplay *); +//static void gtk_buffer_display_init(GtkBufferDisplay *); /* Supprime toutes les références externes. */ -static void gtk_buffer_display_dispose(GtkBufferDisplay *); +//static void gtk_buffer_display_dispose(GtkBufferDisplay *); /* Procède à la libération totale de la mémoire. */ -static void gtk_buffer_display_finalize(GtkBufferDisplay *); +//static void gtk_buffer_display_finalize(GtkBufferDisplay *); /* Intègre le focus dans le rendu du composant. */ static gboolean gtk_buffer_display_focus(GtkWidget *, GdkEventFocus *); @@ -882,30 +1291,6 @@ static GLineCursor *gtk_buffer_display_get_cursor(const GtkBufferDisplay *displa } -/****************************************************************************** -* * -* Paramètres : display = composant GTK à consulter. * -* * -* Description : Fournit la vue associée au tampon de lignes courant. * -* * -* Retour : Vue mise en place. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GBufferView *gtk_buffer_display_get_view(const GtkBufferDisplay *display) -{ - GBufferView *result; /* Instance à retourner */ - - result = display->view; - - g_object_ref(G_OBJECT(result)); - - return result; - -} - /* ---------------------------------------------------------------------------------- */ @@ -1437,3 +1822,5 @@ static gboolean on_block_bar_collapsing_leave(GtkWidget *widget, GdkEventCrossin return FALSE; } + +#endif diff --git a/src/gtkext/bufferview.h b/src/gtkext/bufferview.h index 8f2d63c..1bdfc80 100644 --- a/src/gtkext/bufferview.h +++ b/src/gtkext/bufferview.h @@ -1,8 +1,8 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * gtkbufferdisplay.h - prototypes pour l'affichage de tampons de lignes + * bufferview.h - prototypes pour l'affichage de tampons de lignes * - * Copyright (C) 2016-2019 Cyrille Bagard + * Copyright (C) 2016-2024 Cyrille Bagard * * This file is part of Chrysalide. * @@ -21,41 +21,36 @@ */ -#ifndef _GTKEXT_GTKBUFFER_DISPLAY_H -#define _GTKEXT_GTKBUFFER_DISPLAY_H +#ifndef _GTKEXT_BUFFERVIEW_H +#define _GTKEXT_BUFFERVIEW_H -#include #include #include "../glibext/bufferview.h" +#include "../glibext/helpers.h" -#define GTK_TYPE_BUFFER_DISPLAY (gtk_buffer_display_get_type()) -#define GTK_BUFFER_DISPLAY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_BUFFER_DISPLAY, GtkBufferDisplay)) -#define GTK_BUFFER_DISPLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GTK_TYPE_BUFFER_DISPLAY, GtkBufferDisplayClass)) -#define GTK_IS_BUFFER_DISPLAY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_BUFFER_DISPLAY)) -#define GTK_IS_BUFFER_DISPLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GTK_TYPE_BUFFER_DISPLAY)) -#define GTK_BUFFER_DISPLAY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_BUFFER_VIEW, GtkBufferDisplayClass)) +#define GTK_TYPE_BUFFER_VIEW (gtk_buffer_view_get_type()) +DECLARE_GTYPE(GtkBufferView, gtk_buffer_view, GTK, BUFFER_VIEW); -/* Composant d'affichage de tampon de lignes (instance) */ -typedef struct _GtkBufferDisplay GtkBufferDisplay; -/* Composant d'affichage de tampon de lignes (classe) */ -typedef struct _GtkBufferDisplayClass GtkBufferDisplayClass; + +/* Fournit la vue associée au tampon de lignes courant. */ +GBufferView *gtk_buffer_view_get_view(const GtkBufferView *); + -/* Détermine le type du composant d'affichage de tampon de lignes. */ -GType gtk_buffer_display_get_type(void); -/* Fournit la vue associée au tampon de lignes courant. */ -GBufferView *gtk_buffer_display_get_view(const GtkBufferDisplay *); + +#if 0 + /* ------------------------------ ANIMATION DU CURSEUR ------------------------------ */ @@ -73,6 +68,9 @@ bool gtk_buffer_display_move_caret_to(GtkBufferDisplay *, bool, gint *); /* Ajoute une nouvelle barre d'outils pour bloc au composant. */ void gtk_buffer_display_add_block_bar(GtkBufferDisplay *); +#endif + + -#endif /* _GTKEXT_GTKBUFFER_DISPLAY_H */ +#endif /* _GTKEXT_BUFFERVIEW_H */ diff --git a/src/gtkext/contentview-int.h b/src/gtkext/contentview-int.h index 25c9ddb..01c0c7a 100644 --- a/src/gtkext/contentview-int.h +++ b/src/gtkext/contentview-int.h @@ -28,11 +28,19 @@ #include "contentview.h" +#include "../glibext/bufferview.h" #include "../glibext/tokenstyle.h" +/* Réagit à un défilement chez une barre associée au composant. */ +typedef void (* adjust_scroll_value_fc) (GtkContentView *, GtkOrientation, GtkAdjustment *); + + + + + #if 0 #include @@ -52,10 +60,10 @@ typedef void (* compute_requested_size_fc) (GtkDisplayPanel *, gint *, gint *); /* Détermine la taille des bonds lors de défilements. */ -typedef void (* compute_scroll_inc_fc) (GtkDisplayPanel *, gint, GtkOrientation, gdouble *, gdouble *); +//typedef void (* compute_scroll_inc_fc) (GtkDisplayPanel *, gint, GtkOrientation, gdouble *, gdouble *); /* Réagit à un défilement chez une barre associée au composant. */ -typedef void (* adjust_scroll_value_fc) (GtkDisplayPanel *, GtkAdjustment *, GtkOrientation); +//typedef void (* adjust_scroll_value_fc) (GtkDisplayPanel *, GtkAdjustment *, GtkOrientation); /* Ajuste au besoin la zone affichée pour un curseur. */ typedef void (* prepare_for_cursor_fc) (GtkDisplayPanel *, const GLineCursor *); @@ -94,15 +102,18 @@ struct _GtkContentView { GtkWidget parent; /* A laisser en premier */ + GtkAdjustment *adjustments[2]; /* Barres de défilement h. & v.*/ + GtkScrollablePolicy scroll_policies[2]; /* Politiques de défilement */ + GDisplayOptions *options; /* Options de rendu */ - GTokenStyle *style; /* Centralisation des styles */ -#if 0 + /* Propriété des implémentations */ - GtkAdjustment *hadjustment; /* Barre de défilement horiz. */ - GtkAdjustment *vadjustment; /* Barre de défilement vert. */ - GtkScrollablePolicy hscroll_policy; /* Politique horizontale */ - GtkScrollablePolicy vscroll_policy; /* Politique verticale */ + GtkWidget * const *sub_children; /* Composants embarqués */ + size_t sub_count; /* Quantité de ces composants */ + + +#if 0 double scale; /* Echelle de l'affichage */ @@ -121,13 +132,14 @@ struct _GtkContentView /* Composant d'affichage générique (classe) */ struct _GtkContentViewClass { - GtkFixedClass parent; /* A laisser en premier */ + GtkWidgetClass parent; /* A laisser en premier */ #if 0 - compute_requested_size_fc compute_size; /* Calcul de la taille requise */ - compute_scroll_inc_fc compute_inc; /* Calcul des bonds */ +#endif adjust_scroll_value_fc adjust; /* Réaction à un défilement */ + +#if 0 prepare_for_cursor_fc prepare; /* Préparation de zone affichée*/ get_coordinates_fc get_coordinates; /* Conversion adresse <-> pos. */ get_active_object_fc get_active; /* Infos sur l'objet actif */ @@ -149,20 +161,20 @@ struct _GtkContentViewClass }; -#if 0 - /* Propriétés propres au composant d'affichage */ -typedef enum _ViewPanelProps +typedef enum _ContentViewProps { - VPP_0, - VPP_HADJUSTMENT, - VPP_VADJUSTMENT, - VPP_HSCROLL_POLICY, - VPP_VSCROLL_POLICY + CVP_0, + CVP_HADJUSTMENT, + CVP_VADJUSTMENT, + CVP_HSCROLL_POLICY, + CVP_VSCROLL_POLICY -} ViewPanelProps; +} ContentViewProps; +#if 0 + /* Définit un chemin décrivant la bordure autour du panneau. */ void gtk_display_panel_define_border_path(GtkDisplayPanel *, cairo_t *, const GtkAllocation *); diff --git a/src/gtkext/contentview.c b/src/gtkext/contentview.c index 4b7f79d..77bbb7b 100644 --- a/src/gtkext/contentview.c +++ b/src/gtkext/contentview.c @@ -59,22 +59,51 @@ static void gtk_content_view_dispose(GtkContentView *); /* Procède à la libération totale de la mémoire. */ static void gtk_content_view_finalize(GtkContentView *); + + + + +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + +/* Définit une propriété du composant d'affichage. */ +static void gtk_content_view_set_property(GObject *, guint, const GValue *, GParamSpec *); + +/* Se débarrsse d'un ajustement pour un défilement donné. */ +static void _gtk_content_view_disconnect_adjustment(GtkContentView *, GtkOrientation); + +/* S'associe à un ajustement pour un défilement donné. */ +static void _gtk_content_view_set_adjustment(GtkContentView *, GtkOrientation, GtkAdjustment *); + +/* Réagit à un défilement chez une barre associée au composant. */ +static void _gtk_content_view_adjustment_value_changed(GtkAdjustment *, GtkContentView *); + +/* Fournit une propriété du composant d'affichage. */ +static void gtk_content_view_get_property(GObject *, guint, GValue *, GParamSpec *); + +/* Fournit les mesures mainimale et idéale du composant. */ +static void gtk_content_view_measure(GtkWidget *, GtkOrientation, int, int *, int *, int *, int *); + + + + + #if 0 /* Définit une propriété du composant d'affichage. */ -static void gtk_display_panel_set_property(GObject *, guint, const GValue *, GParamSpec *); +//static void gtk_display_panel_set_property(GObject *, guint, const GValue *, GParamSpec *); /* Fournit une propriété du composant d'affichage. */ -static void gtk_display_panel_get_property(GObject *, guint, GValue *, GParamSpec *); +//static void gtk_display_panel_get_property(GObject *, guint, GValue *, GParamSpec *); /* Détruit un composant d'affichage. */ -static void gtk_display_panel_destroy(GtkWidget *); +//static void gtk_display_panel_destroy(GtkWidget *); /* Encadre la construction graphique initiale de l'affichage. */ static void gtk_display_panel_realize(GtkWidget *); /* S'adapte à la surface concédée par le composant parent. */ -static void gtk_display_panel_size_allocate(GtkWidget *, GtkAllocation *); +//static void gtk_display_panel_size_allocate(GtkWidget *, GtkAllocation *); /* Fournit la hauteur idéale pour le composant d'affichage. */ static void gtk_display_panel_get_preferred_height(GtkWidget *, gint *, gint *); @@ -83,22 +112,22 @@ static void gtk_display_panel_get_preferred_height(GtkWidget *, gint *, gint *); static void gtk_display_panel_get_preferred_width(GtkWidget *, gint *, gint *); /* Détermine la taille des bonds lors de défilements. */ -static void gtk_display_panel_compute_scroll_inc(GtkDisplayPanel *, gint, GtkOrientation, gdouble *, gdouble *); +//static void gtk_display_panel_compute_scroll_inc(GtkDisplayPanel *, gint, GtkOrientation, gdouble *, gdouble *); /* Détermine la taille allouée pour le contenu. */ static void gtk_display_panel_compute_allocation(GtkDisplayPanel *, GtkAllocation *); /* Se débarrsse d'un ajustement pour un défilement donné. */ -static void gtk_display_panel_disconnect_adjustment(GtkDisplayPanel *, GtkOrientation); +//static void gtk_display_panel_disconnect_adjustment(GtkDisplayPanel *, GtkOrientation); /* S'associe à un ajustement pour un défilement donné. */ -static void gtk_display_panel_set_adjustment(GtkDisplayPanel *, GtkOrientation, GtkAdjustment *); +//static void gtk_display_panel_set_adjustment(GtkDisplayPanel *, GtkOrientation, GtkAdjustment *); /* Ajuste les paramètres de défilement du composant. */ -static void gtk_display_panel_update_adjustment(GtkDisplayPanel *, GtkOrientation); +//static void gtk_display_panel_update_adjustment(GtkDisplayPanel *, GtkOrientation); /* Réagit à un défilement chez une barre associée au composant.*/ -static void gtk_display_panel_adjustment_value_changed(GtkAdjustment *, GtkDisplayPanel *); +//static void gtk_display_panel_adjustment_value_changed(GtkAdjustment *, GtkDisplayPanel *); @@ -136,8 +165,8 @@ G_DEFINE_TYPE_WITH_CODE(GtkDisplayPanel, gtk_display_panel, GTK_TYPE_FIXED, /* Détermine le type du composant d'affichage générique. */ -G_DEFINE_TYPE(GtkContentView, gtk_content_view, GTK_TYPE_WIDGET); - +G_DEFINE_TYPE_WITH_CODE(GtkContentView, gtk_content_view, GTK_TYPE_WIDGET, + G_IMPLEMENT_INTERFACE(GTK_TYPE_SCROLLABLE, NULL)); /****************************************************************************** @@ -155,35 +184,43 @@ G_DEFINE_TYPE(GtkContentView, gtk_content_view, GTK_TYPE_WIDGET); static void gtk_content_view_class_init(GtkContentViewClass *class) { GObjectClass *object; /* Plus haut niveau équivalent */ - //GtkWidgetClass *widget; /* Classe de haut niveau */ - //GtkContentViewClass *panel; /* Classe de lus bas niveau */ + GtkWidgetClass *widget; /* Classe de haut niveau */ object = G_OBJECT_CLASS(class); + object->set_property = gtk_content_view_set_property; + object->get_property = gtk_content_view_get_property; object->dispose = (GObjectFinalizeFunc/* ! */)gtk_content_view_dispose; object->finalize = (GObjectFinalizeFunc)gtk_content_view_finalize; + /* Implémentation de l'interface "GtkScrollable" */ + g_object_class_override_property(object, CVP_HADJUSTMENT, "hadjustment"); + g_object_class_override_property(object, CVP_VADJUSTMENT, "vadjustment"); + g_object_class_override_property(object, CVP_HSCROLL_POLICY, "hscroll-policy"); + g_object_class_override_property(object, CVP_VSCROLL_POLICY, "vscroll-policy"); + + + + + + widget = GTK_WIDGET_CLASS(class); + + widget->measure = gtk_content_view_measure; + + + + #if 0 - object->set_property = gtk_display_panel_set_property; - object->get_property = gtk_display_panel_get_property; - /* Implémentation de l'interface "GtkScrollable" */ - g_object_class_override_property(object, VPP_HADJUSTMENT, "hadjustment"); - g_object_class_override_property(object, VPP_VADJUSTMENT, "vadjustment"); - g_object_class_override_property(object, VPP_HSCROLL_POLICY, "hscroll-policy"); - g_object_class_override_property(object, VPP_VSCROLL_POLICY, "vscroll-policy"); widget = GTK_WIDGET_CLASS(class); - widget->destroy = gtk_display_panel_destroy; + //widget->destroy = gtk_display_panel_destroy; widget->realize = gtk_display_panel_realize; widget->size_allocate = gtk_display_panel_size_allocate; widget->get_preferred_height = gtk_display_panel_get_preferred_height; widget->get_preferred_width = gtk_display_panel_get_preferred_width; - panel = GTK_DISPLAY_PANEL_CLASS(class); - - panel->compute_inc = gtk_display_panel_compute_scroll_inc; /* Signaux */ @@ -214,8 +251,13 @@ static void gtk_content_view_class_init(GtkContentViewClass *class) static void gtk_content_view_init(GtkContentView *view) { + view->adjustments[GTK_ORIENTATION_HORIZONTAL] = NULL; + view->adjustments[GTK_ORIENTATION_VERTICAL] = NULL; + + view->scroll_policies[GTK_ORIENTATION_HORIZONTAL] = GTK_POLICY_AUTOMATIC; + view->scroll_policies[GTK_ORIENTATION_VERTICAL] = GTK_POLICY_AUTOMATIC; + view->options = NULL; - view->style = g_token_style_new(GTK_WIDGET(view)); @@ -272,13 +314,16 @@ static void gtk_display_panel_loaded_interface_init(GLoadedPanelInterface *iface static void gtk_content_view_dispose(GtkContentView *view) { + _gtk_content_view_disconnect_adjustment(view, GTK_ORIENTATION_HORIZONTAL); + _gtk_content_view_disconnect_adjustment(view, GTK_ORIENTATION_VERTICAL); + + g_clear_object(&view->adjustments[GTK_ORIENTATION_HORIZONTAL]); + g_clear_object(&view->adjustments[GTK_ORIENTATION_VERTICAL]); + g_clear_object(&view->options); - g_clear_object(&view->style); /* - g_clear_object(&panel->hadjustment); - g_clear_object(&panel->vadjustment); g_clear_object(&panel->options); @@ -309,7 +354,16 @@ static void gtk_content_view_finalize(GtkContentView *view) } -#if 0 + + + + + +/* ---------------------------------------------------------------------------------- */ +/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ +/* ---------------------------------------------------------------------------------- */ + + /****************************************************************************** * * * Paramètres : object = instance de composant GTK à manipuler. * @@ -325,25 +379,25 @@ static void gtk_content_view_finalize(GtkContentView *view) * * ******************************************************************************/ -static void gtk_display_panel_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +static void gtk_content_view_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { - GtkDisplayPanel *panel; /* Autre vision de l'instance */ + GtkContentView *view; /* Autre vision de l'instance */ - panel = GTK_DISPLAY_PANEL(object); + view = GTK_CONTENT_VIEW(object); switch (prop_id) { - case VPP_HADJUSTMENT: - gtk_display_panel_set_adjustment(panel, GTK_ORIENTATION_HORIZONTAL, g_value_get_object(value)); + case CVP_HADJUSTMENT: + _gtk_content_view_set_adjustment(view, GTK_ORIENTATION_HORIZONTAL, g_value_get_object(value)); break; - case VPP_VADJUSTMENT: - gtk_display_panel_set_adjustment(panel, GTK_ORIENTATION_VERTICAL, g_value_get_object(value)); + case CVP_VADJUSTMENT: + _gtk_content_view_set_adjustment(view, GTK_ORIENTATION_VERTICAL, g_value_get_object(value)); break; - case VPP_HSCROLL_POLICY: + case CVP_HSCROLL_POLICY: //viewport->priv->hscroll_policy = g_value_get_enum (value); //gtk_widget_queue_resize (GTK_WIDGET (viewport)); break; - case VPP_VSCROLL_POLICY: + case CVP_VSCROLL_POLICY: //viewport->priv->vscroll_policy = g_value_get_enum (value); //gtk_widget_queue_resize (GTK_WIDGET (viewport)); break; @@ -357,6 +411,105 @@ static void gtk_display_panel_set_property(GObject *object, guint prop_id, const /****************************************************************************** * * +* Paramètres : view = composant GTK d'affichage à mettre à jour. * +* orientation = indication sur le défilement à traiter. * +* * +* Description : Se débarrsse d'un ajustement pour un défilement donné. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void _gtk_content_view_disconnect_adjustment(GtkContentView *view, GtkOrientation orientation) +{ + GtkAdjustment **adjp; /* Ajustement à manipuler */ + + adjp = &view->adjustments[orientation]; + + if (*adjp != NULL) + { + g_signal_handlers_disconnect_by_func(*adjp, _gtk_content_view_adjustment_value_changed, view); + g_clear_object(adjp); + } + +} + + +/****************************************************************************** +* * +* Paramètres : view = composant GTK d'affichage à mettre à jour. * +* orientation = indication sur le défilement à traiter. * +* adj = nouvel ajustement à prendre en compte. * +* * +* Description : S'associe à un ajustement pour un défilement donné. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void _gtk_content_view_set_adjustment(GtkContentView *view, GtkOrientation orientation, GtkAdjustment *adj) +{ + GtkAdjustment **adjp; /* Ajustement à manipuler */ + + adjp = &view->adjustments[orientation]; + + /* S'il n'y a rien à faire... */ + if (adj != NULL && adj == *adjp) + return; + + if (adj == NULL) + adj = gtk_adjustment_new(0.0, 0.0, 0.0, 0.0, 0.0, 0.0); + else + ref_object(adj); + + _gtk_content_view_disconnect_adjustment(view, orientation); + + *adjp = adj; + + g_signal_connect(adj, "value-changed", G_CALLBACK(_gtk_content_view_adjustment_value_changed), view); + + gtk_widget_queue_allocate(GTK_WIDGET(view)); + +} + + +/****************************************************************************** +* * +* Paramètres : adj = défilement dont une valeur a changé. * +* view = panneau d'affichage concerné. * +* * +* Description : Réagit à un défilement chez une barre associée au composant. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void _gtk_content_view_adjustment_value_changed(GtkAdjustment *adj, GtkContentView *view) +{ + GtkOrientation orientation; /* Indification de la barre */ + GtkContentViewClass *class; /* Classe de l'instance */ + + if (adj == view->adjustments[GTK_ORIENTATION_HORIZONTAL]) + orientation = GTK_ORIENTATION_HORIZONTAL; + else + orientation = GTK_ORIENTATION_VERTICAL; + + class = GTK_CONTENT_VIEW_GET_CLASS(view); + + if (class->adjust != NULL) + class->adjust(view, orientation, adj); + +} + + +/****************************************************************************** +* * * Paramètres : object = instance de composant GTK à manipuler. * * prop_id = identifiant de la propriété concernée. * * value = valeur à renvoyer. * @@ -370,25 +523,25 @@ static void gtk_display_panel_set_property(GObject *object, guint prop_id, const * * ******************************************************************************/ -static void gtk_display_panel_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +static void gtk_content_view_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { - GtkDisplayPanel *panel; /* Autre vision de l'instance */ + GtkContentView *view; /* Autre vision de l'instance */ - panel = GTK_DISPLAY_PANEL(object); + view = GTK_CONTENT_VIEW(object); switch (prop_id) { - case VPP_HADJUSTMENT: - g_value_set_object(value, panel->hadjustment); + case CVP_HADJUSTMENT: + g_value_set_object(value, view->adjustments[GTK_ORIENTATION_HORIZONTAL]); break; - case VPP_VADJUSTMENT: - g_value_set_object(value, panel->vadjustment); + case CVP_VADJUSTMENT: + g_value_set_object(value, view->adjustments[GTK_ORIENTATION_VERTICAL]); break; - case VPP_HSCROLL_POLICY: - g_value_set_enum(value, panel->hscroll_policy); + case CVP_HSCROLL_POLICY: + g_value_set_enum(value, view->scroll_policies[GTK_ORIENTATION_HORIZONTAL]); break; - case VPP_VSCROLL_POLICY: - g_value_set_enum(value, panel->vscroll_policy); + case CVP_VSCROLL_POLICY: + g_value_set_enum(value, view->scroll_policies[GTK_ORIENTATION_VERTICAL]); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); @@ -400,6 +553,88 @@ static void gtk_display_panel_get_property(GObject *object, guint prop_id, GValu /****************************************************************************** * * +* Paramètres : widget = composant GTK à examiner. * +* orientation = direction à observer pour les calculs. * +* for_size = taille de la direction opposée. * +* minimum = taille minimale pour le composant. [OUT] * +* natural = taille idéale pour le composant. [OUT] * +* min_baseline = ligne de base minimale. [OUT] * +* nat_baseline = ligne de base idéale. [OUT] * +* * +* Description : Fournit les mesures mainimale et idéale du composant. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_content_view_measure(GtkWidget *widget, GtkOrientation orientation, int for_size, int *minimum, int *natural, int *min_baseline, int *nat_baseline) +{ + GtkContentView *view; /* Version spécialisée */ + size_t i; /* Boucle de parcours */ + int min; /* Valeur minimale locale */ + int nat; /* Valeur idéale locale */ + + view = GTK_CONTENT_VIEW(widget); + + if (minimum != NULL) *minimum = 0; + if (natural != NULL) *natural = 0; + + /* Demande de hauteur minimale / idéale */ + if (orientation == GTK_ORIENTATION_VERTICAL) + { + for (i = 0; i < view->sub_count; i++) + { + gtk_widget_measure(view->sub_children[i], GTK_ORIENTATION_VERTICAL, -1, &min, &nat, NULL, NULL); + + if (minimum != NULL && min > *minimum) + *minimum = min; + + if (natural != NULL && nat > *natural) + *natural = nat; + + } + + } + + /* Demande de largeur minimale / idéale */ + else + { + for (i = 0; i < view->sub_count; i++) + { + gtk_widget_measure(view->sub_children[i], GTK_ORIENTATION_HORIZONTAL, -1, &min, &nat, NULL, NULL); + + if (minimum != NULL) *minimum += min; + if (natural != NULL) *natural += nat; + + } + + } + + if (min_baseline != NULL) *min_baseline = -1; + if (nat_baseline != NULL) *nat_baseline = -1; + +} + + + + + + + + + + + + + + +#if 0 + + +/****************************************************************************** +* * * Paramètres : widget = composant GTK à détruire. * * * * Description : Détruit un composant d'affichage. * @@ -416,8 +651,11 @@ static void gtk_display_panel_destroy(GtkWidget *widget) panel = GTK_DISPLAY_PANEL(widget); - gtk_display_panel_disconnect_adjustment(panel, GTK_ORIENTATION_HORIZONTAL); - gtk_display_panel_disconnect_adjustment(panel, GTK_ORIENTATION_VERTICAL); + GtkContentView *view; /* Autre vision de l'instance */ + + view = GTK_CONTENT_VIEW(widget); + + GTK_WIDGET_CLASS(gtk_display_panel_parent_class)->destroy(widget); @@ -471,32 +709,6 @@ static void gtk_display_panel_realize(GtkWidget *widget) } -/****************************************************************************** -* * -* 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_display_panel_size_allocate(GtkWidget *widget, GtkAllocation *allocation) -{ - GtkDisplayPanel *panel; /* Autre version du composant */ - - GTK_WIDGET_CLASS(gtk_display_panel_parent_class)->size_allocate(widget, allocation); - - panel = GTK_DISPLAY_PANEL(widget); - - gtk_display_panel_update_adjustment(panel, GTK_ORIENTATION_HORIZONTAL); - gtk_display_panel_update_adjustment(panel, GTK_ORIENTATION_VERTICAL); - -} - /****************************************************************************** * * @@ -560,29 +772,6 @@ static void gtk_display_panel_get_preferred_width(GtkWidget *widget, gint *minim } -/****************************************************************************** -* * -* Paramètres : panel = composant GTK d'affichage à mettre à jour. * -* size = taille de l'espace dans la direction donnée. * -* orientation = indication sur le défilement à traiter. * -* step = valeur d'un petit pas de défilement. [OUT] * -* page = valeur d'un grand pas de défilement. [OUT] * -* * -* Description : Détermine la taille des bonds lors de défilements. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void gtk_display_panel_compute_scroll_inc(GtkDisplayPanel *panel, gint size, GtkOrientation orientation, gdouble *step, gdouble *page) -{ - *step = size * 0.1; - *page = size * 0.9; - -} - /****************************************************************************** * * @@ -653,151 +842,8 @@ static void gtk_display_panel_compute_allocation(GtkDisplayPanel *panel, GtkAllo } -/****************************************************************************** -* * -* Paramètres : panel = composant GTK d'affichage à mettre à jour. * -* orientation = indication sur le défilement à traiter. * -* * -* Description : Se débarrsse d'un ajustement pour un défilement donné. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void gtk_display_panel_disconnect_adjustment(GtkDisplayPanel *panel, GtkOrientation orientation) -{ - GtkAdjustment **adjp; /* Ajustement à manipuler */ - - adjp = orientation == GTK_ORIENTATION_HORIZONTAL ? &panel->hadjustment : &panel->vadjustment; - - if (*adjp != NULL) - { - g_signal_handlers_disconnect_by_func(*adjp, gtk_display_panel_adjustment_value_changed, panel); - g_object_unref(G_OBJECT(*adjp)); - *adjp = NULL; - } - -} - - -/****************************************************************************** -* * -* Paramètres : panel = composant GTK d'affichage à mettre à jour. * -* orientation = indication sur le défilement à traiter. * -* adj = nouvel ajustement à prendre en compte. * -* * -* Description : S'associe à un ajustement pour un défilement donné. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void gtk_display_panel_set_adjustment(GtkDisplayPanel *panel, GtkOrientation orientation, GtkAdjustment *adj) -{ - GtkAdjustment **adjp; /* Ajustement à manipuler */ - adjp = orientation == GTK_ORIENTATION_HORIZONTAL ? &panel->hadjustment : &panel->vadjustment; - /* S'il n'y a rien à faire... */ - if (adj != NULL && adj == *adjp) - return; - - if (!adj) - adj = gtk_adjustment_new(0.0, 0.0, 0.0, 0.0, 0.0, 0.0); - - gtk_display_panel_disconnect_adjustment(panel, orientation); - - *adjp = adj; - g_object_ref_sink(adj); - - gtk_display_panel_update_adjustment(panel, orientation); - - g_signal_connect(adj, "value-changed", G_CALLBACK(gtk_display_panel_adjustment_value_changed), panel); - - gtk_display_panel_adjustment_value_changed(adj, panel); - -} - - -/****************************************************************************** -* * -* Paramètres : panel = composant GTK d'affichage à mettre à jour. * -* orientation = indication sur le défilement à traiter. * -* * -* Description : Ajuste les paramètres de défilement du composant. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void gtk_display_panel_update_adjustment(GtkDisplayPanel *panel, GtkOrientation orientation) -{ - GtkAllocation allocation; /* Emplacement du contenu */ - GtkAdjustment *adj; /* Ajustement à manipuler */ - gint req; /* Dimension requise */ - gint allocated; /* Dimension allouée */ - gdouble step_inc; /* Pas de défilement */ - gdouble page_inc; /* ENjambée de défilement */ - - gtk_display_panel_compute_allocation(panel, &allocation); - - if (orientation == GTK_ORIENTATION_HORIZONTAL) - { - adj = panel->hadjustment; - - gtk_widget_get_preferred_width(GTK_WIDGET(panel), &req, NULL); - allocated = allocation.width; - - } - else - { - adj = panel->vadjustment; - - gtk_widget_get_preferred_height(GTK_WIDGET(panel), &req, NULL); - allocated = allocation.height; - - } - - GTK_DISPLAY_PANEL_GET_CLASS(panel)->compute_inc(panel, allocated, orientation, &step_inc, &page_inc); - - gtk_adjustment_configure(adj, gtk_adjustment_get_value(adj), - 0, MAX(req, allocated), - step_inc, - page_inc, - allocated); - -} - - -/****************************************************************************** -* * -* Paramètres : adj = défilement dont une valeur a changé. * -* panel = panneau d'affichage concerné. * -* * -* Description : Réagit à un défilement chez une barre associée au composant. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void gtk_display_panel_adjustment_value_changed(GtkAdjustment *adj, GtkDisplayPanel *panel) -{ - GtkOrientation orientation; /* Indification de la barre */ - - orientation = (adj == panel->hadjustment ? GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL); - - if (GTK_DISPLAY_PANEL_GET_CLASS(panel)->adjust != NULL) - GTK_DISPLAY_PANEL_GET_CLASS(panel)->adjust(panel, adj, orientation); - -} /****************************************************************************** diff --git a/src/gtkext/hexview-int.h b/src/gtkext/hexview-int.h new file mode 100644 index 0000000..2b1c570 --- /dev/null +++ b/src/gtkext/hexview-int.h @@ -0,0 +1,71 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * hexview-int.h - définitions internes pour l'affichage de contenus de binaire + * + * Copyright (C) 2016-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 . + */ + + +#ifndef _GTKEXT_HEXVIEW_INT_H +#define _GTKEXT_HEXVIEW_INT_H + + +#include "bufferview-int.h" +#include "hexview.h" +#include "../glibext/generators/hex.h" + + + +/* Composant d'affichage d'octets bruts et imprimables (instance) */ +struct _GtkHexView +{ + GtkBufferView parent; /* A laisser en premier */ + + union + { +#define _CHILDREN_COUNT 3 + + GtkWidget *children[_CHILDREN_COUNT];/* Sous-composants d'affichage*/ + + struct + { + GtkWidget *offsets; /* Affichage des positions */ + GtkWidget *hex; /* Affichage des octets brut */ + GtkWidget *ascii; /* Affichage des imprimables */ + }; + + }; + + GHexGenerator *generator; /* Générateur unique dédié */ + +}; + +/* Composant d'affichage d'octets bruts et imprimables (classe) */ +struct _GtkHexViewClass +{ + GtkBufferViewClass parent; /* A laisser en premier */ + +}; + + +/* Met en place un nouveau composant d'affichage d'octets bruts. */ +bool gtk_hex_view_create(GtkHexView *, GBinContent *); + + + +#endif /* _GTKEXT_HEXVIEW_INT_H */ diff --git a/src/gtkext/hexview.c b/src/gtkext/hexview.c index 717c1bc..7363079 100644 --- a/src/gtkext/hexview.c +++ b/src/gtkext/hexview.c @@ -24,45 +24,17 @@ #include "hexview.h" -#include "area.h" -#include "contentview-int.h" - - - -/* ------------------------- BASES D'UN COMPOSANT GRAPHIQUE ------------------------- */ - +#include +#include -/* Composant d'affichage d'octets bruts et imprimables (instance) */ -struct _GtkHexView -{ - GtkContentView parent; /* A laisser en premier */ - - union - { -#define _CHILDREN_COUNT 4 - - GtkWidget *children[_CHILDREN_COUNT];/* Sous-composants d'affichage*/ - - struct - { - GtkWidget *offsets; /* Affichage des positions */ - GtkWidget *hex; /* Affichage des octets brut */ - GtkWidget *ascii; /* Affichage des imprimables */ - GtkWidget *vscroll; /* Barre de défilement */ - }; - }; - - bool need_vscrolling; /* Besoin de défilement ? */ +#include "area.h" +#include "hexview-int.h" +#include "../glibext/options/hex.h" -}; -/* Composant d'affichage d'octets bruts et imprimables (classe) */ -struct _GtkHexViewClass -{ - GtkContentViewClass parent; /* A laisser en premier */ -}; +/* ------------------------- BASES D'UN COMPOSANT GRAPHIQUE ------------------------- */ /* Procède à l'initialisation de l'afficheur générique. */ @@ -77,6 +49,12 @@ static void gtk_hex_view_dispose(GtkHexView *); /* Procède à la libération totale de la mémoire. */ static void gtk_hex_view_finalize(GtkHexView *); +/* Procède à l'actualisation de l'affichage d'un sous-composant. */ +static void gtk_hex_view_dispatch_sub_snapshot(GtkWidget *, GtkSnapshot *, GtkWidget *); + +/* Adapte le cache de lignes hexadécimales à la taille courante. */ +static void gtk_hex_view_populate_cache(GtkHexView *); + void demo_snapshot (GtkWidget *widget, GtkSnapshot *snapshot, GtkWidget *parent); @@ -105,7 +83,7 @@ static void gtk_hex_view_measure(GtkWidget *, GtkOrientation, int, int *, int *, /* Détermine le type du composant d'affichage générique. */ -G_DEFINE_TYPE(GtkHexView, gtk_hex_view, GTK_TYPE_CONTENT_VIEW); +G_DEFINE_TYPE(GtkHexView, gtk_hex_view, GTK_TYPE_BUFFER_VIEW); /****************************************************************************** @@ -141,7 +119,6 @@ static void gtk_hex_view_class_init(GtkHexViewClass *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); - gtk_widget_class_bind_template_child(widget, GtkHexView, vscroll); widget->size_allocate = gtk_hex_view_size_allocate; widget->get_request_mode = gtk_hex_view_get_request_mode; @@ -164,15 +141,31 @@ static void gtk_hex_view_class_init(GtkHexViewClass *class) static void gtk_hex_view_init(GtkHexView *view) { + GtkContentView *base; /* Base d'instance supérieure */ + + /* Niveau supérieur */ + + base = GTK_CONTENT_VIEW(view); + + base->options = G_DISPLAY_OPTIONS(g_hex_options_new()); + + base->sub_children = view->children; + base->sub_count = _CHILDREN_COUNT; + + /* Instance courante */ + gtk_widget_init_template(GTK_WIDGET(view)); - 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->offsets), + gtk_hex_view_dispatch_sub_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->hex), + gtk_hex_view_dispatch_sub_snapshot, GTK_WIDGET(view)); - g_raw_scan_cache_register_snapshot(GTK_COMPOSING_AREA(view->ascii), demo_snapshot, GTK_WIDGET(view)); + g_raw_scan_cache_register_snapshot(GTK_COMPOSING_AREA(view->ascii), + gtk_hex_view_dispatch_sub_snapshot, GTK_WIDGET(view)); - view->need_vscrolling = true; + view->generator = NULL; } @@ -193,6 +186,8 @@ static void gtk_hex_view_dispose(GtkHexView *view) { gtk_widget_dispose_template(GTK_WIDGET(view), GTK_TYPE_HEX_VIEW); + g_clear_object(&view->generator); + G_OBJECT_CLASS(gtk_hex_view_parent_class)->dispose(G_OBJECT(view)); } @@ -217,130 +212,225 @@ static void gtk_hex_view_finalize(GtkHexView *view) } +/****************************************************************************** +* * +* Paramètres : content = contenu binaire à exposer de façon brute. * +* * +* Description : Crée un composant d'affichage d'octets bruts et imprimables. * +* * +* Retour : Centralisateur mis en place pour un composant GTK donné. * +* * +* Remarques : - * +* * +******************************************************************************/ +GtkHexView *gtk_hex_view_new(GBinContent *content) +{ + GtkHexView *result; /* Nouvelle instance à renvoyer*/ + result = g_object_new(GTK_TYPE_HEX_VIEW, NULL); + if (!gtk_hex_view_create(result, content)) + g_clear_object(&result); + return result; +} -void demo_snapshot (GtkWidget *widget, GtkSnapshot *snapshot, GtkWidget *parent) -{ - GdkRGBA red, green, yellow, blue; - float w, h; +/****************************************************************************** +* * +* Paramètres : view = composant d'affichage à initialiser pleinement. * +* content = contenu binaire à exposer de façon brute. * +* * +* Description : Met en place un nouveau composant d'affichage d'octets bruts.* +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ - gdk_rgba_parse (&red, "red"); - gdk_rgba_parse (&green, "green"); - gdk_rgba_parse (&yellow, "yellow"); - gdk_rgba_parse (&blue, "blue"); +bool gtk_hex_view_create(GtkHexView *view, GBinContent *content) +{ + bool result; /* Bilan à retourner */ + GtkBufferView *parent; /* Version parente du composant*/ + GBufferCache *cache; /* Tampon à représenter */ - w = gtk_widget_get_width (widget) / 2.0; - h = gtk_widget_get_height (widget) / 2.0; + result = true; - h /= 2.0; + assert(g_display_options_count(GTK_CONTENT_VIEW(view)->options) == 1); - 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)); + parent = GTK_BUFFER_VIEW(view); + cache = g_buffer_cache_new(1, 2); + parent->view = g_buffer_view_new(cache, parent->style); + unref_object(cache); - cairo_t *cr; - int x; + view->generator = g_hex_generator_new(content); - x = 0; + return result; - cr = gtk_snapshot_append_cairo(snapshot, &GRAPHENE_RECT_INIT(0, 0, w * 2, h * 2)); +} - g_token_style_draw_text(GTK_CONTENT_VIEW(parent)->style, - TRT_RAW_FULL, - cr, - &x, 0, - "A.A", 3); - g_token_style_draw_text(GTK_CONTENT_VIEW(parent)->style, - TRT_RAW_NULL, - cr, - &x, 0, - "A.A", 3); +/****************************************************************************** +* * +* Paramètres : widget = composant GTK à redessiner. * +* snapshot = gestionnaire de noeuds de rendu à solliciter. * +* parent = composant GTK parent et cadre de l'appel. * +* * +* Description : Procède à l'actualisation de l'affichage d'un sous-composant.* +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ - cairo_destroy(cr); +static void gtk_hex_view_dispatch_sub_snapshot(GtkWidget *widget, GtkSnapshot *snapshot, GtkWidget *parent) +{ + GtkHexView *view; /* Version spécialisée */ + size_t column; /* Indice de colonne à traiter */ + int width; /* Largeur à disposition */ + int height; /* Hauteur à disposition */ + cairo_t *cr; /* Pinceau pour les dessins */ + view = GTK_HEX_VIEW(parent); + if (widget == view->offsets) + column = HCO_OFFSET; -} + else if (widget == view->hex) + column = HCO_COUNT + 0; + else + { + assert(widget == view->ascii); + column = HCO_COUNT + 1; + } + width = gtk_widget_get_width(widget); + height = gtk_widget_get_height(widget); + cr = gtk_snapshot_append_cairo(snapshot, &GRAPHENE_RECT_INIT(0, 0, width, height)); + g_buffer_view_draw(GTK_BUFFER_VIEW(parent)->view, cr, column, GTK_BUFFER_VIEW(parent)->virt_top, height); + cairo_destroy(cr); +} -bool g_buffer_view_allocate_widths(void *ptr, int width, int height, int fill, int *out); +/****************************************************************************** +* * +* Paramètres : view = composant GTK à mettre à jour. * +* * +* Description : Adapte le cache de lignes hexadécimales à la taille courante.* +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ -bool g_buffer_view_allocate_widths(void *ptr, int width, int height, int fill, int *out) +static void gtk_hex_view_populate_cache(GtkHexView *view) { + 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*/ + GBufferCache *cache; /* Tampon à représenter */ + size_t count; /* Nombre actuel de lignes */ - int i; /* Boucle de parcours */ + /* Détermination du besoin */ + content = g_hex_generator_get_content(view->generator); - for (i = 0; i < fill; i++) - { + full = g_binary_content_compute_size(content); - if (i == 0) - { - out[0] = 40; - } + unref_object(content); - else if ((i + 1) == fill) - { - out[i] = width; - } + line = g_hex_generator_get_bytes_per_line(view->generator); - else - { - out[i] = 230; - } + needed = full / line; + if (full % line > 0) + needed++; - width -= out[i]; + /* Adaptation du tampon interne ? */ + cache = g_buffer_view_get_cache(GTK_BUFFER_VIEW(view)->view); + g_buffer_cache_wlock(cache); - } + count = g_buffer_cache_count_lines(cache); + + if (needed < count) + g_buffer_cache_truncate(cache, needed); + + else if (needed > count) + g_buffer_cache_extend_with(cache, needed, G_TOKEN_GENERATOR(view->generator)); - return false; + g_buffer_cache_wunlock(cache); + unref_object(cache); + + /* Mise à jour de l'affichage ? */ + + if (needed != count) + gtk_widget_queue_resize(GTK_WIDGET(view)); } -int g_buffer_view_measure_height(void *ptr, int width); -int g_buffer_view_measure_height(void *ptr, int width) + + + + + +void demo_snapshot (GtkWidget *widget, GtkSnapshot *snapshot, GtkWidget *parent) { - int result; /* Mesure à retourner */ + GdkRGBA red, green, yellow, blue; + float w, h; - if (width == -1) - result = 1; + gdk_rgba_parse (&red, "red"); + gdk_rgba_parse (&green, "green"); + gdk_rgba_parse (&yellow, "yellow"); + gdk_rgba_parse (&blue, "blue"); - else - result = 5000 / width; + w = gtk_widget_get_width (widget) / 2.0; + h = gtk_widget_get_height (widget) / 2.0; + + h /= 2.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)); - result *= 16; - return result; } + + + + + + + + + + /* ---------------------------------------------------------------------------------- */ /* IMPLEMENTATION DES FONCTIONS DE CLASSE */ /* ---------------------------------------------------------------------------------- */ @@ -364,68 +454,56 @@ int g_buffer_view_measure_height(void *ptr, int width) static void gtk_hex_view_size_allocate(GtkWidget *widget, int width, int height, int baseline) { GtkHexView *view; /* Version spécialisée */ - int vscroll_width; /* Largeur idéale de la barre */ - - GtkAllocation allocated; /* Zone allouée */ + int *min_widths; /* Tailles minimales imposées */ + int *final_widths; /* Tailles finales retenues */ size_t i; /* Boucle de parcours */ - int sub_widths[_CHILDREN_COUNT - 1]; /* Sous-largeurs calculées */ + int available; /* Largeur disponible */ + bool changed; /* Détection de variation */ + GWidthTracker *tracker; /* Collecteur de largeurs */ view = GTK_HEX_VIEW(widget); - allocated.y = 0; - allocated.height = height; - - /* Barre de défilement ? */ - - view->need_vscrolling = g_buffer_view_allocate_widths(NULL, width, height, _CHILDREN_COUNT - 1, sub_widths); + min_widths = alloca(_CHILDREN_COUNT * sizeof(int)); + final_widths = alloca(_CHILDREN_COUNT * sizeof(int)); - gtk_widget_set_visible(view->vscroll, view->need_vscrolling); + for (i = 0; i < _CHILDREN_COUNT; i++) + gtk_widget_measure(view->children[i], GTK_ORIENTATION_HORIZONTAL, -1, &min_widths[i], NULL, NULL, NULL); - if (view->need_vscrolling) - { - gtk_widget_remove_css_class(widget, "without_vscroll"); - gtk_widget_add_css_class(widget, "with_vscroll"); - } - else - { - gtk_widget_remove_css_class(widget, "with_vscroll"); - gtk_widget_add_css_class(widget, "without_vscroll"); - } + /* Passe 1 : tentative sans défilement vertical */ - /** - * Validité de la consistence des feuilles CSS : le changement de classe - * ne doit pas faire évoluer les tailles. - */ - assert(view->need_vscrolling == g_buffer_view_allocate_widths(NULL, width, height, _CHILDREN_COUNT - 1, sub_widths)); + available = width; - if (view->need_vscrolling) - { - gtk_widget_measure(view->vscroll, GTK_ORIENTATION_HORIZONTAL, height, &vscroll_width, NULL, NULL, NULL); + for (i = 0; i < _CHILDREN_COUNT; i++) + available -= min_widths[i]; - allocated.x = width - vscroll_width; - allocated.width = vscroll_width; + changed = g_hex_generator_allocate(view->generator, + GTK_CONTENT_VIEW(view)->options, + GTK_BUFFER_VIEW(view)->style, + available, final_widths); - gtk_widget_size_allocate(view->vscroll, &allocated, baseline); + /* Application des largeurs calculées */ - width -= vscroll_width; + if (changed) + { + gtk_hex_view_populate_cache(view); - } + tracker = g_buffer_view_get_tracker(GTK_BUFFER_VIEW(view)->view); - /* Placement des composants d'affichage */ + for (i = 0; i < _CHILDREN_COUNT; i++) + { + final_widths[i] += min_widths[i]; - g_buffer_view_allocate_widths(NULL, width, height, _CHILDREN_COUNT - 1, sub_widths); + g_width_tracker_set_column_min_width(tracker, i, final_widths[i]); - allocated.x = 0; + } - for (i = 0; i < (_CHILDREN_COUNT - 1); i++) - { - allocated.width = sub_widths[i]; + unref_object(tracker); - gtk_widget_size_allocate(view->children[i], &allocated, baseline); + } - allocated.x += sub_widths[i]; + /* Mise à jour des éléments plus internes */ - } + GTK_WIDGET_CLASS(gtk_hex_view_parent_class)->size_allocate(widget, width, height, baseline); } @@ -453,6 +531,17 @@ static GtkSizeRequestMode gtk_hex_view_get_request_mode(GtkWidget *widget) } + + + + + + + + + + + /****************************************************************************** * * * Paramètres : widget = composant GTK à examiner. * @@ -473,54 +562,60 @@ static GtkSizeRequestMode gtk_hex_view_get_request_mode(GtkWidget *widget) static void gtk_hex_view_measure(GtkWidget *widget, GtkOrientation orientation, int for_size, int *minimum, int *natural, int *min_baseline, int *nat_baseline) { + bool processed; /* Calcul de hauteur effectué */ GtkHexView *view; /* Version spécialisée */ int requested; /* Taille requise à priori */ size_t i; /* Boucle de parcours */ int min; /* Valeur minimale locale */ int nat; /* Valeur idéale locale */ - view = GTK_HEX_VIEW(widget); + processed = false; /* Demande de hauteur minimale / idéale */ - if (orientation == GTK_ORIENTATION_VERTICAL) + if (orientation == GTK_ORIENTATION_VERTICAL && for_size != -1) { - requested = g_buffer_view_measure_height(NULL, for_size); + view = GTK_HEX_VIEW(widget); - if (minimum != NULL) *minimum = requested; - if (natural != NULL) *natural = requested; + requested = 0; for (i = 0; i < _CHILDREN_COUNT; i++) { - gtk_widget_measure(view->children[i], GTK_ORIENTATION_VERTICAL, -1, &min, &nat, NULL, NULL); + gtk_widget_measure(view->children[i], GTK_ORIENTATION_HORIZONTAL, -1, &min, NULL, NULL, NULL); + requested += min; + } - if (minimum != NULL && min > *minimum) - *minimum = min; + for_size -= requested; - if (natural != NULL && nat > *natural) - *natural = nat; + if (for_size > 0) + { + requested = g_hex_generator_mesure_height_for_width(view->generator, + GTK_CONTENT_VIEW(view)->options, + GTK_BUFFER_VIEW(view)->style, + for_size); - } + if (minimum != NULL) *minimum = 0; + if (natural != NULL) *natural = requested; - } + for (i = 0; i < _CHILDREN_COUNT; i++) + { + gtk_widget_measure(view->children[i], GTK_ORIENTATION_VERTICAL, -1, &min, &nat, NULL, NULL); - /* Demande de largeur minimale / idéale */ - else - { - if (minimum != NULL) *minimum = 0; - if (natural != NULL) *natural = 0; + if (minimum != NULL && min > *minimum) + *minimum = min; - for (i = 0; i < _CHILDREN_COUNT; i++) - { - gtk_widget_measure(view->children[i], GTK_ORIENTATION_HORIZONTAL, -1, &min, &nat, NULL, NULL); + if (natural != NULL && nat > *natural) + *natural = nat; + + } - if (minimum != NULL) *minimum += min; - if (natural != NULL) *natural += nat; + processed = true; } } - if (min_baseline != NULL) *min_baseline = -1; - if (nat_baseline != NULL) *nat_baseline = -1; + if (!processed) + GTK_WIDGET_CLASS(gtk_hex_view_parent_class)->measure(widget, orientation, for_size, + minimum, natural, min_baseline, nat_baseline); } diff --git a/src/gtkext/hexview.h b/src/gtkext/hexview.h index 8d3129d..2199786 100644 --- a/src/gtkext/hexview.h +++ b/src/gtkext/hexview.h @@ -28,6 +28,7 @@ #include +#include "../analysis/content.h" #include "../glibext/helpers.h" @@ -37,11 +38,8 @@ DECLARE_GTYPE(GtkHexView, gtk_hex_view, GTK, HEX_VIEW); - - - - - +/* Crée un composant d'affichage d'octets bruts et imprimables. */ +GtkHexView *gtk_hex_view_new(GBinContent *); diff --git a/src/gtkext/hexview.ui b/src/gtkext/hexview.ui index df657ca..ae4586c 100644 --- a/src/gtkext/hexview.ui +++ b/src/gtkext/hexview.ui @@ -1,5 +1,5 @@ -