diff options
63 files changed, 1047 insertions, 311 deletions
@@ -77,6 +77,9 @@ tools/d2c/d2c tools/fuzzing/rost/fast-rost tools/yara2rost/yara2rost +# Images générées +src/data/images/about-bg.png + # Schemas src/schemas/gschemas.compiled src/schemas/*.valid @@ -84,6 +87,8 @@ src/schemas/*.valid # Misc plugins/python/androperms/androperms.db system/pkgconfig/chrysalide.pc +tools/about/bg.png +tools/about/cour10p_b.ttf tools/fuzzing/rost/rost.dict # Themes diff --git a/configure.ac b/configure.ac index 5ac8f62..8429ae6 100644 --- a/configure.ac +++ b/configure.ac @@ -249,6 +249,10 @@ AC_ARG_ENABLE([jsonglib-support], AS_HELP_STRING([--disable-jsonglib-support], [disable jsonglib support [default=no]]), [], [enable_jsonglib_support=yes]) +AC_ARG_ENABLE([hs-support], + AS_HELP_STRING([--disable-hs-support], [disable hs number recognition [default=no]]), + [], [enable_hs_support=yes]) + AC_ARG_ENABLE([python-bindings], AS_HELP_STRING([--disable-python-bindings], [disable Python bindings [default=no]]), [], [enable_python_bindings=yes]) @@ -593,10 +597,24 @@ if test "$libhs_found" = "yes"; then libhs_version=`pkg-config libhs --modversion` else libhs_version='-' + enable_hs_support='' +fi + +AM_CONDITIONAL([BUILD_HS_SUPPORT], [test "x$enable_hs_support" = "xyes"]) + +if test "x$BUILD_HS_SUPPORT_TRUE" = "x"; then + # Hyperscan support is available and enabled + CPPFLAGS="$CPPFLAGS -DINCLUDE_HS_SUPPORT" fi -AC_SUBST(LIBHS_CFLAGS) -AC_SUBST(LIBHS_LIBS) +if test "x$enable_hs_support" = "xyes"; then + + AC_SUBST(LIBHS_CFLAGS) + AC_SUBST(LIBHS_LIBS) + + true # empty if/then body not allowed + +fi #--- Checks for json-glib-1.0 @@ -726,6 +744,8 @@ AC_CONFIG_FILES([stamp-h po/Makefile.in], [echo timestamp > stamp-h]) AC_CONFIG_COMMANDS([marshal], [echo -e "VOID:UINT64\nVOID:INT,UINT64,INT\nVOID:OBJECT,OBJECT\nVOID:ENUM,OBJECT\nVOID:ENUM,ENUM\nVOID:BOOLEAN,UINT64\nVOID:BOOLEAN,ULONG,ULONG\nVOID:INT,INT\nVOID:OBJECT,BOOLEAN\nVOID:ULONG,BOOLEAN\nVOID:DOUBLE,DOUBLE" > src/glibext/chrysamarshal.list]) +AC_CONFIG_COMMANDS([about], [./tools/about/gen.sh $version], [version=r$PACKAGE_VERSION]) + AC_CONFIG_FILES([Makefile doc/Makefile pixmaps/Makefile @@ -961,6 +981,12 @@ else disable_magic_support="yes" fi +if test "x$enable_hs_support" = "xyes"; then + disable_hs_support="no" +else + disable_hs_support="yes" +fi + if test "x$enable_python_bindings" = "xyes"; then disable_python_bindings="no" else @@ -973,6 +999,7 @@ echo Consider local resources..................... : $with_local_resources echo Disable GTK support.......................... : $disable_gtk_support echo Disable cURL support......................... : $disable_curl_support echo Disable Magic support........................ : $disable_magic_support +echo Disable Hyperscan support.................... : $disable_hs_support echo Disable Python bindings...................... : $disable_python_bindings echo Build a Python binary distribution........... : $build_python_package @@ -1,4 +1,4 @@ -define([gitrepo], esyscmd([bash -c "echo -n $(( $(test -d .git && git rev-list HEAD | wc -l) + 4))"])) +define([gitrepo], esyscmd([bash -c "echo -n $(( $(test -d .git && git rev-list --count HEAD) + 4))"])) define([gitversion], ifelse(gitrepo, , 000, gitrepo)) diff --git a/pixmaps/Makefile.am b/pixmaps/Makefile.am index d1dff31..da3de19 100644 --- a/pixmaps/Makefile.am +++ b/pixmaps/Makefile.am @@ -4,19 +4,6 @@ APP_ICONS = \ chrysalide-64.png \ chrysalide-128.png -REVISION_PIX = \ - revision_0.png \ - revision_1.png \ - revision_2.png \ - revision_3.png \ - revision_4.png \ - revision_5.png \ - revision_6.png \ - revision_7.png \ - revision_8.png \ - revision_9.png \ - revision.png - TOOLBAR_BUTTONS = \ tbutton_collapse.png \ tbutton_expand.png \ @@ -41,8 +28,6 @@ OTHER_ICONS = \ breakpoint_normal.png MISC = \ - chrysalide-full.png \ - chrysalide_text.png \ welcome.png CORE = \ @@ -57,13 +42,12 @@ EXTRA_DIST = \ openida_text.xcf \ before-after.png \ $(APP_ICONS) \ - $(REVISION_PIX) \ $(TOOLBAR_BUTTONS) \ $(LIST_ICONS) \ $(ERROR_ICONS) \ $(MISC) \ $(CORE) -pix_DATA = $(APP_ICONS) $(REVISION_PIX) $(TOOLBAR_BUTTONS) $(LIST_ICONS) $(ERROR_ICONS) $(OTHER_ICONS) $(MISC) +pix_DATA = $(APP_ICONS) $(TOOLBAR_BUTTONS) $(LIST_ICONS) $(ERROR_ICONS) $(OTHER_ICONS) $(MISC) pixdir = $(pixmapsdir) diff --git a/pixmaps/chrysalide-full.png b/pixmaps/chrysalide-full.png Binary files differdeleted file mode 100644 index a153353..0000000 --- a/pixmaps/chrysalide-full.png +++ /dev/null diff --git a/pixmaps/chrysalide_text.png b/pixmaps/chrysalide_text.png Binary files differdeleted file mode 100644 index b4d8c78..0000000 --- a/pixmaps/chrysalide_text.png +++ /dev/null diff --git a/pixmaps/revision.png b/pixmaps/revision.png Binary files differdeleted file mode 100644 index 330e108..0000000 --- a/pixmaps/revision.png +++ /dev/null diff --git a/pixmaps/revision_0.png b/pixmaps/revision_0.png Binary files differdeleted file mode 100644 index 0a468de..0000000 --- a/pixmaps/revision_0.png +++ /dev/null diff --git a/pixmaps/revision_1.png b/pixmaps/revision_1.png Binary files differdeleted file mode 100644 index 738a881..0000000 --- a/pixmaps/revision_1.png +++ /dev/null diff --git a/pixmaps/revision_2.png b/pixmaps/revision_2.png Binary files differdeleted file mode 100644 index b567b80..0000000 --- a/pixmaps/revision_2.png +++ /dev/null diff --git a/pixmaps/revision_3.png b/pixmaps/revision_3.png Binary files differdeleted file mode 100644 index 7f5e3fc..0000000 --- a/pixmaps/revision_3.png +++ /dev/null diff --git a/pixmaps/revision_4.png b/pixmaps/revision_4.png Binary files differdeleted file mode 100644 index a21ccbb..0000000 --- a/pixmaps/revision_4.png +++ /dev/null diff --git a/pixmaps/revision_5.png b/pixmaps/revision_5.png Binary files differdeleted file mode 100644 index a9130d9..0000000 --- a/pixmaps/revision_5.png +++ /dev/null diff --git a/pixmaps/revision_6.png b/pixmaps/revision_6.png Binary files differdeleted file mode 100644 index 291febd..0000000 --- a/pixmaps/revision_6.png +++ /dev/null diff --git a/pixmaps/revision_7.png b/pixmaps/revision_7.png Binary files differdeleted file mode 100644 index ccd4d4e..0000000 --- a/pixmaps/revision_7.png +++ /dev/null diff --git a/pixmaps/revision_8.png b/pixmaps/revision_8.png Binary files differdeleted file mode 100644 index 054c250..0000000 --- a/pixmaps/revision_8.png +++ /dev/null diff --git a/pixmaps/revision_9.png b/pixmaps/revision_9.png Binary files differdeleted file mode 100644 index 1123669..0000000 --- a/pixmaps/revision_9.png +++ /dev/null diff --git a/plugins/pychrysalide/core-ui.c b/plugins/pychrysalide/core-ui.c index 0ea15df..00d1cc1 100644 --- a/plugins/pychrysalide/core-ui.c +++ b/plugins/pychrysalide/core-ui.c @@ -28,6 +28,9 @@ #include <i18n.h> +#ifdef DISCARD_LOCAL +# include <core/paths.h> +#endif #include <plugins/manager-int.h> #include <plugins/self.h> diff --git a/plugins/pychrysalide/core.c b/plugins/pychrysalide/core.c index fd4a11f..0fea9c4 100644 --- a/plugins/pychrysalide/core.c +++ b/plugins/pychrysalide/core.c @@ -707,6 +707,7 @@ PyMODINIT_FUNC PyInit_pychrysalide(void) details.standalone = _standalone; + details.add_extra = NULL; details.populate_extra = NULL; details.create_self = g_pychrysalide_plugin_new; diff --git a/src/Makefile.am b/src/Makefile.am index 6013bd5..7411287 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -59,7 +59,7 @@ libchrysacore_la_LDFLAGS = \ -avoid-version -ldl -lm \ $(TOOLKIT_LIBS) $(LIBXML_LIBS) \ $(LIBSQLITE_LIBS) $(LIBARCHIVE_LIBS) \ - $(LIBSSL_LIBS) $(LIBHS_LIBS) + $(LIBSSL_LIBS) if BUILD_CURL_SUPPORT @@ -73,6 +73,12 @@ libchrysacore_la_LDFLAGS += $(LIBMAGIC_LIBS) endif +if BUILD_HS_SUPPORT + +libchrysacore_la_LDFLAGS += $(LIBHS_LIBS) + +endif + libchrysacore4_la_SOURCES = @@ -190,4 +196,4 @@ rost_LDFLAGS = $(LIBGOBJ_LIBS) -L.libs -lchrysacore #SUBDIRS = core glibext $(GTKEXT_SUBDIR) analysis arch format common debug $(GUI_SUBDIR) mangling plugins schemas -SUBDIRS = analysis arch common core data format glibext gtkext gui plugins +SUBDIRS = analysis arch common core data format glibext gtkext gui plugins schemas diff --git a/src/analysis/scan/patterns/backends/Makefile.am b/src/analysis/scan/patterns/backends/Makefile.am index 23b0163..84711a7 100644 --- a/src/analysis/scan/patterns/backends/Makefile.am +++ b/src/analysis/scan/patterns/backends/Makefile.am @@ -6,10 +6,16 @@ libanalysisscanpatternsbackends_la_SOURCES = \ acism-int.h \ acism.h acism.c \ bitap-int.h \ - bitap.h bitap.c \ + bitap.h bitap.c + +if BUILD_HS_SUPPORT + +libanalysisscanpatternsbackends_la_SOURCES += \ hyperscan-int.h \ hyperscan.h hyperscan.c +endif + # Cf. https://www.gnu.org/software/automake/manual/html_node/Per_002dObject-Flags.html AM_CFLAGS = $(LIBGOBJ_CFLAGS) $(LIBHS_CFLAGS) @@ -399,7 +399,7 @@ static void ensure_wm_icon_and_name(void) filename = get_xdg_data_dir("icons/hicolor/scalable/apps/chrysalide-logo.svg", true); - fd = open(filename, O_WRONLY | O_CREAT); + fd = open(filename, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); if (fd == -1) LOG_ERROR_N("open"); diff --git a/src/common/sort.h b/src/common/sort.h index 39a6f33..27e3739 100644 --- a/src/common/sort.h +++ b/src/common/sort.h @@ -37,6 +37,9 @@ int sort_boolean(bool, bool); /* Compare une valeur avec une autre. */ int sort_unsigned_long(unsigned long, unsigned long); +#define sort_size(v1, v2) \ + sort_unsigned_long(v1, v2) + /* Compare une valeur avec une autre. */ int sort_signed_long_long(signed long long, signed long long); diff --git a/src/common/szbin.h b/src/common/szbin.h index 182739a..8524ae3 100644 --- a/src/common/szbin.h +++ b/src/common/szbin.h @@ -143,15 +143,13 @@ typedef struct _sized_binary_t while (0) -#define memcmp_sized_binary(s1, s2) \ - ({ \ - int __ret; \ - size_t __n; \ - __n = (s1)->size < (s2)->size ? (s1)->size : (s2)->size; \ - __ret = memcmp((s1)->data, (s2)->data, __n); \ - if (__ret == 0) \ - __ret = sort_unsigned_long_long((s1)->size, (s2)->size);\ - __ret; \ +#define memcmp_sized_binary(s1, s2) \ + ({ \ + int __ret; \ + __ret = sort_size((s1)->size, (s2)->size); \ + if (__ret == 0) \ + __ret = memcmp((s1)->data, (s2)->data, (s1)->size); \ + __ret; \ }) diff --git a/src/data/images/Makefile.am b/src/data/images/Makefile.am index 068e43f..d5ec84f 100644 --- a/src/data/images/Makefile.am +++ b/src/data/images/Makefile.am @@ -4,6 +4,7 @@ BUILT_SOURCES = resources.h resources.c noinst_LTLIBRARIES = libdataimages.la RES_FILES = \ + about-bg.png \ dock-station-left-symbolic.svg \ dock-station-right-symbolic.svg \ dock-station-bottom-symbolic.svg \ diff --git a/src/data/images/gresource.xml b/src/data/images/gresource.xml index 7659da3..25c8274 100644 --- a/src/data/images/gresource.xml +++ b/src/data/images/gresource.xml @@ -1,5 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <gresources> + <gresource prefix="/re/chrysalide/framework/gui/dialogs/about"> + <file compressed="true" alias="bg.png">about-bg.png</file> + </gresource> <gresource prefix="/re/chrysalide/framework/gui/icons/scalable/actions"> <file compressed="true">dock-station-left-symbolic.svg</file> <file compressed="true">dock-station-right-symbolic.svg</file> diff --git a/src/glibext/widthtracker.c b/src/glibext/widthtracker.c index 7e06578..0a3dbe6 100644 --- a/src/glibext/widthtracker.c +++ b/src/glibext/widthtracker.c @@ -330,13 +330,17 @@ void g_width_tracker_set_column_min_width(GWidthTracker *tracker, size_t col, in void g_width_tracker_compute_width(const GWidthTracker *tracker, int *width) { + size_t col_count; /* Nombre maximum de colonnes */ size_t i; /* Boucle de parcours */ *width = 0; - // FIX access to col_count - for (i = 0; i < tracker->col_count; i++) + + col_count = tracker->opt_count + tracker->reg_count; + + + for (i = 0; i < col_count; i++) *width += tracker->min_widths[i]; } diff --git a/src/gtkext/area.c b/src/gtkext/area.c index 3c59a59..3c573b2 100644 --- a/src/gtkext/area.c +++ b/src/gtkext/area.c @@ -85,6 +85,8 @@ static void gtk_composing_area_class_init(GtkComposingAreaClass *class) widget = GTK_WIDGET_CLASS(class); + gtk_widget_class_set_css_name(widget, "comparea"); + widget->snapshot = gtk_composing_area_snapshot; } diff --git a/src/gtkext/dockstation.c b/src/gtkext/dockstation.c index 359e3a1..80bae75 100644 --- a/src/gtkext/dockstation.c +++ b/src/gtkext/dockstation.c @@ -259,7 +259,7 @@ GtkWidget *gtk_dock_station_new(void) /****************************************************************************** * * -* Paramètres : station = station d'accueil pour panneau à compléter. * +* Paramètres : station = station d'accueil pour panneaux à compléter. * * panel = nouveau panneau à afficher. * * * * Description : Ajoute un panneau à un groupe de tuiles. * @@ -293,7 +293,7 @@ void gtk_dock_station_add_panel(GtkDockStation *station, GtkTiledPanel *panel) /****************************************************************************** * * -* Paramètres : station = station d'accueil pour panneau à compléter. * +* Paramètres : station = station d'accueil pour panneaux à compléter. * * panel = nouveau panneau à afficher. * * * * Description : Ajoute un panneau à conserver à un groupe de tuiles. * @@ -332,7 +332,7 @@ void gtk_dock_station_keep_panel(GtkDockStation *station, GtkTiledPanel *panel) /****************************************************************************** * * -* Paramètres : station = station d'accueil pour panneau à consulter. * +* Paramètres : station = station d'accueil pour panneaux à consulter. * * * * Description : Indique si la station d'accueil contient au moins un panneau.* * * @@ -361,6 +361,51 @@ bool gtk_dock_station_is_empty(const GtkDockStation *station) } +/****************************************************************************** +* * +* Paramètres : station = station d'accueil pour panneaux à manipuler. * +* main = panneau principal visé par l'opération. * +* activated = nature du changement de statut : ajout, retrait ?* +* * +* Description : Note un ajout ou un retrait de panneau principal. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void gtk_dock_station_notify_new_main_panel_state(const GtkDockStation *station, GtkTiledPanel *main, bool activated) +{ + GListModel *list; /* Liste de pages à parcourir */ + guint count; /* Nombre de pages */ + guint i; /* Boucle de parcours */ + GtkStackPage *page; /* Page à consulter */ + GtkWidget *panel; /* Panneau intégré */ + + list = G_LIST_MODEL(gtk_stack_get_pages(station->stack)); + + count = g_list_model_get_n_items(list); + + for (i = 0; i < count; i++) + { + page = GTK_STACK_PAGE(g_list_model_get_object(list, i)); + if (page == NULL) continue; + + panel = gtk_stack_page_get_child(page); + + gtk_tiled_panel_notify_new_main_panel_state(GTK_TILED_PANEL(panel), main, activated); + + unref_object(page); + + } + + unref_object(list); + +} + + + /* ---------------------------------------------------------------------------------- */ /* IMPLEMENTATION DES FONCTIONS DE CLASSE */ /* ---------------------------------------------------------------------------------- */ diff --git a/src/gtkext/dockstation.h b/src/gtkext/dockstation.h index 3106dae..e4c849f 100644 --- a/src/gtkext/dockstation.h +++ b/src/gtkext/dockstation.h @@ -50,6 +50,10 @@ void gtk_dock_station_keep_panel(GtkDockStation *, GtkTiledPanel *); /* Indique si la station d'accueil contient au moins un panneau. */ bool gtk_dock_station_is_empty(const GtkDockStation *); +/* Note un ajout ou un retrait de panneau principal. */ +void gtk_dock_station_notify_new_main_panel_state(const GtkDockStation *, GtkTiledPanel *, bool); + + #if 0 diff --git a/src/gtkext/grid.c b/src/gtkext/grid.c index afc74b7..eb3cdf9 100644 --- a/src/gtkext/grid.c +++ b/src/gtkext/grid.c @@ -544,6 +544,35 @@ void gtk_tiling_grid_add_panel(GtkTilingGrid *grid, GtkTiledPanel *panel, bool k /****************************************************************************** * * +* Paramètres : grid = zone d'affichage en tuiles à manipuler. * +* main = panneau principal visé par l'opération. * +* activated = nature du changement de statut : ajout, retrait ?* +* * +* Description : Note un ajout ou un retrait de panneau principal. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void gtk_tiling_grid_notify_new_main_panel_state(const GtkTilingGrid *grid, GtkTiledPanel *main, bool activated) +{ + gtk_dock_station_notify_new_main_panel_state(grid->top_station, main, activated); + + gtk_dock_station_notify_new_main_panel_state(grid->left_station, main, activated); + + gtk_dock_station_notify_new_main_panel_state(grid->main_station, main, activated); + + gtk_dock_station_notify_new_main_panel_state(grid->right_station, main, activated); + + gtk_dock_station_notify_new_main_panel_state(grid->bottom_station, main, activated); + +} + + +/****************************************************************************** +* * * Paramètres : station = plateforme GTK ayant connu un changement. * * widget = nouvel élément à intégrer. * * grid = gestionnaire de placement en tuile concerné. * diff --git a/src/gtkext/grid.h b/src/gtkext/grid.h index f02cf38..fd98035 100644 --- a/src/gtkext/grid.h +++ b/src/gtkext/grid.h @@ -66,6 +66,9 @@ bool gtk_tiling_grid_get_visible(GtkTilingGrid *, TilingGridBorder); /* Ajoute un panneau à un conteneur en tuiles. */ void gtk_tiling_grid_add_panel(GtkTilingGrid *, GtkTiledPanel *, bool); +/* Note un ajout ou un retrait de panneau principal. */ +void gtk_tiling_grid_notify_new_main_panel_state(const GtkTilingGrid *, GtkTiledPanel *, bool); + /* --------------------- FORME GENERIQUE DE MISE EN DISPOSITION --------------------- */ diff --git a/src/gtkext/hexview.c b/src/gtkext/hexview.c index 5a8dd04..95b592e 100644 --- a/src/gtkext/hexview.c +++ b/src/gtkext/hexview.c @@ -37,6 +37,22 @@ /* ------------------------- BASES D'UN COMPOSANT GRAPHIQUE ------------------------- */ +/* Liste des propriétés */ + +typedef enum _HexViewProperty { + + PROP_0, /* Réservé */ + + PROP_SHOW_OFFSETS, /* Affichage des positions */ + PROP_CONTENT, /* Contenu binaire affiché */ + + N_PROPERTIES + +} HexViewProperty; + +static GParamSpec *_hex_view_properties[N_PROPERTIES] = { NULL, }; + + /* Initialise la classe des afficheurs de tampons bruts. */ static void gtk_hex_view_class_init(GtkHexViewClass *); @@ -44,10 +60,10 @@ static void gtk_hex_view_class_init(GtkHexViewClass *); static void gtk_hex_view_init(GtkHexView *); /* Supprime toutes les références externes. */ -static void gtk_hex_view_dispose(GtkHexView *); +static void gtk_hex_view_dispose(GObject *); /* Procède à la libération totale de la mémoire. */ -static void gtk_hex_view_finalize(GtkHexView *); +static void gtk_hex_view_finalize(GObject *); /* Procède à l'actualisation de l'affichage d'un sous-composant. */ static void gtk_hex_view_dispatch_sub_snapshot(GtkWidget *, GtkSnapshot *, GtkWidget *); @@ -57,14 +73,14 @@ static void gtk_hex_view_populate_cache(GtkHexView *); -void demo_snapshot (GtkWidget *widget, GtkSnapshot *snapshot, GtkWidget *parent); - - - +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ -/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ +/* Met à jour une propriété d'instance GObject. */ +static void gtk_hex_view_set_property(GObject *, guint, const GValue *, GParamSpec *); +/* Fournit la valeur d'une propriété d'instance GObject. */ +static void gtk_hex_view_get_property(GObject *, guint, GValue *, GParamSpec *); /* Prend acte de la taille allouée au composant d'affichage. */ static void gtk_hex_view_size_allocate(GtkWidget *, int, int, int); @@ -105,12 +121,26 @@ static void gtk_hex_view_class_init(GtkHexViewClass *class) object = G_OBJECT_CLASS(class); - object->dispose = (GObjectFinalizeFunc/* ! */)gtk_hex_view_dispose; - object->finalize = (GObjectFinalizeFunc)gtk_hex_view_finalize; + object->dispose = gtk_hex_view_dispose; + object->finalize = gtk_hex_view_finalize; + object->set_property = gtk_hex_view_set_property; + object->get_property = gtk_hex_view_get_property; + + _hex_view_properties[PROP_SHOW_OFFSETS] = + g_param_spec_boolean("show-offsets", NULL, NULL, + TRUE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + _hex_view_properties[PROP_CONTENT] = + g_param_spec_object("content", NULL, NULL, + G_TYPE_BIN_CONTENT, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); + + g_object_class_install_properties(object, N_PROPERTIES, _hex_view_properties); widget = GTK_WIDGET_CLASS(class); - // REMME gtk_widget_class_set_css_name(widget, "GtkHexView"); + gtk_widget_class_set_css_name(widget, "hexview"); g_type_ensure(GTK_TYPE_COMPOSING_AREA); @@ -167,12 +197,14 @@ static void gtk_hex_view_init(GtkHexView *view) view->generator = NULL; + gtk_hex_view_create(view, NULL); + } /****************************************************************************** * * -* Paramètres : view = instance d'objet GLib à traiter. * +* Paramètres : object = instance d'objet GLib à traiter. * * * * Description : Supprime toutes les références externes. * * * @@ -182,20 +214,24 @@ static void gtk_hex_view_init(GtkHexView *view) * * ******************************************************************************/ -static void gtk_hex_view_dispose(GtkHexView *view) +static void gtk_hex_view_dispose(GObject *object) { - gtk_widget_dispose_template(GTK_WIDGET(view), GTK_TYPE_HEX_VIEW); + GtkHexView *view; /* Version spécialisée */ + + gtk_widget_dispose_template(GTK_WIDGET(object), GTK_TYPE_HEX_VIEW); + + view = GTK_HEX_VIEW(object); g_clear_object(&view->generator); - G_OBJECT_CLASS(gtk_hex_view_parent_class)->dispose(G_OBJECT(view)); + G_OBJECT_CLASS(gtk_hex_view_parent_class)->dispose(object); } /****************************************************************************** * * -* Paramètres : view = instance d'objet GLib à traiter. * +* Paramètres : object = instance d'objet GLib à traiter. * * * * Description : Procède à la libération totale de la mémoire. * * * @@ -205,9 +241,9 @@ static void gtk_hex_view_dispose(GtkHexView *view) * * ******************************************************************************/ -static void gtk_hex_view_finalize(GtkHexView *view) +static void gtk_hex_view_finalize(GObject *object) { - G_OBJECT_CLASS(gtk_hex_view_parent_class)->finalize(G_OBJECT(view)); + G_OBJECT_CLASS(gtk_hex_view_parent_class)->finalize(object); } @@ -263,13 +299,43 @@ bool gtk_hex_view_create(GtkHexView *view, GBinContent *content) parent = GTK_BUFFER_VIEW(view); - cache = g_buffer_cache_new(1, 2); + cache = g_buffer_cache_new(1 /* opt_count */, 2 /* reg_count */); parent->view = g_buffer_view_new(cache, parent->style); unref_object(cache); - view->generator = g_hex_generator_new(content); + + + gtk_hex_view_set_content(view, content); + + + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : view = composant d'affichage à consulter. * +* * +* Description : Fournit le contenu associé au composant d'affichage. * +* * +* Retour : Contenu dans lequel puise le générateur pour les lignes. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBinContent *gtk_hex_view_get_content(const GtkHexView *view) +{ + GBinContent *result; /* Référence à retourner */ + + if (view->generator != NULL) + result = g_hex_generator_get_content(view->generator); + else + result = NULL; return result; @@ -278,6 +344,61 @@ bool gtk_hex_view_create(GtkHexView *view, GBinContent *content) /****************************************************************************** * * +* Paramètres : view = composant d'affichage à modifier. * +* content = nouveau contenu pour source de génération. * +* * +* Description : Définit le contenu associé au composant d'affichage. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void gtk_hex_view_set_content(GtkHexView *view, GBinContent *content) +{ + GBinContent *old; /* Ancienne valeur */ + GBufferCache *cache; /* Tampon à représenter */ + + old = gtk_hex_view_get_content(view); + + assert((old == NULL && view->generator == NULL) || (old != NULL && view->generator != NULL)); + + if (old != content) + { + if (view->generator != NULL) + { + cache = g_buffer_view_get_cache(GTK_BUFFER_VIEW(view)->view); + + g_buffer_cache_wlock(cache); + + g_buffer_cache_truncate(cache, 0); + + g_buffer_cache_wunlock(cache); + + unref_object(cache); + + g_clear_object(&view->generator); + + } + + if (content != NULL) + view->generator = g_hex_generator_new(content); + + g_object_notify_by_pspec(G_OBJECT(view), _hex_view_properties[PROP_CONTENT]); + + assert(content != NULL); + gtk_widget_queue_resize(GTK_WIDGET(view)); + + } + + g_clear_object(&old); + +} + + +/****************************************************************************** +* * * Paramètres : widget = composant GTK à redessiner. * * snapshot = gestionnaire de noeuds de rendu à solliciter. * * parent = composant GTK parent et cadre de l'appel. * @@ -380,60 +501,101 @@ static void gtk_hex_view_populate_cache(GtkHexView *view) /* Mise à jour de l'affichage ? */ + /* if (needed != count) gtk_widget_queue_resize(GTK_WIDGET(view)); + */ } +/* ---------------------------------------------------------------------------------- */ +/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ +/* ---------------------------------------------------------------------------------- */ +/****************************************************************************** +* * +* Paramètres : object = instance d'objet GLib à mamnipuler. * +* prop_id = identifiant de la propriété visée. * +* value = valeur à prendre en compte. * +* pspec = définition de la propriété. * +* * +* Description : Met à jour une propriété d'instance GObject. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ - -void demo_snapshot (GtkWidget *widget, GtkSnapshot *snapshot, GtkWidget *parent) +static void gtk_hex_view_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { - GdkRGBA red, green, yellow, blue; - float w, h; - - gdk_rgba_parse (&red, "red"); - gdk_rgba_parse (&green, "green"); - gdk_rgba_parse (&yellow, "yellow"); - gdk_rgba_parse (&blue, "blue"); + GtkHexView *view; /* Version spécialisée */ + GObject *content; /* Contenu sous forme simple */ - w = gtk_widget_get_width (widget) / 2.0; - h = gtk_widget_get_height (widget) / 2.0; + view = GTK_HEX_VIEW(object); - h /= 2.0; + switch (prop_id) + { + case PROP_SHOW_OFFSETS: + g_display_options_set(GTK_CONTENT_VIEW(view)->options, HCO_OFFSET, g_value_get_boolean(value)); + gtk_widget_set_visible(view->offsets, g_value_get_boolean(value)); + break; - 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)); + case PROP_CONTENT: + content = g_value_get_object(value); + gtk_hex_view_set_content(view, G_BIN_CONTENT(content)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } } +/****************************************************************************** +* * +* Paramètres : object = instance d'objet GLib à mamnipuler. * +* prop_id = identifiant de la propriété visée. * +* value = valeur à transmettre. [OUT] * +* pspec = définition de la propriété. * +* * +* Description : Fournit la valeur d'une propriété d'instance GObject. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ +static void gtk_hex_view_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + GtkHexView *view; /* Version spécialisée */ + view = GTK_HEX_VIEW(object); + switch (prop_id) + { + case PROP_SHOW_OFFSETS: + g_value_set_boolean(value, gtk_widget_get_visible(view->offsets)); + break; + case PROP_CONTENT: + g_value_take_object(value, gtk_hex_view_get_content(view)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } - - - - -/* ---------------------------------------------------------------------------------- */ -/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ -/* ---------------------------------------------------------------------------------- */ +} /****************************************************************************** @@ -467,7 +629,13 @@ static void gtk_hex_view_size_allocate(GtkWidget *widget, int width, int height, final_widths = alloca(_CHILDREN_COUNT * sizeof(int)); for (i = 0; i < _CHILDREN_COUNT; i++) - gtk_widget_measure(view->children[i], GTK_ORIENTATION_HORIZONTAL, -1, &min_widths[i], NULL, NULL, NULL); + { + if (!gtk_widget_get_visible(view->children[i])) + min_widths[i] = 0; + else + gtk_widget_measure(view->children[i], GTK_ORIENTATION_HORIZONTAL, -1, &min_widths[i], NULL, NULL, NULL); + + } /* Passe 1 : tentative sans défilement vertical */ @@ -491,7 +659,10 @@ static void gtk_hex_view_size_allocate(GtkWidget *widget, int width, int height, for (i = 0; i < _CHILDREN_COUNT; i++) { - final_widths[i] += min_widths[i]; + if (!gtk_widget_get_visible(view->children[i])) + final_widths[i] = 0; + else + final_widths[i] += min_widths[i]; g_width_tracker_set_column_min_width(tracker, i, final_widths[i]); @@ -531,17 +702,6 @@ static GtkSizeRequestMode gtk_hex_view_get_request_mode(GtkWidget *widget) } - - - - - - - - - - - /****************************************************************************** * * * Paramètres : widget = composant GTK à examiner. * @@ -580,8 +740,12 @@ static void gtk_hex_view_measure(GtkWidget *widget, GtkOrientation orientation, for (i = 0; i < _CHILDREN_COUNT; i++) { + if (!gtk_widget_get_visible(view->children[i])) + continue; + gtk_widget_measure(view->children[i], GTK_ORIENTATION_HORIZONTAL, -1, &min, NULL, NULL, NULL); requested += min; + } for_size -= requested; @@ -593,11 +757,14 @@ static void gtk_hex_view_measure(GtkWidget *widget, GtkOrientation orientation, GTK_BUFFER_VIEW(view)->style, for_size); - if (minimum != NULL) *minimum = 0; + if (minimum != NULL) *minimum = requested; if (natural != NULL) *natural = requested; for (i = 0; i < _CHILDREN_COUNT; i++) { + if (!gtk_widget_get_visible(view->children[i])) + continue; + gtk_widget_measure(view->children[i], GTK_ORIENTATION_VERTICAL, -1, &min, &nat, NULL, NULL); if (minimum != NULL && min > *minimum) diff --git a/src/gtkext/hexview.h b/src/gtkext/hexview.h index 2199786..0d2cd5a 100644 --- a/src/gtkext/hexview.h +++ b/src/gtkext/hexview.h @@ -41,6 +41,12 @@ 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 *); +/* Fournit le contenu associé au composant d'affichage. */ +GBinContent *gtk_hex_view_get_content(const GtkHexView *); + +/* Définit le contenu associé au composant d'affichage. */ +void gtk_hex_view_set_content(GtkHexView *, GBinContent *); + #endif /* _GTKEXT_HEXVIEW_H */ diff --git a/src/gtkext/hexview.ui b/src/gtkext/hexview.ui index ae4586c..9b42936 100644 --- a/src/gtkext/hexview.ui +++ b/src/gtkext/hexview.ui @@ -1,27 +1,29 @@ +<?xml version="1.0" encoding="UTF-8"?> <interface> - <template class="GtkHexView" parent="GtkBufferView"> - <property name="css-name">GtkHexView</property> - <child> - <object class="GtkComposingArea" id="offsets"> - <style> - <class name="gutter"/> - </style> - </object> - </child> - <child> - <object class="GtkComposingArea" id="hex"> - <property name="hexpand">true</property> - <style> - <class name="custom-view"/> - </style> - </object> - </child> - <child> - <object class="GtkComposingArea" id="ascii"> - <style> - <class name="custom-view"/> - </style> - </object> - </child> - </template> + + <template class="GtkHexView" parent="GtkBufferView"> + <child> + <object class="GtkComposingArea" id="offsets"> + <style> + <class name="gutter"/> + </style> + </object> + </child> + <child> + <object class="GtkComposingArea" id="hex"> + <property name="hexpand">true</property> + <style> + <class name="custom-view"/> + </style> + </object> + </child> + <child> + <object class="GtkComposingArea" id="ascii"> + <style> + <class name="custom-view"/> + </style> + </object> + </child> + </template> + </interface> diff --git a/src/gtkext/panel-int.h b/src/gtkext/panel-int.h index cb210d9..5398e51 100644 --- a/src/gtkext/panel-int.h +++ b/src/gtkext/panel-int.h @@ -36,6 +36,8 @@ typedef char * (* get_tiled_panel_path) (const GtkTiledPanel *); /* Fournit les composants adaptés pour la barre de titre. */ typedef GListStore * (* get_tiled_panel_widgets_cb) (const GtkTiledPanel *, bool); +/* Note un ajout ou un retrait de panneau principal. */ +typedef void (* notify_tiled_panel_state_cb) (GtkTiledPanel *, GtkTiledPanel *, bool); /* Elément réactif pour panneaux de l'éditeur (instance) */ @@ -53,6 +55,8 @@ struct _GtkTiledPanelClass get_tiled_panel_path get_default_path; /* Localisation de l'affichage */ get_tiled_panel_widgets_cb get_widgets; /* Récupération de composants */ + notify_tiled_panel_state_cb notify; /* Note d'un ajout ou retrait */ + }; diff --git a/src/gtkext/panel.c b/src/gtkext/panel.c index 48019dc..f63cfa1 100644 --- a/src/gtkext/panel.c +++ b/src/gtkext/panel.c @@ -193,6 +193,32 @@ GListStore *gtk_tiled_panel_get_title_widgets(const GtkTiledPanel *panel, bool l } +/****************************************************************************** +* * +* Paramètres : panel = panneau graphique à manipuler. * +* main = panneau principal visé par l'opération. * +* activated = nature du changement de statut : ajout, retrait ?* +* * +* Description : Note un ajout ou un retrait de panneau principal. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void gtk_tiled_panel_notify_new_main_panel_state(GtkTiledPanel *panel, GtkTiledPanel *main, bool activated) +{ + GtkTiledPanelClass *class; /* Classe à actionner */ + + class = GTK_TILED_PANEL_GET_CLASS(panel); + + if (class->notify != NULL) + class->notify(panel, main, activated); + +} + + diff --git a/src/gtkext/panel.h b/src/gtkext/panel.h index 3b0361e..9b00657 100644 --- a/src/gtkext/panel.h +++ b/src/gtkext/panel.h @@ -44,6 +44,8 @@ char *gtk_tiled_panel_get_path(const GtkTiledPanel *); /* Fournit les composants adaptés pour la barre de titre. */ GListStore *gtk_tiled_panel_get_title_widgets(const GtkTiledPanel *, bool); +/* Note un ajout ou un retrait de panneau principal. */ +void gtk_tiled_panel_notify_new_main_panel_state(GtkTiledPanel *, GtkTiledPanel *, bool); diff --git a/src/gtkext/statusstack-int.h b/src/gtkext/statusstack-int.h index df9db35..721b982 100644 --- a/src/gtkext/statusstack-int.h +++ b/src/gtkext/statusstack-int.h @@ -50,6 +50,12 @@ struct _GtkStatusStack GSourceFunc def_source; /* Appel en fin d'activité */ + /* Message simple par défaut */ + + GtkLabel *def_label; /* Afficheur de message */ + + char *msg; /* Contenu associé */ + /* Navigation */ GtkLabel *nav_segment; /* Désignation du segment */ diff --git a/src/gtkext/statusstack.c b/src/gtkext/statusstack.c index 492d888..92c296a 100644 --- a/src/gtkext/statusstack.c +++ b/src/gtkext/statusstack.c @@ -56,6 +56,10 @@ typedef enum _StatusStackProperty { static GParamSpec *_status_stack_properties[N_PROPERTIES] = { NULL, }; +/* Source d'affichage par défaut */ +#define gtk_status_stack_default_source gtk_status_stack_show_simple_message + + /* Initialise la classe des barres de statut améliorées. */ static void gtk_status_stack_class_init(GtkStatusStackClass *); @@ -87,6 +91,14 @@ static void gtk_status_stack_get_property(GObject *, guint, GValue *, GParamSpec +/* ----------------------- MISE EN AVANT DES MESSAGES SIMPLES ----------------------- */ + + +/* S'assure de l'affichage à jour de la partie "default". */ +static gboolean gtk_status_stack_show_simple_message(gpointer); + + + /* -------------------- STATUT DES INFORMATIONS DE DESASSEMBLAGE -------------------- */ @@ -115,7 +127,7 @@ static void init_navigation_info(navigation_info_t *); static void fini_navigation_info(navigation_info_t *); /* S'assure de l'affichage à jour de la partie "navigation". */ -static gboolean gtk_status_stack_show_current_location(GtkStatusStack *); +static gboolean gtk_status_stack_show_current_location(gpointer); /* Réagit à un clic sur l'icône de zoom. */ static void gtk_status_stack_on_zoom_icon_press(GtkEntry *, GtkEntryIconPosition, GtkStatusStack *); @@ -165,7 +177,7 @@ static void fini_activity_info(activity_info_t *); static activity_status_t *find_activity_status_by_id(activity_info_t *, activity_id_t); /* S'assure de l'affichage à jour de la partie "activité". */ -static gboolean gtk_status_stack_show_current_activity(GtkStatusStack *); +static gboolean gtk_status_stack_show_current_activity(gpointer); @@ -217,6 +229,8 @@ static void gtk_status_stack_class_init(GtkStatusStackClass *class) gtk_widget_class_bind_template_child(widget, GtkStatusStack, main); + gtk_widget_class_bind_template_child(widget, GtkStatusStack, def_label); + gtk_widget_class_bind_template_child(widget, GtkStatusStack, nav_segment); gtk_widget_class_bind_template_child(widget, GtkStatusStack, nav_phys); gtk_widget_class_bind_template_child(widget, GtkStatusStack, nav_virt); @@ -254,7 +268,9 @@ static void gtk_status_stack_init(GtkStatusStack *stack) { gtk_widget_init_template(GTK_WIDGET(stack)); - stack->def_source = NULL; + stack->def_source = gtk_status_stack_default_source; + + stack->msg = NULL; stack->nav_info = calloc(1, sizeof(navigation_info_t)); init_navigation_info(stack->nav_info); @@ -278,6 +294,10 @@ static void gtk_status_stack_init(GtkStatusStack *stack) stack->network_update_tag = g_timeout_add(NETWORK_UPDATE_INTERVAL, G_SOURCE_FUNC(gtk_status_stack_update_network_stats), stack); + /* Premier affichage... */ + + gtk_status_stack_reset_to_default(stack); + } @@ -324,6 +344,9 @@ static void gtk_status_stack_dispose(GtkStatusStack *stack) static void gtk_status_stack_finalize(GtkStatusStack *stack) { + if (stack->msg != NULL) + free(stack->msg); + fini_navigation_info(stack->nav_info); free(stack->nav_info); @@ -370,11 +393,15 @@ GtkStatusStack *gtk_status_stack_new(void) * * ******************************************************************************/ -void gtk_status_stack_reset(GtkStatusStack *stack) +void gtk_status_stack_reset_to_default(GtkStatusStack *stack) { - gtk_stack_set_visible_child_name(stack->main, "default"); + /** + * Une amélioration possible serait de passer à g_idle_add_once(), + * et de s'affranchir des retours G_SOURCE_REMOVE systématiques, + * mais la fonction n'est disponible qu'à partir de la GLib 2.74. + */ - stack->def_source = NULL; + g_idle_add(stack->def_source, stack); } @@ -614,6 +641,69 @@ static void gtk_status_stack_get_property(GObject *object, guint prop_id, GValue /* ---------------------------------------------------------------------------------- */ +/* MISE EN AVANT DES MESSAGES SIMPLES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : stack = barre de statut à actualiser. * +* msg = simple message à faire paraître. * +* * +* Description : Inscrit un message simple dans la barre de statut. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void gtk_status_stack_display_message(GtkStatusStack *stack, const char *msg) +{ + if (stack->msg != NULL) + free(stack->msg); + + if (msg != NULL) + stack->msg = strdup(msg); + else + stack->msg = NULL; + + gtk_status_stack_show_simple_message(stack); + +} + + +/****************************************************************************** +* * +* Paramètres : data = pile de statuts à manipuler. * +* * +* Description : S'assure de l'affichage à jour de la partie "default". * +* * +* Retour : G_SOURCE_REMOVE pour une exécution unique. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static gboolean gtk_status_stack_show_simple_message(gpointer data) +{ + GtkStatusStack *stack; /* Version spécialisée */ + + stack = GTK_STATUS_STACK(data); + + stack->def_source = gtk_status_stack_show_simple_message; + + gtk_label_set_text(stack->def_label, stack->msg != NULL ? stack->msg : ""); + + gtk_stack_set_visible_child_name(stack->main, "default"); + + return G_SOURCE_REMOVE; + +} + + + +/* ---------------------------------------------------------------------------------- */ /* STATUT DES INFORMATIONS DE DESASSEMBLAGE */ /* ---------------------------------------------------------------------------------- */ @@ -744,7 +834,7 @@ void gtk_status_stack_update_current_location(GtkStatusStack *stack, const mrang /****************************************************************************** * * -* Paramètres : stack = pile de statuts à manipuler. * +* Paramètres : data = pile de statuts à manipuler. * * * * Description : S'assure de l'affichage à jour de la partie "navigation". * * * @@ -754,14 +844,15 @@ void gtk_status_stack_update_current_location(GtkStatusStack *stack, const mrang * * ******************************************************************************/ -static gboolean gtk_status_stack_show_current_location(GtkStatusStack *stack) +static gboolean gtk_status_stack_show_current_location(gpointer data) { + GtkStatusStack *stack; /* Version spécialisée */ navigation_info_t *info; /* Informations à constituer */ char raw_pos[6 + VMPA_MAX_LEN + 1]; /* Formatage final en direct */ - stack->def_source = (GSourceFunc)gtk_status_stack_show_current_location; + stack = GTK_STATUS_STACK(data); - gtk_stack_set_visible_child_name(stack->main, "navigation"); + stack->def_source = gtk_status_stack_show_current_location; info = stack->nav_info; @@ -785,6 +876,10 @@ static gboolean gtk_status_stack_show_current_location(GtkStatusStack *stack) gtk_label_set_text(stack->nav_details, info->details != NULL ? info->details : ""); + /* Conclusion */ + + gtk_stack_set_visible_child_name(stack->main, "navigation"); + return G_SOURCE_REMOVE; } @@ -985,7 +1080,7 @@ activity_id_t gtk_status_stack_add_activity(GtkStatusStack *stack, const char *m if (info->tag != 0) g_source_remove(info->tag); - info->tag = g_idle_add((GSourceFunc)gtk_status_stack_show_current_activity, stack); + info->tag = g_idle_add(gtk_status_stack_show_current_activity, stack); g_mutex_unlock(&info->access); @@ -1052,7 +1147,7 @@ void gtk_status_stack_update_activity_message(GtkStatusStack *stack, activity_id if (info->tag != 0) g_source_remove(info->tag); - info->tag = g_idle_add((GSourceFunc)gtk_status_stack_show_current_activity, stack); + info->tag = g_idle_add(gtk_status_stack_show_current_activity, stack); } @@ -1109,7 +1204,7 @@ void gtk_status_stack_update_activity_value(GtkStatusStack *stack, activity_id_t if (info->tag != 0) g_source_remove(info->tag); - info->tag = g_idle_add((GSourceFunc)gtk_status_stack_show_current_activity, stack); + info->tag = g_idle_add(gtk_status_stack_show_current_activity, stack); } @@ -1161,7 +1256,7 @@ void gtk_status_stack_extend_activity_max(GtkStatusStack *stack, activity_id_t i if (info->tag != 0) g_source_remove(info->tag); - info->tag = g_idle_add((GSourceFunc)gtk_status_stack_show_current_activity, stack); + info->tag = g_idle_add(gtk_status_stack_show_current_activity, stack); } @@ -1227,10 +1322,10 @@ void gtk_status_stack_remove_activity(GtkStatusStack *stack, activity_id_t id) if (info->count == 0) { info->tag = 0; - g_idle_add(stack->def_source, stack); + gtk_status_stack_reset_to_default(stack); } else if (is_last) - info->tag = g_idle_add((GSourceFunc)gtk_status_stack_show_current_activity, stack); + info->tag = g_idle_add(gtk_status_stack_show_current_activity, stack); exit: @@ -1241,7 +1336,7 @@ void gtk_status_stack_remove_activity(GtkStatusStack *stack, activity_id_t id) /****************************************************************************** * * -* Paramètres : stack = pile de statuts à manipuler. * +* Paramètres : data = pile de statuts à manipuler. * * * * Description : S'assure de l'affichage à jour de la partie "activité". * * * @@ -1251,11 +1346,14 @@ void gtk_status_stack_remove_activity(GtkStatusStack *stack, activity_id_t id) * * ******************************************************************************/ -static gboolean gtk_status_stack_show_current_activity(GtkStatusStack *stack) +static gboolean gtk_status_stack_show_current_activity(gpointer data) { + GtkStatusStack *stack; /* Version spécialisée */ activity_info_t *info; /* Informations à consulter */ activity_status_t *last; /* Dernier statut à traiter */ + stack = GTK_STATUS_STACK(data); + info = stack->activity_info; g_mutex_lock(&info->access); @@ -1264,14 +1362,14 @@ static gboolean gtk_status_stack_show_current_activity(GtkStatusStack *stack) { if (info->count > 0) { - gtk_stack_set_visible_child_name(stack->main, "activity"); - last = &info->statuses[info->count - 1]; gtk_label_set_text(stack->activity_message, last->message); gtk_progress_bar_set_fraction(stack->activity_progress, (last->current * 1.0) / last->max); + gtk_stack_set_visible_child_name(stack->main, "activity"); + } info->tag = 0; diff --git a/src/gtkext/statusstack.h b/src/gtkext/statusstack.h index 66ad6db..96d008c 100644 --- a/src/gtkext/statusstack.h +++ b/src/gtkext/statusstack.h @@ -45,7 +45,15 @@ DECLARE_GTYPE(GtkStatusStack, gtk_status_stack, GTK, STATUS_STACK); GtkStatusStack *gtk_status_stack_new(void); /* Réinitialise la barre de statut à son stade par défaut. */ -void gtk_status_stack_reset(GtkStatusStack *); +void gtk_status_stack_reset_to_default(GtkStatusStack *); + + + +/* ----------------------- MISE EN AVANT DES MESSAGES SIMPLES ----------------------- */ + + +/* Inscrit un message simple dans la barre de statut. */ +void gtk_status_stack_display_message(GtkStatusStack *, const char *); diff --git a/src/gtkext/statusstack.ui b/src/gtkext/statusstack.ui index 2a6e256..0b7cd6d 100644 --- a/src/gtkext/statusstack.ui +++ b/src/gtkext/statusstack.ui @@ -12,16 +12,19 @@ <!-- Vide par défaut --> <child> - <object class="GtkStackPage" id="stack"> + <object class="GtkStackPage"> <property name="name">default</property> <property name="child"> - <object class="GtkLabel"> + <object class="GtkLabel" id="def_label"> <property name="hexpand">true</property> <property name="halign">fill</property> - <property name="valign">center</property> + <property name="valign">baseline</property> <property name="xalign">0</property> <property name="label"></property> + <style> + <class name="dim-label"/> + </style> </object> </property> diff --git a/src/gui/core/panels.c b/src/gui/core/panels.c index 3232e0c..9fca411 100644 --- a/src/gui/core/panels.c +++ b/src/gui/core/panels.c @@ -299,6 +299,43 @@ bool register_framework_panel_definition(const panel_info_t *info) * * * Paramètres : target = type de définition de panneau recherchée. * * * +* Description : Récupère les particularités d'un panneau graphique. * +* * +* Retour : Détails du comportement associé au panneau visé. * +* * +* Remarques : - * +* * +******************************************************************************/ + +FrameworkPanelPersonality get_framework_panel_personality(GType target) +{ + FrameworkPanelPersonality result; /* Propriétées à retourner */ + size_t i; /* Boucle de parcours */ + ext_panel_info_t *info; /* Informations conservées */ + + result = FPP_NONE; + + for (i = 0; i < _panels_count; i++) + { + info = _panels_list[i]; + + if (info->panel_type == target) + { + result = info->personality; + break; + } + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : target = type de définition de panneau recherchée. * +* * * Description : Met en place (au besoin) un panneau graphique unique. * * * * Retour : Instance de définition identifiée ou NULL en cas d'échec. * diff --git a/src/gui/core/panels.h b/src/gui/core/panels.h index 4d0ce41..e17ef8a 100644 --- a/src/gui/core/panels.h +++ b/src/gui/core/panels.h @@ -71,6 +71,9 @@ void unload_all_framework_panel_definitions(void); /* Enregistre la définition d'un panneau graphique. */ bool register_framework_panel_definition(const panel_info_t *); +/* Récupère les particularités d'un panneau graphique. */ +FrameworkPanelPersonality get_framework_panel_personality(GType); + /* Met en place (au besoin) un panneau graphique unique. */ GtkTiledPanel *get_framework_panel_singleton(GType); diff --git a/src/gui/dialogs/Makefile.am b/src/gui/dialogs/Makefile.am index e910c96..3492f63 100644 --- a/src/gui/dialogs/Makefile.am +++ b/src/gui/dialogs/Makefile.am @@ -3,7 +3,9 @@ BUILT_SOURCES = resources.h resources.c noinst_LTLIBRARIES = libguidialogs.la + UI_FILES = \ + about.css \ about.ui \ preferences.ui # bookmark.ui \ diff --git a/src/gui/dialogs/about-int.h b/src/gui/dialogs/about-int.h index 616c73f..96a470e 100644 --- a/src/gui/dialogs/about-int.h +++ b/src/gui/dialogs/about-int.h @@ -37,20 +37,6 @@ struct _GtkAppAboutDialog { GtkWindow parent; /* A laisser en premier */ - union - { - struct - { - GtkPicture *revision_0; /* Numéro #0 */ - GtkPicture *revision_1; /* Numéro #1 */ - GtkPicture *revision_2; /* Numéro #2 */ - GtkPicture *revision_3; /* Numéro #3 */ - GtkPicture *revision_4; /* Numéro #4 */ - GtkPicture *revision_5; /* Numéro #5 */ - }; - GtkPicture *revisions[6]; /* Tous les numéros d'un coup */ - }; - }; /* Boîte "A propos de" dédiée à l'application (classe) */ diff --git a/src/gui/dialogs/about.c b/src/gui/dialogs/about.c index 956918b..1dca752 100644 --- a/src/gui/dialogs/about.c +++ b/src/gui/dialogs/about.c @@ -44,10 +44,10 @@ static void gtk_app_about_dialog_class_init(GtkAppAboutDialogClass *); static void gtk_app_about_dialog_init(GtkAppAboutDialog *); /* Supprime toutes les références externes. */ -static void gtk_app_about_dialog_dispose(GtkAppAboutDialog *); +static void gtk_app_about_dialog_dispose(GObject *); /* Procède à la libération totale de la mémoire. */ -static void gtk_app_about_dialog_finalize(GtkAppAboutDialog *); +static void gtk_app_about_dialog_finalize(GObject *); @@ -74,22 +74,17 @@ static void gtk_app_about_dialog_class_init(GtkAppAboutDialogClass *class) object = G_OBJECT_CLASS(class); - object->dispose = (GObjectFinalizeFunc/* ! */)gtk_app_about_dialog_dispose; - object->finalize = (GObjectFinalizeFunc)gtk_app_about_dialog_finalize; + object->dispose = gtk_app_about_dialog_dispose; + object->finalize = gtk_app_about_dialog_finalize; widget = GTK_WIDGET_CLASS(class); + gtk_widget_class_set_css_name(widget, "aboutdialog"); + gtk_widget_class_add_binding_action(widget, GDK_KEY_Escape, 0, "window.close", NULL); gtk_widget_class_set_template_from_resource(widget, "/re/chrysalide/framework/gui/dialogs/about.ui"); - gtk_widget_class_bind_template_child(widget, GtkAppAboutDialog, revision_0); - gtk_widget_class_bind_template_child(widget, GtkAppAboutDialog, revision_1); - gtk_widget_class_bind_template_child(widget, GtkAppAboutDialog, revision_2); - gtk_widget_class_bind_template_child(widget, GtkAppAboutDialog, revision_3); - gtk_widget_class_bind_template_child(widget, GtkAppAboutDialog, revision_4); - gtk_widget_class_bind_template_child(widget, GtkAppAboutDialog, revision_5); - } @@ -107,40 +102,14 @@ static void gtk_app_about_dialog_class_init(GtkAppAboutDialogClass *class) static void gtk_app_about_dialog_init(GtkAppAboutDialog *dialog) { - unsigned int revision; /* Numéro de révision */ - unsigned int max; /* Nbre. de boucles à effectuer*/ - unsigned int i; /* Boucle de parcours */ - unsigned int level; /* Unité la plus importante */ - char buffer[64]; /* Nom d'image à forger */ - gtk_widget_init_template(GTK_WIDGET(dialog)); - revision = REVISION; - max = log(revision) / log(10); - - assert(max <= 6); - - for (i = 0; i <= max; i++) - { - level = pow(10, max - i); - - snprintf(buffer, 64, "/org/chrysalide/gui/dialogs/about/revision_%u.png", revision / level); - - gtk_picture_set_resource(dialog->revisions[i], buffer); - - revision %= level; - - } - - for (; i < 6; i++) - gtk_widget_set_visible(GTK_WIDGET(dialog->revisions[i]), FALSE); - } /****************************************************************************** * * -* Paramètres : dialog = instance d'objet GLib à traiter. * +* Paramètres : object = instance d'objet GLib à traiter. * * * * Description : Supprime toutes les références externes. * * * @@ -150,18 +119,18 @@ static void gtk_app_about_dialog_init(GtkAppAboutDialog *dialog) * * ******************************************************************************/ -static void gtk_app_about_dialog_dispose(GtkAppAboutDialog *dialog) +static void gtk_app_about_dialog_dispose(GObject *object) { - gtk_widget_dispose_template(GTK_WIDGET(dialog), GTK_TYPE_APP_ABOUT_DIALOG); + gtk_widget_dispose_template(GTK_WIDGET(object), GTK_TYPE_APP_ABOUT_DIALOG); - G_OBJECT_CLASS(gtk_app_about_dialog_parent_class)->dispose(G_OBJECT(dialog)); + G_OBJECT_CLASS(gtk_app_about_dialog_parent_class)->dispose(object); } /****************************************************************************** * * -* Paramètres : dialog = instance d'objet GLib à traiter. * +* Paramètres : object = instance d'objet GLib à traiter. * * * * Description : Procède à la libération totale de la mémoire. * * * @@ -171,9 +140,9 @@ static void gtk_app_about_dialog_dispose(GtkAppAboutDialog *dialog) * * ******************************************************************************/ -static void gtk_app_about_dialog_finalize(GtkAppAboutDialog *dialog) +static void gtk_app_about_dialog_finalize(GObject *object) { - G_OBJECT_CLASS(gtk_app_about_dialog_parent_class)->finalize(G_OBJECT(dialog)); + G_OBJECT_CLASS(gtk_app_about_dialog_parent_class)->finalize(object); } diff --git a/src/gui/dialogs/about.css b/src/gui/dialogs/about.css new file mode 100644 index 0000000..af3fa97 --- /dev/null +++ b/src/gui/dialogs/about.css @@ -0,0 +1,9 @@ + +aboutdialog > box { + + background-color: black; + + background-image: url('resource:///re/chrysalide/framework/gui/dialogs/about/bg.png'); + background-repeat: no-repeat; + +} diff --git a/src/gui/dialogs/about.ui b/src/gui/dialogs/about.ui index 989e53b..7b519d2 100644 --- a/src/gui/dialogs/about.ui +++ b/src/gui/dialogs/about.ui @@ -8,91 +8,13 @@ <property name="modal">true</property> <property name="resizable">false</property> - <style> - <class name="black-bg"/> - </style> - <child> <object class="GtkBox"> <property name="orientation">vertical</property> - <child> - <object class="GtkPicture" id="logo"> - <property name="margin-top">10</property> - <property name="file">resource://org/chrysalide/gui/dialogs/about/chrysalide-full.png</property> - </object> - </child> - - <!-- - Etage intermédiaire pour ne pas que l'image se voie allouer la largeur entière - de la fenêtre. Sinon des marges sont placées autour du rendu lors que l'image - n'est pas étendue pour couvrir cette largeur entière. - --> - <child> - <object class="GtkBox"> - <property name="orientation">horizontal</property> - <property name="halign">center</property> - <property name="margin-top">14</property> - <child> - <object class="GtkPicture" id="text"> - <property name="width-request">253</property> - <property name="file">resource:///org/chrysalide/gui/dialogs/about/chrysalide_text.png</property> - </object> - </child> - </object> - </child> - - <child> - <object class="GtkBox"> - <property name="orientation">horizontal</property> - <property name="margin-start">149</property> - <child> - <object class="GtkPicture" id="revision"> - <property name="width-request">14</property> - <property name="file">resource:///org/chrysalide/gui/dialogs/about/revision.png</property> - </object> - </child> - <child> - <object class="GtkPicture" id="revision_0"> - <property name="width-request">14</property> - <property name="file">resource:///org/chrysalide/gui/dialogs/about/revision.png</property> - </object> - </child> - <child> - <object class="GtkPicture" id="revision_1"> - <property name="width-request">14</property> - <property name="file">resource:///org/chrysalide/gui/dialogs/about/revision.png</property> - </object> - </child> - <child> - <object class="GtkPicture" id="revision_2"> - <property name="width-request">14</property> - <property name="file">resource:///org/chrysalide/gui/dialogs/about/revision.png</property> - </object> - </child> - <child> - <object class="GtkPicture" id="revision_3"> - <property name="width-request">14</property> - <property name="file">resource:///org/chrysalide/gui/dialogs/about/revision.png</property> - </object> - </child> - <child> - <object class="GtkPicture" id="revision_4"> - <property name="width-request">14</property> - <property name="file">resource:///org/chrysalide/gui/dialogs/about/revision.png</property> - </object> - </child> - <child> - <object class="GtkPicture" id="revision_5"> - <property name="width-request">14</property> - <property name="file">resource:///org/chrysalide/gui/dialogs/about/revision.png</property> - </object> - </child> - </object> - </child> <child> <object class="GtkLabel"> - <property name="margin-top">22</property> + <property name="margin-top">368</property> <property name="margin-bottom">10</property> <property name="label" translatable="yes"><span fgcolor='white'>Copyright (C) 2008-2025 Cyrille Bagard</span></property> <property name="use-markup">True</property> diff --git a/src/gui/dialogs/gresource.xml b/src/gui/dialogs/gresource.xml index 169f440..966d9c8 100644 --- a/src/gui/dialogs/gresource.xml +++ b/src/gui/dialogs/gresource.xml @@ -1,22 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <gresources> <gresource prefix="/re/chrysalide/framework/gui/dialogs"> + <file compressed="true">about.css</file> <file compressed="true">about.ui</file> <file compressed="true">preferences.ui</file> </gresource> - <gresource prefix="/org/chrysalide/gui/dialogs/about"> - <file compressed="true" alias="chrysalide-full.png">../../../pixmaps/chrysalide-full.png</file> - <file compressed="true" alias="chrysalide_text.png">../../../pixmaps/chrysalide_text.png</file> - <file compressed="true" alias="revision.png">../../../pixmaps/revision.png</file> - <file compressed="true" alias="revision_0.png">../../../pixmaps/revision_0.png</file> - <file compressed="true" alias="revision_1.png">../../../pixmaps/revision_1.png</file> - <file compressed="true" alias="revision_2.png">../../../pixmaps/revision_2.png</file> - <file compressed="true" alias="revision_3.png">../../../pixmaps/revision_3.png</file> - <file compressed="true" alias="revision_4.png">../../../pixmaps/revision_4.png</file> - <file compressed="true" alias="revision_5.png">../../../pixmaps/revision_5.png</file> - <file compressed="true" alias="revision_6.png">../../../pixmaps/revision_6.png</file> - <file compressed="true" alias="revision_7.png">../../../pixmaps/revision_7.png</file> - <file compressed="true" alias="revision_8.png">../../../pixmaps/revision_8.png</file> - <file compressed="true" alias="revision_9.png">../../../pixmaps/revision_9.png</file> - </gresource> </gresources> diff --git a/src/gui/panels/logs.c b/src/gui/panels/logs.c index 729a62b..399c4c0 100644 --- a/src/gui/panels/logs.c +++ b/src/gui/panels/logs.c @@ -37,10 +37,10 @@ /* ------------------------- COEUR D'UN PANNEAU D'AFFICHAGE ------------------------- */ -/* Initialise la classe des panneaux d'accueil par défaut. */ +/* Initialise la classe des panneaux d'affichage des journaux. */ static void gtk_logs_panel_class_init(GtkLogsPanelClass *); -/* Initialise une instance de panneau d'accueil par défaut. */ +/* Initialise une instance de panneau d'affichage des journaux. */ static void gtk_logs_panel_init(GtkLogsPanel *); /* Supprime toutes les références externes. */ @@ -72,7 +72,7 @@ G_DEFINE_TYPE(GtkLogsPanel, gtk_logs_panel, GTK_TYPE_TILED_PANEL); * * * Paramètres : class = classe à initialiser. * * * -* Description : Initialise la classe des panneaux d'accueil par défaut. * +* Description : Initialise la classe des panneaux d'affichage des journaux. * * * * Retour : - * * * @@ -113,7 +113,7 @@ static void gtk_logs_panel_class_init(GtkLogsPanelClass *class) * * * Paramètres : panel = instance à initialiser. * * * -* Description : Initialise une instance de panneau d'accueil par défaut. * +* Description : Initialise une instance de panneau d'affichage des journaux. * * * * Retour : - * * * diff --git a/src/gui/style.css b/src/gui/style.css index e21d931..dce41fa 100644 --- a/src/gui/style.css +++ b/src/gui/style.css @@ -36,11 +36,7 @@ list.boxed-list, list.boxed-list > row:last-child { /* about.css */ -.black-bg { - - background-color: black; - -} +@import url('resource:///re/chrysalide/framework/gui/dialogs/about.css'); /* welcome.css */ diff --git a/src/gui/window-int.h b/src/gui/window-int.h index b72a499..4f3dd57 100644 --- a/src/gui/window-int.h +++ b/src/gui/window-int.h @@ -38,6 +38,9 @@ struct _GtkFrameworkWindow GSettings *settings; /* Paramètres globaux */ GtkTilingGrid *grid; /* Réceptacle de panneaux */ + GtkStatusStack *status; /* Barre de statut */ + + GtkTiledPanel *main; /* Panneau principal courant */ }; diff --git a/src/gui/window.c b/src/gui/window.c index dbe7e87..e14ecf7 100644 --- a/src/gui/window.c +++ b/src/gui/window.c @@ -33,7 +33,6 @@ #include "panels/welcome.h" #include "../gtkext/grid.h" #include "../gtkext/helpers.h" -#include "../gtkext/statusstack.h" @@ -106,6 +105,7 @@ static void gtk_framework_window_class_init(GtkFrameworkWindowClass *class) gtk_widget_class_set_template_from_resource(widget, "/re/chrysalide/framework/gui/window.ui"); gtk_widget_class_bind_template_child(widget, GtkFrameworkWindow, grid); + gtk_widget_class_bind_template_child(widget, GtkFrameworkWindow, status); /* Active une action native (cf. https://docs.gtk.org/gtk4/class.Window.html#actions) */ gtk_widget_class_add_binding_action(widget, GDK_KEY_Q, GDK_CONTROL_MASK, "window.close", NULL); @@ -148,6 +148,8 @@ static void gtk_framework_window_init(GtkFrameworkWindow *window) g_settings_bind(window->settings, "window-height", G_OBJECT(window), "default-height", G_SETTINGS_BIND_DEFAULT); g_settings_bind(window->settings, "window-maximized", G_OBJECT(window), "maximized", G_SETTINGS_BIND_DEFAULT); + window->main = NULL; + g_action_map_add_action_entries(G_ACTION_MAP(window), app_entries, G_N_ELEMENTS(app_entries), window); @@ -206,6 +208,8 @@ static void gtk_framework_window_dispose(GObject *object) g_clear_object(&window->settings); + g_clear_object(&window->main); + G_OBJECT_CLASS(gtk_framework_window_parent_class)->dispose(object); } @@ -488,6 +492,31 @@ static void gtk_framework_window_activate_about(GSimpleAction *action, GVariant /****************************************************************************** * * +* Paramètres : window = instance de fenêtre principale à consulter. * +* * +* Description : Fournit une référence à la barre de statut intégrée. * +* * +* Retour : Composant GTK en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GtkStatusStack *gtk_framework_window_get_status_stack(const GtkFrameworkWindow *window) +{ + GtkStatusStack *result; /* Instance à retourner */ + + result = window->status; + ref_object(result); + + return result; + +} + + + +/****************************************************************************** +* * * Paramètres : window = instance de fenêtre principale à remplir. * * panel = nouveau panneau à afficher. * * * @@ -506,6 +535,7 @@ void gtk_framework_window_add(GtkFrameworkWindow *window, /* __steal */GtkTiledP guint count; /* Nombre d'élements présents */ guint i; /* Boucle de parcours */ GtkWidget *widget; /* Composant à intégrer */ + FrameworkPanelPersonality personality; /* Propriétés du panneau */ @@ -538,4 +568,54 @@ void gtk_framework_window_add(GtkFrameworkWindow *window, /* __steal */GtkTiledP } + /* Mise à jour des liens vers un panneau principal */ + + personality = get_framework_panel_personality(G_OBJECT_TYPE(panel)); + + if (personality & FPP_MAIN_PANEL) + gtk_framework_window_notify_new_main_panel_state(window, panel, true); + + else + { + if (window->main != NULL) + gtk_tiled_panel_notify_new_main_panel_state(panel, window->main, true); + } + +} + + +/****************************************************************************** +* * +* Paramètres : window = instance de fenêtre principale à manipuler. * +* main = panneau principal visé par l'opération. * +* activated = nature du changement de statut : ajout, retrait ?* +* * +* Description : Note un ajout ou un retrait de panneau principal. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void gtk_framework_window_notify_new_main_panel_state(GtkFrameworkWindow *window, GtkTiledPanel *main, bool activated) +{ + if (activated) + { + g_clear_object(&window->main); + + window->main = main; + ref_object(main); + + } + + else + { + if (main == window->main) + g_clear_object(&window->main); + + } + + gtk_tiling_grid_notify_new_main_panel_state(window->grid, main, activated); + } diff --git a/src/gui/window.h b/src/gui/window.h index 56c56ec..077d51a 100644 --- a/src/gui/window.h +++ b/src/gui/window.h @@ -30,6 +30,7 @@ #include "../glibext/helpers.h" #include "../gtkext/panel.h" +#include "../gtkext/statusstack.h" @@ -43,13 +44,18 @@ DECLARE_GTYPE(GtkFrameworkWindow, gtk_framework_window, GTK, FRAMEWORK_WINDOW); - /* Crée une nouvelle application principale pour Chrysalide. */ GtkApplicationWindow *gtk_framework_window_new(GtkApplication *); +/* Fournit une référence à la barre de statut intégrée. */ +GtkStatusStack *gtk_framework_window_get_status_stack(const GtkFrameworkWindow *); + /* Ajoute un panneau à la fenêtre principale de Chrysalide. */ void gtk_framework_window_add(GtkFrameworkWindow *, GtkTiledPanel *); +/* Note un ajout ou un retrait de panneau principal. */ +void gtk_framework_window_notify_new_main_panel_state(GtkFrameworkWindow *, GtkTiledPanel *, bool); + #endif /* _GUI_WINDOW_H */ @@ -41,7 +41,9 @@ #include "analysis/scan/scanner.h" #include "analysis/scan/patterns/backends/acism.h" #include "analysis/scan/patterns/backends/bitap.h" -#include "analysis/scan/patterns/backends/hyperscan.h" +#ifdef INCLUDE_HS_SUPPORT +# include "analysis/scan/patterns/backends/hyperscan.h" +#endif #include "core/core.h" #include "core/global.h" #include "core/logs.h" @@ -93,7 +95,11 @@ static void show_rost_help(const char *name) printf("\n"); +#ifdef INCLUDE_HS_SUPPORT printf("\t-A --algorithm=NAME\tSelect one of the available algorithms for data: acism, bitmap, hyperscan (default: acsim).\n"); +#else + printf("\t-A --algorithm=NAME\tSelect one of the available algorithms for data: acism, bitmap (default: acsim).\n"); +#endif printf("\t-C --check-only\t\tValidate the rule syntax without performing a scan (discard the file/dir argument).\n"); printf("\t-j --print-json\t\tPrint matching strings in JSON format instead of simple text.\n"); printf("\t-s --print-strings\tPrint matching strings (default text format only).\n"); @@ -303,8 +309,10 @@ int main(int argc, char **argv) g_scan_options_set_backend_for_data(options, G_TYPE_ACISM_BACKEND); else if (strcmp(optarg, "bitmap") == 0) g_scan_options_set_backend_for_data(options, G_TYPE_BITAP_BACKEND); +#ifdef INCLUDE_HS_SUPPORT else if (strcmp(optarg, "hyperscan") == 0) g_scan_options_set_backend_for_data(options, G_TYPE_HYPERSCAN_BACKEND); +#endif else g_scan_options_set_backend_for_data(options, G_TYPE_INVALID); break; diff --git a/tools/about/build.py b/tools/about/build.py new file mode 100644 index 0000000..2267492 --- /dev/null +++ b/tools/about/build.py @@ -0,0 +1,120 @@ + +# apt install libcairo2-dev pkg-config python3-dev +# pip install pycairo + +import cairo +import math +import sys + +from enum import IntEnum + +from ttf import create_cairo_font_face_for_file + + +WIDTH = 350 +HEIGHT = 430 + + +def deg2rad(degrees): + return degrees * (math.pi / 180) + + +class TextAlignment(IntEnum): + LEFT = 1 + CENTER = 2 + RIGHT = 3 + + +def draw_text(ctx, text, pos, fsize, noise, theta = 0.0, align = TextAlignment.CENTER): + """Dessine un texte en respectant des propriétées.""" + + ctx.save() + + ctx.set_font_size(fsize) + + fascent, fdescent, fheight, fxadvance, fyadvance = ctx.font_extents() + x_off, y_off, tw, th = ctx.text_extents(text)[:4] + + if align == TextAlignment.LEFT: + nx = 0 + elif align == TextAlignment.RIGHT: + nx = -tw + else: + nx = -tw / 2.0 + + ny = fheight / 2 + + ctx.translate(pos[0], pos[1]) + ctx.rotate(theta) + ctx.translate(nx, ny) + ctx.move_to(0,0) + + ctx.text_path(text) + ctx.set_source_surface(noise, 0, -fheight) + ctx.fill_preserve() + ctx.set_source_rgb(1.0, 1.0, 1.0) + ctx.set_line_width(1) + ctx.stroke() + + ctx.restore() + + +if __name__ == '__main__': + """Point d'entrée du script.""" + + surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, WIDTH, HEIGHT) + + cr = cairo.Context(surface) + + face = create_cairo_font_face_for_file('cour10p_b.ttf') + cr.set_font_face(face) + + noise = cairo.ImageSurface.create_from_png('noise.png') + + # Type d'édition + + if len(sys.argv) > 2: + + draw_text(cr, sys.argv[2], [ 300, 25 ], 32, noise, + theta = deg2rad(270), align = TextAlignment.RIGHT) + + cr.set_source_rgb(0, 0, 0) + cr.paint_with_alpha(0.4) + + # Numéro de version + + draw_text(cr, sys.argv[1], [ 149, 10 + 259 + 14 + 42 + 2 ], 23, noise, align=TextAlignment.LEFT) + + cr.set_source_rgb(0, 0, 0) + cr.paint_with_alpha(0.5) + + # Logo + + logo = cairo.ImageSurface.create_from_png('logo.png') + + scale_y = 259 / logo.get_height() + + cr.save() + + cr.translate((WIDTH - (logo.get_width() * scale_y)) / 2, 12) + + cr.scale(scale_y, scale_y) + + cr.set_source_surface(logo, 0, 0) + cr.paint() + + cr.restore() + + # Titre + + draw_text(cr, 'Chrysalide', [ WIDTH / 2, 10 + 259 + 14 + 4 ], 42, noise) + + # cr.rectangle(265, 30, 10, 10) + # cr.set_source_rgb(1, 0, 0) + # cr.fill() + + # cr.rectangle(265, 255, 10, 10) + # cr.set_source_rgb(1, 0, 0) + # cr.fill() + + surface.write_to_png('bg.png') diff --git a/tools/about/courier-10-pitch-bold_EQ97V.zip b/tools/about/courier-10-pitch-bold_EQ97V.zip Binary files differnew file mode 100644 index 0000000..0585fe6 --- /dev/null +++ b/tools/about/courier-10-pitch-bold_EQ97V.zip diff --git a/tools/about/courier10point.zip b/tools/about/courier10point.zip Binary files differnew file mode 100644 index 0000000..82cd0de --- /dev/null +++ b/tools/about/courier10point.zip diff --git a/tools/about/gen.sh b/tools/about/gen.sh new file mode 100755 index 0000000..c22ec59 --- /dev/null +++ b/tools/about/gen.sh @@ -0,0 +1,52 @@ +#!/bin/bash + + +# Cf. https://stackoverflow.com/questions/59895/how-do-i-get-the-directory-where-a-bash-script-is-located-from-within-the-script/246128#246128 +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) + +pushd $SCRIPT_DIR > /dev/null + + +# Obtention de la police Courier-10-Pitch-Bold +# -------------------------------------------- + +# https://fontsgeek.com/fonts/Courier-10-Pitch-Bold +# https://fontsgeek.com/terms-and-conditions + +# => courier-10-pitch-bold_EQ97V.zip + + +# Courier 10 Pitch font missing after upgrade to 17.04? +# https://askubuntu.com/questions/914352/courier-10-pitch-font-missing-after-upgrade-to-17-04 + +# https://groups.google.com/g/trelby/c/CGkpcMBXW9U +# -> http://www.trelby.org/files/release/font/courier10point.zip +# --> https://web.archive.org/web/20140326080337/http://www.trelby.org/files/release/font/courier10point.zip + +# https://news.ycombinator.com/item?id=18802628 +# -> https://www.trelby.org/assets/courier10point.zip + +# => courier10point.zip + +if [ ! -f cour10p_b.ttf ]; then + + unzip -p courier10point.zip courier10point/cour10p_b.ttf > cour10p_b.ttf + +fi + + +# Construction de l'image de fond +#-------------------------------- + +if [ $# -lt 1 -o $# -gt 2 ]; then + + echo "Usage: $0 <version> <edition>" + exit 123 + +fi + +python3 ./build.py $* + +cp bg.png ../../src/data/images/about-bg.png + +popd > /dev/null diff --git a/tools/about/logo.png b/tools/about/logo.png Binary files differnew file mode 100644 index 0000000..9bf9969 --- /dev/null +++ b/tools/about/logo.png diff --git a/tools/about/noise.png b/tools/about/noise.png Binary files differnew file mode 100644 index 0000000..b5d6b91 --- /dev/null +++ b/tools/about/noise.png diff --git a/tools/about/ttf.py b/tools/about/ttf.py new file mode 100644 index 0000000..eb6c027 --- /dev/null +++ b/tools/about/ttf.py @@ -0,0 +1,111 @@ + +# Source: https://www.cairographics.org/cookbook/freetypepython/ + +import ctypes as ct +import cairo + +_initialized = False +def create_cairo_font_face_for_file (filename, faceindex=0, loadoptions=0): + "given the name of a font file, and optional faceindex to pass to FT_New_Face" \ + " and loadoptions to pass to cairo_ft_font_face_create_for_ft_face, creates" \ + " a cairo.FontFace object that may be used to render text with that font." + global _initialized + global _freetype_so + global _cairo_so + global _ft_lib + global _ft_destroy_key + global _surface + + CAIRO_STATUS_SUCCESS = 0 + FT_Err_Ok = 0 + + if not _initialized: + # find shared objects + _freetype_so = ct.CDLL("libfreetype.so.6") + _cairo_so = ct.CDLL("libcairo.so.2") + _cairo_so.cairo_ft_font_face_create_for_ft_face.restype = ct.c_void_p + _cairo_so.cairo_ft_font_face_create_for_ft_face.argtypes = [ ct.c_void_p, ct.c_int ] + _cairo_so.cairo_font_face_get_user_data.restype = ct.c_void_p + _cairo_so.cairo_font_face_get_user_data.argtypes = (ct.c_void_p, ct.c_void_p) + _cairo_so.cairo_font_face_set_user_data.argtypes = (ct.c_void_p, ct.c_void_p, ct.c_void_p, ct.c_void_p) + _cairo_so.cairo_set_font_face.argtypes = [ ct.c_void_p, ct.c_void_p ] + _cairo_so.cairo_font_face_status.argtypes = [ ct.c_void_p ] + _cairo_so.cairo_font_face_destroy.argtypes = (ct.c_void_p,) + _cairo_so.cairo_status.argtypes = [ ct.c_void_p ] + # initialize freetype + _ft_lib = ct.c_void_p() + status = _freetype_so.FT_Init_FreeType(ct.byref(_ft_lib)) + if status != FT_Err_Ok : + raise RuntimeError("Error %d initializing FreeType library." % status) + #end if + + class PycairoContext(ct.Structure): + _fields_ = \ + [ + ("PyObject_HEAD", ct.c_byte * object.__basicsize__), + ("ctx", ct.c_void_p), + ("base", ct.c_void_p), + ] + #end PycairoContext + + _surface = cairo.ImageSurface(cairo.FORMAT_A8, 0, 0) + _ft_destroy_key = ct.c_int() # dummy address + _initialized = True + #end if + + ft_face = ct.c_void_p() + cr_face = None + try : + # load FreeType face + status = _freetype_so.FT_New_Face(_ft_lib, filename.encode("utf-8"), faceindex, ct.byref(ft_face)) + if status != FT_Err_Ok : + raise RuntimeError("Error %d creating FreeType font face for %s" % (status, filename)) + #end if + + # create Cairo font face for freetype face + cr_face = _cairo_so.cairo_ft_font_face_create_for_ft_face(ft_face, loadoptions) + status = _cairo_so.cairo_font_face_status(cr_face) + if status != CAIRO_STATUS_SUCCESS : + raise RuntimeError("Error %d creating cairo font face for %s" % (status, filename)) + #end if + # Problem: Cairo doesn't know to call FT_Done_Face when its font_face object is + # destroyed, so we have to do that for it, by attaching a cleanup callback to + # the font_face. This only needs to be done once for each font face, while + # cairo_ft_font_face_create_for_ft_face will return the same font_face if called + # twice with the same FT Face. + # The following check for whether the cleanup has been attached or not is + # actually unnecessary in our situation, because each call to FT_New_Face + # will return a new FT Face, but we include it here to show how to handle the + # general case. + if _cairo_so.cairo_font_face_get_user_data(cr_face, ct.byref(_ft_destroy_key)) == None : + status = _cairo_so.cairo_font_face_set_user_data \ + ( + cr_face, + ct.byref(_ft_destroy_key), + ft_face, + _freetype_so.FT_Done_Face + ) + if status != CAIRO_STATUS_SUCCESS : + raise RuntimeError("Error %d doing user_data dance for %s" % (status, filename)) + #end if + ft_face = None # Cairo has stolen my reference + #end if + + # set Cairo font face into Cairo context + cairo_ctx = cairo.Context(_surface) + cairo_t = PycairoContext.from_address(id(cairo_ctx)).ctx + _cairo_so.cairo_set_font_face(cairo_t, cr_face) + status = _cairo_so.cairo_font_face_status(cairo_t) + if status != CAIRO_STATUS_SUCCESS : + raise RuntimeError("Error %d creating cairo font face for %s" % (status, filename)) + #end if + + finally : + _cairo_so.cairo_font_face_destroy(cr_face) + _freetype_so.FT_Done_Face(ft_face) + #end try + + # get back Cairo font face as a Python object + face = cairo_ctx.get_font_face() + return face +#end create_cairo_font_face_for_file |
