summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore6
-rw-r--r--configure.ac38
-rw-r--r--gitrev.m42
-rw-r--r--pixmaps/Makefile.am18
-rw-r--r--pixmaps/chrysalide-full.pngbin28830 -> 0 bytes
-rw-r--r--pixmaps/chrysalide_text.pngbin11432 -> 0 bytes
-rw-r--r--pixmaps/revision.pngbin601 -> 0 bytes
-rw-r--r--pixmaps/revision_0.pngbin760 -> 0 bytes
-rw-r--r--pixmaps/revision_1.pngbin545 -> 0 bytes
-rw-r--r--pixmaps/revision_2.pngbin727 -> 0 bytes
-rw-r--r--pixmaps/revision_3.pngbin719 -> 0 bytes
-rw-r--r--pixmaps/revision_4.pngbin691 -> 0 bytes
-rw-r--r--pixmaps/revision_5.pngbin746 -> 0 bytes
-rw-r--r--pixmaps/revision_6.pngbin775 -> 0 bytes
-rw-r--r--pixmaps/revision_7.pngbin585 -> 0 bytes
-rw-r--r--pixmaps/revision_8.pngbin802 -> 0 bytes
-rw-r--r--pixmaps/revision_9.pngbin791 -> 0 bytes
-rw-r--r--plugins/pychrysalide/Makefile.am15
-rw-r--r--plugins/pychrysalide/arch/Makefile.am14
-rw-r--r--plugins/pychrysalide/arch/constants.c5
-rw-r--r--plugins/pychrysalide/arch/constants.h5
-rw-r--r--plugins/pychrysalide/arch/instruction.c866
-rw-r--r--plugins/pychrysalide/arch/instructions/Makefile.am3
-rw-r--r--plugins/pychrysalide/arch/instructions/constants.c58
-rw-r--r--plugins/pychrysalide/arch/instructions/constants.h5
-rw-r--r--plugins/pychrysalide/arch/instructions/raw.c142
-rw-r--r--plugins/pychrysalide/arch/instructions/undefined.c145
-rw-r--r--plugins/pychrysalide/arch/instructions/undefined.h4
-rw-r--r--plugins/pychrysalide/arch/module-ui.c7
-rw-r--r--plugins/pychrysalide/arch/module.c10
-rw-r--r--plugins/pychrysalide/arch/operand.c4
-rw-r--r--plugins/pychrysalide/bindings.c93
-rw-r--r--plugins/pychrysalide/bindings.h17
-rw-r--r--plugins/pychrysalide/convert.c31
-rw-r--r--plugins/pychrysalide/convert.h3
-rw-r--r--plugins/pychrysalide/core-ui.c190
-rw-r--r--plugins/pychrysalide/core.c194
-rw-r--r--plugins/pychrysalide/glibext/secstorage.c9
-rw-r--r--plugins/pychrysalide/gtkext/Makefile.am30
-rw-r--r--plugins/pychrysalide/gtkext/module.c34
-rw-r--r--plugins/pychrysalide/gtkext/panel.c130
-rw-r--r--plugins/pychrysalide/gtkext/panel.h42
-rw-r--r--plugins/pychrysalide/helpers-ui.c141
-rw-r--r--plugins/pychrysalide/helpers-ui.h44
-rw-r--r--plugins/pychrysalide/helpers.c121
-rw-r--r--plugins/pychrysalide/helpers.h13
-rw-r--r--src/Makefile.am13
-rw-r--r--src/analysis/scan/patterns/backends/Makefile.am8
-rw-r--r--src/app.c28
-rw-r--r--src/arch/Makefile.am11
-rw-r--r--src/arch/instruction-int.h126
-rw-r--r--src/arch/instruction-ui-int.h55
-rw-r--r--src/arch/instruction-ui.c254
-rw-r--r--src/arch/instruction-ui.h41
-rw-r--r--src/arch/instruction.c1935
-rw-r--r--src/arch/instruction.h316
-rw-r--r--src/arch/instructions/Makefile.am11
-rw-r--r--src/arch/instructions/raw-int.h56
-rw-r--r--src/arch/instructions/raw-ui.c261
-rw-r--r--src/arch/instructions/raw-ui.h37
-rw-r--r--src/arch/instructions/raw.c696
-rw-r--r--src/arch/instructions/raw.h41
-rw-r--r--src/arch/instructions/undefined-int.h52
-rw-r--r--src/arch/instructions/undefined-ui.c102
-rw-r--r--src/arch/instructions/undefined-ui.h37
-rw-r--r--src/arch/instructions/undefined.c383
-rw-r--r--src/arch/instructions/undefined.h28
-rw-r--r--src/arch/vmpa.h29
-rw-r--r--src/common/Makefile.am1
-rw-r--r--src/common/cpp.h2
-rw-r--r--src/common/sort.h3
-rw-r--r--src/common/szbin.h16
-rw-r--r--src/core/Makefile.am3
-rw-r--r--src/core/core.c21
-rw-r--r--src/core/core.h5
-rw-r--r--src/core/processors.c23
-rw-r--r--src/core/processors.h6
-rw-r--r--src/data/Makefile.am2
-rw-r--r--src/data/images/Makefile.am33
-rw-r--r--src/data/images/dock-station-bottom-symbolic.svg197
-rw-r--r--src/data/images/dock-station-left-symbolic.svg51
-rw-r--r--src/data/images/dock-station-right-symbolic.svg76
-rw-r--r--src/data/images/gresource.xml12
-rw-r--r--src/data/images/logs-symbolic.svg93
-rw-r--r--src/glibext/Makefile.am4
-rw-r--r--src/glibext/bufferline.c334
-rw-r--r--src/glibext/bufferline.h14
-rw-r--r--src/glibext/log-int.h58
-rw-r--r--src/glibext/log.c306
-rw-r--r--src/glibext/log.h43
-rw-r--r--src/glibext/options/asm.h19
-rw-r--r--src/glibext/secstorage.c4
-rw-r--r--src/glibext/sigredir.c (renamed from src/glibext/signal.c)159
-rw-r--r--src/glibext/sigredir.h (renamed from src/glibext/_signal.h)21
-rw-r--r--src/glibext/storage-int.h2
-rw-r--r--src/glibext/widthtracker.c8
-rw-r--r--src/gtkext/Makefile.am6
-rw-r--r--src/gtkext/area.c2
-rw-r--r--src/gtkext/bindings/Makefile.am42
-rw-r--r--src/gtkext/bindings/generated-enums.c.template41
-rw-r--r--src/gtkext/bindings/generated-enums.h.template23
-rw-r--r--src/gtkext/dockstation-int.h18
-rw-r--r--src/gtkext/dockstation.c472
-rw-r--r--src/gtkext/dockstation.h11
-rw-r--r--src/gtkext/dockstation.ui80
-rw-r--r--src/gtkext/gresource.xml2
-rw-r--r--src/gtkext/grid-int.h42
-rw-r--r--src/gtkext/grid.c1310
-rw-r--r--src/gtkext/grid.h46
-rw-r--r--src/gtkext/grid.ui217
-rw-r--r--src/gtkext/hexview.c287
-rw-r--r--src/gtkext/hexview.h6
-rw-r--r--src/gtkext/hexview.ui52
-rw-r--r--src/gtkext/panel-int.h10
-rw-r--r--src/gtkext/panel.c57
-rw-r--r--src/gtkext/panel.h7
-rw-r--r--src/gtkext/statusstack-int.h8
-rw-r--r--src/gtkext/statusstack.c254
-rw-r--r--src/gtkext/statusstack.h10
-rw-r--r--src/gtkext/statusstack.ui14
-rw-r--r--src/gui/core/logs.c32
-rw-r--r--src/gui/core/panels.c59
-rw-r--r--src/gui/core/panels.h3
-rw-r--r--src/gui/dialogs/Makefile.am2
-rw-r--r--src/gui/dialogs/about-int.h14
-rw-r--r--src/gui/dialogs/about.c57
-rw-r--r--src/gui/dialogs/about.css9
-rw-r--r--src/gui/dialogs/about.ui80
-rw-r--r--src/gui/dialogs/gresource.xml16
-rw-r--r--src/gui/dialogs/preferences.c3
-rw-r--r--src/gui/dialogs/prefs/Makefile.am3
-rw-r--r--src/gui/dialogs/prefs/appearance-int.h64
-rw-r--r--src/gui/dialogs/prefs/appearance.c251
-rw-r--r--src/gui/dialogs/prefs/appearance.h41
-rw-r--r--src/gui/dialogs/prefs/appearance.ui184
-rw-r--r--src/gui/dialogs/prefs/gresource.xml1
-rw-r--r--src/gui/panels/Makefile.am7
-rw-r--r--src/gui/panels/gresource.xml3
-rw-r--r--src/gui/panels/log.c451
-rw-r--r--src/gui/panels/log.h67
-rw-r--r--src/gui/panels/log.ui59
-rw-r--r--src/gui/panels/logs-col-icon.ui17
-rw-r--r--src/gui/panels/logs-col-message.ui19
-rw-r--r--src/gui/panels/logs-int.h53
-rw-r--r--src/gui/panels/logs.c227
-rw-r--r--src/gui/panels/logs.h47
-rw-r--r--src/gui/panels/logs.ui58
-rw-r--r--src/gui/style.css18
-rw-r--r--src/gui/window-int.h5
-rw-r--r--src/gui/window.c278
-rw-r--r--src/gui/window.h8
-rw-r--r--src/gui/window.ui20
-rw-r--r--src/rost.c10
-rw-r--r--src/schemas/re.chrysalide.framework.gschema.xml66
-rw-r--r--tests/arch/instruction.py52
-rw-r--r--tools/about/build.py120
-rw-r--r--tools/about/courier-10-pitch-bold_EQ97V.zipbin0 -> 21114 bytes
-rw-r--r--tools/about/courier10point.zipbin0 -> 61784 bytes
-rwxr-xr-xtools/about/gen.sh52
-rw-r--r--tools/about/logo.pngbin0 -> 633982 bytes
-rw-r--r--tools/about/noise.pngbin0 -> 136944 bytes
-rw-r--r--tools/about/ttf.py111
162 files changed, 8966 insertions, 5093 deletions
diff --git a/.gitignore b/.gitignore
index d43ca32..ae3f2cd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -66,6 +66,7 @@ plugins/dalvik/v35/opcodes/
# GLib
src/glibext/chrysamarshal.*
resources.[ch]
+src/gtkext/bindings/*-enums.[ch]
# Binaries
src/chrysalide
@@ -76,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
@@ -83,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 5acf436..8429ae6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -35,6 +35,10 @@ AC_PROG_INSTALL
AC_PROG_MAKE_SET
LT_INIT
+PKG_PROG_PKG_CONFIG([0.28])
+
+PKG_CHECK_VAR([GLIB_MKENUMS], [glib-2.0], [glib_mkenums])
+
CFLAGS=""
AC_EGREP_CPP(yes,
@@ -245,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])
@@ -589,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
@@ -722,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
@@ -862,12 +886,15 @@ AC_CONFIG_FILES([Makefile
src/arch/operands/Makefile
src/common/Makefile
src/core/Makefile
+ src/data/Makefile
+ src/data/images/Makefile
src/debug/Makefile
src/format/Makefile
src/glibext/Makefile
src/glibext/generators/Makefile
src/glibext/options/Makefile
src/gtkext/Makefile
+ src/gtkext/bindings/Makefile
src/gtkext/graph/Makefile
src/gui/Makefile
src/gui/core/Makefile
@@ -954,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
@@ -966,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
diff --git a/gitrev.m4 b/gitrev.m4
index bf2057b..12dab77 100644
--- a/gitrev.m4
+++ b/gitrev.m4
@@ -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
deleted file mode 100644
index a153353..0000000
--- a/pixmaps/chrysalide-full.png
+++ /dev/null
Binary files differ
diff --git a/pixmaps/chrysalide_text.png b/pixmaps/chrysalide_text.png
deleted file mode 100644
index b4d8c78..0000000
--- a/pixmaps/chrysalide_text.png
+++ /dev/null
Binary files differ
diff --git a/pixmaps/revision.png b/pixmaps/revision.png
deleted file mode 100644
index 330e108..0000000
--- a/pixmaps/revision.png
+++ /dev/null
Binary files differ
diff --git a/pixmaps/revision_0.png b/pixmaps/revision_0.png
deleted file mode 100644
index 0a468de..0000000
--- a/pixmaps/revision_0.png
+++ /dev/null
Binary files differ
diff --git a/pixmaps/revision_1.png b/pixmaps/revision_1.png
deleted file mode 100644
index 738a881..0000000
--- a/pixmaps/revision_1.png
+++ /dev/null
Binary files differ
diff --git a/pixmaps/revision_2.png b/pixmaps/revision_2.png
deleted file mode 100644
index b567b80..0000000
--- a/pixmaps/revision_2.png
+++ /dev/null
Binary files differ
diff --git a/pixmaps/revision_3.png b/pixmaps/revision_3.png
deleted file mode 100644
index 7f5e3fc..0000000
--- a/pixmaps/revision_3.png
+++ /dev/null
Binary files differ
diff --git a/pixmaps/revision_4.png b/pixmaps/revision_4.png
deleted file mode 100644
index a21ccbb..0000000
--- a/pixmaps/revision_4.png
+++ /dev/null
Binary files differ
diff --git a/pixmaps/revision_5.png b/pixmaps/revision_5.png
deleted file mode 100644
index a9130d9..0000000
--- a/pixmaps/revision_5.png
+++ /dev/null
Binary files differ
diff --git a/pixmaps/revision_6.png b/pixmaps/revision_6.png
deleted file mode 100644
index 291febd..0000000
--- a/pixmaps/revision_6.png
+++ /dev/null
Binary files differ
diff --git a/pixmaps/revision_7.png b/pixmaps/revision_7.png
deleted file mode 100644
index ccd4d4e..0000000
--- a/pixmaps/revision_7.png
+++ /dev/null
Binary files differ
diff --git a/pixmaps/revision_8.png b/pixmaps/revision_8.png
deleted file mode 100644
index 054c250..0000000
--- a/pixmaps/revision_8.png
+++ /dev/null
Binary files differ
diff --git a/pixmaps/revision_9.png b/pixmaps/revision_9.png
deleted file mode 100644
index 1123669..0000000
--- a/pixmaps/revision_9.png
+++ /dev/null
Binary files differ
diff --git a/plugins/pychrysalide/Makefile.am b/plugins/pychrysalide/Makefile.am
index f0cd477..c574727 100644
--- a/plugins/pychrysalide/Makefile.am
+++ b/plugins/pychrysalide/Makefile.am
@@ -15,12 +15,6 @@ endif
# if BUILD_GTK_SUPPORT
-# GTKEXT_LIBADD = \
-# gtkext/libpychrysagtkext.la
-
-# GTKEXT_SUBDIR = \
-# gtkext
-
# GUI_LIBADD = \
# gui/libpychrysagui.la
@@ -51,7 +45,6 @@ AM_CFLAGS = $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) $(TOOLKIT_CFL
# common/libpychrysacommon.la \
# core/libpychrysacore.la \
# debug/libpychrysadebug.la \
-# $(GTKEXT_LIBADD) \
# $(GUI_LIBADD) \
# mangling/libpychrysamangling.la \
# plugins/libpychrysaplugins.la
@@ -78,11 +71,13 @@ EXTRA_pychrysalideui_la_DEPENDENCIES = pychrysalide.la
pychrysalideui_la_SOURCES = \
core-ui-int.h \
- core-ui.h core-ui.c
+ core-ui.h core-ui.c \
+ helpers-ui.h helpers-ui.c
pychrysalideui_la_LIBADD = \
arch/libpychrysaarchui.la \
- glibext/libpychrysaglibextui.la
+ glibext/libpychrysaglibextui.la \
+ gtkext/libpychrysagtkext.la
# -ldl: dladdr(), dlerror()
pychrysalideui_la_LDFLAGS = \
@@ -100,4 +95,4 @@ dev_HEADERS = $(pychrysalide_la_SOURCES:%c=)
#SUBDIRS = analysis arch common core debug $(GTKEXT_SUBDIR) $(GUI_SUBDIR) mangling plugins
-SUBDIRS = analysis arch common core format glibext plugins
+SUBDIRS = analysis arch common core format glibext gtkext plugins
diff --git a/plugins/pychrysalide/arch/Makefile.am b/plugins/pychrysalide/arch/Makefile.am
index a134947..a0dcfdb 100644
--- a/plugins/pychrysalide/arch/Makefile.am
+++ b/plugins/pychrysalide/arch/Makefile.am
@@ -2,17 +2,12 @@
noinst_LTLIBRARIES = libpychrysaarch4.la libpychrysaarchui.la # libpychrysaarch.la
# libpychrysaarch_la_SOURCES = \
-# constants.h constants.c \
# context.h context.c \
# instriter.h instriter.c \
-# instruction.h instruction.c \
-# module.h module.c \
-# operand.h operand.c \
-# processor.h processor.c \
-# vmpa.h vmpa.c
+# processor.h processor.c
# libpychrysaarch_la_LIBADD = \
-# instructions/libpychrysaarchinstructions.la \
+# \
# operands/libpychrysaarchoperands.la
# libpychrysaarch_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
@@ -21,12 +16,14 @@ noinst_LTLIBRARIES = libpychrysaarch4.la libpychrysaarchui.la # libpychrysaarch.
libpychrysaarch4_la_SOURCES = \
constants.h constants.c \
+ instruction.h instruction.c \
module.h module.c \
operand.h operand.c \
register.h register.c \
vmpa.h vmpa.c
libpychrysaarch4_la_LIBADD = \
+ instructions/libpychrysaarchinstructions.la \
operands/libpychrysaarchoperands.la
libpychrysaarch4_la_CFLAGS = $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
@@ -48,5 +45,4 @@ devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libpychrysaarch_la_SOURCES:%c=)
-# SUBDIRS = instructions operands
-SUBDIRS = operands
+SUBDIRS = instructions operands
diff --git a/plugins/pychrysalide/arch/constants.c b/plugins/pychrysalide/arch/constants.c
index 3604795..5db59ff 100644
--- a/plugins/pychrysalide/arch/constants.c
+++ b/plugins/pychrysalide/arch/constants.c
@@ -25,7 +25,7 @@
#include "constants.h"
-//#include <arch/instruction.h>
+#include <arch/instruction.h>
//#include <arch/processor.h>
#include <arch/vmpa.h>
@@ -33,7 +33,6 @@
#include "../helpers.h"
-#if 0 // FIXME
/******************************************************************************
* *
@@ -116,6 +115,8 @@ bool define_arch_instruction_constants(PyTypeObject *type)
}
+#if 0 // FIXME
+
/******************************************************************************
* *
* Paramètres : type = type dont le dictionnaire est à compléter. *
diff --git a/plugins/pychrysalide/arch/constants.h b/plugins/pychrysalide/arch/constants.h
index b12579e..2f16c4f 100644
--- a/plugins/pychrysalide/arch/constants.h
+++ b/plugins/pychrysalide/arch/constants.h
@@ -30,10 +30,13 @@
#include <stdbool.h>
-#if 0 // FIXME
+
/* Définit les constantes relatives aux instructions. */
bool define_arch_instruction_constants(PyTypeObject *);
+
+#if 0 // FIXME
+
/* Définit les constantes relatives aux processeurs. */
bool define_arch_processor_constants(PyTypeObject *);
diff --git a/plugins/pychrysalide/arch/instruction.c b/plugins/pychrysalide/arch/instruction.c
index 0a9ba16..49daa9c 100644
--- a/plugins/pychrysalide/arch/instruction.c
+++ b/plugins/pychrysalide/arch/instruction.c
@@ -27,13 +27,12 @@
#include <assert.h>
#include <malloc.h>
-#include <string.h>
#include <pygobject.h>
#include <i18n.h>
+#include <plugins/self.h>
#include <arch/instruction-int.h>
-#include <plugins/dt.h>
#include "constants.h"
@@ -41,30 +40,38 @@
#include "vmpa.h"
#include "../access.h"
#include "../helpers.h"
-#include "../glibext/linegen.h"
-
-
-
-static G_DEFINE_QUARK(cached_keyword, get_cached_keyword);
+#include "../glibext/objhole.h"
+#include "../glibext/serialize.h"
/* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */
-/* Accompagne la création d'une instance dérivée en Python. */
-static PyObject *py_arch_instruction_new(PyTypeObject *, PyObject *, PyObject *);
-
/* Initialise la classe générique des instructions. */
-static void py_arch_instruction_init_gclass(GArchInstructionClass *, gpointer);
+static int py_arch_instruction_init_gclass(GArchInstructionClass *, PyTypeObject *);
-CREATE_DYN_ABSTRACT_CONSTRUCTOR(arch_instruction, G_TYPE_ARCH_INSTRUCTION, py_arch_instruction_init_gclass);
+CREATE_DYN_ABSTRACT_CONSTRUCTOR(arch_instruction, G_TYPE_ARCH_INSTRUCTION);
/* Initialise une instance sur la base du dérivé de GObject. */
static int py_arch_instruction_init(PyObject *, PyObject *, PyObject *);
+/* Indique l'encodage d'une instruction de façon détaillée. */
+static char *py_arch_instruction_get_encoding_wrapper(const GArchInstruction *);
+
/* Fournit le nom humain de l'instruction manipulée. */
-static const char *py_arch_instruction_get_class_keyword(GArchInstruction *);
+static char *py_arch_instruction_get_keyword_wrapper(const GArchInstruction *);
+
+
+
+/* ------------------- DEFINITION DES LIAISONS ENTRE INSTRUCTIONS ------------------- */
+
+
+/* Fournit les origines d'une instruction donnée. */
+static PyObject *py_arch_instruction_get_sources(PyObject *, void *);
+
+/* Fournit les destinations d'une instruction donnée. */
+static PyObject *py_arch_instruction_get_destinations(PyObject *, void *);
@@ -72,10 +79,7 @@ static const char *py_arch_instruction_get_class_keyword(GArchInstruction *);
/* Attache un opérande supplémentaire à une instruction. */
-static PyObject *py_arch_instruction_attach_extra_operand(PyObject *, PyObject *);
-
-/* Fournit tous les opérandes d'une instruction. */
-static PyObject *py_arch_instruction_get_operands(PyObject *, void *);
+static PyObject *py_arch_instruction_attach_operand(PyObject *, PyObject *);
/* Remplace un opérande d'une instruction par un autre. */
static PyObject *py_arch_instruction_replace_operand(PyObject *, PyObject *);
@@ -89,34 +93,35 @@ static PyObject *py_arch_instruction_find_operand_path(PyObject *, PyObject *);
/* Obtient l'opérande correspondant à un chemin donné. */
static PyObject *py_arch_instruction_get_operand_from_path(PyObject *, PyObject *);
+/* Fournit tous les opérandes d'une instruction. */
+static PyObject *py_arch_instruction_get_operands(PyObject *, void *);
-/* ------------------- DEFINITION DES LIAISONS ENTRE INSTRUCTIONS ------------------- */
+/* ------------------ LIAISON DE FONCTIONNALITES AVEC L'API PYTHON ------------------ */
-/* Fournit les origines d'une instruction donnée. */
-static PyObject *py_arch_instruction_get_sources(PyObject *, void *);
-/* Fournit les destinations d'une instruction donnée. */
-static PyObject *py_arch_instruction_get_destinations(PyObject *, void *);
+/* Ajoute une information complémentaire à une instruction. */
+static PyObject *py_arch_instruction_set_flag(PyObject *, PyObject *);
+/* Retire une information complémentaire à une instruction. */
+static PyObject *py_arch_instruction_unset_flag(PyObject *, PyObject *);
+/* Détermine si une instruction possède un fanion particulier. */
+static PyObject *py_arch_instruction_has_flag(PyObject *, PyObject *);
-/* --------------------- INSTRUCTIONS D'ARCHITECTURES EN PYTHON --------------------- */
+/* Fournit l'identifiant correspondant à un type d'instructions. */
+static PyObject *py_arch_instruction_get_type_id(PyObject *, void *);
+/* Indique l'encodage d'une instruction de façon détaillée. */
+static PyObject *py_arch_instruction_get_encoding(PyObject *, void *);
-/* Fournit l'identifiant unique pour un ensemble d'instructions. */
-static PyObject *py_arch_instruction_get_unique_id(PyObject *, void *);
+/* Indique l'encodage d'une instruction de façon détaillée. */
+static PyObject *py_arch_instruction_get_keyword(PyObject *, void *);
/* Fournit la place mémoire d'une instruction. */
static PyObject *py_arch_instruction_get_range(PyObject *, void *);
-/* Définit la localisation d'une instruction. */
-static int py_arch_instruction_set_range(PyObject *, PyObject *, void *);
-
-/* Fournit le nom humain de l'instruction manipulée. */
-static PyObject *py_arch_instruction_get_keyword(PyObject *, void *);
-
/* ---------------------------------------------------------------------------------- */
@@ -126,24 +131,23 @@ static PyObject *py_arch_instruction_get_keyword(PyObject *, void *);
/******************************************************************************
* *
-* Paramètres : class = classe à initialiser. *
-* unused = données non utilisées ici. *
+* Paramètres : gclass = classe GLib à initialiser. *
+* pyclass = classe Python à initialiser. *
* *
* Description : Initialise la classe générique des instructions. *
* *
-* Retour : - *
+* Retour : 0 pour indiquer un succès de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
-static void py_arch_instruction_init_gclass(GArchInstructionClass *class, gpointer unused)
+static int py_arch_instruction_init_gclass(GArchInstructionClass *gclass, PyTypeObject *pyclass)
{
- GArchInstructionClass *instr; /* Encore une autre vision... */
-
- instr = G_ARCH_INSTRUCTION_CLASS(class);
+ PY_CLASS_SET_WRAPPER(gclass->get_encoding, py_arch_instruction_get_encoding_wrapper);
+ PY_CLASS_SET_WRAPPER(gclass->get_keyword, py_arch_instruction_get_keyword_wrapper);
- instr->get_keyword = (get_instruction_keyword_fc)py_arch_instruction_get_class_keyword;
+ return 0;
}
@@ -164,17 +168,25 @@ static void py_arch_instruction_init_gclass(GArchInstructionClass *class, gpoint
static int py_arch_instruction_init(PyObject *self, PyObject *args, PyObject *kwds)
{
- unsigned short int uid; /* Indentifiant unique de type */
- const char *keyword; /* Désignation d'instruction */
+ unsigned short int tid; /* Indentifiant unique de type */
int ret; /* Bilan de lecture des args. */
GArchInstruction *instr; /* Instruction à manipuler */
- GQuark cache_key; /* Emplacement local */
- static char *kwlist[] = { "uid", "keyword", NULL };
+#define ARCH_INSTRUCTION_DOC \
+ "The ArchInstruction object provides a base class for instructions" \
+ " of any architecture.\n" \
+ " operands of any kind for new architectures.\n" \
+ "\n" \
+ "Calls to the *__init__* constructor of this abstract object expect"\
+ " one argument: an unique identifier, as an integer value.\n" \
+ "\n" \
+ "The following methods have to be defined for new classes:\n" \
+ "* pychrysalide.arch.ArchRegister._get_encoding();\n" \
+ "* pychrysalide.arch.ArchRegister._get_keyword().\n"
/* Récupération des paramètres */
- ret = PyArg_ParseTupleAndKeywords(args, kwds, "Hs", kwlist, &uid, &keyword);
+ ret = PyArg_ParseTuple(args, "H", &tid);
if (!ret) return -1;
/* Initialisation d'un objet GLib */
@@ -186,13 +198,72 @@ static int py_arch_instruction_init(PyObject *self, PyObject *args, PyObject *kw
instr = G_ARCH_INSTRUCTION(pygobject_get(self));
- cache_key = get_cached_keyword_quark();
+ if (!g_arch_instruction_create(instr, tid))
+ return -1;
+
+ return 0;
- g_object_set_qdata_full(G_OBJECT(instr), cache_key, strdup(keyword), g_free);
+}
- g_arch_instruction_set_unique_id(G_ARCH_INSTRUCTION(instr), uid);
- return 0;
+/******************************************************************************
+* *
+* Paramètres : instr = instruction quelconque à consulter. *
+* *
+* Description : Indique l'encodage d'une instruction de façon détaillée. *
+* *
+* Retour : Description humaine de l'encodage utilisé. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *py_arch_instruction_get_encoding_wrapper(const GArchInstruction *instr)
+{
+ char *result; /* Encodage à retourner */
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
+ PyObject *pyobj; /* Objet Python concerné */
+ PyObject *pyret; /* Bilan d'exécution */
+
+#define PLUGIN_MODULE_GET_ENCODING_WRAPPER PYTHON_WRAPPER_DEF \
+( \
+ _get_encoding, "$self, /", \
+ METH_NOARGS, \
+ "Abstract method describing the encoding related to an" \
+ " instruction.\n" \
+ "\n" \
+ "The result should be the string value.\n" \
+)
+
+ result = NULL;
+
+ gstate = PyGILState_Ensure();
+
+ pyobj = pygobject_new(G_OBJECT(instr));
+
+ if (has_python_method(pyobj, "_get_encoding"))
+ {
+ pyret = run_python_method(pyobj, "_get_encoding", NULL);
+
+ if (pyret != NULL)
+ {
+ if (!PyUnicode_Check(pyret))
+ log_variadic_message(LMT_ERROR, _("The returned raw name must be a string"));
+
+ else
+ result = strdup(PyUnicode_DATA(pyret));
+
+ }
+
+ Py_XDECREF(pyret);
+
+ }
+
+ Py_DECREF(pyobj);
+
+ PyGILState_Release(gstate);
+
+ return result;
}
@@ -209,15 +280,50 @@ static int py_arch_instruction_init(PyObject *self, PyObject *args, PyObject *kw
* *
******************************************************************************/
-static const char *py_arch_instruction_get_class_keyword(GArchInstruction *instr)
+static char *py_arch_instruction_get_keyword_wrapper(const GArchInstruction *instr)
{
- const char *result; /* Désignation à retourner */
- GQuark cache_key; /* Emplacement local */
+ char *result; /* Etiquette à retourner */
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
+ PyObject *pyobj; /* Objet Python concerné */
+ PyObject *pyret; /* Bilan d'exécution */
+
+#define PLUGIN_MODULE_GET_KEYWORD_WRAPPER PYTHON_WRAPPER_DEF \
+( \
+ _get_keyword, "$self, /", \
+ METH_NOARGS, \
+ "Abstract method giving the official name of the assembly" \
+ " instruction.\n" \
+ "\n" \
+ "The result should be the string value.\n" \
+)
+
+ result = NULL;
+
+ gstate = PyGILState_Ensure();
+
+ pyobj = pygobject_new(G_OBJECT(instr));
+
+ if (has_python_method(pyobj, "_get_keyword"))
+ {
+ pyret = run_python_method(pyobj, "_get_keyword", NULL);
+
+ if (pyret != NULL)
+ {
+ if (!PyUnicode_Check(pyret))
+ log_variadic_message(LMT_ERROR, _("The returned raw name must be a string"));
- cache_key = get_cached_keyword_quark();
+ else
+ result = strdup(PyUnicode_DATA(pyret));
- result = g_object_get_qdata(G_OBJECT(instr), cache_key);
- assert(result != NULL);
+ }
+
+ Py_XDECREF(pyret);
+
+ }
+
+ Py_DECREF(pyobj);
+
+ PyGILState_Release(gstate);
return result;
@@ -226,94 +332,201 @@ static const char *py_arch_instruction_get_class_keyword(GArchInstruction *instr
/* ---------------------------------------------------------------------------------- */
-/* MANIPULATION DES OPERANDES */
+/* DEFINITION DES LIAISONS ENTRE INSTRUCTIONS */
/* ---------------------------------------------------------------------------------- */
/******************************************************************************
* *
-* Paramètres : self = architecture concernée par la procédure. *
-* args = instruction représentant le point de départ. *
+* Paramètres : self = instruction d'architecture à manipuler. *
+* unused = adresse non utilisée ici. *
* *
-* Description : Attache un opérande supplémentaire à une instruction. *
+* Description : Fournit les origines d'une instruction donnée. *
* *
-* Retour : None. *
+* Retour : Nombre de ces origines. *
* *
* Remarques : - *
* *
******************************************************************************/
-static PyObject *py_arch_instruction_attach_extra_operand(PyObject *self, PyObject *args)
+static PyObject *py_arch_instruction_get_sources(PyObject *self, void *unused)
{
- GArchOperand *op; /* Opérande concerné à ajouter */
- int ret; /* Bilan de lecture des args. */
- GArchInstruction *instr; /* Instruction manipulée */
+ PyObject *result; /* Instance à retourner */
+ GArchInstruction *instr; /* Version native */
+ size_t count; /* Nombre de liens présents */
+ size_t i; /* Boucle de parcours */
- ret = PyArg_ParseTuple(args, "O&", convert_to_arch_operand, &op);
- if (!ret) return NULL;
+
+ GArchInstruction *src; /* Instruction en source */
+ InstructionLinkType src_type; /* Type de lien */
+ PyObject *linked; /* Source de lien Python */
+ PyObject *lnk_type; /* Nature du lien en Python */
+#ifndef NDEBUG
+ int ret; /* Bilan d'une écriture d'arg. */
+#endif
+
+#define ARCH_INSTRUCTION_SOURCES_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ sources, py_arch_instruction, \
+ "Provide the instructions list driving to the current instruction.\n" \
+ "\n" \
+ "Each item of the resulting tuple is a pair of" \
+ " pychrysalide.arch.ArchInstruction instance and" \
+ " pychrysalide.arch.ArchInstruction.InstructionLinkType value." \
+)
instr = G_ARCH_INSTRUCTION(pygobject_get(self));
- g_object_ref(G_OBJECT(op));
+ g_thick_object_lock(G_THICK_OBJECT(instr));
+
+ count = g_arch_instruction_count_src_links(instr);
+
+ result = PyTuple_New(count);
+
+ for (i = 0; i < count; i++)
+ {
+ src = g_arch_instruction_get_linked_source(instr, i, &src_type);
+
+ linked = pygobject_new(G_OBJECT(src));
+ lnk_type = cast_with_constants_group_from_type(get_python_arch_instruction_type(),
+ "InstructionLinkType", src_type);
+
+#ifndef NDEBUG
+ ret = PyTuple_SetItem(result, i, Py_BuildValue("(OO)", linked, lnk_type));
+ assert(ret == 0);
+#else
+ PyTuple_SetItem(result, i, Py_BuildValue("(OO)", linked, lnk_type));
+#endif
+
+ unref_object(src);
+
+ }
- g_arch_instruction_attach_extra_operand(instr, op);
+ g_thick_object_unlock(G_THICK_OBJECT(instr));
- Py_RETURN_NONE;
+ return result;
}
/******************************************************************************
* *
-* Paramètres : self = objet représentant une instruction. *
+* Paramètres : self = instruction d'architecture à manipuler. *
* unused = adresse non utilisée ici. *
* *
-* Description : Fournit tous les opérandes d'une instruction. *
+* Description : Fournit les destinations d'une instruction donnée. *
* *
-* Retour : Valeur associée à la propriété consultée. *
+* Retour : Nombre de ces destinations. *
* *
* Remarques : - *
* *
******************************************************************************/
-static PyObject *py_arch_instruction_get_operands(PyObject *self, void *unused)
+static PyObject *py_arch_instruction_get_destinations(PyObject *self, void *unused)
{
PyObject *result; /* Instance à retourner */
GArchInstruction *instr; /* Version native */
- size_t count; /* Nombre d'opérandes présents */
+ size_t count; /* Nombre de liens présents */
size_t i; /* Boucle de parcours */
- GArchOperand *operand; /* Opérande à manipuler */
- PyObject *opobj; /* Version Python */
+ GArchInstruction *dest; /* Instruction en source */
+ InstructionLinkType dest_type; /* Type de lien */
+ PyObject *linked; /* Destination de lien Python */
+ PyObject *lnk_type; /* Nature du lien en Python */
#ifndef NDEBUG
int ret; /* Bilan d'une écriture d'arg. */
#endif
+#define ARCH_INSTRUCTION_DESTINATIONS_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ destinations, py_arch_instruction, \
+ "Provide the instructions list following the current instruction.\n" \
+ "\n" \
+ "Each item of the resulting tuple is a pair of" \
+ " pychrysalide.arch.ArchInstruction instance and" \
+ " pychrysalide.arch.ArchInstruction.InstructionLinkType value." \
+)
+
instr = G_ARCH_INSTRUCTION(pygobject_get(self));
- g_arch_instruction_lock_operands(instr);
+ g_thick_object_lock(G_THICK_OBJECT(instr));
- count = _g_arch_instruction_count_operands(instr);
+ count = g_arch_instruction_count_dest_links(instr);
result = PyTuple_New(count);
for (i = 0; i < count; i++)
{
- operand = _g_arch_instruction_get_operand(instr, i);
+ dest = g_arch_instruction_get_linked_destination(instr, i, &dest_type);
- opobj = pygobject_new(G_OBJECT(operand));
+ linked = pygobject_new(G_OBJECT(dest));
+ lnk_type = cast_with_constants_group_from_type(get_python_arch_instruction_type(),
+ "InstructionLinkType", dest_type);
#ifndef NDEBUG
- ret = PyTuple_SetItem(result, i, Py_BuildValue("O", opobj));
+ ret = PyTuple_SetItem(result, i, Py_BuildValue("(OO)", linked, lnk_type));
assert(ret == 0);
#else
- PyTuple_SetItem(result, i, Py_BuildValue("O", opobj));
+ PyTuple_SetItem(result, i, Py_BuildValue("(OO)", linked, lnk_type));
#endif
- g_object_unref(G_OBJECT(operand));
+ unref_object(dest);
}
- g_arch_instruction_unlock_operands(instr);
+ g_thick_object_unlock(G_THICK_OBJECT(instr));
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* MANIPULATION DES OPERANDES */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : self = architecture concernée par la procédure. *
+* args = instruction représentant le point de départ. *
+* *
+* Description : Attache un opérande supplémentaire à une instruction. *
+* *
+* Retour : None. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_arch_instruction_attach_operand(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Bilan à retourner */
+ GArchOperand *op; /* Opérande concerné à ajouter */
+ int ret; /* Bilan de lecture des args. */
+ GArchInstruction *instr; /* Instruction manipulée */
+
+#define ARCH_INSTRUCTION_ATTACH_OPERAND_METHOD PYTHON_METHOD_DEF \
+( \
+ attach_operand, "$self, operand, /", \
+ METH_VARARGS, py_arch_instruction, \
+ "Add an extra operand to an instruction.\n" \
+ "\n" \
+ "The instruction has to be locked during the instruction.\n" \
+ "\n" \
+ "The *operand* argument has to be a pychrysalide.arch.ArchOperand" \
+ " instance." \
+)
+
+ ret = PyArg_ParseTuple(args, "O&", convert_to_arch_operand, &op);
+ if (!ret) return NULL;
+
+ instr = G_ARCH_INSTRUCTION(pygobject_get(self));
+
+ g_arch_instruction_attach_operand(instr, op);
+
+ result = Py_None;
+ Py_INCREF(result);
return result;
@@ -342,6 +555,21 @@ static PyObject *py_arch_instruction_replace_operand(PyObject *self, PyObject *a
GArchInstruction *instr; /* Instruction manipulée */
bool status; /* Bilan de l'opération */
+#define ARCH_INSTRUCTION_REPLACE_OPERAND_METHOD PYTHON_METHOD_DEF \
+( \
+ replace_operand, "$self, old, new, /", \
+ METH_VARARGS, py_arch_instruction, \
+ "Replace an old instruction operand by a another one.\n" \
+ "\n" \
+ "The instruction has to be locked during the instruction.\n" \
+ "\n" \
+ "Both the *old* and *new* arguments have to be a" \
+ " pychrysalide.arch.ArchOperand instance.\n" \
+ "\n" \
+ "The status of the operation is returned as a boolean value: *True*"\
+ " if the operand has been replaced, *False* in case of failure." \
+)
+
ret = PyArg_ParseTuple(args, "O&O&", convert_to_arch_operand, &old, convert_to_arch_operand, &new);
if (!ret) return NULL;
@@ -349,9 +577,6 @@ static PyObject *py_arch_instruction_replace_operand(PyObject *self, PyObject *a
status = g_arch_instruction_replace_operand(instr, old, new);
- if (status)
- g_object_ref(G_OBJECT(new));
-
result = status ? Py_True : Py_False;
Py_INCREF(result);
@@ -381,6 +606,21 @@ static PyObject *py_arch_instruction_detach_operand(PyObject *self, PyObject *ar
GArchInstruction *instr; /* Instruction manipulée */
bool status; /* Bilan de l'opération */
+#define ARCH_INSTRUCTION_DETACH_OPERAND_METHOD PYTHON_METHOD_DEF \
+( \
+ detach_operand, "$self, operand, /", \
+ METH_VARARGS, py_arch_instruction, \
+ "Remove an operand from the instruction.\n" \
+ "\n" \
+ "The instruction has to be locked during the instruction.\n" \
+ "\n" \
+ "The *operand* argument has to be a pychrysalide.arch.ArchOperand" \
+ " instance.\n" \
+ "\n" \
+ "The status of the operation is returned as a boolean value: *True*"\
+ " if the operand has been removed, *False* in case of failure." \
+)
+
ret = PyArg_ParseTuple(args, "O&", convert_to_arch_operand, &target);
if (!ret) return NULL;
@@ -500,7 +740,7 @@ static PyObject *py_arch_instruction_get_operand_from_path(PyObject *self, PyObj
if (op != NULL)
{
result = pygobject_new(G_OBJECT(op));
- g_object_unref(G_OBJECT(op));
+ unref_object(op);
}
else
{
@@ -513,182 +753,258 @@ static PyObject *py_arch_instruction_get_operand_from_path(PyObject *self, PyObj
}
-
-/* ---------------------------------------------------------------------------------- */
-/* DEFINITION DES LIAISONS ENTRE INSTRUCTIONS */
-/* ---------------------------------------------------------------------------------- */
-
-
/******************************************************************************
* *
-* Paramètres : self = instruction d'architecture à manipuler. *
+* Paramètres : self = objet représentant une instruction. *
* unused = adresse non utilisée ici. *
* *
-* Description : Fournit les origines d'une instruction donnée. *
+* Description : Fournit tous les opérandes d'une instruction. *
* *
-* Retour : Nombre de ces origines. *
+* Retour : Valeur associée à la propriété consultée. *
* *
* Remarques : - *
* *
******************************************************************************/
-static PyObject *py_arch_instruction_get_sources(PyObject *self, void *unused)
+static PyObject *py_arch_instruction_get_operands(PyObject *self, void *unused)
{
PyObject *result; /* Instance à retourner */
GArchInstruction *instr; /* Version native */
- size_t count; /* Nombre de liens présents */
+ size_t count; /* Nombre d'opérandes présents */
size_t i; /* Boucle de parcours */
- const instr_link_t *source; /* Origine des liens */
- PyObject *linked; /* Source de lien Python */
- PyObject *type; /* Nature du lien en Python */
+ GArchOperand *operand; /* Opérande à manipuler */
+ PyObject *opobj; /* Version Python */
#ifndef NDEBUG
int ret; /* Bilan d'une écriture d'arg. */
#endif
-#define ARCH_INSTRUCTION_SOURCES_ATTRIB PYTHON_GET_DEF_FULL \
-( \
- sources, py_arch_instruction, \
- "Provide the instructions list driving to the current instruction.\n" \
- "\n" \
- "Each item of the resulting tuple is a pair of" \
- " pychrysalide.arch.ArchInstruction instance and" \
- " pychrysalide.arch.ArchInstruction.InstructionLinkType value." \
+#define ARCH_INSTRUCTION_OPERANDS_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ operands, py_arch_instruction, \
+ "List of instruction attached operands.\n" \
+ "\n" \
+ "The result is a list of pychrysalide.arch.ArchOperand" \
+ " instances, which can be empty." \
)
instr = G_ARCH_INSTRUCTION(pygobject_get(self));
- g_arch_instruction_lock_src(instr);
+ g_thick_object_lock(G_THICK_OBJECT(instr));
- count = g_arch_instruction_count_sources(instr);
+ count = g_arch_instruction_count_operands(instr);
result = PyTuple_New(count);
for (i = 0; i < count; i++)
{
- source = g_arch_instruction_get_source(instr, i);
+ operand = g_arch_instruction_get_operand(instr, i);
- linked = pygobject_new(G_OBJECT(source->linked));
- type = cast_with_constants_group_from_type(get_python_arch_instruction_type(),
- "InstructionLinkType", source->type);
+ opobj = pygobject_new(G_OBJECT(operand));
#ifndef NDEBUG
- ret = PyTuple_SetItem(result, i, Py_BuildValue("(OO)", linked, type));
+ ret = PyTuple_SetItem(result, i, Py_BuildValue("O", opobj));
assert(ret == 0);
#else
- PyTuple_SetItem(result, i, Py_BuildValue("(OO)", linked, type));
+ PyTuple_SetItem(result, i, Py_BuildValue("O", opobj));
#endif
- unref_instr_link(source);
+ unref_object(operand);
}
- g_arch_instruction_unlock_src(instr);
+ g_thick_object_unlock(G_THICK_OBJECT(instr));
return result;
}
+
+/* ---------------------------------------------------------------------------------- */
+/* LIAISON DE FONCTIONNALITES AVEC L'API PYTHON */
+/* ---------------------------------------------------------------------------------- */
+
+
/******************************************************************************
* *
-* Paramètres : self = instruction d'architecture à manipuler. *
-* unused = adresse non utilisée ici. *
+* Paramètres : self = architecture concernée par la procédure. *
+* args = instruction représentant le point de départ. *
* *
-* Description : Fournit les destinations d'une instruction donnée. *
+* Description : Ajoute une information complémentaire à une instruction. *
* *
-* Retour : Nombre de ces destinations. *
+* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
-static PyObject *py_arch_instruction_get_destinations(PyObject *self, void *unused)
+static PyObject *py_arch_instruction_set_flag(PyObject *self, PyObject *args)
{
- PyObject *result; /* Instance à retourner */
- GArchInstruction *instr; /* Version native */
- size_t count; /* Nombre de liens présents */
- size_t i; /* Boucle de parcours */
- const instr_link_t *dest; /* Destination des liens */
- PyObject *linked; /* Destination de lien Python */
- PyObject *type; /* Nature du lien en Python */
-#ifndef NDEBUG
- int ret; /* Bilan d'une écriture d'arg. */
-#endif
-
-#define ARCH_INSTRUCTION_DESTINATIONS_ATTRIB PYTHON_GET_DEF_FULL \
-( \
- destinations, py_arch_instruction, \
- "Provide the instructions list following the current instruction.\n" \
- "\n" \
- "Each item of the resulting tuple is a pair of" \
- " pychrysalide.arch.ArchInstruction instance and" \
- " pychrysalide.arch.ArchInstruction.InstructionLinkType value." \
+ PyObject *result; /* Bilan à retourner */
+ unsigned int flag; /* Fanion(s) à appliquer */
+ int ret; /* Bilan de lecture des args. */
+ GArchInstruction *instr; /* Instruction manipulée */
+ bool status; /* Bilan à transmettre */
+
+#define ARCH_INSTRUCTION_SET_FLAG_METHOD PYTHON_METHOD_DEF \
+( \
+ set_flag, "$self, flag, /", \
+ METH_VARARGS, py_arch_instruction, \
+ "Add some flags to the instruction.\n" \
+ "\n" \
+ "This *flag* argument is an integer value containing" \
+ " bits to apply to the instruction state.\n" \
+ "\n" \
+ "The result is an boolean status: *True* for operation" \
+ " success, *False* otherwise." \
)
+ ret = PyArg_ParseTuple(args, "I", &flag);
+ if (!ret) return NULL;
+
instr = G_ARCH_INSTRUCTION(pygobject_get(self));
- g_arch_instruction_lock_dest(instr);
+ status = g_arch_instruction_set_flag(instr, flag);
- count = g_arch_instruction_count_destinations(instr);
+ result = status ? Py_True : Py_False;
+ Py_INCREF(result);
- result = PyTuple_New(count);
+ return result;
- for (i = 0; i < count; i++)
- {
- dest = g_arch_instruction_get_destination(instr, i);
+}
- linked = pygobject_new(G_OBJECT(dest->linked));
- type = cast_with_constants_group_from_type(get_python_arch_instruction_type(),
- "InstructionLinkType", dest->type);
-#ifndef NDEBUG
- ret = PyTuple_SetItem(result, i, Py_BuildValue("(OO)", linked, type));
- assert(ret == 0);
-#else
- PyTuple_SetItem(result, i, Py_BuildValue("(OO)", linked, type));
-#endif
+/******************************************************************************
+* *
+* Paramètres : self = architecture concernée par la procédure. *
+* args = instruction représentant le point de départ. *
+* *
+* Description : Retire une information complémentaire à une instruction. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_arch_instruction_unset_flag(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Bilan à retourner */
+ unsigned int flag; /* Fanion(s) à appliquer */
+ int ret; /* Bilan de lecture des args. */
+ GArchInstruction *instr; /* Instruction manipulée */
+ bool status; /* Bilan à transmettre */
+
+#define ARCH_INSTRUCTION_UNSET_FLAG_METHOD PYTHON_METHOD_DEF \
+( \
+ unset_flag, "$self, flag, /", \
+ METH_VARARGS, py_arch_instruction, \
+ "Remove some flags from the instruction.\n" \
+ "\n" \
+ "This *flag* argument is an integer value containing" \
+ " bits to delete from the instruction state.\n" \
+ "\n" \
+ "The result is an boolean status: *True* for operation" \
+ " success, *False* otherwise." \
+)
- unref_instr_link(dest);
+ ret = PyArg_ParseTuple(args, "I", &flag);
+ if (!ret) return NULL;
- }
+ instr = G_ARCH_INSTRUCTION(pygobject_get(self));
- g_arch_instruction_unlock_dest(instr);
+ status = g_arch_instruction_unset_flag(instr, flag);
+
+ result = status ? Py_True : Py_False;
+ Py_INCREF(result);
return result;
}
+/******************************************************************************
+* *
+* Paramètres : self = architecture concernée par la procédure. *
+* args = instruction représentant le point de départ. *
+* *
+* Description : Détermine si une instruction possède un fanion particulier. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
-/* ---------------------------------------------------------------------------------- */
-/* INSTRUCTIONS D'ARCHITECTURES EN PYTHON */
-/* ---------------------------------------------------------------------------------- */
+static PyObject *py_arch_instruction_has_flag(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Bilan à retourner */
+ unsigned int flag; /* Fanion(s) à appliquer */
+ int ret; /* Bilan de lecture des args. */
+ GArchInstruction *instr; /* Instruction manipulée */
+ bool status; /* Bilan à transmettre */
+
+#define ARCH_INSTRUCTION_HAS_FLAG_METHOD PYTHON_METHOD_DEF \
+( \
+ has_flag, "$self, flag, /", \
+ METH_VARARGS, py_arch_instruction, \
+ "Tell if some flags are set for the instruction.\n" \
+ "\n" \
+ "This *flag* argument is an integer value containing" \
+ " bits to test for the instruction state.\n" \
+ "\n" \
+ "The result is an boolean status: *True* if the bits" \
+ " are active, *False* otherwise." \
+)
+
+ ret = PyArg_ParseTuple(args, "I", &flag);
+ if (!ret) return NULL;
+
+ instr = G_ARCH_INSTRUCTION(pygobject_get(self));
+
+ status = g_arch_instruction_has_flag(instr, flag);
+
+ result = status ? Py_True : Py_False;
+ Py_INCREF(result);
+
+ return result;
+
+}
/******************************************************************************
* *
-* Paramètres : self = classe représentant une instruction. *
-* closure = adresse non utilisée ici. *
+* Paramètres : self = objet Python concerné par l'appel. *
+* closure = non utilisé ici. *
* *
-* Description : Fournit l'identifiant unique pour un ensemble d'instructions.*
+* Description : Fournit l'identifiant correspondant à un type d'instructions.*
* *
-* Retour : Identifiant unique par type d'instruction. *
+* Retour : Identifiant unique par type d'instruction et architecture. *
* *
* Remarques : - *
* *
******************************************************************************/
-static PyObject *py_arch_instruction_get_unique_id(PyObject *self, void *closure)
+static PyObject *py_arch_instruction_get_type_id(PyObject *self, void *closure)
{
- PyObject *result; /* Conversion à retourner */
- GArchInstruction *instr; /* Version native */
- itid_t uid; /* Identifiant unique associé */
+ PyObject *result; /* Valeur à retourner */
+ GArchInstruction *instr; /* Instruction manipulée */
+ itid_t tid; /* Identifiant à transmettre */
+
+#define ARCH_INSTRUCTION_TYPE_ID_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ type_id, py_arch_instruction, \
+ "Provide the unique identifier given to this kind of" \
+ " instruction.\n" \
+ "\n" \
+ "The returned value is an integer." \
+)
instr = G_ARCH_INSTRUCTION(pygobject_get(self));
- uid = g_arch_instruction_get_unique_id(instr);
+ tid = g_arch_instruction_get_type_id(instr);
- result = PyLong_FromUnsignedLong(uid);
+ result = PyLong_FromUnsignedLong(tid);
return result;
@@ -697,27 +1013,61 @@ static PyObject *py_arch_instruction_get_unique_id(PyObject *self, void *closure
/******************************************************************************
* *
-* Paramètres : self = classe représentant une instruction. *
-* closure = adresse non utilisée ici. *
+* Paramètres : self = objet Python concerné par l'appel. *
+* closure = non utilisé ici. *
* *
-* Description : Fournit la place mémoire d'une instruction. *
+* Description : Indique l'encodage d'une instruction de façon détaillée. *
* *
-* Retour : Valeur associée à la propriété consultée. *
+* Retour : Description humaine de l'encodage utilisé. *
* *
* Remarques : - *
* *
******************************************************************************/
-static PyObject *py_arch_instruction_get_range(PyObject *self, void *closure)
+static PyObject *py_arch_instruction_get_encoding(PyObject *self, void *closure)
{
- PyObject *result; /* Conversion à retourner */
- GArchInstruction *instr; /* Version native */
- const mrange_t *range; /* Espace mémoire à exporter */
+ PyObject *result; /* Valeur à retourner */
+ GArchInstruction *instr; /* Instruction manipulée */
+ char *encoding; /* Encodage d'une instruction */
+
+#define ARCH_INSTRUCTION_ENCODING_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ encoding, py_arch_instruction, \
+ "Describe the encoding related to an instruction.\n" \
+ "\n" \
+ "The returned value is an arbitrary string value." \
+)
instr = G_ARCH_INSTRUCTION(pygobject_get(self));
- range = g_arch_instruction_get_range(instr);
- result = build_from_internal_mrange(range);
+ encoding = g_arch_instruction_get_encoding(instr);
+
+ if (encoding != NULL)
+ {
+ result = PyUnicode_FromString(encoding);
+
+ free(encoding);
+
+ }
+
+ else
+ {
+ /**
+ * La méthode de classe sollicitée a renvoyé une valeur nulle.
+ *
+ * Si cette méthode correspond à une implémentation Python
+ * (avec un appel à not_yet_implemented_method()), une exception
+ * est déjà en place.
+ *
+ * Si aucune exception n'a été prévue, un rattrapage est effectué ici.
+ */
+
+ if (PyErr_Occurred() == NULL)
+ PyErr_SetString(PyExc_NotImplementedError, _("unexpected NULL value as encoding"));
+
+ result = NULL;
+
+ }
return result;
@@ -727,59 +1077,108 @@ static PyObject *py_arch_instruction_get_range(PyObject *self, void *closure)
/******************************************************************************
* *
* Paramètres : self = objet Python concerné par l'appel. *
-* value = valeur fournie à intégrer ou prendre en compte. *
-* closure = adresse non utilisée ici. *
+* closure = non utilisé ici. *
* *
-* Description : Définit la localisation d'une instruction. *
+* Description : Indique l'encodage d'une instruction de façon détaillée. *
* *
-* Retour : Bilan de l'opération pour Python. *
+* Retour : Description humaine de l'encodage utilisé. *
* *
* Remarques : - *
* *
******************************************************************************/
-static int py_arch_instruction_set_range(PyObject *self, PyObject *value, void *closure)
+static PyObject *py_arch_instruction_get_keyword(PyObject *self, void *closure)
{
- int ret; /* Bilan d'analyse */
- mrange_t *range; /* Espace mémoire à manipuler */
- GArchInstruction *instr; /* Version native */
+ PyObject *result; /* Valeur à retourner */
+ GArchInstruction *instr; /* Instruction manipulée */
+ char *keyword; /* Désignation d'une instruct° */
+
+#define ARCH_INSTRUCTION_KEYWORD_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ keyword, py_arch_instruction, \
+ "Give the official name of the assembly instruction.\n" \
+ "\n" \
+ "The returned value is a string value." \
+)
- ret = PyObject_IsInstance(value, (PyObject *)get_python_mrange_type());
- if (!ret) return -1;
+ instr = G_ARCH_INSTRUCTION(pygobject_get(self));
- range = get_internal_mrange(value);
+ keyword = g_arch_instruction_get_keyword(instr);
- instr = G_ARCH_INSTRUCTION(pygobject_get(self));
- g_arch_instruction_set_range(instr, range);
+ if (keyword != NULL)
+ {
+ result = PyUnicode_FromString(keyword);
- return 0;
+ free(keyword);
+
+ }
+
+ else
+ {
+ /**
+ * La méthode de classe sollicitée a renvoyé une valeur nulle.
+ *
+ * Si cette méthode correspond à une implémentation Python
+ * (avec un appel à not_yet_implemented_method()), une exception
+ * est déjà en place.
+ *
+ * Si aucune exception n'a été prévue, un rattrapage est effectué ici.
+ */
+
+ if (PyErr_Occurred() == NULL)
+ PyErr_SetString(PyExc_NotImplementedError, _("unexpected NULL value as keyword"));
+
+ result = NULL;
+
+ }
+
+ return result;
}
/******************************************************************************
* *
-* Paramètres : self = classe représentant une instruction. *
-* unused = adresse non utilisée ici. *
+* Paramètres : self = objet Python concerné par l'appel. *
+* closure = non utilisé ici. *
* *
-* Description : Fournit le nom humain de l'instruction manipulée. *
+* Description : Fournit la place mémoire d'une instruction. *
* *
-* Retour : Valeur associée à la propriété consultée. *
+* Retour : Définition de localisation ou *None*. *
* *
* Remarques : - *
* *
******************************************************************************/
-static PyObject *py_arch_instruction_get_keyword(PyObject *self, void *unused)
+static PyObject *py_arch_instruction_get_range(PyObject *self, void *closure)
{
- PyObject *result; /* Trouvailles à retourner */
- GArchInstruction *instr; /* Version native */
- const char *kw; /* Valeur récupérée */
+ PyObject *result; /* Valeur à retourner */
+ GArchInstruction *instr; /* Instruction manipulée */
+ mrange_t range; /* Localisation d'instruction */
+ bool valid; /* Validité de la localisation */
+
+#define ARCH_INSTRUCTION_RANGE_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ range, py_arch_instruction, \
+ "Give access to the memory range covered by the" \
+ " current instruction.\n" \
+ "\n" \
+ "The returned value is a pychrysalide.arch.mrange" \
+ " instance or *None* if no location is currently" \
+ " defined." \
+)
instr = G_ARCH_INSTRUCTION(pygobject_get(self));
- kw = g_arch_instruction_get_keyword(instr);
- result = PyUnicode_FromString(kw);
+ valid = g_arch_instruction_get_range(instr, &range);
+
+ if (valid)
+ result = build_from_internal_mrange(&range);
+ else
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
return result;
@@ -801,45 +1200,25 @@ static PyObject *py_arch_instruction_get_keyword(PyObject *self, void *unused)
PyTypeObject *get_python_arch_instruction_type(void)
{
static PyMethodDef py_arch_instruction_methods[] = {
- {
- "attach_operand", py_arch_instruction_attach_extra_operand,
- METH_VARARGS,
- "attach_operand($self, op, /)\n--\n\nAdd a new operand to the instruction."
- },
- {
- "replace_operand", py_arch_instruction_replace_operand,
- METH_VARARGS,
- "replace_operand($self, old, new, /)\n--\n\nReplace an old instruction operand by a another one."
- },
- {
- "detach_operand", py_arch_instruction_detach_operand,
- METH_VARARGS,
- "detach_operand($self, target, /)\n--\n\nRemove an operand from the instruction."
- },
+ ARCH_INSTRUCTION_ATTACH_OPERAND_METHOD,
+ ARCH_INSTRUCTION_REPLACE_OPERAND_METHOD,
+ ARCH_INSTRUCTION_DETACH_OPERAND_METHOD,
ARCH_INSTRUCTION_FIND_OPERAND_PATH_METHOD,
ARCH_INSTRUCTION_GET_OPERAND_FROM_PATH_METHOD,
+ ARCH_INSTRUCTION_SET_FLAG_METHOD,
+ ARCH_INSTRUCTION_UNSET_FLAG_METHOD,
+ ARCH_INSTRUCTION_HAS_FLAG_METHOD,
{ NULL }
};
static PyGetSetDef py_arch_instruction_getseters[] = {
- {
- "uid", py_arch_instruction_get_unique_id, NULL,
- "Provide the unique identification number given to this kind of instruction.", NULL
- },
- {
- "range", py_arch_instruction_get_range, py_arch_instruction_set_range,
- "Give access to the memory range covered by the current instruction.", NULL
- },
- {
- "keyword", (getter)py_arch_instruction_get_keyword, (setter)NULL,
- "Give le name of the assembly instruction.", NULL
- },
- {
- "operands", (getter)py_arch_instruction_get_operands, (setter)NULL,
- "Provide the list of instruction attached operands.", NULL
- },
ARCH_INSTRUCTION_SOURCES_ATTRIB,
ARCH_INSTRUCTION_DESTINATIONS_ATTRIB,
+ ARCH_INSTRUCTION_OPERANDS_ATTRIB,
+ ARCH_INSTRUCTION_TYPE_ID_ATTRIB,
+ ARCH_INSTRUCTION_ENCODING_ATTRIB,
+ ARCH_INSTRUCTION_KEYWORD_ATTRIB,
+ ARCH_INSTRUCTION_RANGE_ATTRIB,
{ NULL }
};
@@ -852,7 +1231,7 @@ PyTypeObject *get_python_arch_instruction_type(void)
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_BASETYPE,
- .tp_doc = "PyChrysalide instruction for a given architecture.",
+ .tp_doc = ARCH_INSTRUCTION_DOC,
.tp_methods = py_arch_instruction_methods,
.tp_getset = py_arch_instruction_getseters,
@@ -893,9 +1272,14 @@ bool ensure_python_arch_instruction_is_registered(void)
dict = PyModule_GetDict(module);
- if (!ensure_python_line_generator_is_registered())
+ if (!ensure_python_thick_object_is_registered())
return false;
+ if (!ensure_python_serializable_object_is_registered())
+ return false;
+
+ pyg_register_class_init(G_TYPE_ARCH_INSTRUCTION, (PyGClassInitFunc)py_arch_instruction_init_gclass);
+
if (!register_class_for_pygobject(dict, G_TYPE_ARCH_INSTRUCTION, type))
return false;
diff --git a/plugins/pychrysalide/arch/instructions/Makefile.am b/plugins/pychrysalide/arch/instructions/Makefile.am
index 65efe42..29c2a45 100644
--- a/plugins/pychrysalide/arch/instructions/Makefile.am
+++ b/plugins/pychrysalide/arch/instructions/Makefile.am
@@ -7,7 +7,8 @@ libpychrysaarchinstructions_la_SOURCES = \
raw.h raw.c \
undefined.h undefined.c
-libpychrysaarchinstructions_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+libpychrysaarchinstructions_la_CFLAGS = $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+ $(TOOLKIT_CFLAGS) \
-I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
diff --git a/plugins/pychrysalide/arch/instructions/constants.c b/plugins/pychrysalide/arch/instructions/constants.c
index af7baa9..257c501 100644
--- a/plugins/pychrysalide/arch/instructions/constants.c
+++ b/plugins/pychrysalide/arch/instructions/constants.c
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* constants.c - ajout des constantes de base pour les instructions
*
- * Copyright (C) 2020 Cyrille Bagard
+ * Copyright (C) 2020-2025 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -112,3 +112,59 @@ bool define_undefined_instruction_constants(PyTypeObject *type)
return result;
}
+
+
+/******************************************************************************
+* *
+* Paramètres : arg = argument quelconque à tenter de convertir. *
+* dst = destination des valeurs récupérées en cas de succès. *
+* *
+* Description : Tente de convertir en constante ExpectedBehavior. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_undefined_expected_behavior(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+ unsigned long value; /* Valeur récupérée */
+
+ result = PyObject_IsInstance(arg, (PyObject *)&PyLong_Type);
+
+ switch (result)
+ {
+ case -1:
+ /* L'exception est déjà fixée par Python */
+ result = 0;
+ break;
+
+ case 0:
+ PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to ExpectedBehavior");
+ break;
+
+ case 1:
+ value = PyLong_AsUnsignedLong(arg);
+
+ if (value > IEB_RESERVED)
+ {
+ PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to ExpectedBehavior");
+ result = 0;
+ }
+
+ else
+ *((InstrExpectedBehavior *)dst) = value;
+
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/arch/instructions/constants.h b/plugins/pychrysalide/arch/instructions/constants.h
index 2f0c587..b6ef9a4 100644
--- a/plugins/pychrysalide/arch/instructions/constants.h
+++ b/plugins/pychrysalide/arch/instructions/constants.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* constants.h - prototypes pour l'ajout des constantes de base pour les instructions
*
- * Copyright (C) 2020 Cyrille Bagard
+ * Copyright (C) 2020-2025 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -37,6 +37,9 @@ bool define_raw_instruction_constants(PyTypeObject *);
/* Définit les constantes liées aux comportements erratiques. */
bool define_undefined_instruction_constants(PyTypeObject *);
+/* Tente de convertir en constante ExpectedBehavior. */
+int convert_to_undefined_expected_behavior(PyObject *, void *);
+
#endif /* _PLUGINS_PYCHRYSALIDE_ARCH_INSTRUCTIONS_CONSTANTS_H */
diff --git a/plugins/pychrysalide/arch/instructions/raw.c b/plugins/pychrysalide/arch/instructions/raw.c
index 7e58b96..ae730e8 100644
--- a/plugins/pychrysalide/arch/instructions/raw.c
+++ b/plugins/pychrysalide/arch/instructions/raw.c
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* raw.c - équivalent Python du fichier "arch/instructions/raw.h"
*
- * Copyright (C) 2018-2020 Cyrille Bagard
+ * Copyright (C) 2018-2025 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -28,26 +28,33 @@
#include <pygobject.h>
-#include <i18n.h>
-#include <arch/instructions/raw.h>
-#include <plugins/dt.h>
+#include <arch/instructions/raw-int.h>
#include "constants.h"
#include "../instruction.h"
#include "../vmpa.h"
#include "../../access.h"
+#include "../../constants.h"
#include "../../helpers.h"
#include "../../analysis/content.h"
+#include "../../glibext/portion.h"
-/* Accompagne la création d'une instance dérivée en Python. */
-static PyObject *py_raw_instruction_new(PyTypeObject *, PyObject *, PyObject *);
+/* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */
+
+
+CREATE_DYN_CONSTRUCTOR(raw_instruction, G_TYPE_RAW_INSTRUCTION);
/* Initialise une instance sur la base du dérivé de GObject. */
static int py_raw_instruction_init(PyObject *, PyObject *, PyObject *);
+
+
+/* ------------------------ FONCTIONNALITES DE L'INSTRUCTION ------------------------ */
+
+
/* Indique si le contenu de l'instruction est du bourrage. */
static PyObject *py_raw_instruction_get_padding(PyObject *, void *);
@@ -62,64 +69,9 @@ static int py_raw_instruction_set_string(PyObject *, PyObject *, void *);
-/******************************************************************************
-* *
-* Paramètres : type = type du nouvel objet à mettre en place. *
-* args = éventuelle liste d'arguments. *
-* kwds = éventuel dictionnaire de valeurs mises à disposition. *
-* *
-* Description : Accompagne la création d'une instance dérivée en Python. *
-* *
-* Retour : Nouvel objet Python mis en place ou NULL en cas d'échec. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static PyObject *py_raw_instruction_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
- PyObject *result; /* Objet à retourner */
- PyTypeObject *base; /* Type de base à dériver */
- bool first_time; /* Evite les multiples passages*/
- GType gtype; /* Nouveau type de processeur */
- bool status; /* Bilan d'un enregistrement */
-
- /* Validations diverses */
-
- base = get_python_raw_instruction_type();
-
- if (type == base)
- goto simple_way;
-
- /* Mise en place d'un type dédié */
-
- first_time = (g_type_from_name(type->tp_name) == 0);
-
- gtype = build_dynamic_type(G_TYPE_RAW_INSTRUCTION, type->tp_name, NULL, NULL, NULL);
-
- if (first_time)
- {
- status = register_class_for_dynamic_pygobject(gtype, type);
-
- if (!status)
- {
- result = NULL;
- goto exit;
- }
-
- }
-
- /* On crée, et on laisse ensuite la main à PyGObject_Type.tp_init() */
-
- simple_way:
-
- result = PyType_GenericNew(type, args, kwds);
-
- exit:
-
- return result;
-
-}
+/* ---------------------------------------------------------------------------------- */
+/* GLUE POUR CREATION DEPUIS PYTHON */
+/* ---------------------------------------------------------------------------------- */
/******************************************************************************
@@ -139,20 +91,17 @@ static PyObject *py_raw_instruction_new(PyTypeObject *type, PyObject *args, PyOb
static int py_raw_instruction_init(PyObject *self, PyObject *args, PyObject *kwds)
{
int result; /* Bilan à retourner */
+ GBinaryPortion *area; /* Zone de contenance */
vmpa2t *addr; /* Texte de lecture */
- unsigned long mem_size; /* Taille de portion brute */
+ MemoryDataSize size; /* Taille de portion brute */
unsigned long long value; /* Valeur brute à considérer */
GBinContent *content; /* Contenu à lire au besoin */
unsigned long count; /* Nombre d'éléments à lister */
- unsigned int endian; /* Type de boutisme impliqué */
+ SourceEndian endian; /* Type de boutisme impliqué */
int ret; /* Bilan de lecture des args. */
- GArchInstruction *fake; /* Instruction à copier */
- GArchInstruction *instr; /* Instruction à manipuler */
- size_t op_count; /* Nombre d'opérande à copier */
- size_t i; /* Boucle de parcours */
- GArchOperand *op; /* Opérande à transférer */
+ GRawInstruction *instr; /* Instruction à manipuler */
- static char *kwlist[] = { "addr", "mem_size", "value", "content", "count", "endian", NULL };
+ static char *kwlist[] = { "area", "addr", "size", "value", "content", "count", "endian", NULL };
#define RAW_INSTRUCTION_DOC \
"The RawInstruction object handles data which is not (yet?) disassembled" \
@@ -187,9 +136,14 @@ static int py_raw_instruction_init(PyObject *self, PyObject *args, PyObject *kwd
count = 0;
endian = 0;
- ret = PyArg_ParseTupleAndKeywords(args, kwds, "O&k|KO&kI", kwlist,
- convert_any_to_vmpa, &addr, &mem_size,
- &value, convert_to_binary_content, &content, &count, &endian);
+ ret = PyArg_ParseTupleAndKeywords(args, kwds, "O&O&O&|KO&kO&", kwlist,
+ convert_to_binary_portion, &area,
+ convert_any_to_vmpa, &addr,
+ convert_to_memory_data_size, &size,
+ &value,
+ convert_to_binary_content, &content,
+ &count,
+ convert_to_source_endian, &endian);
if (!ret) return -1;
/* Initialisation d'un objet GLib */
@@ -199,35 +153,19 @@ static int py_raw_instruction_init(PyObject *self, PyObject *args, PyObject *kwd
/* Eléments de base */
- if (content != NULL)
- fake = g_raw_instruction_new_array(content, mem_size, count, addr, endian);
- else
- fake = g_raw_instruction_new_from_value(addr, mem_size, value);
+ instr = G_RAW_INSTRUCTION(pygobject_get(self));
- if (fake == NULL)
+ if (content != NULL)
{
- PyErr_SetString(PyExc_ValueError, _("Unable to build the object with the given parameters."));
- goto clean_exit;
+ if (!g_raw_instruction_create_array(instr, area, addr, size, content, count, endian))
+ goto clean_exit;
}
-
- instr = G_ARCH_INSTRUCTION(pygobject_get(self));
-
- g_arch_instruction_lock_operands(fake);
-
- op_count = _g_arch_instruction_count_operands(fake);
-
- for (i = 0; i < op_count; i++)
+ else
{
- op = _g_arch_instruction_get_operand(fake, i);
- g_arch_instruction_attach_extra_operand(instr, op);
+ if (!g_raw_instruction_create_value(instr, area, addr, size, value))
+ goto clean_exit;
}
- g_arch_instruction_unlock_operands(fake);
-
- g_arch_instruction_set_range(instr, g_arch_instruction_get_range(fake));
-
- g_object_unref(G_OBJECT(fake));
-
result = 0;
clean_exit:
@@ -239,6 +177,12 @@ static int py_raw_instruction_init(PyObject *self, PyObject *args, PyObject *kwd
}
+
+/* ---------------------------------------------------------------------------------- */
+/* FONCTIONNALITES DE L'INSTRUCTION */
+/* ---------------------------------------------------------------------------------- */
+
+
/******************************************************************************
* *
* Paramètres : self = classe représentant une instruction. *
@@ -271,7 +215,6 @@ static PyObject *py_raw_instruction_get_padding(PyObject *self, void *closure)
result = state ? Py_True : Py_False;
Py_INCREF(result);
-
return result;
}
@@ -342,7 +285,6 @@ static PyObject *py_raw_instruction_get_string(PyObject *self, void *closure)
result = state ? Py_True : Py_False;
Py_INCREF(result);
-
return result;
}
diff --git a/plugins/pychrysalide/arch/instructions/undefined.c b/plugins/pychrysalide/arch/instructions/undefined.c
index 1246daa..1c2bccc 100644
--- a/plugins/pychrysalide/arch/instructions/undefined.c
+++ b/plugins/pychrysalide/arch/instructions/undefined.c
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* undefined.c - équivalent Python du fichier "arch/instructions/undefined.h"
*
- * Copyright (C) 2019 Cyrille Bagard
+ * Copyright (C) 2019-2025 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -28,9 +28,7 @@
#include <pygobject.h>
-#include <i18n.h>
#include <arch/instructions/undefined-int.h>
-#include <plugins/dt.h>
#include "constants.h"
@@ -40,75 +38,27 @@
-/* Accompagne la création d'une instance dérivée en Python. */
-static PyObject *py_undef_instruction_new(PyTypeObject *, PyObject *, PyObject *);
+/* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */
-/* Initialise une instance sur la base du dérivé de GObject. */
-static int py_undef_instruction_init(PyObject *, PyObject *, PyObject *);
-
-/* Indique le type de conséquences réél de l'instruction. */
-static PyObject *py_undef_instruction_get_behavior(PyObject *, void *);
-
-
-
-/******************************************************************************
-* *
-* Paramètres : type = type du nouvel objet à mettre en place. *
-* args = éventuelle liste d'arguments. *
-* kwds = éventuel dictionnaire de valeurs mises à disposition. *
-* *
-* Description : Accompagne la création d'une instance dérivée en Python. *
-* *
-* Retour : Nouvel objet Python mis en place ou NULL en cas d'échec. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static PyObject *py_undef_instruction_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
- PyObject *result; /* Objet à retourner */
- PyTypeObject *base; /* Type de base à dériver */
- bool first_time; /* Evite les multiples passages*/
- GType gtype; /* Nouveau type de processeur */
- bool status; /* Bilan d'un enregistrement */
-
- /* Validations diverses */
- base = get_python_undefined_instruction_type();
+CREATE_DYN_CONSTRUCTOR(undefined_instruction, G_TYPE_UNDEFINED_INSTRUCTION);
- if (type == base)
- goto simple_way;
-
- /* Mise en place d'un type dédié */
-
- first_time = (g_type_from_name(type->tp_name) == 0);
-
- gtype = build_dynamic_type(G_TYPE_UNDEF_INSTRUCTION, type->tp_name, NULL, NULL, NULL);
-
- if (first_time)
- {
- status = register_class_for_dynamic_pygobject(gtype, type);
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_undefined_instruction_init(PyObject *, PyObject *, PyObject *);
- if (!status)
- {
- result = NULL;
- goto exit;
- }
- }
- /* On crée, et on laisse ensuite la main à PyGObject_Type.tp_init() */
+/* ------------------------ FONCTIONNALITES DE L'INSTRUCTION ------------------------ */
- simple_way:
- result = PyType_GenericNew(type, args, kwds);
+/* Indique le type de conséquences réél de l'instruction. */
+static PyObject *py_undefined_instruction_get_behavior(PyObject *, void *);
- exit:
- return result;
-}
+/* ---------------------------------------------------------------------------------- */
+/* GLUE POUR CREATION DEPUIS PYTHON */
+/* ---------------------------------------------------------------------------------- */
/******************************************************************************
@@ -125,30 +75,27 @@ static PyObject *py_undef_instruction_new(PyTypeObject *type, PyObject *args, Py
* *
******************************************************************************/
-static int py_undef_instruction_init(PyObject *self, PyObject *args, PyObject *kwds)
+static int py_undefined_instruction_init(PyObject *self, PyObject *args, PyObject *kwds)
{
- unsigned long behavior; /* Conséquence pour l'instruct°*/
+ InstrExpectedBehavior behavior; /* Conséquence pour l'instruct°*/
int ret; /* Bilan de lecture des args. */
- GUndefInstruction *instr; /* Instruction à manipuler */
- undef_extra_data_t *extra; /* Données insérées à modifier */
+ GUndefinedInstruction *instr; /* Instruction à manipuler */
- static char *kwlist[] = { "behavior", NULL };
-
-#define UNDEF_INSTRUCTION_DOC \
- "UndefInstruction represents all kinds of instructions which are" \
+#define UNDEFINED_INSTRUCTION_DOC \
+ "UndefinedInstruction represents all kinds of instructions which are" \
" officially not part of a runnable instruction set.\n" \
"\n" \
"Instances can be created using the following constructor:\n" \
"\n" \
- " UndefInstruction(behavior)" \
+ " UndefinedInstruction(behavior)" \
"\n" \
"Where behavior is a" \
- " pychrysalide.arch.instructions.UndefInstruction.ExpectedBehavior" \
+ " pychrysalide.arch.instructions.UndefinedInstruction.ExpectedBehavior" \
" constant describing the state of the CPU once the instruction is run."
/* Récupération des paramètres */
- ret = PyArg_ParseTupleAndKeywords(args, kwds, "k", kwlist, &behavior);
+ ret = PyArg_ParseTuple(args, "O&", convert_to_undefined_expected_behavior, &behavior);
if (!ret) return -1;
/* Initialisation d'un objet GLib */
@@ -158,17 +105,22 @@ static int py_undef_instruction_init(PyObject *self, PyObject *args, PyObject *k
/* Eléments de base */
- instr = G_UNDEF_INSTRUCTION(pygobject_get(self));
-
- extra = GET_UNDEF_INSTR_EXTRA(instr);
+ instr = G_UNDEFINED_INSTRUCTION(pygobject_get(self));
- extra->behavior = behavior;
+ if (!g_undefined_instruction_create(instr, behavior))
+ return -1;
return 0;
}
+
+/* ---------------------------------------------------------------------------------- */
+/* FONCTIONNALITES DE L'INSTRUCTION */
+/* ---------------------------------------------------------------------------------- */
+
+
/******************************************************************************
* *
* Paramètres : self = classe représentant une instruction. *
@@ -182,24 +134,25 @@ static int py_undef_instruction_init(PyObject *self, PyObject *args, PyObject *k
* *
******************************************************************************/
-static PyObject *py_undef_instruction_get_behavior(PyObject *self, void *closure)
+static PyObject *py_undefined_instruction_get_behavior(PyObject *self, void *closure)
{
PyObject *result; /* Conversion à retourner */
- GUndefInstruction *instr; /* Version native */
+ GUndefinedInstruction *instr; /* Version native */
InstrExpectedBehavior behavior; /* Comportement attendu */
-#define UNDEF_INSTRUCTION_BEHAVIOR_ATTRIB PYTHON_GET_DEF_FULL \
-( \
- behavior, py_undef_instruction, \
- "Consequence carried by the undefined instruction.\n" \
- "\n" \
- "The result is provided as a" \
- " pychrysalide.arch.instructions.UndefInstruction.ExpectedBehavior" \
- " constant." \
+#define UNDEFINED_INSTRUCTION_BEHAVIOR_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ behavior, py_undefined_instruction, \
+ "Consequence carried by the undefined instruction.\n" \
+ "\n" \
+ "The result is provided as a" \
+ " pychrysalide.arch.instructions.UndefinedInstruction.ExpectedBehavior" \
+ " constant." \
)
- instr = G_UNDEF_INSTRUCTION(pygobject_get(self));
- behavior = g_undef_instruction_get_behavior(instr);
+ instr = G_UNDEFINED_INSTRUCTION(pygobject_get(self));
+
+ behavior = g_undefined_instruction_get_behavior(instr);
result = cast_with_constants_group_from_type(get_python_undefined_instruction_type(),
"ExpectedBehavior", behavior);
@@ -228,7 +181,7 @@ PyTypeObject *get_python_undefined_instruction_type(void)
};
static PyGetSetDef py_undefined_instruction_getseters[] = {
- UNDEF_INSTRUCTION_BEHAVIOR_ATTRIB,
+ UNDEFINED_INSTRUCTION_BEHAVIOR_ATTRIB,
{ NULL }
};
@@ -236,18 +189,18 @@ PyTypeObject *get_python_undefined_instruction_type(void)
PyVarObject_HEAD_INIT(NULL, 0)
- .tp_name = "pychrysalide.arch.instructions.UndefInstruction",
+ .tp_name = "pychrysalide.arch.instructions.UndefinedInstruction",
.tp_basicsize = sizeof(PyGObject),
.tp_flags = Py_TPFLAGS_DEFAULT,
- .tp_doc = UNDEF_INSTRUCTION_DOC,
+ .tp_doc = UNDEFINED_INSTRUCTION_DOC,
.tp_methods = py_undefined_instruction_methods,
.tp_getset = py_undefined_instruction_getseters,
- .tp_init = py_undef_instruction_init,
- .tp_new = py_undef_instruction_new,
+ .tp_init = py_undefined_instruction_init,
+ .tp_new = py_undefined_instruction_new,
};
@@ -260,7 +213,7 @@ PyTypeObject *get_python_undefined_instruction_type(void)
* *
* Paramètres : module = module dont la définition est à compléter. *
* *
-* Description : Prend en charge l'objet 'pychrysalide.....UndefInstruction'. *
+* Description : Prend en charge l'objet '....UndefinedInstruction'. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -285,7 +238,7 @@ bool ensure_python_undefined_instruction_is_registered(void)
if (!ensure_python_arch_instruction_is_registered())
return false;
- if (!register_class_for_pygobject(dict, G_TYPE_UNDEF_INSTRUCTION, type))
+ if (!register_class_for_pygobject(dict, G_TYPE_UNDEFINED_INSTRUCTION, type))
return false;
if (!define_undefined_instruction_constants(type))
@@ -329,7 +282,7 @@ int convert_to_undefined_instruction(PyObject *arg, void *dst)
break;
case 1:
- *((GUndefInstruction **)dst) = G_UNDEF_INSTRUCTION(pygobject_get(arg));
+ *((GUndefinedInstruction **)dst) = G_UNDEFINED_INSTRUCTION(pygobject_get(arg));
break;
default:
diff --git a/plugins/pychrysalide/arch/instructions/undefined.h b/plugins/pychrysalide/arch/instructions/undefined.h
index 3fa0453..1453612 100644
--- a/plugins/pychrysalide/arch/instructions/undefined.h
+++ b/plugins/pychrysalide/arch/instructions/undefined.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* undefined.h - prototypes pour l'équivalent Python du fichier "arch/instructions/undefined.h"
*
- * Copyright (C) 2019 Cyrille Bagard
+ * Copyright (C) 2019-2025 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -34,7 +34,7 @@
/* Fournit un accès à une définition de type à diffuser. */
PyTypeObject *get_python_undefined_instruction_type(void);
-/* Prend en charge l'objet 'pychrysalide.arch.instructions.UndefInstruction'. */
+/* Prend en charge l'objet 'pychrysalide.arch.instructions.UndefinedInstruction'. */
bool ensure_python_undefined_instruction_is_registered(void);
/* Tente de convertir en instruction non définie. */
diff --git a/plugins/pychrysalide/arch/module-ui.c b/plugins/pychrysalide/arch/module-ui.c
index 201f760..65d1290 100644
--- a/plugins/pychrysalide/arch/module-ui.c
+++ b/plugins/pychrysalide/arch/module-ui.c
@@ -29,6 +29,7 @@
#include "operand-ui.h"
+#include "../glibext/generator.h"
@@ -52,6 +53,12 @@ bool populate_arch_module_ui(void)
if (result) result = ensure_python_arch_operand_ui_is_registered();
+ /**
+ * Préparation du terrain pour les instructions, sans lien directe
+ * de la partie UI depuis la partie NOX.
+ */
+ if (result) result = ensure_python_token_generator_is_registered();
+
assert(result);
return result;
diff --git a/plugins/pychrysalide/arch/module.c b/plugins/pychrysalide/arch/module.c
index 3f52a58..94f5ad7 100644
--- a/plugins/pychrysalide/arch/module.c
+++ b/plugins/pychrysalide/arch/module.c
@@ -32,14 +32,12 @@
#include "context.h"
#include "instriter.h"
*/
-//#include "instruction.h"
+#include "instruction.h"
#include "operand.h"
//#include "processor.h"
#include "register.h"
#include "vmpa.h"
-/*
#include "instructions/module.h"
-*/
#include "operands/module.h"
#include "../helpers.h"
@@ -77,9 +75,7 @@ bool add_arch_module(PyObject *super)
result = (module != NULL);
- /*
if (result) result = add_arch_instructions_module(module);
- */
if (result) result = add_arch_operands_module(module);
return result;
@@ -109,16 +105,14 @@ bool populate_arch_module(void)
if (result) result = ensure_python_proc_context_is_registered();
if (result) result = ensure_python_instr_iterator_is_registered();
*/
- //if (result) result = ensure_python_arch_instruction_is_registered();
+ if (result) result = ensure_python_arch_instruction_is_registered();
if (result) result = ensure_python_arch_operand_is_registered();
//if (result) result = ensure_python_arch_processor_is_registered();
if (result) result = ensure_python_arch_register_is_registered();
if (result) result = ensure_python_vmpa_is_registered();
if (result) result = ensure_python_mrange_is_registered();
- /*
if (result) result = populate_arch_instructions_module();
- */
if (result) result = populate_arch_operands_module();
assert(result);
diff --git a/plugins/pychrysalide/arch/operand.c b/plugins/pychrysalide/arch/operand.c
index 42bd247..2281dae 100644
--- a/plugins/pychrysalide/arch/operand.c
+++ b/plugins/pychrysalide/arch/operand.c
@@ -94,6 +94,10 @@ static PyObject *py_arch_operand_set_flag(PyObject *, PyObject *);
/* Retire une information complémentaire à un opérande. */
static PyObject *py_arch_operand_unset_flag(PyObject *, PyObject *);
+/* Détermine si un opérande possède un fanion particulier. */
+static PyObject *py_arch_operand_has_flag(PyObject *, PyObject *);
+
+
/* ---------------------------------------------------------------------------------- */
diff --git a/plugins/pychrysalide/bindings.c b/plugins/pychrysalide/bindings.c
index 7e87e27..f120c3b 100644
--- a/plugins/pychrysalide/bindings.c
+++ b/plugins/pychrysalide/bindings.c
@@ -33,6 +33,7 @@
#include <common/cpp.h>
+#include <common/environment.h>
#include <common/extstr.h>
#include <core/core.h>
#include <plugins/pglist.h>
@@ -52,10 +53,6 @@
#include "glibext/module.h"
/* #include "debug/module.h" */
#include "format/module.h"
-/* #ifdef INCLUDE_GTK_SUPPORT */
-/* # include "gtkext/module.h" */
-/* # include "gui/module.h" */
-/* #endif */
/* #include "mangling/module.h" */
#include "plugins/module.h"
@@ -149,7 +146,7 @@ static void ensure_native_pygobject_type(PyTypeObject **);
static PyObject *get_existing_modules(void);
/* Définit les différents modules du support Python. */
-static PyObject *create_basic_modules(void);
+static PyObject *create_basic_modules(const pyinit_details_t *);
/* Inscrit les défintions des objets Python de Chrysalide. */
static bool populate_python_modules(const pyinit_details_t *);
@@ -158,6 +155,7 @@ static bool populate_python_modules(const pyinit_details_t *);
static void restore_original_pygobject_type(PyTypeObject *);
+
/* ------------------------ FONCTIONS GLOBALES DE CHRYSALIDE ------------------------ */
@@ -978,7 +976,7 @@ static PyObject *get_existing_modules(void)
/******************************************************************************
* *
-* Paramètres : - *
+* Paramètres : details = précisions de chargement complémentaires. *
* *
* Description : Définit les différents modules du support Python. *
* *
@@ -988,7 +986,7 @@ static PyObject *get_existing_modules(void)
* *
******************************************************************************/
-static PyObject *create_basic_modules(void)
+static PyObject *create_basic_modules(const pyinit_details_t *details)
{
PyObject *result; /* Module Python à retourner */
bool status; /* Bilan des inclusions */
@@ -1036,14 +1034,17 @@ static PyObject *create_basic_modules(void)
*/
if (status) status = add_format_module(result);
/*
-#ifdef INCLUDE_GTK_SUPPORT
- if (status) status = add_gtkext_module(result);
- if (status) status = add_gui_module(result);
-#endif
if (status) status = add_mangling_module(result);
*/
if (status) status = add_plugins_module(result);
+ /**
+ * Ajout de modules UI supplémentaires éventuels.
+ */
+
+ if (status && details->add_extra != NULL)
+ status = details->add_extra(result);
+
if (!status)
{
Py_DECREF(result);
@@ -1081,8 +1082,8 @@ static bool populate_python_modules(const pyinit_details_t *details)
* un chargement préliminaire, si besoin est.
*/
- if (details->populate_extra)
- result = details->populate_extra();
+ if (details->populate_extra != NULL)
+ result = details->populate_extra(false);
else
result = true;
@@ -1101,14 +1102,22 @@ static bool populate_python_modules(const pyinit_details_t *details)
*/
if (result) result = populate_format_module();
/*
-#ifdef INCLUDE_GTK_SUPPORT
- if (result) result = populate_gtkext_module();
- if (result) result = populate_gui_module();
-#endif
if (result) result = populate_mangling_module();
*/
if (result) result = populate_plugins_module();
+ /**
+ * Certaines définitions reposent sur une déclinaison de GtkWidget,
+ * dont le chargement va remplacer la définition statique de GObject
+ * par une version allouée dynamiquement.
+ *
+ * De telles définitions doivent donc être prise en compte à la fin
+ * du chargement.
+ */
+
+ if (result && details->populate_extra != NULL)
+ result = details->populate_extra(true);
+
return result;
}
@@ -1202,7 +1211,7 @@ PyObject *init_python_pychrysalide_module(const pyinit_details_t *details)
ensure_native_pygobject_type(&py_gobj_def);
- result = create_basic_modules();
+ result = create_basic_modules(details);
if (result == NULL)
PyErr_SetString(PyExc_SystemError, "failed to create all PyChrysalide modules.");
@@ -1356,6 +1365,54 @@ void log_pychrysalide_exception(const char *prefix, ...)
/* ---------------------------------------------------------------------------------- */
+/* INTERVENTION DANS LA GESTION DE GREFFONS */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : plugin = instance représentant le greffon courant. *
+* path = chemin supplémentaire pour l'espace de recherche. *
+* *
+* Description : Complète les chemins de recherches de Python. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void extend_python_path(const GPluginModule *plugin, const char *path)
+{
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
+ PyObject *list; /* Liste de chemins à compléter*/
+ PyObject *new; /* Nouveau chemin à intégrer */
+
+ gstate = PyGILState_Ensure();
+
+ list = PySys_GetObject("path");
+ assert(list != NULL);
+
+ new = PyUnicode_FromString(path);
+ assert(new != NULL);
+
+ PyList_Append(list, new);
+
+ Py_DECREF(new);
+
+ add_to_env_var("PYTHONPATH", path, ":");
+
+ PyGILState_Release(gstate);
+
+ g_plugin_module_log_variadic_message(plugin, LMT_INFO,
+ _("PYTHONPATH environment variable set to '%s'"),
+ getenv("PYTHONPATH"));
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
/* FONCTIONS GLOBALES DE CHRYSALIDE */
/* ---------------------------------------------------------------------------------- */
diff --git a/plugins/pychrysalide/bindings.h b/plugins/pychrysalide/bindings.h
index 1758747..036f852 100644
--- a/plugins/pychrysalide/bindings.h
+++ b/plugins/pychrysalide/bindings.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* bindings.h - prototypes pour les éléments d'un socle commun aux fonctionnalités graphiques et non graphiques
*
- * Copyright (C) 2024 Cyrille Bagard
+ * Copyright (C) 2024-2025 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -44,6 +44,9 @@
+/* ------------------------ FONCTIONNALITES DE MISE EN PLACE ------------------------ */
+
+
/* Charge un module GI dans Python avec une version attendue. */
bool import_namespace_from_gi_repository(const char *, const char *);
@@ -52,7 +55,9 @@ typedef struct _pyinit_details_t
{
bool standalone; /* Chargement depuis Python ? */
- bool (* populate_extra) (void); /* Ajout de types ? */
+ bool (* add_extra) (PyObject *); /* Ajout de modules ? */
+
+ bool (* populate_extra) (bool); /* Ajout de types ? */
/**
* Prototype de la fonction de création, à garder synchronisé avec
@@ -70,4 +75,12 @@ void log_pychrysalide_exception(const char *, ...);
+/* -------------------- INTERVENTION DANS LA GESTION DE GREFFONS -------------------- */
+
+
+/* Complète les chemins de recherches de Python. */
+void extend_python_path(const GPluginModule *, const char *);
+
+
+
#endif /* _PLUGINS_PYCHRYSALIDE_BINDINGS_H */
diff --git a/plugins/pychrysalide/convert.c b/plugins/pychrysalide/convert.c
index c67c8ba..08866cb 100644
--- a/plugins/pychrysalide/convert.c
+++ b/plugins/pychrysalide/convert.c
@@ -87,3 +87,34 @@ int convert_to_gsettings(PyObject *arg, void *dst)
return result;
}
+
+
+/******************************************************************************
+* *
+* Paramètres : arg = argument quelconque à tenter de convertir. *
+* dst = destination des valeurs récupérées en cas de succès. *
+* *
+* Description : Tente de convertir en instance GSettings ou NULL. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_gsettings_or_none(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ if (arg == Py_None)
+ {
+ *((GSettings **)dst) = NULL;
+ result = 1;
+ }
+
+ else
+ result = convert_to_gsettings(arg, dst);
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/convert.h b/plugins/pychrysalide/convert.h
index 7bdf7da..86d7528 100644
--- a/plugins/pychrysalide/convert.h
+++ b/plugins/pychrysalide/convert.h
@@ -33,6 +33,9 @@
/* Tente de convertir en instance GSettings. */
int convert_to_gsettings(PyObject *, void *);
+/* Tente de convertir en instance GSettings ou NULL. */
+int convert_to_gsettings_or_none(PyObject *, void *);
+
#endif /* _PLUGINS_PYCHRYSALIDE_CONVERT_H */
diff --git a/plugins/pychrysalide/core-ui.c b/plugins/pychrysalide/core-ui.c
index 1fb7931..00d1cc1 100644
--- a/plugins/pychrysalide/core-ui.c
+++ b/plugins/pychrysalide/core-ui.c
@@ -28,6 +28,10 @@
#include <i18n.h>
+#ifdef DISCARD_LOCAL
+# include <core/paths.h>
+#endif
+#include <plugins/manager-int.h>
#include <plugins/self.h>
@@ -35,6 +39,8 @@
#include "core-ui-int.h"
#include "arch/module-ui.h"
#include "glibext/module-ui.h"
+#include "gtkext/module.h"
+//#include "gui/module.h"
@@ -49,14 +55,17 @@ static bool _standalone = true;
/* Initialise la classe des greffons de support Python. */
static void g_pychrysalide_plugin_ui_class_init(GPyChrysalidePluginUIClass *);
+/* Procède à l'initialisation de l'interface de gestion. */
+static void g_pychrysalide_plugin_ui_plugin_manager_interface_init(GPluginManagerInterface *);
+
/* Initialise une instance de greffon de support Python. */
static void g_pychrysalide_plugin_ui_init(GPyChrysalidePluginUI *);
/* Supprime toutes les références externes. */
-static void g_pychrysalide_plugin_ui_dispose(GPyChrysalidePluginUI *);
+static void g_pychrysalide_plugin_ui_dispose(GObject *);
/* Procède à la libération totale de la mémoire. */
-static void g_pychrysalide_plugin_ui_finalize(GPyChrysalidePluginUI *);
+static void g_pychrysalide_plugin_ui_finalize(GObject *);
@@ -64,15 +73,26 @@ static void g_pychrysalide_plugin_ui_finalize(GPyChrysalidePluginUI *);
/* Prend acte de l'activation du greffon. */
-static bool g_pychrysalide_plugin_ui_enable(GPyChrysalidePluginUI *);
+static bool g_pychrysalide_plugin_ui_enable(GPluginModule *);
+
+
+
+/* -------------------- INTERVENTION DANS LA GESTION DE GREFFONS -------------------- */
+
+
+/* Prend acte du chargement de l'ensemble des greffons natifs. */
+static void g_pychrysalide_plugin_ui_handle_native_plugins_loaded_event(GPluginManager *);
/* --------------------------- POINT D'ENTREE POUR PYTHON --------------------------- */
+/*Ajoute des modules UI aux extensions Python. */
+static bool add_python_ui_modules(PyObject *);
+
/* Inscrit les défintions des objets UI Python de Chrysalide. */
-static bool populate_python_modules_ui(void);
+static bool populate_python_modules_ui(bool);
@@ -82,7 +102,8 @@ static bool populate_python_modules_ui(void);
/* Indique le type défini pour un greffon de liaison Python */
-G_DEFINE_TYPE(GPyChrysalidePluginUI, g_pychrysalide_plugin_ui, G_TYPE_PYCHRYSALIDE_PLUGIN);
+G_DEFINE_TYPE_WITH_CODE(GPyChrysalidePluginUI, g_pychrysalide_plugin_ui, G_TYPE_PYCHRYSALIDE_PLUGIN,
+ G_IMPLEMENT_INTERFACE(G_TYPE_PLUGIN_MANAGER, g_pychrysalide_plugin_ui_plugin_manager_interface_init));
NATIVE_PLUGIN_ENTRYPOINT(g_pychrysalide_plugin_ui_new);
@@ -107,12 +128,31 @@ static void g_pychrysalide_plugin_ui_class_init(GPyChrysalidePluginUIClass *clas
object = G_OBJECT_CLASS(class);
- object->dispose = (GObjectFinalizeFunc/* ! */)g_pychrysalide_plugin_ui_dispose;
- object->finalize = (GObjectFinalizeFunc)g_pychrysalide_plugin_ui_finalize;
+ object->dispose = g_pychrysalide_plugin_ui_dispose;
+ object->finalize = g_pychrysalide_plugin_ui_finalize;
plugin = G_PLUGIN_MODULE_CLASS(class);
- plugin->enable = (pg_management_fc)g_pychrysalide_plugin_ui_enable;
+ plugin->enable = g_pychrysalide_plugin_ui_enable;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : iface = interface GLib à initialiser. *
+* *
+* Description : Procède à l'initialisation de l'interface de gestion. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_pychrysalide_plugin_ui_plugin_manager_interface_init(GPluginManagerInterface *iface)
+{
+ iface->handle_native = g_pychrysalide_plugin_ui_handle_native_plugins_loaded_event;
}
@@ -137,7 +177,7 @@ static void g_pychrysalide_plugin_ui_init(GPyChrysalidePluginUI *plugin)
/******************************************************************************
* *
-* Paramètres : plugin = instance d'objet GLib à traiter. *
+* Paramètres : object = instance d'objet GLib à traiter. *
* *
* Description : Supprime toutes les références externes. *
* *
@@ -147,16 +187,16 @@ static void g_pychrysalide_plugin_ui_init(GPyChrysalidePluginUI *plugin)
* *
******************************************************************************/
-static void g_pychrysalide_plugin_ui_dispose(GPyChrysalidePluginUI *plugin)
+static void g_pychrysalide_plugin_ui_dispose(GObject *object)
{
- G_OBJECT_CLASS(g_pychrysalide_plugin_ui_parent_class)->dispose(G_OBJECT(plugin));
+ G_OBJECT_CLASS(g_pychrysalide_plugin_ui_parent_class)->dispose(object);
}
/******************************************************************************
* *
-* Paramètres : plugin = instance d'objet GLib à traiter. *
+* Paramètres : object = instance d'objet GLib à traiter. *
* *
* Description : Procède à la libération totale de la mémoire. *
* *
@@ -166,9 +206,9 @@ static void g_pychrysalide_plugin_ui_dispose(GPyChrysalidePluginUI *plugin)
* *
******************************************************************************/
-static void g_pychrysalide_plugin_ui_finalize(GPyChrysalidePluginUI *plugin)
+static void g_pychrysalide_plugin_ui_finalize(GObject *object)
{
- G_OBJECT_CLASS(g_pychrysalide_plugin_ui_parent_class)->finalize(G_OBJECT(plugin));
+ G_OBJECT_CLASS(g_pychrysalide_plugin_ui_parent_class)->finalize(object);
}
@@ -241,22 +281,24 @@ bool g_pychrysalide_plugin_ui_create(GPyChrysalidePluginUI *plugin, GModule *mod
* *
******************************************************************************/
-static bool g_pychrysalide_plugin_ui_enable(GPyChrysalidePluginUI *plugin)
+static bool g_pychrysalide_plugin_ui_enable(GPluginModule *plugin)
{
bool result; /* Bilan à retourner */
+ GPyChrysalidePlugin *pychr_plugin; /* Version spécialisée */
PyGILState_STATE gstate; /* Sauvegarde d'environnement */
int ret; /* Bilan de préparatifs */
_standalone = false;
+ pychr_plugin = G_PYCHRYSALIDE_PLUGIN(plugin);
+
/* Chargement du module pour Python */
ret = PyImport_AppendInittab("pychrysalide", &PyInit_pychrysalideui);
if (ret == -1)
{
- g_plugin_module_log_simple_message(G_PLUGIN_MODULE(plugin),
- LMT_ERROR,
+ g_plugin_module_log_simple_message(plugin, LMT_ERROR,
_("Can not extend the existing table of Python built-in modules."));
result = false;
@@ -268,7 +310,7 @@ static bool g_pychrysalide_plugin_ui_enable(GPyChrysalidePluginUI *plugin)
gstate = PyGILState_Ensure();
- G_PYCHRYSALIDE_PLUGIN(plugin)->py_module = PyImport_ImportModule("pychrysalide");
+ pychr_plugin->py_module = PyImport_ImportModule("pychrysalide");
/**
* Pour mémoire, une situation concrête conduisant à un échec :
@@ -283,7 +325,7 @@ static bool g_pychrysalide_plugin_ui_enable(GPyChrysalidePluginUI *plugin)
// TODO : check (2025)
- result = (G_PYCHRYSALIDE_PLUGIN(plugin)->py_module != NULL);
+ result = (pychr_plugin->py_module != NULL);
PyGILState_Release(gstate);
@@ -296,13 +338,103 @@ static bool g_pychrysalide_plugin_ui_enable(GPyChrysalidePluginUI *plugin)
/* ---------------------------------------------------------------------------------- */
+/* INTERVENTION DANS LA GESTION DE GREFFONS */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : manager = interface à manipuler. *
+* *
+* Description : Accompagne la fin du chargement des modules natifs. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_pychrysalide_plugin_ui_handle_native_plugins_loaded_event(GPluginManager *manager)
+{
+ GPluginModule *plugin; /* Version de base du greffon */
+#ifdef DISCARD_LOCAL
+ char *edir; /* Répertoire de base effectif */
+ DIR *dir; /* Répertoire à parcourir */
+#endif
+ GPluginManagerInterface *iface; /* Interface utilisée */
+ GPluginManagerInterface *parent_iface; /* Interface parente */
+
+ plugin = G_PLUGIN_MODULE(manager);
+
+ /* Définition des zones d'influence */
+
+#ifndef DISCARD_LOCAL
+
+ extend_python_path(plugin, PACKAGE_SOURCE_DIR G_DIR_SEPARATOR_S "plugins" G_DIR_SEPARATOR_S "pythonui");
+
+#else
+
+ edir = get_effective_directory(PLUGINS_DATA_DIR G_DIR_SEPARATOR_S "pythonui");
+
+ dir = opendir(edir);
+
+ if (dir != NULL)
+ {
+ closedir(dir);
+
+ extend_python_path(plugin, edir);
+
+ }
+
+ free(edir);
+
+#endif
+
+ /* Chargements des extensions Python */
+
+ iface = G_PLUGIN_MANAGER_GET_IFACE(manager);
+
+ parent_iface = g_type_interface_peek_parent(iface);
+
+ parent_iface->handle_native(manager);
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
/* POINT D'ENTREE POUR PYTHON */
/* ---------------------------------------------------------------------------------- */
/******************************************************************************
* *
-* Paramètres : - *
+* Paramètres : super = module dont la définition est à compléter. *
+* *
+* Description : Ajoute des modules UI aux extensions Python. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool add_python_ui_modules(PyObject *super)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ if (result) result = add_gtkext_module(super);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modify = autorisation de motification du type GObject. *
* *
* Description : Inscrit les défintions des objets UI Python de Chrysalide. *
* *
@@ -312,14 +444,25 @@ static bool g_pychrysalide_plugin_ui_enable(GPyChrysalidePluginUI *plugin)
* *
******************************************************************************/
-static bool populate_python_modules_ui(void)
+static bool populate_python_modules_ui(bool modify)
{
bool result; /* Bilan à retourner */
result = true;
- if (result) result = populate_arch_module_ui();
- if (result) result = populate_glibext_module_ui();
+ if (!modify)
+ {
+ if (result) result = populate_arch_module_ui();
+ if (result) result = populate_glibext_module_ui();
+
+ }
+
+ else
+ {
+ if (result) result = populate_gtkext_module();
+ //if (result) result = populate_gui_module();
+
+ }
return result;
@@ -345,6 +488,7 @@ PyMODINIT_FUNC PyInit_pychrysalideui(void)
details.standalone = _standalone;
+ details.add_extra = add_python_ui_modules;
details.populate_extra = populate_python_modules_ui;
details.create_self = g_pychrysalide_plugin_ui_new;
diff --git a/plugins/pychrysalide/core.c b/plugins/pychrysalide/core.c
index 51a06a1..0fea9c4 100644
--- a/plugins/pychrysalide/core.c
+++ b/plugins/pychrysalide/core.c
@@ -24,24 +24,14 @@
#include "core.h"
-#include "core-int.h"
-
-
-
-
-
#undef NO_IMPORT_PYGOBJECT
#include <pygobject.h>
#define NO_IMPORT_PYGOBJECT
-#include "core.h"
-
-
#include <assert.h>
#include <errno.h>
#include <malloc.h>
-//#include <pygobject.h>
#include <stdarg.h>
#include <stdbool.h>
#include <string.h>
@@ -60,10 +50,9 @@
#include <plugins/self.h>
-
-
#include "access.h"
#include "bindings.h"
+#include "core-int.h"
@@ -72,14 +61,6 @@ static bool _standalone = true;
-
-
-
-
-
-
-
-
/* ---------------------- COMPOSITION DE NOUVEAU GREFFON NATIF ---------------------- */
@@ -93,10 +74,10 @@ static void g_pychrysalide_plugin_plugin_manager_interface_init(GPluginManagerIn
static void g_pychrysalide_plugin_init(GPyChrysalidePlugin *);
/* Supprime toutes les références externes. */
-static void g_pychrysalide_plugin_dispose(GPyChrysalidePlugin *);
+static void g_pychrysalide_plugin_dispose(GObject *);
/* Procède à la libération totale de la mémoire. */
-static void g_pychrysalide_plugin_finalize(GPyChrysalidePlugin *);
+static void g_pychrysalide_plugin_finalize(GObject *);
@@ -104,19 +85,16 @@ static void g_pychrysalide_plugin_finalize(GPyChrysalidePlugin *);
/* Prend acte de l'activation du greffon. */
-static bool g_pychrysalide_plugin_enable(GPyChrysalidePlugin *);
+static bool g_pychrysalide_plugin_enable(GPluginModule *);
/* Prend acte de la désactivation du greffon. */
-static bool g_pychrysalide_plugin_disable(GPyChrysalidePlugin *);
+static bool g_pychrysalide_plugin_disable(GPluginModule *);
/* -------------------- INTERVENTION DANS LA GESTION DE GREFFONS -------------------- */
-/* Complète les chemins de recherches de Python. */
-static void extend_python_path(const char *);
-
/* Crée un greffon à partir de code Python. */
static GPluginModule *create_python_plugin(const char *, const char *);
@@ -124,7 +102,7 @@ static GPluginModule *create_python_plugin(const char *, const char *);
static void load_python_plugins(GPluginModule *);
/* Prend acte du chargement de l'ensemble des greffons natifs. */
-static void g_pychrysalide_plugin_handle_native_plugins_loaded_event(GPyChrysalidePlugin *);
+static void g_pychrysalide_plugin_handle_native_plugins_loaded_event(GPluginManager *);
@@ -160,13 +138,13 @@ static void g_pychrysalide_plugin_class_init(GPyChrysalidePluginClass *class)
object = G_OBJECT_CLASS(class);
- object->dispose = (GObjectFinalizeFunc/* ! */)g_pychrysalide_plugin_dispose;
- object->finalize = (GObjectFinalizeFunc)g_pychrysalide_plugin_finalize;
+ object->dispose = g_pychrysalide_plugin_dispose;
+ object->finalize = g_pychrysalide_plugin_finalize;
plugin = G_PLUGIN_MODULE_CLASS(class);
- plugin->enable = (pg_management_fc)g_pychrysalide_plugin_enable;
- plugin->disable = (pg_management_fc)g_pychrysalide_plugin_disable;
+ plugin->enable = g_pychrysalide_plugin_enable;
+ plugin->disable = g_pychrysalide_plugin_disable;
}
@@ -185,7 +163,7 @@ static void g_pychrysalide_plugin_class_init(GPyChrysalidePluginClass *class)
static void g_pychrysalide_plugin_plugin_manager_interface_init(GPluginManagerInterface *iface)
{
- iface->handle_native = (handle_native_plugins_cb)g_pychrysalide_plugin_handle_native_plugins_loaded_event;
+ iface->handle_native = g_pychrysalide_plugin_handle_native_plugins_loaded_event;
}
@@ -213,7 +191,7 @@ static void g_pychrysalide_plugin_init(GPyChrysalidePlugin *plugin)
/******************************************************************************
* *
-* Paramètres : plugin = instance d'objet GLib à traiter. *
+* Paramètres : object = instance d'objet GLib à traiter. *
* *
* Description : Supprime toutes les références externes. *
* *
@@ -223,16 +201,16 @@ static void g_pychrysalide_plugin_init(GPyChrysalidePlugin *plugin)
* *
******************************************************************************/
-static void g_pychrysalide_plugin_dispose(GPyChrysalidePlugin *plugin)
+static void g_pychrysalide_plugin_dispose(GObject *object)
{
- G_OBJECT_CLASS(g_pychrysalide_plugin_parent_class)->dispose(G_OBJECT(plugin));
+ G_OBJECT_CLASS(g_pychrysalide_plugin_parent_class)->dispose(object);
}
/******************************************************************************
* *
-* Paramètres : plugin = instance d'objet GLib à traiter. *
+* Paramètres : object = instance d'objet GLib à traiter. *
* *
* Description : Procède à la libération totale de la mémoire. *
* *
@@ -242,9 +220,9 @@ static void g_pychrysalide_plugin_dispose(GPyChrysalidePlugin *plugin)
* *
******************************************************************************/
-static void g_pychrysalide_plugin_finalize(GPyChrysalidePlugin *plugin)
+static void g_pychrysalide_plugin_finalize(GObject *object)
{
- G_OBJECT_CLASS(g_pychrysalide_plugin_parent_class)->finalize(G_OBJECT(plugin));
+ G_OBJECT_CLASS(g_pychrysalide_plugin_parent_class)->finalize(object);
}
@@ -323,22 +301,24 @@ bool g_pychrysalide_plugin_create(GPyChrysalidePlugin *plugin, GModule *module)
* *
******************************************************************************/
-static bool g_pychrysalide_plugin_enable(GPyChrysalidePlugin *plugin)
+static bool g_pychrysalide_plugin_enable(GPluginModule *plugin)
{
bool result; /* Bilan à retourner */
+ GPyChrysalidePlugin *pychr_plugin; /* Version spécialisée */
PyGILState_STATE gstate; /* Sauvegarde d'environnement */
int ret; /* Bilan de préparatifs */
_standalone = false;
+ pychr_plugin = G_PYCHRYSALIDE_PLUGIN(plugin);
+
/* Chargement du module pour Python */
ret = PyImport_AppendInittab("pychrysalide", &PyInit_pychrysalide);
if (ret == -1)
{
- g_plugin_module_log_simple_message(G_PLUGIN_MODULE(plugin),
- LMT_ERROR,
+ g_plugin_module_log_simple_message(plugin, LMT_ERROR,
_("Can not extend the existing table of Python built-in modules."));
result = false;
@@ -350,7 +330,7 @@ static bool g_pychrysalide_plugin_enable(GPyChrysalidePlugin *plugin)
gstate = PyGILState_Ensure();
- plugin->py_module = PyImport_ImportModule("pychrysalide");
+ pychr_plugin->py_module = PyImport_ImportModule("pychrysalide");
/**
* Pour mémoire, une situation concrête conduisant à un échec :
@@ -365,7 +345,7 @@ static bool g_pychrysalide_plugin_enable(GPyChrysalidePlugin *plugin)
// TODO : check (2025)
- result = (plugin->py_module != NULL);
+ result = (pychr_plugin->py_module != NULL);
PyGILState_Release(gstate);
@@ -388,14 +368,17 @@ static bool g_pychrysalide_plugin_enable(GPyChrysalidePlugin *plugin)
* *
******************************************************************************/
-static bool g_pychrysalide_plugin_disable(GPyChrysalidePlugin *plugin)
+static bool g_pychrysalide_plugin_disable(GPluginModule *plugin)
{
bool result; /* Bilan à retourner */
+ GPyChrysalidePlugin *pychr_plugin; /* Version spécialisée */
bool standalone; /* Nature du chargement */
PyGILState_STATE gstate; /* Sauvegarde d'environnement */
result = true;
+ pychr_plugin = G_PYCHRYSALIDE_PLUGIN(plugin);
+
/**
* Le champ plugin->py_module n'est défini que via la fonction
* g_pychrysalide_plugin_enable(), qui n'est pas sollicitée lorsque
@@ -407,7 +390,7 @@ static bool g_pychrysalide_plugin_disable(GPyChrysalidePlugin *plugin)
* initial ici.
*/
- standalone = (plugin->py_module == NULL);
+ standalone = (pychr_plugin->py_module == NULL);
/**
* Si on se trouve embarqué dans un interpréteur Python, le déchargement
@@ -430,8 +413,8 @@ static bool g_pychrysalide_plugin_disable(GPyChrysalidePlugin *plugin)
clear_all_accesses_to_python_modules();
- Py_XDECREF(plugin->py_module);
- plugin->py_module = NULL;
+ Py_XDECREF(pychr_plugin->py_module);
+ pychr_plugin->py_module = NULL;
if (!standalone)
PyGILState_Release(gstate);
@@ -449,38 +432,6 @@ static bool g_pychrysalide_plugin_disable(GPyChrysalidePlugin *plugin)
/******************************************************************************
* *
-* Paramètres : path = chemin supplémentaire pour l'espace de recherche. *
-* *
-* Description : Complète les chemins de recherches de Python. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void extend_python_path(const char *path)
-{
- PyObject *list; /* Liste de chemins à compléter*/
- PyObject *new; /* Nouveau chemin à intégrer */
-
- list = PySys_GetObject("path");
- assert(list != NULL);
-
- new = PyUnicode_FromString(path);
- assert(new != NULL);
-
- PyList_Append(list, new);
-
- Py_DECREF(new);
-
- add_to_env_var("PYTHONPATH", path, ":");
-
-}
-
-
-/******************************************************************************
-* *
* Paramètres : modname = nom du module à charger. *
* filename = chemin d'accès au code Python à charger. *
* *
@@ -568,48 +519,18 @@ static GPluginModule *create_python_plugin(const char *modname, const char *file
static void load_python_plugins(GPluginModule *plugin)
{
-#ifdef DISCARD_LOCAL
- char *edir; /* Répertoire de base effectif */
-#endif
- DIR *dir; /* Répertoire à parcourir */
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
char *paths; /* Emplacements de greffons */
char *save; /* Sauvegarde pour ré-entrance */
char *path; /* Chemin à fouiller */
+ DIR *dir; /* Répertoire à parcourir */
struct dirent *entry; /* Elément trouvé */
char *modname; /* Nom du module pour Python */
char *filename; /* Chemin d'accès reconstruit */
GPluginModule *pyplugin; /* Lien vers un grffon Python */
bool status; /* Bilan d'une opération */
- /* Définition des zones d'influence */
-
-#ifndef DISCARD_LOCAL
-
- extend_python_path(PACKAGE_SOURCE_DIR G_DIR_SEPARATOR_S "plugins" G_DIR_SEPARATOR_S "python");
-
-#else
-
- edir = get_effective_directory(PLUGINS_DATA_DIR G_DIR_SEPARATOR_S "python");
-
- dir = opendir(edir);
-
- if (dir != NULL)
- {
- closedir(dir);
-
- extend_python_path(edir);
-
- }
-
- free(edir);
-
-#endif
-
- g_plugin_module_log_variadic_message(plugin, LMT_INFO,
- _("PYTHONPATH environment variable set to '%s'"),
- getenv("PYTHONPATH"));
-
- /* Chargements des extensions Python */
+ gstate = PyGILState_Ensure();
paths = get_env_var("PYTHONPATH");
@@ -622,7 +543,7 @@ static void load_python_plugins(GPluginModule *plugin)
dir = opendir(path);
if (dir == NULL)
{
- perror("opendir");
+ LOG_ERROR_N("opendir");
continue;
}
@@ -639,7 +560,7 @@ static void load_python_plugins(GPluginModule *plugin)
if (entry == NULL)
{
if (errno != 0)
- perror("readdir");
+ LOG_ERROR_N("readdir");
break;
@@ -703,12 +624,14 @@ static void load_python_plugins(GPluginModule *plugin)
free(paths);
+ PyGILState_Release(gstate);
+
}
/******************************************************************************
* *
-* Paramètres : plugin = interface à manipuler. *
+* Paramètres : manager = interface à manipuler. *
* *
* Description : Accompagne la fin du chargement des modules natifs. *
* *
@@ -718,15 +641,43 @@ static void load_python_plugins(GPluginModule *plugin)
* *
******************************************************************************/
-static void g_pychrysalide_plugin_handle_native_plugins_loaded_event(GPyChrysalidePlugin *plugin)
+static void g_pychrysalide_plugin_handle_native_plugins_loaded_event(GPluginManager *manager)
{
- PyGILState_STATE gstate; /* Sauvegarde d'environnement */
+ GPluginModule *plugin; /* Version de base du greffon */
+#ifdef DISCARD_LOCAL
+ char *edir; /* Répertoire de base effectif */
+ DIR *dir; /* Répertoire à parcourir */
+#endif
- gstate = PyGILState_Ensure();
+ plugin = G_PLUGIN_MODULE(manager);
- load_python_plugins(G_PLUGIN_MODULE(plugin));
+ /* Définition des zones d'influence */
- PyGILState_Release(gstate);
+#ifndef DISCARD_LOCAL
+
+ extend_python_path(plugin, PACKAGE_SOURCE_DIR G_DIR_SEPARATOR_S "plugins" G_DIR_SEPARATOR_S "python");
+
+#else
+
+ edir = get_effective_directory(PLUGINS_DATA_DIR G_DIR_SEPARATOR_S "python");
+
+ dir = opendir(edir);
+
+ if (dir != NULL)
+ {
+ closedir(dir);
+
+ extend_python_path(plugin, edir);
+
+ }
+
+ free(edir);
+
+#endif
+
+ /* Chargements des extensions Python */
+
+ load_python_plugins(plugin);
}
@@ -756,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/plugins/pychrysalide/glibext/secstorage.c b/plugins/pychrysalide/glibext/secstorage.c
index b5adb7c..5935d29 100644
--- a/plugins/pychrysalide/glibext/secstorage.c
+++ b/plugins/pychrysalide/glibext/secstorage.c
@@ -106,14 +106,15 @@ static int py_secret_storage_init(PyObject *self, PyObject *args, PyObject *kwds
"\n" \
"Instances can be created using the following constructor:\n" \
"\n" \
- " SecretStorage(settings)" \
+ " SecretStorage(settings=None)" \
"\n" \
- "The *settings* arguement must point to a GSettings intance;" \
- " the main configuration settings are used by default." \
+ "The *settings* arguement may point to a GSettings instance." \
+ " This optional argument is mainly used for testing purpose;" \
+ " the main configuration settings are used by default."
settings = NULL;
- ret = PyArg_ParseTuple(args, "|O&", convert_to_gsettings, &settings);
+ ret = PyArg_ParseTuple(args, "|O&", convert_to_gsettings_or_none, &settings);
if (!ret) return -1;
/* Initialisation d'un objet GLib */
diff --git a/plugins/pychrysalide/gtkext/Makefile.am b/plugins/pychrysalide/gtkext/Makefile.am
index 2e1260f..1d91751 100644
--- a/plugins/pychrysalide/gtkext/Makefile.am
+++ b/plugins/pychrysalide/gtkext/Makefile.am
@@ -1,19 +1,23 @@
noinst_LTLIBRARIES = libpychrysagtkext.la
+# libpychrysagtkext_la_SOURCES = \
+# blockdisplay.h blockdisplay.c \
+# bufferdisplay.h bufferdisplay.c \
+# displaypanel.h displaypanel.c \
+# dockable.h dockable.c \
+# easygtk.h easygtk.c \
+# module.h module.c \
+# named.h named.c
+
libpychrysagtkext_la_SOURCES = \
- blockdisplay.h blockdisplay.c \
- bufferdisplay.h bufferdisplay.c \
- displaypanel.h displaypanel.c \
- dockable.h dockable.c \
- easygtk.h easygtk.c \
- module.h module.c \
- named.h named.c
-
-libpychrysagtkext_la_LIBADD = \
- graph/libpychrysagtkextgraph.la
-
-libpychrysagtkext_la_CFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+ panel.h panel.c \
+ module.h module.c
+
+# libpychrysagtkext_la_LIBADD = \
+# graph/libpychrysagtkextgraph.la
+
+libpychrysagtkext_la_CFLAGS = $(LIBGTK4_CFLAGS) $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
-I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
@@ -22,4 +26,4 @@ devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libpychrysagtkext_la_SOURCES:%c=)
-SUBDIRS = graph
+#SUBDIRS = graph
diff --git a/plugins/pychrysalide/gtkext/module.c b/plugins/pychrysalide/gtkext/module.c
index f8264af..fa59b2b 100644
--- a/plugins/pychrysalide/gtkext/module.c
+++ b/plugins/pychrysalide/gtkext/module.c
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* module.c - intégration du répertoire gtkext en tant que module
*
- * Copyright (C) 2018-2019 Cyrille Bagard
+ * Copyright (C) 2018-2025 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -28,13 +28,13 @@
#include <assert.h>
-#include "blockdisplay.h"
-#include "bufferdisplay.h"
-#include "displaypanel.h"
-#include "dockable.h"
-#include "easygtk.h"
-#include "named.h"
-#include "graph/module.h"
+//#include "blockdisplay.h"
+//#include "bufferdisplay.h"
+//#include "displaypanel.h"
+//#include "dockable.h"
+//#include "named.h"
+#include "panel.h"
+//#include "graph/module.h"
#include "../helpers.h"
@@ -71,7 +71,7 @@ bool add_gtkext_module(PyObject *super)
result = (module != NULL);
- if (result) result = add_gtkext_graph_module(module);
+ //if (result) result = add_gtkext_graph_module(module);
if (!result)
Py_XDECREF(module);
@@ -99,14 +99,16 @@ bool populate_gtkext_module(void)
result = true;
- if (result) result = ensure_python_block_display_is_registered();
- if (result) result = ensure_python_buffer_display_is_registered();
- if (result) result = ensure_python_display_panel_is_registered();
- if (result) result = ensure_python_dockable_is_registered();
- if (result) result = ensure_python_easygtk_is_registered();
- if (result) result = ensure_python_built_named_widget_is_registered();
+ if (result) result = ensure_python_tiled_panel_is_registered();
- if (result) result = populate_gtkext_graph_module();
+ //if (result) result = ensure_python_block_display_is_registered();
+ //if (result) result = ensure_python_buffer_display_is_registered();
+ //if (result) result = ensure_python_display_panel_is_registered();
+ //if (result) result = ensure_python_dockable_is_registered();
+ //if (result) result = ensure_python_easygtk_is_registered();
+ //if (result) result = ensure_python_built_named_widget_is_registered();
+
+ //if (result) result = populate_gtkext_graph_module();
assert(result);
diff --git a/plugins/pychrysalide/gtkext/panel.c b/plugins/pychrysalide/gtkext/panel.c
new file mode 100644
index 0000000..9f6589a
--- /dev/null
+++ b/plugins/pychrysalide/gtkext/panel.c
@@ -0,0 +1,130 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * panel.c - prototypes pour l'équivalent Python du fichier "gtkext/panel.c"
+ *
+ * Copyright (C) 2025 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "panel.h"
+
+
+#include <pygobject.h>
+
+
+#include <gtkext/panel.h>
+
+
+#include "../access.h"
+#include "../helpers.h"
+#include "../helpers-ui.h"
+
+
+
+#define TILED_PANEL_DOC \
+ "The TiledPanel class defines a panel widget for the framework main" \
+ " window."
+
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_tiled_panel_type(void)
+{
+ static PyMethodDef py_tiled_panel_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_tiled_panel_getseters[] = {
+ { NULL }
+ };
+
+ static PyTypeObject py_tiled_panel_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.gtkext.TiledPanel",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = TILED_PANEL_DOC,
+
+ .tp_methods = py_tiled_panel_methods,
+ .tp_getset = py_tiled_panel_getseters,
+
+ };
+
+ static PyTypeObject *result = NULL;
+
+ if (result == NULL)
+ result = define_python_dynamic_type(&py_tiled_panel_type);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide.gtkext.TiledPanel'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_tiled_panel_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python 'TiledPanel' */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_tiled_panel_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.gtkext");
+
+ dict = PyModule_GetDict(module);
+
+ if (!ensure_gtk_widget_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, GTK_TYPE_TILED_PANEL, type))
+ return false;
+
+ }
+
+ return true;
+
+}
diff --git a/plugins/pychrysalide/gtkext/panel.h b/plugins/pychrysalide/gtkext/panel.h
new file mode 100644
index 0000000..c5cbe86
--- /dev/null
+++ b/plugins/pychrysalide/gtkext/panel.h
@@ -0,0 +1,42 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * panel.h - prototypes pour l'équivalent Python du fichier "gtkext/panel.h"
+ *
+ * Copyright (C) 2025 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_PYCHRYSALIDE_GTKEXT_PANEL_H
+#define _PLUGINS_PYCHRYSALIDE_GTKEXT_PANEL_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_tiled_panel_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.gtkext.TiledPanel'. */
+bool ensure_python_tiled_panel_is_registered(void);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_GTKEXT_PANEL_H */
diff --git a/plugins/pychrysalide/helpers-ui.c b/plugins/pychrysalide/helpers-ui.c
new file mode 100644
index 0000000..982e676
--- /dev/null
+++ b/plugins/pychrysalide/helpers-ui.c
@@ -0,0 +1,141 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * helpers-ui.c - simplification des interactions UI de base avec Python
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "helpers-ui.h"
+
+
+#include <assert.h>
+#include <pygobject.h>
+#include <gtk/gtk.h>
+
+
+#include "bindings.h"
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* CONFORTS CIBLANT PYGOBJECT */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Assure une prise en charge de l'objet Gtk.WIdget. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_gtk_widget_is_registered(void)
+{
+ bool result; /* Bilan à retourner */
+ PyObject *gtk_mod; /* Module Python Gtk */
+ PyObject *widget_type; /* Module "GtkWidget" */
+
+ /**
+ * Afin d'éviter le message d'avertissement suivant, la version attendue
+ * est demandée :
+ *
+ * PyGIWarning: Gtk was imported without specifying a version first.
+ * Use gi.require_version('Gtk', '4.0') before import to ensure that the right version gets loaded.
+ *
+ */
+ result = import_namespace_from_gi_repository("Gtk", "4.0");
+
+ if (result)
+ {
+ gtk_mod = PyImport_ImportModule("gi.repository.Gtk");
+ assert(gtk_mod != NULL);
+
+ widget_type = PyObject_GetAttrString(gtk_mod, "Widget");
+
+ result = (widget_type != NULL);
+
+ Py_DECREF(gtk_mod);
+ Py_XDECREF(widget_type);
+
+ }
+
+ return result;
+
+}
+
+
+
+/******************************************************************************
+* *
+* Paramètres : arg = argument quelconque à tenter de convertir. *
+* dst = destination des valeurs récupérées en cas de succès. *
+* *
+* Description : Tente de convertir en instance de composant GTK. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_gtk_widget(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+ PyObject *gtk_mod; /* Module Python Gtk */
+ PyObject *widget_type; /* Module "GtkWidget" */
+ int ret; /* Bilan d'une conversion */
+
+ result = 0;
+
+ gtk_mod = PyImport_ImportModule("gi.repository.Gtk");
+
+ if (gtk_mod == NULL)
+ {
+ PyErr_SetString(PyExc_TypeError, "unable to find the Gtk Python module");
+ goto done;
+ }
+
+ widget_type = PyObject_GetAttrString(gtk_mod, "Widget");
+
+ Py_DECREF(gtk_mod);
+
+ ret = PyObject_TypeCheck(arg, (PyTypeObject *)widget_type);
+
+ Py_DECREF(widget_type);
+
+ if (!ret)
+ {
+ PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to GTK widget");
+ goto done;
+ }
+
+ *((GtkWidget **)dst) = GTK_WIDGET(pygobject_get(arg));
+
+ result = 1;
+
+ done:
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/helpers-ui.h b/plugins/pychrysalide/helpers-ui.h
new file mode 100644
index 0000000..b575905
--- /dev/null
+++ b/plugins/pychrysalide/helpers-ui.h
@@ -0,0 +1,44 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * helpers-ui.h - prototypes pour la simplification des interactions UI de base avec Python
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_PYCHRYSALIDE_HELPERS_UI_H
+#define _PLUGINS_PYCHRYSALIDE_HELPERS_UI_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* --------------------------- CONFORTS CIBLANT PYGOBJECT --------------------------- */
+
+
+/* Assure une prise en charge de l'objet Gtk.WIdget. */
+bool ensure_gtk_widget_is_registered(void);
+
+/* Tente de convertir en instance de composant GTK. */
+int convert_to_gtk_widget(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_HELPERS_UI_H */
diff --git a/plugins/pychrysalide/helpers.c b/plugins/pychrysalide/helpers.c
index 0c84278..4ff768c 100644
--- a/plugins/pychrysalide/helpers.c
+++ b/plugins/pychrysalide/helpers.c
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* helpers.c - simplification des interactions de base avec Python
*
- * Copyright (C) 2018-2024 Cyrille Bagard
+ * Copyright (C) 2018-2025 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -32,9 +32,6 @@
#include <stdlib.h>
#include <string.h>
#include <strings.h>
-#ifdef INCLUDE_GTK_SUPPORT
-# include <gtk/gtk.h>
-#endif
#include <i18n.h>
@@ -1260,122 +1257,6 @@ int convert_to_gobject(PyObject *arg, void *dst)
#if 0
-#ifdef INCLUDE_GTK_SUPPORT
-
-
-/******************************************************************************
-* *
-* Paramètres : arg = argument quelconque à tenter de convertir. *
-* dst = destination des valeurs récupérées en cas de succès. *
-* *
-* Description : Tente de convertir en instance de composant GTK. *
-* *
-* Retour : Bilan de l'opération, voire indications supplémentaires. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-int convert_to_gtk_widget(PyObject *arg, void *dst)
-{
- int result; /* Bilan à retourner */
- PyObject *gtk_mod; /* Module Python Gtk */
- PyObject *widget_type; /* Module "GtkWidget" */
- int ret; /* Bilan d'une conversion */
-
- result = 0;
-
- gtk_mod = PyImport_ImportModule("gi.repository.Gtk");
-
- if (gtk_mod == NULL)
- {
- PyErr_SetString(PyExc_TypeError, "unable to find the Gtk Python module");
- goto done;
- }
-
- widget_type = PyObject_GetAttrString(gtk_mod, "Widget");
-
- Py_DECREF(gtk_mod);
-
- ret = PyObject_TypeCheck(arg, (PyTypeObject *)widget_type);
-
- Py_DECREF(widget_type);
-
- if (!ret)
- {
- PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to GTK widget");
- goto done;
- }
-
- *((GtkWidget **)dst) = GTK_WIDGET(pygobject_get(arg));
-
- result = 1;
-
- done:
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : arg = argument quelconque à tenter de convertir. *
-* dst = destination des valeurs récupérées en cas de succès. *
-* *
-* Description : Tente de convertir en instance de conteneur GTK. *
-* *
-* Retour : Bilan de l'opération, voire indications supplémentaires. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-int convert_to_gtk_container(PyObject *arg, void *dst)
-{
- int result; /* Bilan à retourner */
- PyObject *gtk_mod; /* Module Python Gtk */
- PyObject *container_type; /* Module "GtkContainer" */
- int ret; /* Bilan d'une conversion */
-
- result = 0;
-
- gtk_mod = PyImport_ImportModule("gi.repository.Gtk");
-
- if (gtk_mod == NULL)
- {
- PyErr_SetString(PyExc_TypeError, "unable to find the Gtk Python module");
- goto done;
- }
-
- container_type = PyObject_GetAttrString(gtk_mod, "Container");
-
- Py_DECREF(gtk_mod);
-
- ret = PyObject_TypeCheck(arg, (PyTypeObject *)container_type);
-
- Py_DECREF(container_type);
-
- if (!ret)
- {
- PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to GTK container");
- goto done;
- }
-
- *((GtkContainer **)dst) = GTK_CONTAINER(pygobject_get(arg));
-
- result = 1;
-
- done:
-
- return result;
-
-}
-
-
-#endif
-
-
/******************************************************************************
* *
* Paramètres : color = couleur dans sa définition native à copier. *
diff --git a/plugins/pychrysalide/helpers.h b/plugins/pychrysalide/helpers.h
index 745d013..f1c6337 100644
--- a/plugins/pychrysalide/helpers.h
+++ b/plugins/pychrysalide/helpers.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* helpers.h - prototypes pour la simplification des interactions de base avec Python
*
- * Copyright (C) 2018-2024 Cyrille Bagard
+ * Copyright (C) 2018-2025 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -313,17 +313,6 @@ int convert_to_gobject(PyObject *, void *);
#if 0
-#ifdef INCLUDE_GTK_SUPPORT
-
-/* Tente de convertir en instance de composant GTK. */
-int convert_to_gtk_widget(PyObject *, void *);
-
-/* Tente de convertir en instance de conteneur GTK. */
-int convert_to_gtk_container(PyObject *, void *);
-
-#endif
-
-
#if !defined(INCLUDE_GTK_SUPPORT) && !defined(HOMEMADE_RGBA)
# define HOMEMADE_RGBA
diff --git a/src/Makefile.am b/src/Makefile.am
index 5c4d1e3..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 =
@@ -103,13 +109,14 @@ libchrysacoreui_la_SOURCES =
libchrysacoreui_la_LIBADD = \
arch/libarchui.la \
+ data/images/libdataimages.la \
glibext/libglibextui.la \
gtkext/libgtkext4.la \
gui/libgui4.la
# -lm: log()
libchrysacoreui_la_LDFLAGS = \
- $(LIBGTK4_CFLAGS) -L.libs -lchrysacore4 \
+ $(LIBGTK4_LIBS) -L.libs -lchrysacore4 \
-lm
@@ -189,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 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)
diff --git a/src/app.c b/src/app.c
index 2e0d4fa..ef62135 100644
--- a/src/app.c
+++ b/src/app.c
@@ -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");
@@ -505,6 +505,32 @@ int main(int argc, char **argv)
set_log_verbosity(verbosity);
+ /**
+ * Même s'il est dit que l'usage de GtkApplication permet de s'affranchir
+ * d'un appel à gtk_init(), il se trouve que la journalisation en mode
+ * graphique peut solliciter le panneau en GTK pour afficher des messages
+ * avant la mise en place de l'applicatif GTK principal :
+ *
+ * #2 0x00007ffff7b33403 in gtk_css_lookup_resolve (lookup=lookup@entry=0x7fffffff88a0, provider=provider@entry=0x0, sstyle=sstyle@entry=0x7fffe800a730, parent_style=parent_style@entry=0x0) at ../gtk/gtkcssstaticstyle.c:911
+ * #3 0x00007ffff7b3389f in gtk_css_static_style_new_compute (provider=0x0, filter=filter@entry=0x7fffffff8ea0, node=node@entry=0x0, change=<optimized out>, change@entry=0) at ../gtk/gtkcssstaticstyle.c:1026
+ * #4 0x00007ffff7b3392c in gtk_css_static_style_get_default () at ../gtk/gtkcssstaticstyle.c:711
+ * #5 0x00007ffff7b24b09 in gtk_css_node_init (cssnode=0x7fffe800a5b0) at ../gtk/gtkcssnode.c:641
+ * #6 0x00007ffff75d8dab in g_type_create_instance () at /lib/x86_64-linux-gnu/libgobject-2.0.so.0
+ * [...]
+ * #10 0x00007ffff7b3b8fa in gtk_css_widget_node_new (widget=widget@entry=0x5555555bf1b0) at ../gtk/gtkcsswidgetnode.c:160
+ * #11 0x00007ffff7ae4576 in gtk_widget_init (instance=<optimized out>, g_class=0x5555555be380) at ../gtk/gtkwidget.c:2345
+ * [...]
+ * #16 0x00007ffff73fd3f4 in get_framework_panel_singleton (...) at panels.c:329
+ * #17 0x00007ffff73fce35 in do_log_message_alt (...) at logs.c:56
+ * [...]
+ * #23 0x00007ffff74566db in init_all_plugins (load=true) at pglist.c:103
+ * #24 0x0000555555556d44 in main (argc=2, argv=0x7fffffffb568) at app.c:514
+ *
+ * L'initialisation permettant un retour de gtk_settings_get_default() non
+ * nul est ainsi forcée au plus tôt avec un appel à gtk_init() manuel.
+ */
+ gtk_init();
+
if (!load_core_components(ACC_GLOBAL_VARS))
goto exit;
diff --git a/src/arch/Makefile.am b/src/arch/Makefile.am
index 127ca4c..6683854 100644
--- a/src/arch/Makefile.am
+++ b/src/arch/Makefile.am
@@ -13,18 +13,17 @@ noinst_LTLIBRARIES = libarch.la libarchui.la
# libarch_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS)
# libarch_la_LIBADD = \
-# instructions/libarchinstructions.la \
# operands/libarchoperands.la
-# instruction-int.h \
-# instruction.h instruction.c \
#
# processor-int.h \
# processor.h processor.c \
#
libarch_la_SOURCES = \
+ instruction-int.h \
+ instruction.h instruction.c \
operand-int.h \
operand.h operand.c \
register-int.h \
@@ -34,10 +33,13 @@ libarch_la_SOURCES = \
libarch_la_CFLAGS = $(LIBGOBJ_CFLAGS)
libarch_la_LIBADD = \
+ instructions/libarchinstructions.la \
operands/libarchoperands.la
libarchui_la_SOURCES = \
+ instruction-ui-int.h \
+ instruction-ui.h instruction-ui.c \
operand-ui-int.h \
operand-ui.h operand-ui.c
@@ -52,5 +54,4 @@ devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%)
dev_HEADERS = $(libarch_la_SOURCES:%c=) $(libarchui_la_SOURCES:%c=)
-#SUBDIRS = instructions operands
-SUBDIRS = operands
+SUBDIRS = instructions operands
diff --git a/src/arch/instruction-int.h b/src/arch/instruction-int.h
index 7dbbe27..d426cea 100644
--- a/src/arch/instruction-int.h
+++ b/src/arch/instruction-int.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* instruction-int.h - prototypes pour la définition générique interne des instructions
*
- * Copyright (C) 2008-2020 Cyrille Bagard
+ * Copyright (C) 2008-2025 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -25,18 +25,29 @@
#define _ARCH_INSTRUCTION_INT_H
+#include <stdint.h>
+
+
#include "instruction.h"
-#include "../analysis/storage/storage.h"
#include "../common/array.h"
-#include "../glibext/objhole.h"
+#include "../glibext/objhole-int.h"
/* Indique l'encodage d'une instruction de façon détaillée. */
-typedef const char * (* get_instruction_encoding_fc) (const GArchInstruction *);
+typedef char * (* get_instruction_encoding_fc) (const GArchInstruction *);
/* Fournit le nom humain de l'instruction manipulée. */
-typedef const char * (* get_instruction_keyword_fc) (GArchInstruction * );
+typedef char * (* get_instruction_keyword_fc) (const GArchInstruction *);
+
+
+
+#if 0
+
+#include "../analysis/storage/storage.h"
+
+
+
/* Complète un désassemblage accompli pour une instruction. */
typedef void (* call_instruction_hook_fc) (GArchInstruction *, InstrProcessHook, GArchProcessor *, GProcContext *, GExeFormat *);
@@ -67,80 +78,45 @@ typedef bool (* store_instruction_fc) (GArchInstruction *, GObjectStorage *, pac
-/* Informations glissées dans la structure GObject de GArchOperand */
-typedef struct _instr_extra_data_t
-{
- itid_t uid; /* Identifiant unique du type */
-
- ArchInstrFlag flags; /* Informations complémentaires*/
-
-} instr_extra_data_t;
+#endif
-/* Informations glissées dans la structure GObject de GArchInstruction */
-typedef union _instr_obj_extra_t
-{
- instr_extra_data_t data; /* Données embarquées */
- lockable_obj_extra_t lockable; /* Gestion d'accès aux fanions */
-} instr_obj_extra_t;
+/* Conservation d'une adresse et de propriétées */
+typedef unsigned long compact_ins_link_t;
/* Définition générique d'une instruction d'architecture (instance) */
struct _GArchInstruction
{
- GObject parent; /* A laisser en premier */
+ GThickObject parent; /* A laisser en premier */
-#if 1 //__SIZEOF_INT__ == __SIZEOF_LONG__
+ GBinaryPortion *rel_area; /* Zone de référence */
+ rel_mrange_t rel_range; /* Emplacement compressé */
/**
- * L'inclusion des informations suivantes dépend de l'architecture.
- *
- * Si la structure GObject possède un trou, on remplit de préférence
- * ce dernier.
+ * A laisser à la suite de la localisation précédente pour éviter
+ * les espaces vide dans la structure.
*/
+ uint16_t link_count; /* Quantité de liens établis */
- instr_obj_extra_t extra; /* Externalisation embarquée */
-
-#endif
-
- mrange_t range; /* Emplacement en mémoire */
+ compact_ins_link_t *links; /* Liste de ces liens */
flat_array_t *operands; /* Liste des opérandes */
- /**
- * Il existe le besoin indéniable d'un verrou pour les accès aux instructions
- * liées. Il faut par ailleurs un verrou distinct pour les sources et les
- * destinations car une même instruction peut boucler sur elle même et la
- * fonction g_arch_instruction_change_link() pose des verrous sur les
- * deux extrémités.
- *
- * La GLib propose les fonctions g_bit_lock() / g_bit_unlock(), légères mais
- * sans distinction entre lectures et écritures. Tant pis : la réduction de
- * l'empreinte mémoire prime !
- *
- * Par contre la documentation indique :
- *
- * """
- * Attempting to lock on two different bits within the same integer is not supported.
- * """
- *
- * Donc on doit bien conserver un compteur distinct pour chaque extrémité.
- * Cela correspond de toute façon à la définition optimisée des tableaux
- * suivante.
- */
-
- flat_array_t *from; /* Origines des références */
- flat_array_t *to; /* Instructions visées */
-
};
/* Définition générique d'une instruction d'architecture (classe) */
struct _GArchInstructionClass
{
- GObjectClass parent; /* A laisser en premier */
+ GThickObjectClass parent; /* A laisser en premier */
get_instruction_encoding_fc get_encoding; /* Obtention de l'encodage */
get_instruction_keyword_fc get_keyword; /* Texte humain équivalent */
+
+#if 0
+
+ //get_instruction_encoding_fc get_encoding; /* Obtention de l'encodage */
+ //get_instruction_keyword_fc get_keyword; /* Texte humain équivalent */
call_instruction_hook_fc call_hook; /* Décrochages éventuels */
build_instruction_tooltip_fc build_tooltip; /* Construction d'une bulle*/
get_instruction_desc_fc get_desc; /* Description assez complète */
@@ -155,22 +131,50 @@ struct _GArchInstructionClass
//get_instruction_rw_regs_fc get_rw_regs; /* Liste des registres liés */
+#endif
+
};
+/* Met en place une instruction d'architecture. */
+bool g_arch_instruction_create(GArchInstruction *, itid_t);
+
+
+
/**
* Accès aux informations éventuellement déportées.
*/
-#if 1 //__SIZEOF_INT__ == __SIZEOF_LONG__
-# define GET_ARCH_INSTR_EXTRA(ins) (instr_extra_data_t *)&ins->extra
+#define ARCH_INSTRUCTION_EXTRA_DATA \
+ \
+ unsigned int reserved : GOBJECT_RESERVED_EXTRA_BITS; \
+ \
+ /** \
+ * itid_t \
+ */ \
+ unsigned int tid : 16; \
+ \
+ /** \
+ * ArchOperandFlag \
+ */ \
+ unsigned int flags : 8;
-#else
-# define GET_ARCH_INSTR_EXTRA(ins) GET_GOBJECT_EXTRA(G_OBJECT(ins), instr_extra_data_t)
+/* Informations glissées dans la structure GObject de GArchOperand */
+typedef struct _instruction_extra_data_t
+{
+ ARCH_INSTRUCTION_EXTRA_DATA; /* Socle commun */
+
+} instruction_extra_data_t;
+
+
+#define GET_ARCH_INSTR_EXTRA(op) \
+ GET_GOBJECT_EXTRA(op, instruction_extra_data_t)
+
+#define SET_ARCH_INSTR_EXTRA(op, data) \
+ SET_GOBJECT_EXTRA(op, instruction_extra_data_t, data)
-#endif
/**
diff --git a/src/arch/instruction-ui-int.h b/src/arch/instruction-ui-int.h
new file mode 100644
index 0000000..b07f40c
--- /dev/null
+++ b/src/arch/instruction-ui-int.h
@@ -0,0 +1,55 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * instruction-ui-int.h - prototypes pour la définition générique interne des instructions sous forme graphique
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ARCH_INSTRUCTION_UI_INT_H
+#define _ARCH_INSTRUCTION_UI_INT_H
+
+
+#include "instruction-ui.h"
+
+
+
+#if 0
+
+/* Traduit un opérande en version humainement lisible. */
+typedef void (* print_operand_ui_fc) (const GArchOperandUI *, GBufferLine *);
+
+/* Construit un petit résumé concis de l'opérande. */
+typedef char * (* build_operand_ui_tooltip_fc) (const GArchOperandUI *, const GLoadedBinary *);
+
+
+
+/* Définition générique d'un opérande d'architecture (interface) */
+struct _GArchOperandUIInterface
+{
+ GTypeInterface base_iface; /* A laisser en premier */
+
+ print_operand_ui_fc print; /* Texte humain équivalent */
+ build_operand_ui_tooltip_fc build_tooltip; /* Définition de description*/
+
+};
+
+#endif
+
+
+#endif /* _ARCH_INSTRUCTION_UI_INT_H */
diff --git a/src/arch/instruction-ui.c b/src/arch/instruction-ui.c
new file mode 100644
index 0000000..7f923d8
--- /dev/null
+++ b/src/arch/instruction-ui.c
@@ -0,0 +1,254 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * instruction-ui.c - gestion générique des instructions sous forme graphique
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "instruction-ui.h"
+
+
+#include "instruction-int.h"
+#include "operand-ui.h"
+#include "../analysis/content.h"
+#include "../common/cpp.h"
+#include "../glibext/generator-int.h"
+#include "../glibext/options/asm.h"
+
+
+
+/* ------------------------ OFFRE DE CAPACITES DE GENERATION ------------------------ */
+
+
+/* Renseigne sur les propriétés liées à un générateur. */
+static BufferLineFlags g_arch_instruction_ui_get_flags(const GTokenGenerator *, size_t, size_t);
+
+/* Etablit dans une ligne de rendu le contenu représenté. */
+static void g_arch_instruction_ui_populate_line(const GTokenGenerator *, size_t, size_t, GBufferLine *, void *);
+
+#if 0
+
+/* Retrouve l'emplacement correspondant à une position donnée. */
+static void g_arch_instruction_ui_compute_cursor(const GArchInstruction *, gint, size_t, size_t, GLineCursor **);
+
+/* Détermine si le conteneur s'inscrit dans une plage donnée. */
+static int g_arch_instruction_ui_contain_cursor(const GArchInstruction *, size_t, size_t, const GLineCursor *);
+
+#endif
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* OFFRE DE CAPACITES DE GENERATION */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : iface = interface GLib à initialiser. *
+* *
+* Description : Procède à l'initialisation de l'interface de génération. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_arch_instruction_ui_token_generator_iface_init(GTokenGeneratorInterface *iface)
+{
+ /**
+ * La procédure par défaut de iface->count() ne doit pas être retouchée !
+ */
+
+ iface->get_flags = g_arch_instruction_ui_get_flags;
+ iface->populate = g_arch_instruction_ui_populate_line;
+
+#if 0
+ iface->compute = (linegen_compute_fc)g_arch_instruction_ui_compute_cursor;
+ iface->contain = (linegen_contain_fc)g_arch_instruction_ui_contain_cursor;
+#endif
+
+}
+
+
+/******************************************************************************
+* *
+* 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. *
+* *
+* Description : Renseigne sur les propriétés liées à un générateur. *
+* *
+* Retour : Propriétés particulières associées. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static BufferLineFlags g_arch_instruction_ui_get_flags(const GTokenGenerator *generator, size_t index, size_t repeat)
+{
+ BufferLineFlags result; /* Fanions à retourner */
+
+ result = BLF_HAS_CODE;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* 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_arch_instruction_ui_populate_line(const GTokenGenerator *generator, size_t index, size_t repeat, GBufferLine *line, void *data)
+{
+ GArchInstruction *instr; /* Version spécialisée */
+ GBinContent *content; /* Contenu brut d'origine */
+ mrange_t range; /* Emplacement couvert */
+ char *key; /* Mot clef principal */
+ size_t count; /* Nombre d'opérandes en place */
+ size_t i; /* Boucle de parcours */
+ GArchOperand *op; /* Opérande à manipuler */
+
+ instr = G_ARCH_INSTRUCTION(generator);
+ content = G_BIN_CONTENT(data);
+
+ /* Prologue */
+
+ if (g_arch_instruction_get_range(instr, &range))
+ {
+ g_buffer_line_fill_physical(line, ACO_PHYSICAL, MDS_32_BITS_UNSIGNED, get_mrange_addr(&range));
+
+ g_buffer_line_fill_virtual(line, ACO_VIRTUAL, MDS_32_BITS_UNSIGNED, get_mrange_addr(&range));
+
+ g_buffer_line_fill_content(line, ACO_BINARY, content, &range, VMPA_NO_PHYSICAL);
+
+ }
+
+ /* Instruction proprement dite */
+
+ key = g_arch_instruction_get_keyword(instr);
+
+ g_buffer_line_append_text(line, ACO_ASSEMBLY_HEAD, TRT_INSTRUCTION, SL(key), NULL, G_OBJECT(instr));
+
+ free(key);
+
+ /* Liste des opérandes */
+
+ g_thick_object_lock(G_THICK_OBJECT(instr));
+
+ count = g_arch_instruction_count_operands(instr);
+
+ if (count > 0)
+ {
+ op = g_arch_instruction_get_operand(instr, 0);
+ g_arch_operand_ui_print(G_ARCH_OPERAND_UI(op), line);
+ unref_object(op);
+
+ for (i = 1; i < count; i++)
+ {
+ g_buffer_line_append_text(line, ACO_ASSEMBLY, TRT_PUNCT, STCSL(","), NULL, NULL);
+ g_buffer_line_append_text(line, ACO_ASSEMBLY, TRT_NONE, STCSL(" "), NULL, NULL);
+
+ op = g_arch_instruction_get_operand(instr, i);
+ g_arch_operand_ui_print(G_ARCH_OPERAND_UI(op), line);
+ unref_object(op);
+
+ }
+
+ }
+
+ g_thick_object_unlock(G_THICK_OBJECT(instr));
+
+}
+
+
+#if 0
+
+
+/******************************************************************************
+* *
+* Paramètres : instr = 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. *
+* cursor = emplacement à constituer. [OUT] *
+* *
+* Description : Retrouve l'emplacement correspondant à une position donnée. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_arch_instruction_ui_compute_cursor(const GArchInstruction *instr, gint x, size_t index, size_t repeat, GLineCursor **cursor)
+{
+ *cursor = g_binary_cursor_new();
+
+ g_binary_cursor_update(G_BINARY_CURSOR(*cursor), get_mrange_addr(&instr->range));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : instr = générateur à consulter. *
+* index = indice de cette même ligne dans le tampon global. *
+* repeat = indice d'utilisations successives du générateur. *
+* cursor = emplacement à analyser. *
+* *
+* Description : Détermine si le conteneur s'inscrit dans une plage donnée. *
+* *
+* Retour : Bilan de la détermination, utilisable en comparaisons. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int g_arch_instruction_ui_contain_cursor(const GArchInstruction *instr, size_t index, size_t repeat, const GLineCursor *cursor)
+{
+ int result; /* Conclusion à retourner */
+ vmpa2t addr; /* Autre emplacement à comparer*/
+
+ assert(G_IS_BINARY_CURSOR(cursor));
+
+ g_binary_cursor_retrieve(G_BINARY_CURSOR(cursor), &addr);
+
+ result = cmp_mrange_with_vmpa(&instr->range, &addr);
+
+ return result;
+
+}
+
+
+#endif
diff --git a/src/arch/instruction-ui.h b/src/arch/instruction-ui.h
new file mode 100644
index 0000000..62a52f2
--- /dev/null
+++ b/src/arch/instruction-ui.h
@@ -0,0 +1,41 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * instruction-ui.h - prototypes pour la gestion générique des instructions sous forme graphique
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ARCH_INSTRUCTION_UI_H
+#define _ARCH_INSTRUCTION_UI_H
+
+
+#include "../glibext/generator.h"
+#include "../glibext/helpers.h"
+
+
+
+/* ------------------------ OFFRE DE CAPACITES DE GENERATION ------------------------ */
+
+
+/* Procède à l'initialisation de l'interface de génération. */
+void g_arch_instruction_ui_token_generator_iface_init(GTokenGeneratorInterface *);
+
+
+
+#endif /* _ARCH_INSTRUCTION_UI_H */
diff --git a/src/arch/instruction.c b/src/arch/instruction.c
index cd1e9c7..36bdecb 100644
--- a/src/arch/instruction.c
+++ b/src/arch/instruction.c
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* instruction.c - gestion générique des instructions
*
- * Copyright (C) 2008-2020 Cyrille Bagard
+ * Copyright (C) 2008-2025 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -26,102 +26,93 @@
#include <assert.h>
#include <malloc.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
+#include <limits.h>
#include <string.h>
#include "instruction-int.h"
-#include "storage.h"
-#include "../analysis/storage/serialize-int.h"
-#include "../core/columns.h"
+#include "../common/leb128.h"
#include "../core/logs.h"
#include "../core/processors.h"
-#include "../glibext/gbinarycursor.h"
-#include "../glibext/linegen-int.h"
+#include "../glibext/serialize-int.h"
-/* Initialise la classe générique des instructions. */
-static void g_arch_instruction_class_init(GArchInstructionClass *);
-
-/* Initialise une instance d'opérande d'architecture. */
-static void g_arch_instruction_init(GArchInstruction *);
-/* Procède à l'initialisation de l'interface de génération. */
-static void g_arch_instruction_generator_init(GLineGeneratorInterface *);
-/* Procède à l'initialisation de l'interface de sérialisation. */
-static void g_arch_instruction_serializable_init(GSerializableObjectInterface *);
-
-/* Supprime toutes les références externes. */
-static void g_arch_instruction_dispose(GArchInstruction *);
-
-/* Procède à la libération totale de la mémoire. */
-static void g_arch_instruction_finalize(GArchInstruction *);
+/* ----------------------- DEFINITION GENERIQUE D'INSTRUCTION ----------------------- */
+/* Initialise la classe générique des instructions. */
+static void g_arch_instruction_class_init(GArchInstructionClass *);
+/* Procède à l'initialisation de l'interface de sérialisation. */
+static void g_arch_instruction_serializable_object_iface_init(GSerializableObjectInterface *);
-/* Charge un contenu depuis une mémoire tampon. */
-static bool g_arch_instruction_load_destinations(GArchInstruction *, GObjectStorage *, packed_buffer_t *);
+/* Initialise une instance d'opérande d'architecture. */
+static void g_arch_instruction_init(GArchInstruction *);
-/* Sauvegarde toutes les destinations d'une instruction. */
-bool g_arch_instruction_store_destinations(GArchInstruction *, GObjectStorage *, packed_buffer_t *);
+/* Supprime toutes les références externes. */
+static void g_arch_instruction_dispose(GObject *);
+/* Procède à la libération totale de la mémoire. */
+static void g_arch_instruction_finalize(GObject *);
+/* ------------------- DEFINITION DES LIAISONS ENTRE INSTRUCTIONS ------------------- */
-/* ------------------------ OFFRE DE CAPACITES DE GENERATION ------------------------ */
+#define COMPACT_INS_LINK_MASK_DIR (1ul << (__WORDSIZE - 1))
+#define COMPACT_INS_LINK_MASK_TYPE 0xf
+#define COMPACT_INS_LINK_MASK (COMPACT_INS_LINK_MASK_DIR | COMPACT_INS_LINK_MASK_TYPE)
-/* Indique le nombre de ligne prêtes à être générées. */
-static size_t g_arch_instruction_count_lines(const GArchInstruction *);
+#define COMPACT_INS_LINK_FROM (0ul << (__WORDSIZE - 1))
+#define COMPACT_INS_LINK_TO (1ul << (__WORDSIZE - 1))
-#ifdef INCLUDE_GTK_SUPPORT
+#define COMPACT_INS_LINK_DIR(cl) (cl & COMPACT_INS_LINK_MASK_DIR)
+#define COMPACT_INS_LINK_PTR(cl) ((GArchInstruction *)(cl & ~COMPACT_INS_LINK_MASK))
+#define COMPACT_INS_LINK_TYPE(cl) (cl & COMPACT_INS_LINK_MASK_TYPE)
-/* Retrouve l'emplacement correspondant à une position donnée. */
-static void g_arch_instruction_compute_cursor(const GArchInstruction *, gint, size_t, size_t, GLineCursor **);
+#define MAKE_COMPACT_INS_LINK(d, i, t) \
+ (compact_ins_link_t)(d | (unsigned long)i | t)
-/* Détermine si le conteneur s'inscrit dans une plage donnée. */
-static int g_arch_instruction_contain_cursor(const GArchInstruction *, size_t, size_t, const GLineCursor *);
+/* Détermine si un type de lien existe dans une instruction. */
+static bool _g_arch_instruction_has_link(const GArchInstruction *, compact_ins_link_t, InstructionLinkType);
-#endif
+/* Détermine si un lien existe entre deux instructions. */
+static bool _g_arch_instruction_has_link_with(const GArchInstruction *, compact_ins_link_t, const GArchInstruction *);
-/* Renseigne sur les propriétés liées à un générateur. */
-static BufferLineFlags g_arch_instruction_get_flags2(const GArchInstruction *, size_t, size_t);
+/* Fournit la quantité d'instructions pointant vers une autre. */
+static size_t _g_arch_instruction_count_links(const GArchInstruction *, compact_ins_link_t);
-/* Ajoute à un tampon GLib le contenu de l'instance spécifiée. */
-static void _g_arch_instruction_print(GArchInstruction *, GBufferLine *, size_t, size_t, const GBinContent *);
+/* Fournit les détails d'un lien donné avec une instruction. */
+static GArchInstruction *_g_arch_instruction_get_linked_instruction(const GArchInstruction *, size_t, compact_ins_link_t, InstructionLinkType *);
-/* Imprime dans une ligne de rendu le contenu représenté. */
-static void g_arch_instruction_print(GArchInstruction *, GBufferLine *, size_t, size_t, const GBinContent *);
-/* -------------------- CONSERVATION ET RECHARGEMENT DES DONNEES -------------------- */
+/* ------------------- MECANISMES DE CONSERVATION ET RESTAURATION ------------------- */
-/* Charge un contenu depuis une mémoire tampon. */
-static bool _g_arch_instruction_load(GArchInstruction *, GObjectStorage *, packed_buffer_t *);
+/* Charge un objet depuis un flux de données. */
+static bool g_arch_instruction_load(GSerializableObject *, GObjectStorage *, int);
-/* Charge un contenu depuis une mémoire tampon. */
-static bool g_arch_instruction_load(GArchInstruction *, GObjectStorage *, packed_buffer_t *);
+/* Sauvegarde un objet dans un flux de données. */
+static bool g_arch_instruction_store(const GSerializableObject *, GObjectStorage *, int);
-/* Sauvegarde un contenu dans une mémoire tampon. */
-static bool _g_arch_instruction_store(GArchInstruction *, GObjectStorage *, packed_buffer_t *);
-/* Sauvegarde un contenu dans une mémoire tampon. */
-static bool g_arch_instruction_store(GArchInstruction *, GObjectStorage *, packed_buffer_t *);
+/* ---------------------------------------------------------------------------------- */
+/* DEFINITION GENERIQUE D'INSTRUCTION */
+/* ---------------------------------------------------------------------------------- */
/* Indique le type défini pour une instruction d'architecture. */
-G_DEFINE_TYPE_WITH_CODE(GArchInstruction, g_arch_instruction, G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE(G_TYPE_LINE_GENERATOR, g_arch_instruction_generator_init)
- G_IMPLEMENT_INTERFACE(G_TYPE_SERIALIZABLE_OBJECT, g_arch_instruction_serializable_init));
+G_DEFINE_TYPE_WITH_CODE(GArchInstruction, g_arch_instruction, G_TYPE_THICK_OBJECT,
+ G_IMPLEMENT_INTERFACE(G_TYPE_SERIALIZABLE_OBJECT, g_arch_instruction_serializable_object_iface_init)
+ G_IMPLEMENT_INTERFACE_IF_SYM(g_token_generator_get_type, g_arch_instruction_ui_token_generator_iface_init));
+
/******************************************************************************
@@ -139,28 +130,20 @@ G_DEFINE_TYPE_WITH_CODE(GArchInstruction, g_arch_instruction, G_TYPE_OBJECT,
static void g_arch_instruction_class_init(GArchInstructionClass *klass)
{
GObjectClass *object; /* Autre version de la classe */
- GArchInstructionClass *instr; /* Encore une autre vision... */
object = G_OBJECT_CLASS(klass);
- object->dispose = (GObjectFinalizeFunc/* ! */)g_arch_instruction_dispose;
- object->finalize = (GObjectFinalizeFunc)g_arch_instruction_finalize;
-
- instr = G_ARCH_INSTRUCTION_CLASS(klass);
-
- instr->print = (print_instruction_fc)_g_arch_instruction_print;
-
- instr->load = (load_instruction_fc)_g_arch_instruction_load;
- instr->store = (store_instruction_fc)_g_arch_instruction_store;
+ object->dispose = g_arch_instruction_dispose;
+ object->finalize = g_arch_instruction_finalize;
}
/******************************************************************************
* *
-* Paramètres : instr = instance à initialiser. *
+* Paramètres : iface = interface GLib à initialiser. *
* *
-* Description : Initialise une instance d'instruction d'architecture. *
+* Description : Procède à l'initialisation de l'interface de sérialisation. *
* *
* Retour : - *
* *
@@ -168,27 +151,19 @@ static void g_arch_instruction_class_init(GArchInstructionClass *klass)
* *
******************************************************************************/
-static void g_arch_instruction_init(GArchInstruction *instr)
+static void g_arch_instruction_serializable_object_iface_init(GSerializableObjectInterface *iface)
{
- instr_extra_data_t *extra; /* Données insérées à modifier */
-
- extra = GET_ARCH_INSTR_EXTRA(instr);
-
- INIT_GOBJECT_EXTRA_LOCK(extra);
-
- instr->operands = NULL;
-
- instr->from = NULL;
- instr->to = NULL;
+ iface->load = g_arch_instruction_load;
+ iface->store = g_arch_instruction_store;
}
/******************************************************************************
* *
-* Paramètres : iface = interface GLib à initialiser. *
+* Paramètres : instr = instance à initialiser. *
* *
-* Description : Procède à l'initialisation de l'interface de génération. *
+* Description : Initialise une instance d'instruction d'architecture. *
* *
* Retour : - *
* *
@@ -196,42 +171,22 @@ static void g_arch_instruction_init(GArchInstruction *instr)
* *
******************************************************************************/
-static void g_arch_instruction_generator_init(GLineGeneratorInterface *iface)
+static void g_arch_instruction_init(GArchInstruction *instr)
{
- iface->count = (linegen_count_lines_fc)g_arch_instruction_count_lines;
-#ifdef INCLUDE_GTK_SUPPORT
- iface->compute = (linegen_compute_fc)g_arch_instruction_compute_cursor;
- iface->contain = (linegen_contain_fc)g_arch_instruction_contain_cursor;
-#endif
- iface->get_flags = (linegen_get_flags_fc)g_arch_instruction_get_flags2;
- iface->print = (linegen_print_fc)g_arch_instruction_print;
-
-}
+ instr->rel_area = NULL;
+ instr->link_count = 0;
-/******************************************************************************
-* *
-* Paramètres : iface = interface GLib à initialiser. *
-* *
-* Description : Procède à l'initialisation de l'interface de sérialisation. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ instr->links = NULL;
-static void g_arch_instruction_serializable_init(GSerializableObjectInterface *iface)
-{
- iface->load = (load_serializable_object_cb)g_arch_instruction_load;
- iface->store = (store_serializable_object_cb)g_arch_instruction_store;
+ instr->operands = NULL;
}
/******************************************************************************
* *
-* Paramètres : instr = instance d'objet GLib à traiter. *
+* Paramètres : object = instance d'objet GLib à traiter. *
* *
* Description : Supprime toutes les références externes. *
* *
@@ -241,43 +196,38 @@ static void g_arch_instruction_serializable_init(GSerializableObjectInterface *i
* *
******************************************************************************/
-static void g_arch_instruction_dispose(GArchInstruction *instr)
+static void g_arch_instruction_dispose(GObject *object)
{
+ GArchInstruction *instr; /* Version spécialisée */
size_t count; /* Nombre d'opérandes en place */
size_t i; /* Boucle de parcours */
GArchOperand *op; /* Opérande à manipuler */
- g_arch_instruction_lock_operands(instr);
+ instr = G_ARCH_INSTRUCTION(object);
+
+ g_clear_object(&instr->rel_area);
+
+ g_arch_instruction_delete_all_links(instr);
- count = _g_arch_instruction_count_operands(instr);
+ g_thick_object_lock(G_THICK_OBJECT(instr));
+
+ count = g_arch_instruction_count_operands(instr);
for (i = 0; i < count; i++)
{
- op = _g_arch_instruction_get_operand(instr, 0);
+ op = g_arch_instruction_get_operand(instr, 0);
rem_item_from_flat_array(&instr->operands, 0, sizeof(GArchOperand *));
/**
* Une fois pour l'obtention, une autre pour la libération !
*/
- g_object_unref(G_OBJECT(op));
- g_object_unref(G_OBJECT(op));
+ unref_object(op);
+ unref_object(op);
}
- g_arch_instruction_unlock_operands(instr);
-
-#ifndef NDEBUG
- g_arch_instruction_lock_src(instr);
- assert(count_flat_array_items(instr->from) == 0);
- g_arch_instruction_unlock_src(instr);
-#endif
-
-#ifndef NDEBUG
- g_arch_instruction_lock_dest(instr);
- assert(count_flat_array_items(instr->to) == 0);
- g_arch_instruction_unlock_dest(instr);
-#endif
+ g_thick_object_unlock(G_THICK_OBJECT(instr));
G_OBJECT_CLASS(g_arch_instruction_parent_class)->dispose(G_OBJECT(instr));
@@ -286,7 +236,7 @@ static void g_arch_instruction_dispose(GArchInstruction *instr)
/******************************************************************************
* *
-* Paramètres : instr = instance d'objet GLib à traiter. *
+* Paramètres : object = instance d'objet GLib à traiter. *
* *
* Description : Procède à la libération totale de la mémoire. *
* *
@@ -296,38 +246,26 @@ static void g_arch_instruction_dispose(GArchInstruction *instr)
* *
******************************************************************************/
-static void g_arch_instruction_finalize(GArchInstruction *instr)
+static void g_arch_instruction_finalize(GObject *object)
{
- G_OBJECT_CLASS(g_arch_instruction_parent_class)->finalize(G_OBJECT(instr));
+ GArchInstruction *instr; /* Version spécialisée */
-}
+ instr = G_ARCH_INSTRUCTION(object);
+ if (instr->links != NULL)
+ free(instr->links);
-/******************************************************************************
-* *
-* Paramètres : instr = instruction quelconque à consulter. *
-* *
-* Description : Indique l'encodage d'une instruction de façon détaillée. *
-* *
-* Retour : Description humaine de l'encodage utilisé. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-const char *g_arch_instruction_get_encoding(const GArchInstruction *instr)
-{
- return G_ARCH_INSTRUCTION_GET_CLASS(instr)->get_encoding(instr);
+ G_OBJECT_CLASS(g_arch_instruction_parent_class)->finalize(G_OBJECT(instr));
}
/******************************************************************************
* *
-* Paramètres : instr = instruction quelconque à modifier. *
-* flag = drapeau d'information complémentaire à planter. *
+* Paramètres : instr = instance à initialiser pleinement. *
+* tid = identifiant associé au type d'instructions ciblé. *
* *
-* Description : Ajoute une information complémentaire à une instruction. *
+* Description : Met en place une instruction d'architecture. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -335,22 +273,18 @@ const char *g_arch_instruction_get_encoding(const GArchInstruction *instr)
* *
******************************************************************************/
-bool g_arch_instruction_set_flag(GArchInstruction *instr, ArchInstrFlag flag)
+bool g_arch_instruction_create(GArchInstruction *instr, itid_t tid)
{
bool result; /* Bilan à retourner */
- instr_extra_data_t *extra; /* Données insérées à modifier */
+ instruction_extra_data_t extra; /* Données insérées à modifier */
- assert(flag <= AIF_HIGH_USER);
+ result = true;
extra = GET_ARCH_INSTR_EXTRA(instr);
- LOCK_GOBJECT_EXTRA(extra);
-
- result = !(extra->flags & flag);
+ extra.tid = tid;
- extra->flags |= flag;
-
- UNLOCK_GOBJECT_EXTRA(extra);
+ SET_ARCH_INSTR_EXTRA(instr, &extra);
return result;
@@ -359,33 +293,24 @@ bool g_arch_instruction_set_flag(GArchInstruction *instr, ArchInstrFlag flag)
/******************************************************************************
* *
-* Paramètres : instr = instruction quelconque à modifier. *
-* flag = drapeau d'information complémentaire à planter. *
+* Paramètres : instr = instruction quelconque à consulter. *
* *
-* Description : Retire une information complémentaire à une instruction. *
+* Description : Fournit l'identifiant correspondant à un type d'instructions.*
* *
-* Retour : Bilan de l'opération. *
+* Retour : Identifiant unique par type d'instruction et architecture. *
* *
* Remarques : - *
* *
******************************************************************************/
-bool g_arch_instruction_unset_flag(GArchInstruction *instr, ArchInstrFlag flag)
+itid_t g_arch_instruction_get_type_id(const GArchInstruction *instr)
{
- bool result; /* Bilan à retourner */
- instr_extra_data_t *extra; /* Données insérées à modifier */
-
- assert(flag <= AIF_HIGH_USER);
+ itid_t result; /* Numéro à retourner */
+ instruction_extra_data_t extra; /* Données insérées à modifier */
extra = GET_ARCH_INSTR_EXTRA(instr);
- LOCK_GOBJECT_EXTRA(extra);
-
- result = (extra->flags & flag);
-
- extra->flags &= ~flag;
-
- UNLOCK_GOBJECT_EXTRA(extra);
+ result = extra.tid;
return result;
@@ -395,30 +320,23 @@ bool g_arch_instruction_unset_flag(GArchInstruction *instr, ArchInstrFlag flag)
/******************************************************************************
* *
* Paramètres : instr = instruction quelconque à consulter. *
-* flag = drapeau d'information à rechercher. *
* *
-* Description : Détermine si une instruction possède un fanion particulier. *
+* Description : Indique l'encodage d'une instruction de façon détaillée. *
* *
-* Retour : Bilan de la détection. *
+* Retour : Description humaine de l'encodage utilisé. *
* *
* Remarques : - *
* *
******************************************************************************/
-bool g_arch_instruction_has_flag(const GArchInstruction *instr, ArchInstrFlag flag)
+char *g_arch_instruction_get_encoding(const GArchInstruction *instr)
{
- bool result; /* Bilan à retourner */
- instr_extra_data_t *extra; /* Données insérées à modifier */
-
- assert(flag <= AIF_HIGH_USER);
-
- extra = GET_ARCH_INSTR_EXTRA(instr);
-
- LOCK_GOBJECT_EXTRA(extra);
+ char *result; /* Encodage à retourner */
+ GArchInstructionClass *class; /* Classe des instructions */
- result = (extra->flags & flag);
+ class = G_ARCH_INSTRUCTION_GET_CLASS(instr);
- UNLOCK_GOBJECT_EXTRA(extra);
+ result = class->get_encoding(instr);
return result;
@@ -427,28 +345,24 @@ bool g_arch_instruction_has_flag(const GArchInstruction *instr, ArchInstrFlag fl
/******************************************************************************
* *
-* Paramètres : instr = instruction quelconque à modifier. *
+* Paramètres : instr = instruction d'assemblage à consulter. *
* *
-* Description : Fournit les informations complémentaires d'une instruction. *
+* Description : Fournit le nom humain de l'instruction manipulée. *
* *
-* Retour : Eventuels drapeaux d'information complémentaire à plantés. *
+* Retour : Mot clef de bas niveau. *
* *
* Remarques : - *
* *
******************************************************************************/
-ArchInstrFlag g_arch_instruction_get_flags(const GArchInstruction *instr)
+char *g_arch_instruction_get_keyword(const GArchInstruction *instr)
{
- ArchInstrFlag result; /* Fanions à retourner */
- instr_extra_data_t *extra; /* Données insérées à modifier */
-
- extra = GET_ARCH_INSTR_EXTRA(instr);
-
- LOCK_GOBJECT_EXTRA(extra);
+ char *result; /* Etiquette à retourner */
+ GArchInstructionClass *class; /* Classe des instructions */
- result = extra->flags;
+ class = G_ARCH_INSTRUCTION_GET_CLASS(instr);
- UNLOCK_GOBJECT_EXTRA(extra);
+ result = class->get_keyword(instr);
return result;
@@ -457,10 +371,12 @@ ArchInstrFlag g_arch_instruction_get_flags(const GArchInstruction *instr)
/******************************************************************************
* *
-* Paramètres : instr = instruction quelconque à consulter. *
-* uid = identifiant unique par type d'instruction. *
+* Paramètres : instr = instruction quelconque à compléter. *
+* area = portion de binaire incluant l'instruction. *
+* start = adresse virtuelle et/ou position physique. *
+* length = taille de l'instruction. *
* *
-* Description : Définit l'identifiant unique pour un ensemble d'instructions.*
+* Description : Calcule la localisation d'une instruction. *
* *
* Retour : - *
* *
@@ -468,358 +384,214 @@ ArchInstrFlag g_arch_instruction_get_flags(const GArchInstruction *instr)
* *
******************************************************************************/
-void g_arch_instruction_set_unique_id(GArchInstruction *instr, itid_t uid)
+void g_arch_instruction_compute_range(GArchInstruction *instr, GBinaryPortion *area, const vmpa2t *start, phys_t length)
{
- instr_extra_data_t *extra; /* Données insérées à modifier */
+ const mrange_t *a_range; /* Couverture de la portion */
+ phys_t diff; /* Décalage à appliquer */
- extra = GET_ARCH_INSTR_EXTRA(instr);
-
- LOCK_GOBJECT_EXTRA(extra);
+ a_range = g_binary_portion_get_range(area);
- extra->uid = uid;
+ assert(mrange_contains_addr(a_range, start));
- UNLOCK_GOBJECT_EXTRA(extra);
+ diff = compute_vmpa_diff(get_mrange_addr(a_range), start);
-}
+ instr->rel_area = area;
+ ref_object(area);
-
-/******************************************************************************
-* *
-* Paramètres : instr = instruction quelconque à consulter. *
-* *
-* Description : Fournit l'identifiant unique pour un ensemble d'instructions.*
-* *
-* Retour : Identifiant unique par type d'instruction et architecture. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-itid_t g_arch_instruction_get_unique_id(const GArchInstruction *instr)
-{
- itid_t result; /* Numéro à retourner */
- instr_extra_data_t *extra; /* Données insérées à consulter*/
-
- extra = GET_ARCH_INSTR_EXTRA(instr);
-
- LOCK_GOBJECT_EXTRA(extra);
-
- result = extra->uid;
-
- UNLOCK_GOBJECT_EXTRA(extra);
-
- return result;
+ init_rel_mrange(&instr->rel_range, diff, length);
}
/******************************************************************************
* *
-* Paramètres : instr = instruction quelconque à traiter. *
-* type = type de procédure à utiliser. *
-* proc = représentation de l'architecture utilisée. *
-* context = contexte associé à la phase de désassemblage. *
-* format = accès aux données du binaire d'origine. *
+* Paramètres : instr = instruction quelconque à consulter. *
+* range = localisation de l'instruction. [OUT] *
* *
-* Description : Complète un désassemblage accompli pour une instruction. *
+* Description : Fournit la place mémoire d'une instruction. *
* *
-* Retour : - *
+* Retour : Validité de la localisation : existence d'une définition ? *
* *
* Remarques : - *
* *
******************************************************************************/
-void g_arch_instruction_call_hook(GArchInstruction *instr, InstrProcessHook type, GArchProcessor *proc, GProcContext *context, GExeFormat *format)
+bool g_arch_instruction_get_range(const GArchInstruction *instr, mrange_t *range)
{
- GArchInstructionClass *class; /* Classe des instructions */
+ bool result; /* Statut à retourner */
+ const mrange_t *a_range; /* Couverture de la portion */
+ vmpa2t start; /* Position de départ complète */
- class = G_ARCH_INSTRUCTION_GET_CLASS(instr);
+ result = (instr->rel_area != NULL);
- if (class->call_hook != NULL)
- class->call_hook(instr, type, proc, context, format);
+ if (result)
+ {
+ a_range = g_binary_portion_get_range(instr->rel_area);
-}
+ copy_vmpa(&start, get_mrange_addr(a_range));
+ advance_vmpa(&start, get_rel_mrange_offset(&instr->rel_range));
+ init_mrange(range, &start, get_rel_mrange_length(&instr->rel_range));
-/******************************************************************************
-* *
-* Paramètres : instr = instruction quelconque à modifier. *
-* address = adresse virtuelle et/ou position physique. *
-* length = taille de l'instruction. *
-* *
-* Description : Définit la localisation d'une instruction. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ }
-void g_arch_instruction_set_range(GArchInstruction *instr, const mrange_t *range)
-{
- copy_mrange(&instr->range, range);
+ return result;
}
/******************************************************************************
* *
-* Paramètres : instr = instruction quelconque à consulter. *
+* Paramètres : instr = instruction à venir modifier. *
+* flag = drapeau d'information complémentaire à planter. *
* *
-* Description : Fournit la place mémoire d'une instruction. *
+* Description : Ajoute une information complémentaire à une instruction. *
* *
-* Retour : Zone mémoire couverte par l'instruction. *
+* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
-const mrange_t *g_arch_instruction_get_range(const GArchInstruction *instr)
+bool g_arch_instruction_set_flag(GArchInstruction *instr, ArchInstructionFlag flag)
{
- return &instr->range;
+ bool result; /* Bilan à retourner */
+ instruction_extra_data_t extra; /* Données insérées à modifier */
-}
+ assert(flag <= AIF_HIGH_USER);
+ extra = GET_ARCH_INSTR_EXTRA(instr);
+ result = !(extra.flags & flag);
-/******************************************************************************
-* *
-* Paramètres : instr = instruction quelconque à consulter. *
-* offset = position physique dans le code binaire/NULL. [OUT] *
-* length = taille de l'instruction ou NULL. [OUT] *
-* address = adresse virtuelle ou position physique/NULL. [OUT] *
-* *
-* Description : Fournit la localisation d'une instruction. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ extra.flags |= flag;
-void g_arch_instruction_get_location(const GArchInstruction *instr, off_t *offset, off_t *length, vmpa_t *address)
-{
- //if (offset != NULL) *offset = instr->offset;
- //if (length != NULL) *length = instr->length;
+ SET_ARCH_INSTR_EXTRA(instr, &extra);
- //if (address != NULL) *address = instr->address;
+ return result;
}
-
/******************************************************************************
* *
-* Paramètres : instr = instruction à consulter. *
-* rregs = liste des rgistres lus. [OUT] *
-* rcount = nombre de registres lus. [OUT] *
-* wregs = liste des rgistres écrits. [OUT] *
-* wcount = nombre de registres écrits. [OUT] *
+* Paramètres : instr = instruction à venir modifier. *
+* flag = drapeau d'information complémentaire à planter. *
* *
-* Description : Liste les registres lus et écrits par l'instruction. *
+* Description : Retire une information complémentaire à une instruction. *
* *
-* Retour : - *
+* Retour : Bilan de l'opération. *
* *
-* Remarques : Les compteurs de références sont à décrémenter après usage ! *
+* Remarques : - *
* *
******************************************************************************/
-void g_arch_instruction_get_rw_registers(const GArchInstruction *instr, GArchRegister ***rregs, size_t *rcount, GArchRegister ***wregs, size_t *wcount)
+bool g_arch_instruction_unset_flag(GArchInstruction *instr, ArchInstructionFlag flag)
{
-#if 0
+ bool result; /* Bilan à retourner */
+ instruction_extra_data_t extra; /* Données insérées à modifier */
- size_t i; /* Boucle de parcours */
+ assert(flag <= AIF_HIGH_USER);
- *rregs = NULL;
- *rcount = 0;
- *wregs = NULL;
- *wcount = 0;
+ extra = GET_ARCH_INSTR_EXTRA(instr);
- instr->get_rw_regs(instr, rregs, rcount, wregs, wcount);
+ result = (extra.flags & flag);
- for (i = 0; i < *rcount; i++)
- g_object_ref(G_OBJECT((*rregs)[i]));
+ extra.flags &= ~flag;
- for (i = 0; i < *wcount; i++)
- g_object_ref(G_OBJECT((*wregs)[i]));
+ SET_ARCH_INSTR_EXTRA(instr, &extra);
-#endif
+ return result;
}
-
-/* ---------------------------------------------------------------------------------- */
-/* MANIPULATION DES OPERANDES */
-/* ---------------------------------------------------------------------------------- */
-
-
/******************************************************************************
* *
-* Paramètres : instr = instruction à mettre à jour. *
+* Paramètres : instr = instruction à venir consulter. *
+* flag = drapeau d'information à rechercher. *
* *
-* Description : Verrouille les accès à la liste des opérandes. *
+* Description : Détermine si une instruction possède un fanion particulier. *
* *
-* Retour : - *
+* Retour : Bilan de la détection. *
* *
* Remarques : - *
* *
******************************************************************************/
-void g_arch_instruction_lock_operands(GArchInstruction *instr)
+bool g_arch_instruction_has_flag(const GArchInstruction *instr, ArchInstructionFlag flag)
{
- lock_flat_array(&instr->operands);
+ bool result; /* Bilan à retourner */
+ instruction_extra_data_t extra; /* Données insérées à modifier */
-}
+ assert(flag <= AIF_HIGH_USER);
+ extra = GET_ARCH_INSTR_EXTRA(instr);
-/******************************************************************************
-* *
-* Paramètres : instr = instruction à mettre à jour. *
-* *
-* Description : Déverrouille les accès à la liste des opérandes. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ result = (extra.flags & flag);
-void g_arch_instruction_unlock_operands(GArchInstruction *instr)
-{
- unlock_flat_array(&instr->operands);
+ return result;
}
/******************************************************************************
* *
-* Paramètres : instr = instance à mettre à jour. *
-* operand = instruction à venir associer. *
+* Paramètres : instr = instruction à venir consulter. *
* *
-* Description : Attache un opérande supplémentaire à une instruction. *
+* Description : Fournit les particularités de l'instruction. *
* *
-* Retour : - *
+* Retour : Somme de tous les fanions associés à l'opérande. *
* *
* Remarques : - *
* *
******************************************************************************/
-void g_arch_instruction_attach_extra_operand(GArchInstruction *instr, GArchOperand *operand)
+ArchInstructionFlag g_arch_instruction_get_flags(const GArchInstruction *instr)
{
- GSingletonFactory *factory; /* Unise à instances uniques */
- GArchOperand *singleton; /* Instance retenue */
-
- factory = get_operands_factory();
-
- singleton = G_ARCH_OPERAND(g_singleton_factory_get_instance(factory, G_SINGLETON_CANDIDATE(operand)));
-
- g_object_unref(G_OBJECT(operand));
- g_object_unref(G_OBJECT(factory));
-
- g_arch_instruction_lock_operands(instr);
-
- add_item_to_flat_array(&instr->operands, &singleton, sizeof(GArchOperand *));
-
- g_arch_instruction_unlock_operands(instr);
+ ArchInstructionFlag result; /* Fanions à retourner */
+ instruction_extra_data_t extra; /* Données insérées à modifier */
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : instr = instance à consulter. *
-* *
-* Description : Indique la quantité d'opérandes présents dans l'instruction. *
-* *
-* Retour : Nombre d'opérandes attachés. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ extra = GET_ARCH_INSTR_EXTRA(instr);
-size_t _g_arch_instruction_count_operands(const GArchInstruction *instr)
-{
- size_t result; /* Décompte à retourner */
-
- result = count_flat_array_items(instr->operands);
+ result = extra.flags;
return result;
}
-/******************************************************************************
-* *
-* Paramètres : instr = instance à consulter. *
-* index = indice de l'opérande concerné. *
-* *
-* Description : Fournit un opérande donné d'une instruction. *
-* *
-* Retour : Opérande trouvée. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GArchOperand *_g_arch_instruction_get_operand(const GArchInstruction *instr, size_t index)
-{
- GArchOperand *result; /* Opérande à retourner */
- GArchOperand **ptr; /* Adresse dans le tableau */
-
- ptr = get_flat_array_item(instr->operands, index, sizeof(GArchOperand *));
-
- result = *ptr;
-
- g_object_ref(G_OBJECT(result));
-
- return result;
-}
+/* ---------------------------------------------------------------------------------- */
+/* DEFINITION DES LIAISONS ENTRE INSTRUCTIONS */
+/* ---------------------------------------------------------------------------------- */
/******************************************************************************
* *
-* Paramètres : instr = instance à mettre à jour. *
-* old = ancienne opérande à détacher. *
-* new = nouvelle opérande à attacher. *
+* Paramètres : instr = instruction dont les liens sont à consulter. *
+* dir = direction du lien recherché. *
+* type = type de lien à détecter. *
* *
-* Description : Remplace un opérande d'une instruction par un autre. *
+* Description : Détermine si un type de lien existe dans une instruction. *
* *
-* Retour : Bilan de l'opération. *
+* Retour : Bilan du statut courant de l'instruction. *
* *
* Remarques : - *
* *
******************************************************************************/
-bool _g_arch_instruction_replace_operand(GArchInstruction *instr, GArchOperand *old, GArchOperand *new)
+static bool _g_arch_instruction_has_link(const GArchInstruction *instr, compact_ins_link_t dir, InstructionLinkType type)
{
bool result; /* Bilan à retourner */
- size_t count; /* Nombre d'opérandes en place */
- size_t i; /* Boucle de parcours */
- GArchOperand *op; /* Opérande à manipuler */
-
- result = false;
-
- count = _g_arch_instruction_count_operands(instr);
-
- for (i = 0; i < count && !result; i++)
- {
- op = _g_arch_instruction_get_operand(instr, i);
+ uint16_t i; /* Boucle de parcours */
- result = (op == old);
-
- g_object_unref(G_OBJECT(op));
-
- }
-
- if (result)
- {
- rpl_item_in_flat_array(instr->operands, i - 1, &new, sizeof(GArchOperand *));
+ assert(g_thick_object_check_lock(G_THICK_OBJECT(instr)));
- g_object_unref(G_OBJECT(old));
+ result = false;
- }
+ for (i = 0; i < instr->link_count && !result; i++)
+ result = COMPACT_INS_LINK_DIR(instr->links[i]) == dir;
return result;
@@ -828,45 +600,22 @@ bool _g_arch_instruction_replace_operand(GArchInstruction *instr, GArchOperand *
/******************************************************************************
* *
-* Paramètres : instr = instance à mettre à jour. *
-* target = instruction à venir dissocier. *
+* Paramètres : instr = instruction dont les liens sont à consulter. *
+* type = type de lien à détecter. *
* *
-* Description : Détache un opérande liée d'une instruction. *
+* Description : Détermine si un type de lien amène à une instruction. *
* *
-* Retour : Bilan de l'opération. *
+* Retour : Bilan du statut courant de l'instruction. *
* *
* Remarques : - *
* *
******************************************************************************/
-bool _g_arch_instruction_detach_operand(GArchInstruction *instr, GArchOperand *target)
+bool g_arch_instruction_has_src_link(const GArchInstruction *instr, InstructionLinkType type)
{
bool result; /* Bilan à retourner */
- size_t count; /* Nombre d'opérandes en place */
- size_t i; /* Boucle de parcours */
- GArchOperand *op; /* Opérande à manipuler */
-
- result = false;
-
- count = _g_arch_instruction_count_operands(instr);
- for (i = 0; i < count && !result; i++)
- {
- op = _g_arch_instruction_get_operand(instr, i);
-
- result = (op == target);
-
- g_object_unref(G_OBJECT(op));
-
- }
-
- if (result)
- {
- rem_item_from_flat_array(&instr->operands, i - 1, sizeof(GArchOperand *));
-
- g_object_unref(G_OBJECT(target));
-
- }
+ result = _g_arch_instruction_has_link(instr, COMPACT_INS_LINK_FROM, type);
return result;
@@ -875,78 +624,22 @@ bool _g_arch_instruction_detach_operand(GArchInstruction *instr, GArchOperand *t
/******************************************************************************
* *
-* Paramètres : instr = instance à consulter. *
-* target = instruction à venir retrouver. *
+* Paramètres : instr = instruction dont les liens sont à consulter. *
+* type = type de lien à détecter. *
* *
-* Description : Détermine le chemin conduisant à un opérande. *
+* Description : Détermine si un type de lien émerge d'une instruction. *
* *
-* Retour : Chemin d'accès à l'opérande ou NULL en cas d'absence. *
+* Retour : Bilan du statut courant de l'instruction. *
* *
* Remarques : - *
* *
******************************************************************************/
-char *g_arch_instruction_find_operand_path(GArchInstruction *instr, const GArchOperand *target)
+bool g_arch_instruction_has_dest_link(const GArchInstruction *instr, InstructionLinkType type)
{
- char *result; /* Chemin à retourner */
- size_t count; /* Nombre d'opérandes en place */
- size_t i; /* Boucle de parcours */
- GArchOperand *op; /* Opérande à manipuler */
- int ret; /* Bilan d'une construction */
- char *sub_path; /* Sous-chemin emprunté */
-
- result = NULL;
-
- g_arch_instruction_lock_operands(instr);
-
- count = _g_arch_instruction_count_operands(instr);
-
- /* Première passe : accès direct */
-
- for (i = 0; i < count && result == NULL; i++)
- {
- op = _g_arch_instruction_get_operand(instr, i);
-
- if (op == target)
- {
- ret = asprintf(&result, "%zu", i);
- if (ret == -1)
- {
- LOG_ERROR_N("asprintf");
- result = NULL;
- }
- }
-
- g_object_unref(G_OBJECT(op));
-
- }
-
- /* Seconde passe : accès profond */
-
- for (i = 0; i < count && result == NULL; i++)
- {
- op = _g_arch_instruction_get_operand(instr, i);
-
- sub_path = g_arch_operand_find_inner_operand_path(op, target);
-
- if (sub_path != NULL)
- {
- ret = asprintf(&result, "%zu:%s", i, sub_path);
- if (ret == -1)
- {
- LOG_ERROR_N("asprintf");
- result = NULL;
- }
-
- free(sub_path);
-
- }
-
- g_object_unref(G_OBJECT(op));
-
- }
+ bool result; /* Bilan à retourner */
- g_arch_instruction_unlock_operands(instr);
+ result = _g_arch_instruction_has_link(instr, COMPACT_INS_LINK_TO, type);
return result;
@@ -955,104 +648,65 @@ char *g_arch_instruction_find_operand_path(GArchInstruction *instr, const GArchO
/******************************************************************************
* *
-* Paramètres : instr = instance à consulter. *
-* path = chemin d'accès à un opérande à retrouver. *
+* Paramètres : instr = instruction dont les liens sont à consulter. *
+* dir = direction du lien recherché. *
+* linked = seconde instruction à considérer. *
* *
-* Description : Obtient l'opérande correspondant à un chemin donné. *
+* Description : Détermine si un lien existe entre deux instructions. *
* *
-* Retour : Opérande trouvé ou NULL en cas d'échec. *
+* Retour : Bilan du statut courant de l'instruction. *
* *
* Remarques : - *
* *
******************************************************************************/
-GArchOperand *g_arch_instruction_get_operand_from_path(GArchInstruction *instr, const char *path)
+static bool _g_arch_instruction_has_link_with(const GArchInstruction *instr, compact_ins_link_t dir, const GArchInstruction *linked)
{
- GArchOperand *result; /* Opérande trouvée à renvoyer */
- size_t index; /* Indice de l'opérande visé */
- char *end; /* Poursuite du parcours ? */
- GArchOperand *found; /* Opérande trouvé */
-
- result = NULL;
-
- g_arch_instruction_lock_operands(instr);
-
- /* Recherche au premier niveau */
-
- index = strtoul(path, &end, 10);
-
- if ((index == ULONG_MAX && errno == ERANGE) || (index == 0 && errno == EINVAL))
- {
- LOG_ERROR_N("strtoul");
- goto done;
- }
-
- found = _g_arch_instruction_get_operand(instr, index);
- if (found == NULL) goto done;
-
- if (*end == '\0')
- {
- result = found;
- goto done;
- }
-
- /* Recherche en profondeur */
-
- assert(*end == ':');
-
- result = g_arch_operand_get_inner_operand_from_path(found, end + 1);
+ bool result; /* Bilan à retourner */
+ uint16_t i; /* Boucle de parcours */
- g_object_unref(G_OBJECT(found));
+ assert(g_thick_object_check_lock(G_THICK_OBJECT(instr)));
- done:
+ result = false;
- g_arch_instruction_unlock_operands(instr);
+ for (i = 0; i < instr->link_count && !result; i++)
+ result = COMPACT_INS_LINK_PTR(instr->links[i]) == linked;
return result;
}
-
-/* ---------------------------------------------------------------------------------- */
-/* DEFINITION DES LIAISONS ENTRE INSTRUCTIONS */
-/* ---------------------------------------------------------------------------------- */
-
-
/******************************************************************************
* *
-* Paramètres : instr = instruction à mettre à jour. *
-* src = sélection de l'extrémité à traiter. *
-* lock = indique le sens du verrouillage à mener. *
+* Paramètres : instr = instruction dont les liens sont à consulter. *
+* src = seconde instruction à considérer. *
* *
-* Description : Met à disposition un encadrement des accès aux liens. *
+* Description : Détermine si une instruction est source d'une autre. *
* *
-* Retour : - *
+* Retour : Bilan du statut courant de l'instruction. *
* *
* Remarques : - *
* *
******************************************************************************/
-void g_arch_instruction_lock_unlock_links(GArchInstruction *instr, bool src, bool lock)
+bool g_arch_instruction_has_src_link_with(const GArchInstruction *instr, const GArchInstruction *src)
{
- flat_array_t **array; /* Choix du tableau ciblé */
+ bool result; /* Bilan à retourner */
- array = (src ? &instr->from : &instr->to);
+ result = _g_arch_instruction_has_link_with(instr, COMPACT_INS_LINK_FROM, src);
- if (lock)
- lock_flat_array(array);
- else
- unlock_flat_array(array);
+ return result;
}
/******************************************************************************
* *
-* Paramètres : instr = instruction dont les informations sont à consulter. *
-* type = type de lien à détecter. *
+* Paramètres : instr = instruction dont les liens sont à consulter. *
+* dest = seconde instruction à considérer. *
* *
-* Description : Détermine si un type de lien existe dans une instruction. *
+* Description : Détermine si une instruction est destination d'une autre. *
* *
* Retour : Bilan du statut courant de l'instruction. *
* *
@@ -1060,30 +714,11 @@ void g_arch_instruction_lock_unlock_links(GArchInstruction *instr, bool src, boo
* *
******************************************************************************/
-bool g_arch_instruction_has_link(GArchInstruction *instr, InstructionLinkType type)
+bool g_arch_instruction_has_dest_link_with(const GArchInstruction *instr, const GArchInstruction *dest)
{
bool result; /* Bilan à retourner */
- size_t count; /* Nombre de liens à parcourir */
- size_t i; /* Boucle de parcours */
- const instr_link_t *dlink; /* Définition de destination */
-
- result = false;
-
- g_arch_instruction_lock_dest(instr);
- count = g_arch_instruction_count_destinations(instr);
-
- for (i = 0; i < count && !result; i++)
- {
- dlink = g_arch_instruction_get_destination(instr, i);
-
- result = (dlink->type == type);
-
- unref_instr_link(dlink);
-
- }
-
- g_arch_instruction_unlock_dest(instr);
+ result = _g_arch_instruction_has_link_with(instr, COMPACT_INS_LINK_TO, dest);
return result;
@@ -1092,54 +727,53 @@ bool g_arch_instruction_has_link(GArchInstruction *instr, InstructionLinkType ty
/******************************************************************************
* *
-* Paramètres : instr = instruction dont les informations sont à consulter. *
+* Paramètres : instr = instruction dont les informations sont à manipuler. *
* dest = ligne visée par la liaison (côté destination). *
+* type = type de lien à construire. *
* *
-* Description : Détermine si un lien est déjà établi entre deux instructions.*
+* Description : Etablit un lien entre deux instructions. *
* *
-* Retour : Bilan de l'état actuel des liaisons. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-bool g_arch_instruction_has_link_to(GArchInstruction *instr, const GArchInstruction *dest)
+void g_arch_instruction_link(GArchInstruction *instr, GArchInstruction *dest, InstructionLinkType type)
{
- bool result; /* Bilan à retourner */
- size_t count; /* Nombre de liens à parcourir */
- size_t i; /* Boucle de parcours */
- const instr_link_t *dlink; /* Définition de destination */
+ compact_ins_link_t new_from; /* Nouvel enregistrement #1 */
+ compact_ins_link_t new_to; /* Nouvel enregistrement #2 */
- result = false;
+ new_from = MAKE_COMPACT_INS_LINK(COMPACT_INS_LINK_FROM, instr, type);
+ ref_object(instr);
- g_arch_instruction_lock_dest(instr);
+ new_to = MAKE_COMPACT_INS_LINK(COMPACT_INS_LINK_TO, dest, type);
+ ref_object(dest);
- count = g_arch_instruction_count_destinations(instr);
+ g_thick_object_lock(G_THICK_OBJECT(instr));
+ g_thick_object_lock(G_THICK_OBJECT(dest));
- for (i = 0; i < count && !result; i++)
- {
- dlink = g_arch_instruction_get_destination(instr, i);
-
- result = (dlink->linked == dest);
+ dest->links = realloc(dest->links, ++dest->link_count * sizeof(compact_ins_link_t));
- unref_instr_link(dlink);
+ dest->links[dest->link_count - 1] = new_from;
- }
+ instr->links = realloc(instr->links, ++instr->link_count * sizeof(compact_ins_link_t));
- g_arch_instruction_unlock_dest(instr);
+ instr->links[instr->link_count - 1] = new_to;
- return result;
+ g_thick_object_unlock(G_THICK_OBJECT(dest));
+ g_thick_object_unlock(G_THICK_OBJECT(instr));
}
/******************************************************************************
* *
-* Paramètres : instr = instruction dont les informations sont à consulter. *
+* Paramètres : instr = instruction dont les informations sont à manipuler. *
* dest = ligne visée par la liaison (côté destination). *
* type = type de lien à construire. *
* *
-* Description : Etablit un lien entre deux instructions. *
+* Description : Supprime un lien entre deux instructions. *
* *
* Retour : - *
* *
@@ -1147,43 +781,59 @@ bool g_arch_instruction_has_link_to(GArchInstruction *instr, const GArchInstruct
* *
******************************************************************************/
-void g_arch_instruction_link_with(GArchInstruction *instr, GArchInstruction *dest, InstructionLinkType type)
+void g_arch_instruction_unlink(GArchInstruction *instr, GArchInstruction *dest, InstructionLinkType type)
{
- instr_link_t new_src; /* Nouveau lien à définir #1 */
- instr_link_t new_dst; /* Nouveau lien à définir #2 */
+ compact_ins_link_t old_from; /* Ancien enregistrement #1 */
+ compact_ins_link_t old_to; /* Ancien enregistrement #2 */
+ uint16_t i_from; /* Boucle de parcours #1 */
+ uint16_t i_to; /* Boucle de parcours #2 */
+ bool status; /* Bilan des recherches */
+
+ old_from = MAKE_COMPACT_INS_LINK(COMPACT_INS_LINK_FROM, instr, type);
+
+ old_to = MAKE_COMPACT_INS_LINK(COMPACT_INS_LINK_TO, dest, type);
- /* Côté destination */
+ g_thick_object_lock(G_THICK_OBJECT(instr));
+ g_thick_object_lock(G_THICK_OBJECT(dest));
- new_src.linked = instr;
- new_src.type = type;
+ for (i_from = 0; i_from < dest->link_count; i_from++)
+ if (dest->links[i_from] == old_from)
+ break;
- ref_instr_link((&new_src));
+ for (i_to = 0; i_to < instr->link_count; i_to++)
+ if (instr->links[i_to] == old_to)
+ break;
- /* Côté point de départ */
+ assert((i_from < dest->link_count && i_to < instr->link_count)
+ || (i_from == dest->link_count && i_to == instr->link_count));
- new_dst.linked = dest;
- new_dst.type = type;
+ status = (i_from < dest->link_count && i_to < instr->link_count);
- ref_instr_link((&new_dst));
+ if (status)
+ {
+ if ((i_from + 1) < dest->link_count)
+ memmove(&dest->links[i_from], &dest->links[i_from + 1],
+ (dest->link_count - i_from - 1) * sizeof(compact_ins_link_t));
- /* Ajout dans le respect d'une cohérence globale */
+ dest->links = realloc(dest->links, --dest->link_count * sizeof(compact_ins_link_t));
- g_arch_instruction_lock_src(dest);
- g_arch_instruction_lock_dest(instr);
+ if ((i_to + 1) < instr->link_count)
+ memmove(&instr->links[i_to], &instr->links[i_to + 1],
+ (instr->link_count - i_to - 1) * sizeof(compact_ins_link_t));
- add_item_to_flat_array(&dest->from, &new_src, sizeof(instr_link_t));
+ instr->links = realloc(instr->links, --instr->link_count * sizeof(compact_ins_link_t));
- add_item_to_flat_array(&instr->to, &new_dst, sizeof(instr_link_t));
+ }
- g_arch_instruction_unlock_dest(instr);
- g_arch_instruction_unlock_src(dest);
+ g_thick_object_unlock(G_THICK_OBJECT(dest));
+ g_thick_object_unlock(G_THICK_OBJECT(instr));
}
/******************************************************************************
* *
-* Paramètres : instr = instruction dont les informations sont à consulter. *
+* Paramètres : instr = instruction dont les informations sont à manipuler. *
* dest = ligne visée par la liaison (côté destination). *
* old = ancien type de lien construit. *
* new = nouveau type de lien à construire. *
@@ -1199,67 +849,43 @@ void g_arch_instruction_link_with(GArchInstruction *instr, GArchInstruction *des
bool g_arch_instruction_change_link(GArchInstruction *instr, GArchInstruction *dest, InstructionLinkType old, InstructionLinkType new)
{
bool result; /* Bilan à retourner */
- size_t count; /* Raccourci pour la lecture */
- size_t i; /* Boucle de parcours */
- instr_link_t *slink; /* Définition de source */
- instr_link_t *dlink; /* Définition de destination */
-
- result = false;
+ compact_ins_link_t old_from; /* Ancien enregistrement #1 */
+ compact_ins_link_t new_from; /* Nouvel enregistrement #1 */
+ compact_ins_link_t old_to; /* Ancien enregistrement #2 */
+ compact_ins_link_t new_to; /* Nouvel enregistrement #2 */
+ uint16_t i_from; /* Boucle de parcours #1 */
+ uint16_t i_to; /* Boucle de parcours #2 */
- /**
- * Note : pour la récupération des liens de sources et de destinations,
- * on n'utilise pas les fonctions g_arch_instruction_get_(source|destination)(),
- * qui renvoient un pointeur non modifiable.
- *
- * On a en effet besoin de modifier le type de lien.
- */
+ old_from = MAKE_COMPACT_INS_LINK(COMPACT_INS_LINK_FROM, instr, old);
+ new_from = MAKE_COMPACT_INS_LINK(COMPACT_INS_LINK_FROM, instr, new);
+ old_to = MAKE_COMPACT_INS_LINK(COMPACT_INS_LINK_TO, dest, old);
+ new_to = MAKE_COMPACT_INS_LINK(COMPACT_INS_LINK_TO, dest, new);
- g_arch_instruction_lock_src(dest);
+ g_thick_object_lock(G_THICK_OBJECT(instr));
+ g_thick_object_lock(G_THICK_OBJECT(dest));
- /* Côté destination */
-
- count = g_arch_instruction_count_sources(dest);
-
- for (i = 0; i < count; i++)
- {
- slink = get_flat_array_item(dest->from, i, sizeof(instr_link_t));
-
- if (slink->linked == instr && slink->type == old)
+ for (i_from = 0; i_from < dest->link_count; i_from++)
+ if (dest->links[i_from] == old_from)
break;
- }
-
- if (i == count)
- goto gaicl_exit;
+ for (i_to = 0; i_to < instr->link_count; i_to++)
+ if (instr->links[i_to] == old_to)
+ break;
- /* Côté point de départ */
+ assert((i_from < dest->link_count && i_to < instr->link_count)
+ || (i_from == dest->link_count && i_to == instr->link_count));
- count = g_arch_instruction_count_destinations(instr);
+ result = (i_from < dest->link_count && i_to < instr->link_count);
- for (i = 0; i < count; i++)
+ if (result)
{
- dlink = get_flat_array_item(instr->to, i, sizeof(instr_link_t));
-
- if (dlink->linked == dest && dlink->type == old)
- break;
-
+ dest->links[i_from] = new_from;
+ instr->links[i_to] = new_to;
}
- if (i == count)
- goto gaicl_exit;
-
- /* Si les deux extrémités sont raccord... */
-
- slink->type = new;
-
- dlink->type = new;
-
- result = true;
-
- gaicl_exit:
-
- g_arch_instruction_unlock_src(dest);
+ g_thick_object_unlock(G_THICK_OBJECT(dest));
+ g_thick_object_unlock(G_THICK_OBJECT(instr));
return result;
@@ -1280,116 +906,92 @@ bool g_arch_instruction_change_link(GArchInstruction *instr, GArchInstruction *d
void g_arch_instruction_delete_all_links(GArchInstruction *instr)
{
- instr_link_t *link_src; /* Lien à supprimer #2 */
- GArchInstruction *other; /* Instruction de l'autre bout */
- size_t count; /* Quantié de liens présents */
- size_t i; /* Boucle de parcours */
- instr_link_t *link_dst; /* Lien à supprimer #1 */
+ GArchInstruction *linked; /* Autre instruction liée */
+ InstructionLinkType type; /* Type de liaison */
- /* Coté sources */
+ g_thick_object_lock(G_THICK_OBJECT(instr));
- g_arch_instruction_lock_src(instr);
-
- while (count_flat_array_items(instr->from) > 0)
+ while (g_arch_instruction_count_src_links(instr) > 0)
{
- link_src = get_flat_array_item(instr->from, 0, sizeof(instr_link_t));
-
- other = link_src->linked;
+ linked = g_arch_instruction_get_linked_source(instr, 0, &type);
- g_arch_instruction_lock_dest(other);
+ g_thick_object_unlock(G_THICK_OBJECT(instr));
- count = count_flat_array_items(other->to);
+ g_arch_instruction_unlink(linked, instr, type);
- for (i = 0; i < count; i++)
- {
- link_dst = get_flat_array_item(other->to, i, sizeof(instr_link_t));
+ g_thick_object_lock(G_THICK_OBJECT(instr));
- if (link_dst->linked == instr && link_dst->type == link_src->type)
- {
- unref_instr_link(link_dst);
-
- rem_item_from_flat_array(&other->to, i, sizeof(instr_link_t));
-
- break;
-
- }
-
- }
-
- assert(i < count);
-
- g_arch_instruction_unlock_dest(other);
-
- unref_instr_link(link_src);
-
- rem_item_from_flat_array(&instr->from, 0, sizeof(instr_link_t));
+ unref_object(linked);
}
- g_arch_instruction_unlock_src(instr);
-
- /* Coté destinations */
-
- g_arch_instruction_lock_dest(instr);
-
- while (count_flat_array_items(instr->to) > 0)
+ while (g_arch_instruction_count_dest_links(instr) > 0)
{
- link_dst = get_flat_array_item(instr->to, 0, sizeof(instr_link_t));
+ linked = g_arch_instruction_get_linked_destination(instr, 0, &type);
- other = link_dst->linked;
+ g_thick_object_unlock(G_THICK_OBJECT(instr));
- g_arch_instruction_lock_src(other);
+ g_arch_instruction_unlink(instr, linked, type);
- count = count_flat_array_items(other->from);
+ g_thick_object_lock(G_THICK_OBJECT(instr));
- for (i = 0; i < count; i++)
- {
- link_src = get_flat_array_item(other->from, i, sizeof(instr_link_t));
+ unref_object(linked);
- if (link_src->linked == instr && link_src->type == link_dst->type)
- {
- unref_instr_link(link_src);
-
- rem_item_from_flat_array(&other->from, i, sizeof(instr_link_t));
+ }
- break;
+ g_thick_object_unlock(G_THICK_OBJECT(instr));
- }
+}
- }
- assert(i < count);
+/******************************************************************************
+* *
+* Paramètres : instr = instruction dont les liens sont à consulter. *
+* dir = direction des liens à considérer. *
+* *
+* Description : Fournit la quantité d'instructions pointant vers une autre. *
+* *
+* Retour : Nombre de ces liens. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
- g_arch_instruction_unlock_src(other);
+static size_t _g_arch_instruction_count_links(const GArchInstruction *instr, compact_ins_link_t dir)
+{
+ size_t result; /* Nombre de liens à renvoyer */
+ uint16_t i; /* Boucle de parcours */
- unref_instr_link(link_dst);
+ assert(g_thick_object_check_lock(G_THICK_OBJECT(instr)));
- rem_item_from_flat_array(&instr->to, 0, sizeof(instr_link_t));
+ result = 0;
- }
+ for (i = 0; i < instr->link_count; i++)
+ if (COMPACT_INS_LINK_DIR(instr->links[i]) == dir)
+ result++;
- g_arch_instruction_unlock_dest(instr);
+ return result;
}
/******************************************************************************
* *
-* Paramètres : instr = instruction dont les informations sont à consulter. *
+* Paramètres : instr = instruction dont les liens sont à consulter. *
* *
-* Description : Fournit la quantité d'instructions pointant vers une autre. *
+* Description : Fournit la quantité d'instructions placées en source. *
* *
-* Retour : Nombre de ces origines. *
+* Retour : Nombre de ces liens. *
* *
* Remarques : - *
* *
******************************************************************************/
-size_t g_arch_instruction_count_sources(const GArchInstruction *instr)
+size_t g_arch_instruction_count_src_links(const GArchInstruction *instr)
{
size_t result; /* Nombre de liens à renvoyer */
- result = count_flat_array_items(instr->from);
+ result = _g_arch_instruction_count_links(instr, COMPACT_INS_LINK_FROM);
return result;
@@ -1398,24 +1000,21 @@ size_t g_arch_instruction_count_sources(const GArchInstruction *instr)
/******************************************************************************
* *
-* Paramètres : instr = instruction dont les informations sont à consulter. *
-* index = indice de l'élément à retrouver. *
+* Paramètres : instr = instruction dont les liens sont à consulter. *
* *
-* Description : Fournit les détails d'une origine d'une instruction donnée. *
+* Description : Fournit la quantité d'instructions placées en destination. *
* *
-* Retour : Lien déterminé vers une instruction d'origine. *
+* Retour : Nombre de ces liens. *
* *
* Remarques : - *
* *
******************************************************************************/
-const instr_link_t *g_arch_instruction_get_source(GArchInstruction *instr, size_t index)
+size_t g_arch_instruction_count_dest_links(const GArchInstruction *instr)
{
- instr_link_t *result; /* Détails présents à renvoyer */
-
- result = get_flat_array_item(instr->from, index, sizeof(instr_link_t));
+ size_t result; /* Nombre de liens à renvoyer */
- ref_instr_link(result);
+ result = _g_arch_instruction_count_links(instr, COMPACT_INS_LINK_TO);
return result;
@@ -1424,43 +1023,47 @@ const instr_link_t *g_arch_instruction_get_source(GArchInstruction *instr, size_
/******************************************************************************
* *
-* Paramètres : instr = instruction dont les informations sont à consulter. *
-* count = quantié de liens présents. [OUT] *
+* Paramètres : instr = instruction dont les liens sont à consulter. *
+* index = indice de l'élément à retrouver. *
+* dir = direction des liens à considérer. *
+* type = type de lien enregistré. [OUT] *
* *
-* Description : Fournit tous les détails d'origine d'une instruction donnée. *
+* Description : Fournit les détails d'un lien donné avec une instruction. *
* *
-* Retour : Liens vers des instructions d'origine à libérer. *
+* Retour : Autre instruction pointée par l'instruction, voire NULL. *
* *
* Remarques : - *
* *
******************************************************************************/
-instr_link_t *g_arch_instruction_get_sources(GArchInstruction *instr, size_t *count)
+static GArchInstruction *_g_arch_instruction_get_linked_instruction(const GArchInstruction *instr, size_t index, compact_ins_link_t dir, InstructionLinkType *type)
{
- instr_link_t *result; /* Détails présents à renvoyer */
- size_t i; /* Boucle de parcours */
- const instr_link_t *link; /* Lien à fournir */
-
- g_arch_instruction_lock_src(instr);
+ GArchInstruction *result; /* Instance ciblée à renvoyer */
+ uint16_t i; /* Boucle de parcours */
- *count = g_arch_instruction_count_sources(instr);
+ assert(g_thick_object_check_lock(G_THICK_OBJECT(instr)));
- if (*count == 0)
- result = NULL;
+ result = NULL;
+ *type = ILT_COUNT;
- else
+ for (i = 0; i < instr->link_count; i++)
{
- result = (instr_link_t *)malloc(*count * sizeof(instr_link_t));
+ if (COMPACT_INS_LINK_DIR(instr->links[i]) != dir)
+ continue;
- for (i = 0; i < *count; i++)
+ if (index == 0)
{
- link = g_arch_instruction_get_source(instr, i);
- memcpy(&result[i], link, sizeof(instr_link_t));
+ result = COMPACT_INS_LINK_PTR(instr->links[i]);
+ *type = COMPACT_INS_LINK_TYPE(instr->links[i]);
}
+ else
+ index--;
+
}
- g_arch_instruction_unlock_src(instr);
+ if (result != NULL)
+ ref_object(result);
return result;
@@ -1469,21 +1072,23 @@ instr_link_t *g_arch_instruction_get_sources(GArchInstruction *instr, size_t *co
/******************************************************************************
* *
-* Paramètres : instr = instruction dont les informations sont à consulter. *
+* Paramètres : instr = instruction dont les liens sont à consulter. *
+* index = indice de l'élément à retrouver. *
+* type = type de lien enregistré. [OUT] *
* *
-* Description : Donne le nombre d'instructions non naturellement suivantes. *
+* Description : Fournit les détails d'une source donnée d'une instruction. *
* *
-* Retour : Nombre de ces destinations. *
+* Retour : Autre instruction pointée par l'instruction, voire NULL. *
* *
* Remarques : - *
* *
******************************************************************************/
-size_t g_arch_instruction_count_destinations(const GArchInstruction *instr)
+GArchInstruction *g_arch_instruction_get_linked_source(const GArchInstruction *instr, size_t index, InstructionLinkType *type)
{
- size_t result; /* Nombre de liens à renvoyer */
+ GArchInstruction *result; /* Instance ciblée à renvoyer */
- result = count_flat_array_items(instr->to);
+ result = _g_arch_instruction_get_linked_instruction(instr, index, COMPACT_INS_LINK_FROM, type);
return result;
@@ -1492,71 +1097,54 @@ size_t g_arch_instruction_count_destinations(const GArchInstruction *instr)
/******************************************************************************
* *
-* Paramètres : instr = instruction dont les informations sont à consulter. *
+* Paramètres : instr = instruction dont les liens sont à consulter. *
* index = indice de l'élément à retrouver. *
+* type = type de lien enregistré. [OUT] *
* *
-* Description : Fournit les détails d'une destination d'une instruction. *
+* Description : Fournit les détails d'une destination donnée d'une instruct. *
* *
-* Retour : Lien déterminé vers une instruction de destination. *
+* Retour : Autre instruction pointée par l'instruction, voire NULL. *
* *
* Remarques : - *
* *
******************************************************************************/
-const instr_link_t *g_arch_instruction_get_destination(GArchInstruction *instr, size_t index)
+GArchInstruction *g_arch_instruction_get_linked_destination(const GArchInstruction *instr, size_t index, InstructionLinkType *type)
{
- instr_link_t *result; /* Détails présents à renvoyer */
-
- result = get_flat_array_item(instr->to, index, sizeof(instr_link_t));
+ GArchInstruction *result; /* Instance ciblée à renvoyer */
- ref_instr_link(result);
+ result = _g_arch_instruction_get_linked_instruction(instr, index, COMPACT_INS_LINK_TO, type);
return result;
}
+
+/* ---------------------------------------------------------------------------------- */
+/* MANIPULATION DES OPERANDES */
+/* ---------------------------------------------------------------------------------- */
+
+
/******************************************************************************
* *
-* Paramètres : instr = instruction dont les informations sont à consulter. *
-* type = type de lien recherché. *
+* Paramètres : instr = instance à consulter. *
* *
-* Description : Fournit la destination d'une instruction et d'un type donné. *
+* Description : Indique la quantité d'opérandes présents dans l'instruction. *
* *
-* Retour : Instruction de destination trouvée ou NULL. *
+* Retour : Nombre d'opérandes attachés. *
* *
* Remarques : - *
* *
******************************************************************************/
-GArchInstruction *g_arch_instruction_get_given_destination(GArchInstruction *instr, InstructionLinkType type)
+size_t g_arch_instruction_count_operands(const GArchInstruction *instr)
{
- GArchInstruction *result; /* Résultat à remonter */
- size_t count; /* Nombre de liens à parcourir */
- size_t i; /* Boucle de parcours */
- const instr_link_t *dest; /* Destination à étudier */
-
- result = NULL;
-
- g_arch_instruction_lock_dest(instr);
-
- count = g_arch_instruction_count_destinations(instr);
-
- for (i = 0; i < count && result == NULL; i++)
- {
- dest = g_arch_instruction_get_destination(instr, i);
-
- if (dest->type == type)
- {
- result = dest->linked;
- g_object_ref(G_OBJECT(result));
- }
+ size_t result; /* Décompte à retourner */
- unref_instr_link(dest);
+ assert(g_thick_object_check_lock(G_THICK_OBJECT(instr)));
- }
-
- g_arch_instruction_unlock_dest(instr);
+ result = count_flat_array_items(instr->operands);
return result;
@@ -1565,56 +1153,45 @@ GArchInstruction *g_arch_instruction_get_given_destination(GArchInstruction *ins
/******************************************************************************
* *
-* Paramètres : instr = instruction dont les informations sont à consulter. *
-* count = quantié de liens présents. [OUT] *
+* Paramètres : instr = instance à mettre à jour. *
+* operand = instruction à venir associer. *
* *
-* Description : Fournit tous les détails de destination d'une instruction. *
+* Description : Attache un opérande supplémentaire à une instruction. *
* *
-* Retour : Liens vers des instructions de destination à libérer. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-instr_link_t *g_arch_instruction_get_destinations(GArchInstruction *instr, size_t *count)
+void g_arch_instruction_attach_operand(GArchInstruction *instr, GArchOperand *operand)
{
- instr_link_t *result; /* Détails présents à renvoyer */
- size_t i; /* Boucle de parcours */
- const instr_link_t *link; /* Lien à fournir */
-
- g_arch_instruction_lock_dest(instr);
-
- *count = g_arch_instruction_count_destinations(instr);
+ GSingletonFactory *factory; /* Unise à instances uniques */
+ GSingletonCandidate *singleton; /* Instance retenue */
+ GArchOperand *stored; /* Forme d'opérande conservée */
- if (*count == 0)
- result = NULL;
+ assert(g_thick_object_check_lock(G_THICK_OBJECT(instr)));
- else
- {
- result = (instr_link_t *)malloc(*count * sizeof(instr_link_t));
+ factory = get_operands_factory();
- for (i = 0; i < *count; i++)
- {
- link = g_arch_instruction_get_destination(instr, i);
- memcpy(&result[i], link, sizeof(instr_link_t));
- }
+ singleton = g_singleton_factory_get_instance(factory, G_SINGLETON_CANDIDATE(operand));
- }
+ unref_object(factory);
- g_arch_instruction_unlock_dest(instr);
+ stored = G_ARCH_OPERAND(singleton);
- return result;
+ add_item_to_flat_array(&instr->operands, &stored, sizeof(GArchOperand *));
}
/******************************************************************************
* *
-* Paramètres : instr = élément GLib à constuire. *
-* storage = conservateur de données à manipuler ou NULL. *
-* pbuf = zone tampon à lire. *
+* Paramètres : instr = instance à mettre à jour. *
+* old = ancienne opérande à détacher. *
+* new = nouvelle opérande à attacher. *
* *
-* Description : Charge un contenu depuis une mémoire tampon. *
+* Description : Remplace un opérande d'une instruction par un autre. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -1622,40 +1199,47 @@ instr_link_t *g_arch_instruction_get_destinations(GArchInstruction *instr, size_
* *
******************************************************************************/
-static bool g_arch_instruction_load_destinations(GArchInstruction *instr, GObjectStorage *storage, packed_buffer_t *pbuf)
+bool g_arch_instruction_replace_operand(GArchInstruction *instr, GArchOperand *old, GArchOperand *new)
{
bool result; /* Bilan à retourner */
- uleb128_t count; /* Nombre de liens à charger */
- uleb128_t i; /* Boucle de parcours */
- GArchInstruction *linked; /* Lien vers une instruction */
- uleb128_t type; /* Valeur ULEB128 à charger */
+ size_t count; /* Nombre d'opérandes en place */
+ size_t i; /* Boucle de parcours */
+ GArchOperand *op; /* Opérande à manipuler */
+ GSingletonFactory *factory; /* Unise à instances uniques */
+ GSingletonCandidate *singleton; /* Instance retenue */
+ GArchOperand *stored; /* Forme d'opérande conservée */
- g_arch_instruction_lock_dest(instr);
+ assert(g_thick_object_check_lock(G_THICK_OBJECT(instr)));
- result = unpack_uleb128(&count, pbuf);
+ result = false;
- for (i = 0; i < count && result; i++)
+ count = g_arch_instruction_count_operands(instr);
+
+ for (i = 0; i < count && !result; i++)
{
- linked = G_ARCH_INSTRUCTION(g_object_storage_unpack_object(storage, "instructions", pbuf));
- if (linked == NULL)
- {
- result = false;
- break;
- }
+ op = g_arch_instruction_get_operand(instr, i);
- result = unpack_uleb128(&type, pbuf);
- if (!result)
- {
- g_object_unref(G_OBJECT(linked));
- break;
- }
+ result = (op == old);
- g_arch_instruction_link_with(instr, linked, type);
- g_object_unref(G_OBJECT(linked));
+ unref_object(op);
}
- g_arch_instruction_unlock_dest(instr);
+ if (result)
+ {
+ factory = get_operands_factory();
+
+ singleton = g_singleton_factory_get_instance(factory, G_SINGLETON_CANDIDATE(new));
+
+ unref_object(factory);
+
+ stored = G_ARCH_OPERAND(singleton);
+
+ rpl_item_in_flat_array(instr->operands, i - 1, &stored, sizeof(GArchOperand *));
+
+ unref_object(old);
+
+ }
return result;
@@ -1664,11 +1248,10 @@ static bool g_arch_instruction_load_destinations(GArchInstruction *instr, GObjec
/******************************************************************************
* *
-* Paramètres : instr = instruction dont les informations sont à consulter.*
-* storage = conservateur de données à manipuler ou NULL. *
-* pbuf = zone tampon à remplir. *
+* Paramètres : instr = instance à mettre à jour. *
+* target = instruction à venir dissocier. *
* *
-* Description : Sauvegarde toutes les destinations d'une instruction. *
+* Description : Détache un opérande liée d'une instruction. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -1676,87 +1259,67 @@ static bool g_arch_instruction_load_destinations(GArchInstruction *instr, GObjec
* *
******************************************************************************/
-bool g_arch_instruction_store_destinations(GArchInstruction *instr, GObjectStorage *storage, packed_buffer_t *pbuf)
+bool g_arch_instruction_detach_operand(GArchInstruction *instr, GArchOperand *target)
{
bool result; /* Bilan à retourner */
- size_t count; /* Nombre d'éléments à traiter */
- size_t kept; /* Nombre de liens conservés */
+ size_t count; /* Nombre d'opérandes en place */
size_t i; /* Boucle de parcours */
- const instr_link_t *link; /* Lien vers une instruction */
-
- g_arch_instruction_lock_dest(instr);
+ GArchOperand *op; /* Opérande à manipuler */
- count = g_arch_instruction_count_destinations(instr);
+ assert(g_thick_object_check_lock(G_THICK_OBJECT(instr)));
- /**
- * Le type de lien ILT_REF n'est mis en place que lors de la création
- * d'opérandes de type G_TYPE_TARGET_OPERAND, et sera donc remis en place
- * dynamiquement lors de la restauration de ces derniers.
- */
+ result = false;
- kept = 0;
+ count = g_arch_instruction_count_operands(instr);
- for (i = 0; i < count; i++)
+ for (i = 0; i < count && !result; i++)
{
- link = g_arch_instruction_get_destination(instr, i);
+ op = g_arch_instruction_get_operand(instr, i);
- if (link->type != ILT_REF)
- kept++;
+ result = (op == target);
- unref_instr_link(link);
+ unref_object(op);
}
- result = pack_uleb128((uleb128_t []){ kept }, pbuf);
-
- for (i = 0; i < count && result; i++)
+ if (result)
{
- link = g_arch_instruction_get_destination(instr, i);
-
- if (link->type != ILT_REF)
- {
- result = g_object_storage_pack_object(storage, "instructions",
- G_SERIALIZABLE_OBJECT(link->linked), pbuf);
-
- if (result)
- result = pack_uleb128((uleb128_t []){ link->type }, pbuf);
-
- }
+ rem_item_from_flat_array(&instr->operands, i - 1, sizeof(GArchOperand *));
- unref_instr_link(link);
+ unref_object(target);
}
- g_arch_instruction_unlock_dest(instr);
-
return result;
}
-
-/* ---------------------------------------------------------------------------------- */
-/* CONVERSIONS DU FORMAT DES INSTRUCTIONS */
-/* ---------------------------------------------------------------------------------- */
-
-
/******************************************************************************
* *
-* Paramètres : instr = instruction d'assemblage à consulter. *
+* Paramètres : instr = instance à consulter. *
+* index = indice de l'opérande concerné. *
* *
-* Description : Fournit le nom humain de l'instruction manipulée. *
+* Description : Fournit un opérande donné d'une instruction. *
* *
-* Retour : Mot clef de bas niveau. *
+* Retour : Opérande trouvée. *
* *
* Remarques : - *
* *
******************************************************************************/
-const char *g_arch_instruction_get_keyword(GArchInstruction *instr)
+GArchOperand *g_arch_instruction_get_operand(const GArchInstruction *instr, size_t index)
{
- const char *result; /* Désignation à retourner */
+ GArchOperand *result; /* Opérande à retourner */
+ GArchOperand **ptr; /* Adresse dans le tableau */
+
+ assert(g_thick_object_check_lock(G_THICK_OBJECT(instr)));
- result = G_ARCH_INSTRUCTION_GET_CLASS(instr)->get_keyword(instr);
+ ptr = get_flat_array_item(instr->operands, index, sizeof(GArchOperand *));
+
+ result = *ptr;
+
+ ref_object(result);
return result;
@@ -1765,450 +1328,396 @@ const char *g_arch_instruction_get_keyword(GArchInstruction *instr)
/******************************************************************************
* *
-* Paramètres : instr = instruction d'assemblage à consulter. *
+* Paramètres : instr = instance à consulter. *
+* target = instruction à venir retrouver. *
* *
-* Description : Construit un petit résumé concis de l'instruction. *
+* Description : Détermine le chemin conduisant à un opérande. *
* *
-* Retour : Chaîne de caractères à libérer après usage ou NULL. *
+* Retour : Chemin d'accès à l'opérande ou NULL en cas d'absence. *
* *
* Remarques : - *
* *
******************************************************************************/
-char *g_arch_instruction_build_tooltip(const GArchInstruction *instr)
+char *g_arch_instruction_find_operand_path(GArchInstruction *instr, const GArchOperand *target)
{
- char *result; /* Description à retourner */
- GArchInstructionClass *class; /* Classe des instructions */
+ char *result; /* Chemin à retourner */
+ size_t count; /* Nombre d'opérandes en place */
+ size_t i; /* Boucle de parcours */
+ GArchOperand *op; /* Opérande à manipuler */
+ int ret; /* Bilan d'une construction */
+ char *sub_path; /* Sous-chemin emprunté */
- class = G_ARCH_INSTRUCTION_GET_CLASS(instr);
+ result = NULL;
- if (class->build_tooltip != NULL)
- result = class->build_tooltip(instr);
+ g_thick_object_lock(G_THICK_OBJECT(instr));
- else
- result = NULL;
+ count = g_arch_instruction_count_operands(instr);
- return result;
+ /* Première passe : accès direct */
-}
+ for (i = 0; i < count && result == NULL; i++)
+ {
+ op = g_arch_instruction_get_operand(instr, i);
+ if (op == target)
+ {
+ ret = asprintf(&result, "%zu", i);
+ if (ret == -1)
+ {
+ LOG_ERROR_N("asprintf");
+ result = NULL;
+ }
+ }
-/******************************************************************************
-* *
-* Paramètres : instr = instruction d'assemblage à consulter. *
-* *
-* Description : Fournit une description pour l'instruction manipulée. *
-* *
-* Retour : Chaîne de caractères avec balises éventuelles. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ unref_object(op);
-const char *g_arch_instruction_get_description(const GArchInstruction *instr)
-{
- const char *result; /* Description à retourner */
+ }
- result = G_ARCH_INSTRUCTION_GET_CLASS(instr)->get_desc(instr);
+ /* Seconde passe : accès profond */
- return result;
-
-}
+ for (i = 0; i < count && result == NULL; i++)
+ {
+ op = g_arch_instruction_get_operand(instr, i);
+ sub_path = NULL;//g_arch_operand_find_inner_operand_path(op, target);
+ if (sub_path != NULL)
+ {
+ ret = asprintf(&result, "%zu:%s", i, sub_path);
+ if (ret == -1)
+ {
+ LOG_ERROR_N("asprintf");
+ result = NULL;
+ }
-/* ---------------------------------------------------------------------------------- */
-/* OFFRE DE CAPACITES DE GENERATION */
-/* ---------------------------------------------------------------------------------- */
+ free(sub_path);
+ }
-/******************************************************************************
-* *
-* Paramètres : instr = 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 : - *
-* *
-******************************************************************************/
+ unref_object(op);
-static size_t g_arch_instruction_count_lines(const GArchInstruction *instr)
-{
- return 1;
+ }
-}
+ g_thick_object_unlock(G_THICK_OBJECT(instr));
+ return result;
-#ifdef INCLUDE_GTK_SUPPORT
+}
/******************************************************************************
* *
-* Paramètres : instr = 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. *
-* cursor = emplacement à constituer. [OUT] *
+* Paramètres : instr = instance à consulter. *
+* path = chemin d'accès à un opérande à retrouver. *
* *
-* Description : Retrouve l'emplacement correspondant à une position donnée. *
+* Description : Obtient l'opérande correspondant à un chemin donné. *
* *
-* Retour : - *
+* Retour : Opérande trouvé ou NULL en cas d'échec. *
* *
* Remarques : - *
* *
******************************************************************************/
-static void g_arch_instruction_compute_cursor(const GArchInstruction *instr, gint x, size_t index, size_t repeat, GLineCursor **cursor)
+GArchOperand *g_arch_instruction_get_operand_from_path(GArchInstruction *instr, const char *path)
{
- *cursor = g_binary_cursor_new();
+ GArchOperand *result; /* Opérande trouvée à renvoyer */
+ size_t index; /* Indice de l'opérande visé */
+ char *end; /* Poursuite du parcours ? */
+ GArchOperand *found; /* Opérande trouvé */
- g_binary_cursor_update(G_BINARY_CURSOR(*cursor), get_mrange_addr(&instr->range));
+ result = NULL;
-}
+ g_thick_object_lock(G_THICK_OBJECT(instr));
+ /* Recherche au premier niveau */
-/******************************************************************************
-* *
-* Paramètres : instr = générateur à consulter. *
-* index = indice de cette même ligne dans le tampon global. *
-* repeat = indice d'utilisations successives du générateur. *
-* cursor = emplacement à analyser. *
-* *
-* Description : Détermine si le conteneur s'inscrit dans une plage donnée. *
-* *
-* Retour : Bilan de la détermination, utilisable en comparaisons. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ index = strtoul(path, &end, 10);
-static int g_arch_instruction_contain_cursor(const GArchInstruction *instr, size_t index, size_t repeat, const GLineCursor *cursor)
-{
- int result; /* Conclusion à retourner */
- vmpa2t addr; /* Autre emplacement à comparer*/
+ if ((index == ULONG_MAX && errno == ERANGE) || (index == 0 && errno == EINVAL))
+ {
+ LOG_ERROR_N("strtoul");
+ goto done;
+ }
+
+ found = g_arch_instruction_get_operand(instr, index);
+ if (found == NULL) goto done;
+
+ if (*end == '\0')
+ {
+ result = found;
+ goto done;
+ }
+
+ /* Recherche en profondeur */
+
+ assert(*end == ':');
+
+ result = NULL;//g_arch_operand_get_inner_operand_from_path(found, end + 1);
- assert(G_IS_BINARY_CURSOR(cursor));
+ unref_object(found);
- g_binary_cursor_retrieve(G_BINARY_CURSOR(cursor), &addr);
+ done:
- result = cmp_mrange_with_vmpa(&instr->range, &addr);
+ g_thick_object_unlock(G_THICK_OBJECT(instr));
return result;
}
-#endif
+
+/* ---------------------------------------------------------------------------------- */
+/* MECANISMES DE CONSERVATION ET RESTAURATION */
+/* ---------------------------------------------------------------------------------- */
/******************************************************************************
* *
-* Paramètres : instr = générateur à consulter. *
-* index = indice de cette même ligne dans le tampon global. *
-* repeat = indice d'utilisations successives du générateur. *
+* Paramètres : object = élément GLib à constuire. *
+* storage = conservateur de données à manipuler. *
+* fd = flux ouvert en lecture. *
* *
-* Description : Renseigne sur les propriétés liées à un générateur. *
+* Description : Charge un objet depuis un flux de données. *
* *
-* Retour : Propriétés particulières associées. *
+* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
-static BufferLineFlags g_arch_instruction_get_flags2(const GArchInstruction *instr, size_t index, size_t repeat)
+static bool g_arch_instruction_load(GSerializableObject *object, GObjectStorage *storage, int fd)
{
- return BLF_HAS_CODE;
+ bool result; /* Bilan à retourner */
+ uleb128_t extra; /* Données embarquées */
+
+ /* Propriétés internes */
+
+ result = load_uleb128(&extra, fd);
+
+ if (result)
+ g_thick_object_set_extra(G_THICK_OBJECT(object), extra);
+
+ /* Liaisons avec d'autres instructions */
+
+ return result;
}
/******************************************************************************
* *
-* Paramètres : instr = instruction d'assemblage à représenter. *
-* line = ligne de rendu à compléter. *
-* 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. *
+* Paramètres : object = élément GLib à consulter. *
+* storage = conservateur de données à manipuler. *
+* fd = flux ouvert en écriture. *
* *
-* Description : Ajoute à un tampon GLib le contenu de l'instance spécifiée. *
+* Description : Sauvegarde un objet dans un flux de données. *
* *
-* Retour : - *
+* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
-static void _g_arch_instruction_print(GArchInstruction *instr, GBufferLine *line, size_t index, size_t repeat, const GBinContent *content)
+static bool g_arch_instruction_store(const GSerializableObject *object, GObjectStorage *storage, int fd)
{
- const char *key; /* Mot clef principal */
- size_t klen; /* Taille de ce mot clef */
- size_t count; /* Nombre d'opérandes en place */
+ bool result; /* Bilan à retourner */
+ GArchInstruction *instr; /* Version spécialisée */
+ size_t src_count; /* Quantité de sources */
+ size_t dest_count; /* Quantité de destinations */
+ off64_t *ins_offsets; /* Emplacements d'instructions */
size_t i; /* Boucle de parcours */
- GArchOperand *op; /* Opérande à manipuler */
+ GArchInstruction *linked; /* Instruction liée */
+ size_t op_count; /* Quantité d'opérandes */
+ off64_t *op_offsets; /* Emplacements d'opérandes */
+ GArchOperand *op; /* Opérande à traiter */
+ guint extra; /* Données embarquées */
+ InstructionLinkType type; /* Type de lien */
- g_buffer_line_fill_phys(line, DLC_PHYSICAL, MDS_32_BITS_UNSIGNED, get_mrange_addr(&instr->range));
+ assert(g_thick_object_check_lock(G_THICK_OBJECT(object)));
- g_buffer_line_fill_virt(line, DLC_VIRTUAL, MDS_32_BITS_UNSIGNED, get_mrange_addr(&instr->range));
+ /* Préparation des références aux instructions liées */
- g_buffer_line_fill_content(line, DLC_BINARY, content, &instr->range, VMPA_NO_PHYSICAL);
+ instr = G_ARCH_INSTRUCTION(object);
- /* Instruction proprement dite */
+ src_count = g_arch_instruction_count_src_links(instr);
+ dest_count = g_arch_instruction_count_dest_links(instr);
- key = g_arch_instruction_get_keyword(instr);
- klen = strlen(key);
+ ins_offsets = malloc((src_count + dest_count) * sizeof(off64_t));
- g_buffer_line_append_text(line, DLC_ASSEMBLY_HEAD, key, klen, RTT_INSTRUCTION, G_OBJECT(instr));
+ for (i = 0; i < src_count && result; i++)
+ {
+ linked = g_arch_instruction_get_linked_source(instr, i, (InstructionLinkType []) { 0 });
- /* Liste des opérandes */
+ result = g_object_storage_store_object(storage, "instructions",
+ G_SERIALIZABLE_OBJECT(linked), &ins_offsets[i]);
- g_arch_instruction_lock_operands(instr);
+ unref_object(linked);
- count = _g_arch_instruction_count_operands(instr);
+ }
- if (count > 0)
+ for (i = 0; i < dest_count && result; i++)
{
- op = _g_arch_instruction_get_operand(instr, 0);
- g_arch_operand_print(op, line);
- g_object_unref(G_OBJECT(op));
+ linked = g_arch_instruction_get_linked_destination(instr, i, (InstructionLinkType []) { 0 });
- for (i = 1; i < count; i++)
- {
- g_buffer_line_append_text(line, DLC_ASSEMBLY, ",", 1, RTT_PUNCT, NULL);
- g_buffer_line_append_text(line, DLC_ASSEMBLY, " ", 1, RTT_RAW, NULL);
+ result = g_object_storage_store_object(storage, "instructions",
+ G_SERIALIZABLE_OBJECT(linked), &ins_offsets[src_count + i]);
- op = _g_arch_instruction_get_operand(instr, i);
+ unref_object(linked);
- g_arch_operand_print(op, line);
+ }
- g_object_unref(G_OBJECT(op));
+ if (!result)
+ goto exit_with_ins_off;
- }
+ /* Préparation des références aux opérandes embarqués */
- }
+ op_count = g_arch_instruction_count_operands(instr);
- g_arch_instruction_unlock_operands(instr);
+ op_offsets = malloc(op_count * sizeof(off64_t));
-}
+ for (i = 0; i < op_count && result; i++)
+ {
+ op = g_arch_instruction_get_operand(instr, i);
+ result = g_object_storage_store_object(storage, "operandss",
+ G_SERIALIZABLE_OBJECT(op), &op_offsets[i]);
-/******************************************************************************
-* *
-* Paramètres : instr = générateur à utiliser pour l'impression. *
-* line = ligne de rendu à compléter. *
-* 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. *
-* *
-* Description : Imprime dans une ligne de rendu le contenu représenté. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ unref_object(op);
-static void g_arch_instruction_print(GArchInstruction *instr, GBufferLine *line, size_t index, size_t repeat, const GBinContent *content)
-{
- G_ARCH_INSTRUCTION_GET_CLASS(instr)->print(instr, line, index, repeat, content);
+ }
-}
+ if (!result)
+ goto exit_with_op_off;
+ /* Propriétés internes */
+ extra = g_thick_object_get_extra(G_THICK_OBJECT(object));
-/* ---------------------------------------------------------------------------------- */
-/* CONSERVATION ET RECHARGEMENT DES DONNEES */
-/* ---------------------------------------------------------------------------------- */
+ result = store_uleb128((uleb128_t []) { extra }, fd);
+ if (!result) goto exit;
+ /* Liaisons avec d'autres instructions */
-/******************************************************************************
-* *
-* Paramètres : instr = élément GLib à constuire. *
-* storage = conservateur de données à manipuler ou NULL. *
-* pbuf = zone tampon à lire. *
-* *
-* Description : Charge un contenu depuis une mémoire tampon. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ instr = G_ARCH_INSTRUCTION(object);
-static bool _g_arch_instruction_load(GArchInstruction *instr, GObjectStorage *storage, packed_buffer_t *pbuf)
-{
- bool result; /* Bilan à retourner */
- instr_extra_data_t *extra; /* Données insérées à consulter*/
- uleb128_t value; /* Valeur ULEB128 à charger */
- uleb128_t count; /* Nombre d'éléments à traiter */
- uleb128_t i; /* Boucle de parcours */
- GArchOperand *op; /* Opérande à traiter */
+ src_count = g_arch_instruction_count_src_links(instr);
+ dest_count = g_arch_instruction_count_dest_links(instr);
- extra = GET_ARCH_INSTR_EXTRA(instr);
+ result = store_uleb128((uleb128_t []) { src_count }, fd);
+ if (!result) goto exit;
- LOCK_GOBJECT_EXTRA(extra);
+ result = store_uleb128((uleb128_t []) { dest_count }, fd);
+ if (!result) goto exit;
- result = unpack_uleb128(&value, pbuf);
+ for (i = 0; i < src_count && result; i++)
+ {
+ linked = g_arch_instruction_get_linked_source(instr, i, &type);
- if (result)
- extra->uid = value;
+ result = store_uleb128((uleb128_t []) { type }, fd);
- if (result)
- {
- result = unpack_uleb128(&value, pbuf);
+ unref_object(linked);
if (result)
- extra->flags = value;
+ result = store_uleb128((uleb128_t []) { ins_offsets[i] }, fd);
}
- UNLOCK_GOBJECT_EXTRA(extra);
-
- if (result)
- result = unpack_mrange(&instr->range, pbuf);
-
- if (result)
+ for (i = 0; i < dest_count && result; i++)
{
- result = unpack_uleb128(&count, pbuf);
+ linked = g_arch_instruction_get_linked_destination(instr, i, &type);
- for (i = 0; i < count && result; i++)
- {
- op = G_ARCH_OPERAND(g_object_storage_unpack_object(storage, "operands", pbuf));
- result = (op != NULL);
+ result = store_uleb128((uleb128_t []) { type }, fd);
- if (result)
- g_arch_instruction_attach_extra_operand(instr, op);
+ unref_object(linked);
- }
+ if (result)
+ result = store_uleb128((uleb128_t []) { ins_offsets[src_count + i] }, fd);
}
- if (result)
- result = g_arch_instruction_load_destinations(instr, storage, pbuf);
-
- return result;
+ /* Opérandes embarqués */
-}
+ result = store_uleb128((uleb128_t []) { op_count }, fd);
+ if (!result) goto exit;
+ for (i = 0; i < op_count && result; i++)
+ result = store_uleb128((uleb128_t []) { op_offsets[i] }, fd);
-/******************************************************************************
-* *
-* Paramètres : instr = élément GLib à constuire. *
-* storage = conservateur de données à manipuler ou NULL. *
-* pbuf = zone tampon à lire. *
-* *
-* Description : Charge un contenu depuis une mémoire tampon. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ exit:
+ exit_with_op_off:
-static bool g_arch_instruction_load(GArchInstruction *instr, GObjectStorage *storage, packed_buffer_t *pbuf)
-{
- bool result; /* Bilan à retourner */
- GArchInstructionClass *class; /* Classe à activer */
+ free(op_offsets);
- class = G_ARCH_INSTRUCTION_GET_CLASS(instr);
+ exit_with_ins_off:
- result = class->load(instr, storage, pbuf);
+ free(ins_offsets);
return result;
}
-/******************************************************************************
-* *
-* Paramètres : instr = élément GLib à consulter. *
-* storage = conservateur de données à manipuler ou NULL. *
-* pbuf = zone tampon à remplir. *
-* *
-* Description : Sauvegarde un contenu dans une mémoire tampon. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-static bool _g_arch_instruction_store(GArchInstruction *instr, GObjectStorage *storage, packed_buffer_t *pbuf)
-{
- bool result; /* Bilan à retourner */
- instr_extra_data_t *extra; /* Données insérées à consulter*/
- size_t count; /* Nombre d'éléments à traiter */
- size_t i; /* Boucle de parcours */
- GArchOperand *op; /* Opérande à traiter */
-
- extra = GET_ARCH_INSTR_EXTRA(instr);
- LOCK_GOBJECT_EXTRA(extra);
- result = pack_uleb128((uleb128_t []){ extra->uid }, pbuf);
- if (result)
- result = pack_uleb128((uleb128_t []){ extra->flags }, pbuf);
- UNLOCK_GOBJECT_EXTRA(extra);
- if (result)
- result = pack_mrange(&instr->range, pbuf);
- if (result)
- {
- g_arch_instruction_lock_operands(instr);
- count = _g_arch_instruction_count_operands(instr);
- result = pack_uleb128((uleb128_t []){ count }, pbuf);
- for (i = 0; i < count && result; i++)
- {
- op = _g_arch_instruction_get_operand(instr, i);
- result = g_object_storage_pack_object(storage, "operands", G_SERIALIZABLE_OBJECT(op), pbuf);
- g_object_unref(G_OBJECT(op));
- }
- g_arch_instruction_unlock_operands(instr);
- }
- if (result)
- result = g_arch_instruction_store_destinations(instr, storage, pbuf);
+#if 0
- return result;
-}
/******************************************************************************
* *
-* Paramètres : instr = élément GLib à consulter. *
-* storage = conservateur de données à manipuler ou NULL. *
-* pbuf = zone tampon à remplir. *
+* Paramètres : instr = instruction quelconque à traiter. *
+* type = type de procédure à utiliser. *
+* proc = représentation de l'architecture utilisée. *
+* context = contexte associé à la phase de désassemblage. *
+* format = accès aux données du binaire d'origine. *
* *
-* Description : Sauvegarde un contenu dans une mémoire tampon. *
+* Description : Complète un désassemblage accompli pour une instruction. *
* *
-* Retour : Bilan de l'opération. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-static bool g_arch_instruction_store(GArchInstruction *instr, GObjectStorage *storage, packed_buffer_t *pbuf)
+void g_arch_instruction_call_hook(GArchInstruction *instr, InstrProcessHook type, GArchProcessor *proc, GProcContext *context, GExeFormat *format)
{
- bool result; /* Bilan à retourner */
- GArchInstructionClass *class; /* Classe à activer */
+ GArchInstructionClass *class; /* Classe des instructions */
class = G_ARCH_INSTRUCTION_GET_CLASS(instr);
- result = class->store(instr, storage, pbuf);
-
- return result;
+ if (class->call_hook != NULL)
+ class->call_hook(instr, type, proc, context, format);
}
+
+
+
+
+
+#endif
+
+
+
+
+
+
+
+
+
+
diff --git a/src/arch/instruction.h b/src/arch/instruction.h
index 3c9c149..98bc73e 100644
--- a/src/arch/instruction.h
+++ b/src/arch/instruction.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* instruction.h - prototypes pour la gestion générique des instructions
*
- * Copyright (C) 2008-2020 Cyrille Bagard
+ * Copyright (C) 2008-2025 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -25,194 +25,118 @@
#define _ARCH_INSTRUCTION_H
-#include <sys/types.h>
+#include <stdbool.h>
+#include <stdint.h>
-#include "context.h"
#include "operand.h"
-#include "register.h"
#include "vmpa.h"
-#include "../analysis/type.h"
-#include "../common/packed.h"
-#include "../format/executable.h"
+#include "../glibext/helpers.h"
+#include "../glibext/portion.h"
-#define G_TYPE_ARCH_INSTRUCTION g_arch_instruction_get_type()
-#define G_ARCH_INSTRUCTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_arch_instruction_get_type(), GArchInstruction))
-#define G_IS_ARCH_INSTRUCTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_arch_instruction_get_type()))
-#define G_ARCH_INSTRUCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ARCH_INSTRUCTION, GArchInstructionClass))
-#define G_IS_ARCH_INSTRUCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ARCH_INSTRUCTION))
-#define G_ARCH_INSTRUCTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ARCH_INSTRUCTION, GArchInstructionClass))
+/* ----------------------- DEFINITION GENERIQUE D'INSTRUCTION ----------------------- */
-/* Définition générique d'une instruction d'architecture (instance) */
-typedef struct _GArchInstruction GArchInstruction;
+#define G_TYPE_ARCH_INSTRUCTION (g_arch_instruction_get_type())
-/* Définition générique d'une instruction d'architecture (classe) */
-typedef struct _GArchInstructionClass GArchInstructionClass;
+DECLARE_GTYPE(GArchInstruction, g_arch_instruction, G, ARCH_INSTRUCTION);
-/* Drapeaux pour informations complémentaires */
-
-#define AIF_USER_BIT 4
-
-typedef enum _ArchInstrFlag
-{
- AIF_NONE = (0 << 0), /* Aucune information */
- AIF_ROUTINE_START = (1 << 0), /* Début de routine */
- AIF_RETURN_POINT = (1 << 1), /* Retour de fonction appelée */
- AIF_COND_RETURN_POINT = (1 << 2), /* Retour éventuel de fonction */
- AIF_CALL = (1 << 3), /* Instruction d'appel */
-
- AIF_LOW_USER = (1 << AIF_USER_BIT), /* Premier bit disponible */
- AIF_HIGH_USER = (1 << 7), /* Dernier bit disponible */
-
-} ArchInstrFlag;
-
/* Type pour les types d'instructions */
typedef uint16_t itid_t;
-/* Types de crochet de traitement */
-typedef enum _InstrProcessHook
-{
- IPH_FETCH, /* Itinéraire de désassemblage */
- IPH_LINK, /* Edition des liens */
- IPH_POST, /* Résolution des symboles */
-
- IPH_COUNT
-
-} InstrProcessHook;
-
-
-/* Indique le type défini pour une instruction d'architecture. */
-GType g_arch_instruction_get_type(void);
+/* Fournit l'identifiant correspondant à un type d'instructions. */
+itid_t g_arch_instruction_get_type_id(const GArchInstruction *);
/* Indique l'encodage d'une instruction de façon détaillée. */
-const char *g_arch_instruction_get_encoding(const GArchInstruction *);
-
-/* Ajoute une information complémentaire à une instruction. */
-bool g_arch_instruction_set_flag(GArchInstruction *, ArchInstrFlag);
+char *g_arch_instruction_get_encoding(const GArchInstruction *);
-/* Retire une information complémentaire à une instruction. */
-bool g_arch_instruction_unset_flag(GArchInstruction *, ArchInstrFlag);
-
-/* Détermine si une instruction possède un fanion particulier. */
-bool g_arch_instruction_has_flag(const GArchInstruction *, ArchInstrFlag);
+/* Fournit le nom humain de l'instruction manipulée. */
+char *g_arch_instruction_get_keyword(const GArchInstruction *);
-/* Fournit les informations complémentaires d'une instruction. */
-ArchInstrFlag g_arch_instruction_get_flags(const GArchInstruction *);
-/* Définit l'identifiant unique pour un ensemble d'instructions. */
-void g_arch_instruction_set_unique_id(GArchInstruction *, itid_t);
+ /* Type de masques pour les encodages d'instructions */
+typedef enum _InstructionBytesMask
+{
+ /**
+ * Correspond aux bits fixes : pas de valeurs de registre ni de valeur entière.
+ */
+ IBM_LOOSE,
-/* Fournit l'identifiant unique pour un ensemble d'instructions. */
-itid_t g_arch_instruction_get_unique_id(const GArchInstruction *);
+ /**
+ * Dissimulation des références à des éléments externes pouvant varier avec
+ * entre compilations : adresses de saut ou d'appel, références vers des tables,
+ * etc.
+ */
+ IBM_LOCAL,
+ /**
+ * Dissimulation des déplacements à partir d'une base.
+ */
+ IBM_STRICT,
-/**
- * La définition de "GArchProcessor", utile aux traitements complémentaires, ne peut
- * se faire en incluant le fichier d'en-tête "processor.h", pour cause de références
- * circulaires.
- *
- * On procède donc à une seconde déclaration, en attendant éventuellement mieux.
- */
+ /**
+ * Conservation de toutes les valeurs immédiates et dissimulation des registres.
+ */
+ IBM_LARGE,
-/* Depuis "processeur.h" : définition générique d'un processeur d'architecture (instance) */
-typedef struct _GArchProcessor GArchProcessor;
+ IBM_COUNT
+} InstructionBytesMask;
-/* Complète un désassemblage accompli pour une instruction. */
-typedef void (* instr_hook_fc) (GArchInstruction *, GArchProcessor *, GProcContext *, GExeFormat *);
-
-/* Complète un désassemblage accompli pour une instruction. */
-void g_arch_instruction_call_hook(GArchInstruction *, InstrProcessHook, GArchProcessor *, GProcContext *, GExeFormat *);
-/* Définit la localisation d'une instruction. */
-void g_arch_instruction_set_range(GArchInstruction *, const mrange_t *);
+/* Calcule la localisation d'une instruction. */
+void g_arch_instruction_compute_range(GArchInstruction *, GBinaryPortion *, const vmpa2t *, phys_t);
/* Fournit la place mémoire d'une instruction. */
-const mrange_t *g_arch_instruction_get_range(const GArchInstruction *);
-
-
-
-/* Fournit la localisation d'une instruction. */
-void g_arch_instruction_get_location(const GArchInstruction *, off_t *, off_t *, vmpa_t *) __attribute__ ((deprecated));
+bool g_arch_instruction_get_range(const GArchInstruction *, mrange_t *);
+#define AIF_USER_BIT 4
-/* Liste les registres lus et écrits par l'instruction. */
-void g_arch_instruction_get_rw_registers(const GArchInstruction *, GArchRegister ***, size_t *, GArchRegister ***, size_t *) __attribute__ ((deprecated));
+typedef enum _ArchInstructionFlag
+{
+ AIF_NONE = (0 << 0), /* Aucune information */
+ AIF_ROUTINE_START = (1 << 0), /* Début de routine */
+ AIF_RETURN_POINT = (1 << 1), /* Retour de fonction appelée */
+ AIF_COND_RETURN_POINT = (1 << 2), /* Retour éventuel de fonction */
+ AIF_CALL = (1 << 3), /* Instruction d'appel */
+ AIF_LOW_USER = (1 << AIF_USER_BIT), /* Premier bit disponible */
+ AIF_HIGH_USER = (1 << 7), /* Dernier bit disponible */
+} ArchInstructionFlag;
-/* --------------------------- MANIPULATION DES OPERANDES --------------------------- */
+#define AIF_USER_FLAG(n) (1 << (AIF_USER_BIT + n))
-/* Verrouille les accès à la liste des opérandes. */
-void g_arch_instruction_lock_operands(GArchInstruction *);
+/* Ajoute une information complémentaire à une instruction. */
+bool g_arch_instruction_set_flag(GArchInstruction *, ArchInstructionFlag);
-/* Déverrouille les accès à la liste des opérandes. */
-void g_arch_instruction_unlock_operands(GArchInstruction *);
+/* Retire une information complémentaire à une instruction. */
+bool g_arch_instruction_unset_flag(GArchInstruction *, ArchInstructionFlag);
-/* Attache un opérande supplémentaire à une instruction. */
-void g_arch_instruction_attach_extra_operand(GArchInstruction *, GArchOperand *);
+/* Détermine si une instruction possède un fanion particulier. */
+bool g_arch_instruction_has_flag(const GArchInstruction *, ArchInstructionFlag);
-/* Indique la quantité d'opérandes présents dans l'instruction. */
-size_t _g_arch_instruction_count_operands(const GArchInstruction *);
+/* Fournit les particularités de l'instruction. */
+ArchInstructionFlag g_arch_instruction_get_flags(const GArchInstruction *);
-/* Fournit un opérande donné d'une instruction. */
-GArchOperand *_g_arch_instruction_get_operand(const GArchInstruction *, size_t);
-/* Remplace un opérande d'une instruction par un autre. */
-bool _g_arch_instruction_replace_operand(GArchInstruction *, GArchOperand *, GArchOperand *);
+/* Types de crochet de traitement */
+typedef enum _InstrProcessHook
+{
+ IPH_FETCH, /* Itinéraire de désassemblage */
+ IPH_LINK, /* Edition des liens */
+ IPH_POST, /* Résolution des symboles */
-/* Détache un opérande liée d'une instruction. */
-bool _g_arch_instruction_detach_operand(GArchInstruction *, GArchOperand *);
-
-
-#define g_arch_instruction_count_operands(ins) \
- ({ \
- size_t __result; \
- g_arch_instruction_lock_operands(ins); \
- __result = _g_arch_instruction_count_operands(ins); \
- g_arch_instruction_unlock_operands(ins); \
- __result; \
- })
-
-#define g_arch_instruction_get_operand(ins, idx) \
- ({ \
- GArchOperand *__result; \
- g_arch_instruction_lock_operands(ins); \
- __result = _g_arch_instruction_get_operand(ins, idx); \
- g_arch_instruction_unlock_operands(ins); \
- __result; \
- })
-
-#define g_arch_instruction_replace_operand(ins, o, n) \
- ({ \
- bool __result; \
- g_arch_instruction_lock_operands(ins); \
- __result = _g_arch_instruction_replace_operand(ins, o, n); \
- g_arch_instruction_unlock_operands(ins); \
- __result; \
- })
-
-#define g_arch_instruction_detach_operand(ins, o) \
- ({ \
- bool __result; \
- g_arch_instruction_lock_operands(ins); \
- __result = _g_arch_instruction_detach_operand(ins, o); \
- g_arch_instruction_unlock_operands(ins); \
- __result; \
- })
+ IPH_COUNT
+} InstrProcessHook;
-/* Détermine le chemin conduisant à un opérande. */
-char *g_arch_instruction_find_operand_path(GArchInstruction *, const GArchOperand *);
-/* Obtient l'opérande correspondant à un chemin donné. */
-GArchOperand *g_arch_instruction_get_operand_from_path(GArchInstruction *, const char *);
@@ -236,30 +160,24 @@ typedef enum _InstructionLinkType
} InstructionLinkType;
-/* Déscription d'une liaison entre deux instructions */
-typedef struct _instr_link_t
-{
- GArchInstruction *linked; /* Autre instruction liée */
- InstructionLinkType type; /* Type de liaison */
-
-} instr_link_t;
-
-#define ref_instr_link(l) g_object_ref(G_OBJECT(l->linked));
-#define unref_instr_link(l) g_object_unref(G_OBJECT(l->linked));
+/* Détermine si un type de lien amène à une instruction. */
+bool g_arch_instruction_has_src_link(const GArchInstruction *, InstructionLinkType);
+/* Détermine si un type de lien émerge d'une instruction. */
+bool g_arch_instruction_has_dest_link(const GArchInstruction *, InstructionLinkType);
-/* Met à disposition un encadrement des accès aux liens. */
-void g_arch_instruction_lock_unlock_links(GArchInstruction *, bool, bool);
+/* Détermine si une instruction est source d'une autre. */
+bool g_arch_instruction_has_src_link_with(const GArchInstruction *, const GArchInstruction *);
-/* Détermine si un type de lien existe dans une instruction. */
-bool g_arch_instruction_has_link(GArchInstruction *, InstructionLinkType);
-
-/* Détermine si un lien est déjà établi entre deux instructions. */
-bool g_arch_instruction_has_link_to(GArchInstruction *, const GArchInstruction *);
+/* Détermine si une instruction est destination d'une autre. */
+bool g_arch_instruction_has_dest_link_with(const GArchInstruction *, const GArchInstruction *);
/* Etablit un lien entre deux instructions. */
-void g_arch_instruction_link_with(GArchInstruction *, GArchInstruction *, InstructionLinkType);
+void g_arch_instruction_link(GArchInstruction *, GArchInstruction *, InstructionLinkType);
+
+/* Supprime un lien entre deux instructions. */
+void g_arch_instruction_unlink(GArchInstruction *, GArchInstruction *, InstructionLinkType);
/* Change la nature d'un lien entre deux instructions. */
bool g_arch_instruction_change_link(GArchInstruction *, GArchInstruction *, InstructionLinkType, InstructionLinkType);
@@ -267,46 +185,72 @@ bool g_arch_instruction_change_link(GArchInstruction *, GArchInstruction *, Inst
/* Supprime tous les liens établis avec d'autres instructions. */
void g_arch_instruction_delete_all_links(GArchInstruction *);
-#define g_arch_instruction_lock_src(ins) g_arch_instruction_lock_unlock_links(ins, true, true)
-#define g_arch_instruction_unlock_src(ins) g_arch_instruction_lock_unlock_links(ins, true, false)
+/* Fournit la quantité d'instructions placées en source. */
+size_t g_arch_instruction_count_src_links(const GArchInstruction *);
-/* Fournit la quantité d'instructions pointant vers une autre. */
-size_t g_arch_instruction_count_sources(const GArchInstruction *);
+/* Fournit la quantité d'instructions placées en destination. */
+size_t g_arch_instruction_count_dest_links(const GArchInstruction *);
-/* Fournit les détails d'une origine d'une instruction donnée. */
-const instr_link_t *g_arch_instruction_get_source(GArchInstruction *, size_t);
+/* Fournit les détails d'une source donnée d'une instruction. */
+GArchInstruction *g_arch_instruction_get_linked_source(const GArchInstruction *, size_t, InstructionLinkType *);
-/* Fournit tous les détails d'origine d'une instruction donnée. */
-instr_link_t *g_arch_instruction_get_sources(GArchInstruction *, size_t *);
+/* Fournit les détails d'une destination donnée d'une instruction. */
+GArchInstruction *g_arch_instruction_get_linked_destination(const GArchInstruction *, size_t, InstructionLinkType *);
-#define g_arch_instruction_lock_dest(ins) g_arch_instruction_lock_unlock_links(ins, false, true)
-#define g_arch_instruction_unlock_dest(ins) g_arch_instruction_lock_unlock_links(ins, false, false)
-/* Donne le nombre d'instructions non naturellement suivantes. */
-size_t g_arch_instruction_count_destinations(const GArchInstruction *);
-/* Fournit les détails d'une destination d'une instruction. */
-const instr_link_t *g_arch_instruction_get_destination(GArchInstruction *, size_t);
+/* --------------------------- MANIPULATION DES OPERANDES --------------------------- */
-/* Fournit la destination d'une instruction et d'un type donné. */
-GArchInstruction *g_arch_instruction_get_given_destination(GArchInstruction *, InstructionLinkType);
-/* Fournit tous les détails de destination d'une instruction. */
-instr_link_t *g_arch_instruction_get_destinations(GArchInstruction *, size_t *);
+/* Indique la quantité d'opérandes présents dans l'instruction. */
+size_t g_arch_instruction_count_operands(const GArchInstruction *);
+/* Attache un opérande supplémentaire à une instruction. */
+void g_arch_instruction_attach_operand(GArchInstruction *, GArchOperand *);
+/* Remplace un opérande d'une instruction par un autre. */
+bool g_arch_instruction_replace_operand(GArchInstruction *, GArchOperand *, GArchOperand *);
-/* --------------------- CONVERSIONS DU FORMAT DES INSTRUCTIONS --------------------- */
+/* Détache un opérande liée d'une instruction. */
+bool g_arch_instruction_detach_operand(GArchInstruction *, GArchOperand *);
+/* Fournit un opérande donné d'une instruction. */
+GArchOperand *g_arch_instruction_get_operand(const GArchInstruction *, size_t);
+
+/* Détermine le chemin conduisant à un opérande. */
+char *g_arch_instruction_find_operand_path(GArchInstruction *, const GArchOperand *);
+
+/* Obtient l'opérande correspondant à un chemin donné. */
+GArchOperand *g_arch_instruction_get_operand_from_path(GArchInstruction *, const char *);
+
+
+
+
+#if 0
+
+
+
+/**
+ * La définition de "GArchProcessor", utile aux traitements complémentaires, ne peut
+ * se faire en incluant le fichier d'en-tête "processor.h", pour cause de références
+ * circulaires.
+ *
+ * On procède donc à une seconde déclaration, en attendant éventuellement mieux.
+ */
+
+/* Depuis "processeur.h" : définition générique d'un processeur d'architecture (instance) */
+typedef struct _GArchProcessor GArchProcessor;
+
+
+/* Complète un désassemblage accompli pour une instruction. */
+typedef void (* instr_hook_fc) (GArchInstruction *, GArchProcessor *, GProcContext *, GExeFormat *);
+
+/* Complète un désassemblage accompli pour une instruction. */
+void g_arch_instruction_call_hook(GArchInstruction *, InstrProcessHook, GArchProcessor *, GProcContext *, GExeFormat *);
-/* Fournit le nom humain de l'instruction manipulée. */
-const char *g_arch_instruction_get_keyword(GArchInstruction *);
-/* Construit un petit résumé concis de l'instruction. */
-char *g_arch_instruction_build_tooltip(const GArchInstruction *);
-/* Fournit une description pour l'instruction manipulée. */
-const char *g_arch_instruction_get_description(const GArchInstruction *);
+#endif
diff --git a/src/arch/instructions/Makefile.am b/src/arch/instructions/Makefile.am
index 28cf90f..d6fc4bd 100644
--- a/src/arch/instructions/Makefile.am
+++ b/src/arch/instructions/Makefile.am
@@ -1,12 +1,19 @@
-noinst_LTLIBRARIES = libarchinstructions.la
+noinst_LTLIBRARIES = libarchinstructions.la libarchinstructionsui.la
libarchinstructions_la_SOURCES = \
+ raw-int.h \
raw.h raw.c \
undefined-int.h \
undefined.h undefined.c
-libarchinstructions_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS)
+libarchinstructions_la_CFLAGS = $(LIBGOBJ_CFLAGS)
+
+libarchinstructionsui_la_SOURCES = \
+ raw-ui.h raw-ui.c \
+ undefined-ui.h undefined-ui.c
+
+libarchinstructionsui_la_CFLAGS = $(LIBGTK4_CFLAGS)
devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%)
diff --git a/src/arch/instructions/raw-int.h b/src/arch/instructions/raw-int.h
new file mode 100644
index 0000000..4a5e64b
--- /dev/null
+++ b/src/arch/instructions/raw-int.h
@@ -0,0 +1,56 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * raw-int.h - prototypes pour la définition interne des instructions de données brutes
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ARCH_INSTRUCTIONS_RAW_INT_H
+#define _ARCH_INSTRUCTIONS_RAW_INT_H
+
+
+#include "raw.h"
+#include "../instruction-int.h"
+
+
+
+/* Définition générique d'une instruction brute d'architecture (instance) */
+struct _GRawInstruction
+{
+ GArchInstruction parent; /* A laisser en premier */
+
+};
+
+/* Définition générique d'une instruction brute d'architecture (instance) */
+struct _GRawInstructionClass
+{
+ GArchInstructionClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place une instruction de type 'db/dw/etc' simple. */
+bool g_raw_instruction_create_value(GRawInstruction *, GBinaryPortion *, const vmpa2t *, MemoryDataSize, uint64_t);
+
+/* Met en place une instruction de type 'db/dw/etc' étendue. */
+bool g_raw_instruction_create_array(GRawInstruction *, GBinaryPortion *, vmpa2t *, MemoryDataSize, const GBinContent *, size_t, SourceEndian);
+
+
+
+#endif /* _ARCH_INSTRUCTIONS_RAW_INT_H */
diff --git a/src/arch/instructions/raw-ui.c b/src/arch/instructions/raw-ui.c
new file mode 100644
index 0000000..1026dfb
--- /dev/null
+++ b/src/arch/instructions/raw-ui.c
@@ -0,0 +1,261 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * raw-ui.c - opérandes représentant des instructions de données brutes sous forme graphique
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "raw-ui.h"
+
+
+#include <assert.h>
+#include <ctype.h>
+#include <malloc.h>
+
+
+#include "raw.h"
+#include "../operand-ui.h"
+#include "../operands/immediate.h"
+#include "../../glibext/objhole.h"
+#include "../../glibext/options/asm.h"
+
+
+
+/* Etablit dans une ligne de rendu le contenu représenté. */
+static void g_raw_instruction_ui_populate_line(const GTokenGenerator *, size_t, size_t, GBufferLine *, void *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : iface = interface GLib à initialiser. *
+* *
+* Description : Procède à l'initialisation de l'interface de génération. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_raw_instruction_ui_token_generator_iface_init(GTokenGeneratorInterface *iface)
+{
+ iface->populate = g_raw_instruction_ui_populate_line;
+
+}
+
+
+/******************************************************************************
+* *
+* 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_raw_instruction_ui_populate_line(const GTokenGenerator *generator, size_t index, size_t repeat, GBufferLine *line, void *data)
+{
+ GArchInstruction *instr; /* Version spécialisée #1 */
+ GRawInstruction *raw; /* Version spécialisée #2 */
+ GBinContent *content; /* Contenu brut d'origine */
+ mrange_t range; /* Emplacement couvert */
+ phys_t max_displayed_len; /* Quantité de code affichée */
+ char *key; /* Mot clef principal */
+ char *string; /* Chaîne reconstituée */
+ size_t iter; /* Tête d'écriture */
+ bool first; /* Mémorise une énumération */
+ size_t count; /* Nombre d'opérandes en place */
+ size_t i; /* Boucle de parcours */
+ GArchOperand *op; /* Opérande à manipuler */
+ GImmediateOperand *imm; /* Version opérande de valeur */
+ char byte; /* Octet à afficher (ou pas) */
+#ifndef NDEBUG
+ bool status; /* Bilan d'une récupération */
+#endif
+
+ instr = G_ARCH_INSTRUCTION(generator);
+ raw = G_RAW_INSTRUCTION(instr);
+ content = G_BIN_CONTENT(data);
+
+ g_thick_object_lock(G_THICK_OBJECT(instr));
+
+ /* Prologue */
+
+ if (g_arch_instruction_get_range(instr, &range))
+ {
+ /* Localisation */
+
+ g_buffer_line_fill_physical(line, ACO_PHYSICAL, MDS_32_BITS_UNSIGNED, get_mrange_addr(&range));
+
+ g_buffer_line_fill_virtual(line, ACO_VIRTUAL, MDS_32_BITS_UNSIGNED, get_mrange_addr(&range));
+
+ /* Contenu */
+
+ if (g_raw_instruction_is_padding(raw))
+ max_displayed_len = 0;
+
+ else if (g_raw_instruction_is_string(raw))
+ max_displayed_len = 1;
+
+ else
+ {
+ max_displayed_len = get_mrange_length(&range);
+ max_displayed_len /= g_arch_instruction_count_operands(instr);
+ }
+
+ g_buffer_line_fill_content(line, ACO_BINARY, content, &range, max_displayed_len);
+
+ }
+
+ /* Instruction proprement dite */
+
+ key = g_arch_instruction_get_keyword(instr);
+
+ g_buffer_line_append_text(line, ACO_ASSEMBLY_HEAD, TRT_INSTRUCTION, SL(key), NULL, G_OBJECT(instr));
+
+ free(key);
+
+ /* Contenu sous forme d'opérandes */
+
+ if (g_raw_instruction_is_padding(raw))
+ g_buffer_line_append_text(line, ACO_ASSEMBLY, TRT_CHR_PRINTABLE, STCSL("..."), NULL, NULL);
+
+ else
+ {
+ string = NULL;
+ iter = 0;
+
+ first = true;
+
+ count = g_arch_instruction_count_operands(instr);
+
+ for (i = 0; i < count; i++)
+ {
+ op = g_arch_instruction_get_operand(instr, i);
+
+ if (!G_IS_IMMEDIATE_OPERAND(op))
+ goto fallback;
+
+ imm = G_IMMEDIATE_OPERAND(op);
+
+ if (g_immediate_operand_get_size(imm) != MDS_8_BITS)
+ goto fallback;
+
+ if (!g_raw_instruction_is_string(raw) && g_immediate_operand_get_display(imm) != IOD_CHAR)
+ goto fallback;
+
+#ifndef NDEBUG
+ status = g_immediate_operand_get_value(imm, MDS_8_BITS, &byte);
+ assert(status);
+#else
+ g_immediate_operand_get_value(imm, MDS_8_BITS, &byte);
+#endif
+
+ /* Si le caractère doit apparaître en hexadécimal... */
+
+ if (!isprint(byte))
+ goto fallback;
+
+ /* Impression de l'octet */
+
+ if (string == NULL)
+ {
+ string = calloc(count + 3, sizeof(char));
+
+ strcpy(string, "\"");
+ iter = 1;
+
+ }
+
+ string[iter++] = byte;
+
+ unref_object(op);
+
+ continue;
+
+ fallback:
+
+ /* Si une chaîne précède */
+
+ if (string != NULL && iter > 1)
+ {
+ if (!first)
+ {
+ g_buffer_line_append_text(line, ACO_ASSEMBLY, TRT_PUNCT, STCSL(","), NULL, NULL);
+ g_buffer_line_append_text(line, ACO_ASSEMBLY, TRT_CHR_PRINTABLE, STCSL(" "), NULL, NULL);
+ }
+ else
+ first = false;
+
+ string[iter++] = '"';
+
+ g_buffer_line_append_text(line, ACO_ASSEMBLY, TRT_STRING, string, iter, NULL, NULL);
+
+ iter = 1;
+
+ }
+
+ /* Intégration en tant qu'opérande classique */
+
+ if (!first)
+ {
+ g_buffer_line_append_text(line, ACO_ASSEMBLY, TRT_PUNCT, STCSL(","), NULL, NULL);
+ g_buffer_line_append_text(line, ACO_ASSEMBLY, TRT_CHR_PRINTABLE, STCSL(" "), NULL, NULL);
+ }
+ else
+ first = false;
+
+ g_arch_operand_ui_print(G_ARCH_OPERAND_UI(op), line);
+
+ unref_object(op);
+
+ }
+
+ /* Si au final une chaîne traine encore */
+
+ if (string != NULL && iter > 1)
+ {
+ if (!first)
+ {
+ g_buffer_line_append_text(line, ACO_ASSEMBLY, TRT_PUNCT, STCSL(","), NULL, NULL);
+ g_buffer_line_append_text(line, ACO_ASSEMBLY, TRT_CHR_PRINTABLE, STCSL(" "), NULL, NULL);
+ }
+
+ string[iter++] = '"';
+
+ g_buffer_line_append_text(line, ACO_ASSEMBLY, TRT_STRING, string, iter, NULL, NULL);
+
+ }
+
+ if (string != NULL)
+ free(string);
+
+ }
+
+ g_thick_object_unlock(G_THICK_OBJECT(instr));
+
+}
diff --git a/src/arch/instructions/raw-ui.h b/src/arch/instructions/raw-ui.h
new file mode 100644
index 0000000..cd604e6
--- /dev/null
+++ b/src/arch/instructions/raw-ui.h
@@ -0,0 +1,37 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * raw-ui.h - prototypes pour les opérandes représentant des instructions de données brutes sous forme graphique
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ARCH_OPERANDS_RAW_UI_H
+#define _ARCH_OPERANDS_RAW_UI_H
+
+
+#include "../../glibext/generator-int.h"
+
+
+
+/* Procède à l'initialisation de l'interface de génération. */
+void g_raw_instruction_ui_token_generator_iface_init(GTokenGeneratorInterface *);
+
+
+
+#endif /* _ARCH_OPERANDS_RAW_UI_H */
diff --git a/src/arch/instructions/raw.c b/src/arch/instructions/raw.c
index 26282fa..87297f1 100644
--- a/src/arch/instructions/raw.c
+++ b/src/arch/instructions/raw.c
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* raw.c - instructions pures vues de l'esprit
*
- * Copyright (C) 2014-2020 Cyrille Bagard
+ * Copyright (C) 2014-2025 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -25,36 +25,19 @@
#include <assert.h>
-#include <ctype.h>
#include <string.h>
#include <i18n.h>
-#include "../instruction-int.h"
+#include "raw-int.h"
#include "../operands/immediate.h"
-#include "../operands/target.h"
-#include "../../core/columns.h"
+//#include "../operands/target.h" // FIXME
-/* ------------------------- INSTRUCTION INCONNUE / DONNEES ------------------------- */
-
-
-/* Définition générique d'une instruction brute d'architecture (instance) */
-struct _GRawInstruction
-{
- GArchInstruction parent; /* A laisser en premier */
-
-};
-
-/* Définition générique d'une instruction brute d'architecture (classe) */
-struct _GRawInstructionClass
-{
- GArchInstructionClass parent; /* A laisser en premier */
-
-};
+/* --------------------- INSTRUCTION AVEC JEU DE DONNEES BRUTES --------------------- */
/* Initialise la classe des instructions brutes d'architecture. */
@@ -64,40 +47,26 @@ static void g_raw_instruction_class_init(GRawInstructionClass *);
static void g_raw_instruction_init(GRawInstruction *);
/* Supprime toutes les références externes. */
-static void g_raw_instruction_dispose(GRawInstruction *);
+static void g_raw_instruction_dispose(GObject *);
/* Procède à la libération totale de la mémoire. */
-static void g_raw_instruction_finalize(GRawInstruction *);
-
-/* Indique l'encodage d'une instruction de façon détaillée. */
-static const char *g_raw_instruction_get_encoding(const GRawInstruction *);
-
-/* Fournit le nom humain de l'instruction manipulée. */
-static const char *g_raw_instruction_get_keyword(const GRawInstruction *);
+static void g_raw_instruction_finalize(GObject *);
-/* -------------------- CONSERVATION SUR DISQUE DES INSTRUCTIONS -------------------- */
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
-/* Charge une instruction depuis une mémoire tampon. */
-static bool g_raw_instruction_unserialize(GRawInstruction *, GAsmStorage *, GBinFormat *, packed_buffer_t *);
-
-/* Sauvegarde une instruction dans une mémoire tampon. */
-static bool g_raw_instruction_serialize(GRawInstruction *, GAsmStorage *, packed_buffer_t *);
-
-
-
-/* ------------------------ OFFRE DE CAPACITES DE GENERATION ------------------------ */
-
+/* Indique l'encodage d'une instruction de façon détaillée. */
+static char *g_raw_instruction_get_encoding(const GArchInstruction *);
-/* Ajoute à un tampon GLib le contenu de l'instance spécifiée. */
-static void g_raw_instruction_print(GRawInstruction *, GBufferLine *, size_t, size_t, const GBinContent *);
+/* Fournit le nom humain de l'instruction manipulée. */
+static char *g_raw_instruction_get_keyword(const GArchInstruction *);
/* ---------------------------------------------------------------------------------- */
-/* INSTRUCTION INCONNUE / DONNEES */
+/* INSTRUCTION AVEC JEU DE DONNEES BRUTES */
/* ---------------------------------------------------------------------------------- */
@@ -124,18 +93,13 @@ static void g_raw_instruction_class_init(GRawInstructionClass *klass)
object = G_OBJECT_CLASS(klass);
- object->dispose = (GObjectFinalizeFunc/* ! */)g_raw_instruction_dispose;
- object->finalize = (GObjectFinalizeFunc)g_raw_instruction_finalize;
+ object->dispose = g_raw_instruction_dispose;
+ object->finalize = g_raw_instruction_finalize;
instr = G_ARCH_INSTRUCTION_CLASS(klass);
- instr->get_encoding = (get_instruction_encoding_fc)g_raw_instruction_get_encoding;
- instr->get_keyword = (get_instruction_keyword_fc)g_raw_instruction_get_keyword;
-
- instr->unserialize = (unserialize_instruction_fc)g_raw_instruction_unserialize;
- instr->serialize = (serialize_instruction_fc)g_raw_instruction_serialize;
-
- instr->print = (print_instruction_fc)g_raw_instruction_print;
+ instr->get_encoding = g_raw_instruction_get_encoding;
+ instr->get_keyword = g_raw_instruction_get_keyword;
}
@@ -160,7 +124,7 @@ static void g_raw_instruction_init(GRawInstruction *instr)
/******************************************************************************
* *
-* Paramètres : instr = instance d'objet GLib à traiter. *
+* Paramètres : object = instance d'objet GLib à traiter. *
* *
* Description : Supprime toutes les références externes. *
* *
@@ -170,16 +134,16 @@ static void g_raw_instruction_init(GRawInstruction *instr)
* *
******************************************************************************/
-static void g_raw_instruction_dispose(GRawInstruction *instr)
+static void g_raw_instruction_dispose(GObject *object)
{
- G_OBJECT_CLASS(g_raw_instruction_parent_class)->dispose(G_OBJECT(instr));
+ G_OBJECT_CLASS(g_raw_instruction_parent_class)->dispose(object);
}
/******************************************************************************
* *
-* Paramètres : instr = instance d'objet GLib à traiter. *
+* Paramètres : object = instance d'objet GLib à traiter. *
* *
* Description : Procède à la libération totale de la mémoire. *
* *
@@ -189,16 +153,17 @@ static void g_raw_instruction_dispose(GRawInstruction *instr)
* *
******************************************************************************/
-static void g_raw_instruction_finalize(GRawInstruction *instr)
+static void g_raw_instruction_finalize(GObject *object)
{
- G_OBJECT_CLASS(g_raw_instruction_parent_class)->finalize(G_OBJECT(instr));
+ G_OBJECT_CLASS(g_raw_instruction_parent_class)->finalize(object);
}
/******************************************************************************
* *
-* Paramètres : addr = position à associer à l'instruction. *
+* Paramètres : area = portion de binaire incluant l'instruction. *
+* addr = adresse virtuelle et/ou position physique. *
* size = taille de l'opérande souhaitée. *
* value = valeur sur x bits à venir récupérer. *
* *
@@ -210,127 +175,106 @@ static void g_raw_instruction_finalize(GRawInstruction *instr)
* *
******************************************************************************/
-GArchInstruction *g_raw_instruction_new_from_value(const vmpa2t *addr, MemoryDataSize size, uint64_t value)
+GArchInstruction *g_raw_instruction_new_from_value(GBinaryPortion *area, const vmpa2t *addr, MemoryDataSize size, uint64_t value)
{
GArchInstruction *result; /* Instruction à retourner */
- GArchOperand *operand; /* Octet non décodé à afficher */
- mrange_t range; /* Couverture de l'instruction */
result = g_object_new(G_TYPE_RAW_INSTRUCTION, NULL);
- operand = g_imm_operand_new_from_value(size, value);
- if (operand == NULL) goto error;
+ if (!g_raw_instruction_create_value(G_RAW_INSTRUCTION(result), area, addr, size, value))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : instr = instance à initialiser pleinement. *
+* area = portion de binaire incluant l'instruction. *
+* addr = adresse virtuelle et/ou position physique. *
+* size = taille de chacun des éléments à représenter. *
+* value = valeur sur x bits à venir récupérer. *
+* *
+* Description : Met en place une instruction de type 'db/dw/etc' simple. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_raw_instruction_create_value(GRawInstruction *instr, GBinaryPortion *area, const vmpa2t *addr, MemoryDataSize size, uint64_t value)
+{
+ bool result; /* Bilan à retourner */
+ GArchOperand *operand; /* Octet non décodé à afficher */
+ uint16_t length; /* Taille de l'instruction */
+
+ result = false;
+
+ operand = g_immediate_operand_new_from_value(size, value);
+ if (operand == NULL) goto exit;
g_arch_operand_set_flag(operand, IOF_ZERO_PADDING_BY_DEFAULT | IOF_ZERO_PADDING);
- g_arch_instruction_attach_extra_operand(result, operand);
+ g_thick_object_lock(G_THICK_OBJECT(instr));
+
+ g_arch_instruction_attach_operand(G_ARCH_INSTRUCTION(instr), operand);
+ unref_object(operand);
+
+ g_thick_object_unlock(G_THICK_OBJECT(instr));
switch (size)
{
case MDS_8_BITS_UNSIGNED:
case MDS_8_BITS_SIGNED:
- init_mrange(&range, addr, 1);
+ length = 1;
break;
case MDS_16_BITS_UNSIGNED:
case MDS_16_BITS_SIGNED:
- init_mrange(&range, addr, 2);
+ length = 2;
break;
case MDS_32_BITS_UNSIGNED:
case MDS_32_BITS_SIGNED:
- init_mrange(&range, addr, 4);
+ length = 4;
break;
case MDS_64_BITS_UNSIGNED:
case MDS_64_BITS_SIGNED:
- init_mrange(&range, addr, 8);
+ length = 8;
break;
default:
assert(false);
- goto error;
+ goto exit;
break;
}
- g_arch_instruction_set_range(result, &range);
+ g_arch_instruction_compute_range(G_ARCH_INSTRUCTION(instr), area, addr, length);
- return result;
-
- error:
-
- g_object_unref(G_OBJECT(result));
-
- return NULL;
-
-}
+ result = true;
-
-/******************************************************************************
-* *
-* Paramètres : content = flux de données à analyser. *
-* addr = position courante dans ce flux. [OUT] *
-* *
-* Description : Crée une instruction de type 'db/dw/etc' pour un uleb128. *
-* *
-* Retour : Instruction mise en place. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GArchInstruction *g_raw_instruction_new_uleb128(const GBinContent *content, vmpa2t *addr)
-{
- GArchInstruction *result; /* Instruction à retourner */
- vmpa2t start; /* Départ original de lecture */
- uleb128_t value; /* Valeur uleb128 à représenter*/
- phys_t diff; /* Couverture de la lecture */
- MemoryDataSize leb_size; /* Taille de la valeur */
- GArchOperand *operand; /* Octet non décodé à afficher */
- mrange_t range; /* Couverture de l'instruction */
-
- result = NULL;
-
- copy_vmpa(&start, addr);
-
- if (!g_binary_content_read_uleb128(content, addr, &value))
- goto error;
-
- diff = compute_vmpa_diff(&start, addr);
-
- leb_size = MDS_FROM_BYTES(diff);
- assert(leb_size != MDS_UNDEFINED);
-
- result = g_object_new(G_TYPE_RAW_INSTRUCTION, NULL);
-
- init_mrange(&range, &start, diff);
- g_arch_instruction_set_range(result, &range);
-
- operand = g_imm_operand_new_from_value(leb_size, (uint64_t)value);
- if (operand == NULL) goto error;
-
- g_arch_operand_set_flag(operand, IOF_ZERO_PADDING_BY_DEFAULT | IOF_ZERO_PADDING);
-
- g_arch_instruction_attach_extra_operand(result, operand);
+ exit:
return result;
- error:
-
- g_clear_object(&result);
-
- return NULL;
-
}
/******************************************************************************
* *
-* Paramètres : content = flux de données à analyser. *
-* addr = position courante dans ce flux. [OUT] *
+* Paramètres : area = portion de binaire incluant l'instruction. *
+* addr = adresse virtuelle et/ou position physique. *
+* size = taille de chacun des éléments à représenter. *
+* content = flux de données à analyser. *
+* count = nombre de ces éléments. *
+* endian = ordre des bits dans la source. *
* *
-* Description : Crée une instruction de type 'db/dw/etc' pour un sleb128. *
+* Description : Crée une instruction de type 'db/dw/etc' étendue. *
* *
* Retour : Instruction mise en place. *
* *
@@ -338,256 +282,174 @@ GArchInstruction *g_raw_instruction_new_uleb128(const GBinContent *content, vmpa
* *
******************************************************************************/
-GArchInstruction *g_raw_instruction_new_sleb128(const GBinContent *content, vmpa2t *addr)
+GArchInstruction *g_raw_instruction_new_array(GBinaryPortion *area, vmpa2t *addr, MemoryDataSize size, const GBinContent *content, size_t count, SourceEndian endian)
{
GArchInstruction *result; /* Instruction à retourner */
- vmpa2t start; /* Départ original de lecture */
- uleb128_t value; /* Valeur uleb128 à représenter*/
- phys_t diff; /* Couverture de la lecture */
- MemoryDataSize leb_size; /* Taille de la valeur */
- GArchOperand *operand; /* Octet non décodé à afficher */
- mrange_t range; /* Couverture de l'instruction */
-
- result = NULL;
-
- copy_vmpa(&start, addr);
-
- if (!g_binary_content_read_uleb128(content, addr, &value))
- goto error;
-
- diff = compute_vmpa_diff(&start, addr);
-
- leb_size = MDS_FROM_BYTES(diff) | MDS_SIGN;
- assert(leb_size != MDS_SIGN);
result = g_object_new(G_TYPE_RAW_INSTRUCTION, NULL);
- init_mrange(&range, &start, diff);
- g_arch_instruction_set_range(result, &range);
-
- operand = g_imm_operand_new_from_value(leb_size, (uint64_t)value);
- if (operand == NULL) goto error;
-
- g_arch_operand_set_flag(operand, IOF_ZERO_PADDING_BY_DEFAULT | IOF_ZERO_PADDING);
-
- g_arch_instruction_attach_extra_operand(result, operand);
+ if (!g_raw_instruction_create_array(G_RAW_INSTRUCTION(result), area, addr, size, content, count, endian))
+ g_clear_object(&result);
return result;
- error:
-
- g_clear_object(&result);
-
- return NULL;
-
}
/******************************************************************************
* *
-* Paramètres : content = flux de données à analyser. *
+* Paramètres : instr = instance à initialiser pleinement. *
+* area = portion de binaire incluant l'instruction. *
+* addr = adresse virtuelle et/ou position physique. *
* size = taille de chacun des éléments à représenter. *
+* content = flux de données à analyser. *
* count = nombre de ces éléments. *
-* addr = position courante dans ce flux. [OUT] *
* endian = ordre des bits dans la source. *
* *
-* Description : Crée une instruction de type 'db/dw/etc' étendue. *
+* Description : Met en place une instruction de type 'db/dw/etc' étendue. *
* *
-* Retour : Instruction mise en place. *
+* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
-GArchInstruction *g_raw_instruction_new_array(const GBinContent *content, MemoryDataSize size, size_t count, vmpa2t *addr, SourceEndian endian)
+bool g_raw_instruction_create_array(GRawInstruction *instr, GBinaryPortion *area, vmpa2t *addr, MemoryDataSize size, const GBinContent *content, size_t count, SourceEndian endian)
{
- GArchInstruction *result; /* Instruction à retourner */
- vmpa2t old; /* Sauvegarde de la position */
+ bool result; /* Bilan à retourner */
+ vmpa2t start; /* Sauvegarde de la position */
size_t i; /* Boucle de parcours */
GArchOperand *operand; /* Octet non décodé à afficher */
- mrange_t range; /* Couverture de l'instruction */
+ phys_t diff; /* Décalage à appliquer */
+
+ result = false;
/* Par soucis de cohérence */
- if (count == 0) return NULL;
+ if (count == 0)
+ goto exit;
- result = g_object_new(G_TYPE_RAW_INSTRUCTION, NULL);
+ copy_vmpa(&start, addr);
- copy_vmpa(&old, addr);
+ g_thick_object_lock(G_THICK_OBJECT(instr));
for (i = 0; i < count; i++)
{
- operand = g_imm_operand_new_from_data(size, content, addr, endian);
- if (operand == NULL) goto error;
+ operand = g_immediate_operand_new_from_data(size, content, addr, (bool []){ false /* unused */ }, endian);
+ if (operand == NULL) break;
g_arch_operand_set_flag(operand, IOF_ZERO_PADDING_BY_DEFAULT | IOF_ZERO_PADDING);
- g_arch_instruction_attach_extra_operand(result, operand);
+ g_arch_instruction_attach_operand(G_ARCH_INSTRUCTION(instr), operand);
+ unref_object(operand);
}
- init_mrange(&range, &old, compute_vmpa_diff(addr, &old));
+ g_thick_object_unlock(G_THICK_OBJECT(instr));
- g_arch_instruction_set_range(result, &range);
+ if (i < count)
+ goto exit;
- return result;
+ diff = compute_vmpa_diff(addr, &start);
+
+ g_arch_instruction_compute_range(G_ARCH_INSTRUCTION(instr), area, &start, diff);
- error:
+ result = true;
- g_object_unref(G_OBJECT(result));
+ exit:
- return NULL;
+ return result;
}
/******************************************************************************
* *
-* Paramètres : instr = instruction quelconque à consulter. *
+* Paramètres : instr = instruction à traiter. *
+* is_padding = nouveau statut à associer au contenu. *
* *
-* Description : Indique l'encodage d'une instruction de façon détaillée. *
+* Description : Marque l'instruction comme ne contenant que du bourrage. *
* *
-* Retour : Description humaine de l'encodage utilisé. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-static const char *g_raw_instruction_get_encoding(const GRawInstruction *instr)
+void g_raw_instruction_mark_as_padding(GRawInstruction *instr, bool is_padding)
{
- const char *result; /* Description à retourner */
-
- if (g_raw_instruction_is_string(instr))
- result = _("String");
+ if (is_padding)
+ g_arch_instruction_set_flag(G_ARCH_INSTRUCTION(instr), RIF_PADDING);
else
- result = _("Raw");
-
- return result;
+ g_arch_instruction_unset_flag(G_ARCH_INSTRUCTION(instr), RIF_PADDING);
}
/******************************************************************************
* *
-* Paramètres : instr = instruction d'assemblage à consulter. *
+* Paramètres : instr = instruction à traiter. *
+* is_padding = nouveau statut à associer au contenu. *
* *
-* Description : Fournit le nom humain de l'instruction manipulée. *
+* Description : Indique si le contenu de l'instruction est du bourrage. *
* *
-* Retour : Mot clef de bas niveau. *
+* Retour : Statut du contenu de l'instruction. *
* *
* Remarques : - *
* *
******************************************************************************/
-static const char *g_raw_instruction_get_keyword(const GRawInstruction *instr)
+bool g_raw_instruction_is_padding(const GRawInstruction *instr)
{
- GArchOperand *operand; /* Octet décodé à afficher */
- MemoryDataSize size; /* Taille de valeur associée */
-
- static char *defines[] = { "dn", "db", "dw", "dd", "dq" };
-
- operand = g_arch_instruction_get_operand(G_ARCH_INSTRUCTION(instr), 0);
-
- if (G_IS_TARGET_OPERAND(operand))
- size = g_target_operand_get_size(G_TARGET_OPERAND(operand));
- else
- size = g_imm_operand_get_size(G_IMM_OPERAND(operand));
+ bool result; /* Indication à retourner */
- g_object_unref(G_OBJECT(operand));
+ result = g_arch_instruction_has_flag(G_ARCH_INSTRUCTION(instr), RIF_PADDING);
- return defines[MDS_RANGE(size)];
+ return result;
}
-
-/* ---------------------------------------------------------------------------------- */
-/* CONSERVATION SUR DISQUE DES INSTRUCTIONS */
-/* ---------------------------------------------------------------------------------- */
-
-
/******************************************************************************
* *
-* Paramètres : instr = instruction d'assemblage à consulter. *
-* storage = mécanisme de sauvegarde à manipuler. *
-* format = format binaire chargé associé à l'architecture. *
-* pbuf = zone tampon à remplir. *
+* Paramètres : instr = instruction à traiter. *
+* is_string = nouveau statut à associer au contenu. *
* *
-* Description : Charge une instruction depuis une mémoire tampon. *
+* Description : Marque l'instruction comme contenant une chaîne de texte. *
* *
-* Retour : Bilan de l'opération. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-static bool g_raw_instruction_unserialize(GRawInstruction *instr, GAsmStorage *storage, GBinFormat *format, packed_buffer_t *pbuf)
+void g_raw_instruction_mark_as_string(GRawInstruction *instr, bool is_string)
{
- bool result; /* Bilan à retourner */
- GArchInstructionClass *parent; /* Classe parente à consulter */
- uint8_t boolean; /* Valeur booléenne */
-
- parent = G_ARCH_INSTRUCTION_CLASS(g_raw_instruction_parent_class);
-
- result = parent->unserialize(G_ARCH_INSTRUCTION(instr), storage, format, pbuf);
-
- if (result)
- {
- result = extract_packed_buffer(pbuf, &boolean, sizeof(uint8_t), false);
-
- if (result)
- g_raw_instruction_mark_as_padding(instr, (boolean == 1));
-
- }
-
- if (result)
- {
- result = extract_packed_buffer(pbuf, &boolean, sizeof(uint8_t), false);
-
- if (result)
- g_raw_instruction_mark_as_string(instr, (boolean == 1));
-
- }
-
- return result;
+ if (is_string)
+ g_arch_instruction_set_flag(G_ARCH_INSTRUCTION(instr), RIF_STRING);
+ else
+ g_arch_instruction_unset_flag(G_ARCH_INSTRUCTION(instr), RIF_STRING);
}
/******************************************************************************
* *
-* Paramètres : instr = instruction d'assemblage à consulter. *
-* storage = mécanisme de sauvegarde à manipuler. *
-* pbuf = zone tampon à remplir. *
+* Paramètres : instr = instruction à traiter. *
+* is_string = nouveau statut à associer au contenu. *
* *
-* Description : Sauvegarde une instruction dans une mémoire tampon. *
+* Description : Indique si le contenu de l'instruction est un texte. *
* *
-* Retour : Bilan de l'opération. *
+* Retour : Statut du contenu de l'instruction. *
* *
* Remarques : - *
* *
******************************************************************************/
-static bool g_raw_instruction_serialize(GRawInstruction *instr, GAsmStorage *storage, packed_buffer_t *pbuf)
+bool g_raw_instruction_is_string(const GRawInstruction *instr)
{
- bool result; /* Bilan à retourner */
- GArchInstructionClass *parent; /* Classe parente à consulter */
- uint8_t boolean; /* Valeur booléenne */
-
- parent = G_ARCH_INSTRUCTION_CLASS(g_raw_instruction_parent_class);
-
- result = parent->serialize(G_ARCH_INSTRUCTION(instr), storage, pbuf);
-
- if (result)
- {
- boolean = (g_raw_instruction_is_padding(instr) ? 1 : 0);
- result = extend_packed_buffer(pbuf, &boolean, sizeof(uint8_t), false);
- }
+ bool result; /* Indication à retourner */
- if (result)
- {
- boolean = (g_raw_instruction_is_string(instr) ? 1 : 0);
- result = extend_packed_buffer(pbuf, &boolean, sizeof(uint8_t), false);
- }
+ result = g_arch_instruction_has_flag(G_ARCH_INSTRUCTION(instr), RIF_STRING);
return result;
@@ -596,285 +458,73 @@ static bool g_raw_instruction_serialize(GRawInstruction *instr, GAsmStorage *sto
/* ---------------------------------------------------------------------------------- */
-/* OFFRE DE CAPACITES DE GENERATION */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
/* ---------------------------------------------------------------------------------- */
/******************************************************************************
* *
-* Paramètres : instr = instruction d'assemblage à représenter. *
-* line = ligne de rendu à compléter. *
-* 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. *
+* Paramètres : instr = instruction quelconque à consulter. *
* *
-* Description : Ajoute à un tampon GLib le contenu de l'instance spécifiée. *
+* Description : Indique l'encodage d'une instruction de façon détaillée. *
* *
-* Retour : - *
+* Retour : Description humaine de l'encodage utilisé. *
* *
* Remarques : - *
* *
******************************************************************************/
-static void g_raw_instruction_print(GRawInstruction *instr, GBufferLine *line, size_t index, size_t repeat, const GBinContent *content)
+static char *g_raw_instruction_get_encoding(const GArchInstruction *instr)
{
- GArchInstruction *base; /* Autre version de l'instance */
- phys_t max_displayed_len; /* Quantité de code affichée */
- const char *key; /* Mot clef principal */
- size_t klen; /* Taille de ce mot clef */
- char *string; /* Chaîne reconstituée */
- size_t iter; /* Tête d'écriture */
- bool first; /* Mémorise une énumération */
- size_t count; /* Nombre d'opérandes en place */
- size_t i; /* Boucle de parcours */
- GArchOperand *op; /* Opérande à manipuler */
- GImmOperand *imm; /* Version opérande de valeur */
- char byte; /* Octet à afficher (ou pas) */
-#ifndef NDEBUG
- bool status; /* Bilan d'une récupération */
-#endif
-
- base = G_ARCH_INSTRUCTION(instr);
-
- /* Localisation */
-
- g_buffer_line_fill_phys(line, DLC_PHYSICAL, MDS_32_BITS_UNSIGNED, get_mrange_addr(&base->range));
-
- g_buffer_line_fill_virt(line, DLC_VIRTUAL, MDS_32_BITS_UNSIGNED, get_mrange_addr(&base->range));
-
- /* Contenu */
-
- if (g_raw_instruction_is_padding(instr))
- max_displayed_len = 0;
-
- else if (g_raw_instruction_is_string(instr))
- max_displayed_len = 1;
-
- else
- {
- max_displayed_len = get_mrange_length(&base->range);
- max_displayed_len /= g_arch_instruction_count_operands(base);
- }
-
- g_buffer_line_fill_content(line, DLC_BINARY, content, &base->range, max_displayed_len);
-
- /* Zone du code d'assemblage */
+ char *result; /* Description à retourner */
+ GRawInstruction *raw; /* Version spécialisée */
- key = g_arch_instruction_get_keyword(base);
- klen = strlen(key);
-
- g_buffer_line_append_text(line, DLC_ASSEMBLY_HEAD, key, klen, RTT_INSTRUCTION, NULL);
-
- if (g_raw_instruction_is_padding(instr))
- g_buffer_line_append_text(line, DLC_ASSEMBLY, "...", 3, RTT_RAW, NULL);
+ raw = G_RAW_INSTRUCTION(instr);
+ if (g_raw_instruction_is_string(raw))
+ result = strdup(_("String"));
else
- {
- string = NULL;
- iter = 0;
-
- first = true;
-
- g_arch_instruction_lock_operands(base);
-
- count = _g_arch_instruction_count_operands(base);
-
- for (i = 0; i < count; i++)
- {
- op = _g_arch_instruction_get_operand(base, i);
-
- if (!G_IS_IMM_OPERAND(op))
- goto grip_fallback;
-
- imm = G_IMM_OPERAND(op);
-
- if (g_imm_operand_get_size(imm) != MDS_8_BITS)
- goto grip_fallback;
-
- if (!g_raw_instruction_is_string(instr) && g_imm_operand_get_display(imm) != IOD_CHAR)
- goto grip_fallback;
-
-#ifndef NDEBUG
- status = g_imm_operand_get_value(imm, MDS_8_BITS, &byte);
- assert(status);
-#else
- g_imm_operand_get_value(imm, MDS_8_BITS, &byte);
-#endif
-
- /* Si le caractère doit apparaître en hexadécimal... */
-
- if (!isprint(byte))
- goto grip_fallback;
-
- /* Impression de l'octet */
-
- if (string == NULL)
- {
- string = (char *)calloc(count + 3, sizeof(char));
-
- strcpy(string, "\"");
- iter = 1;
-
- }
-
- string[iter++] = byte;
-
- g_object_unref(G_OBJECT(op));
-
- continue;
-
- grip_fallback:
-
- /* Si une chaîne précède */
-
- if (string != NULL && iter > 1)
- {
- if (!first)
- {
- g_buffer_line_append_text(line, DLC_ASSEMBLY, ",", 1, RTT_PUNCT, NULL);
- g_buffer_line_append_text(line, DLC_ASSEMBLY, " ", 1, RTT_RAW, NULL);
- }
- else
- first = false;
-
- string[iter++] = '"';
-
- g_buffer_line_append_text(line, DLC_ASSEMBLY, string, iter, RTT_STRING, NULL);
-
- iter = 1;
-
- }
-
- /* Intégration en tant qu'opérande classique */
-
- if (!first)
- {
- g_buffer_line_append_text(line, DLC_ASSEMBLY, ",", 1, RTT_PUNCT, NULL);
- g_buffer_line_append_text(line, DLC_ASSEMBLY, " ", 1, RTT_RAW, NULL);
- }
- else
- first = false;
-
- g_arch_operand_print(op, line);
-
- g_object_unref(G_OBJECT(op));
-
- }
-
- /* Si au final une chaîne traine encore */
-
- if (string != NULL && iter > 1)
- {
- if (!first)
- {
- g_buffer_line_append_text(line, DLC_ASSEMBLY, ",", 1, RTT_PUNCT, NULL);
- g_buffer_line_append_text(line, DLC_ASSEMBLY, " ", 1, RTT_RAW, NULL);
- }
-
- string[iter++] = '"';
-
- g_buffer_line_append_text(line, DLC_ASSEMBLY, string, iter, RTT_STRING, NULL);
-
- }
+ result = strdup(_("Raw"));
- g_arch_instruction_unlock_operands(base);
-
- if (string != NULL)
- free(string);
-
- }
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : instr = instruction à traiter. *
-* is_padding = nouveau statut à associer au contenu. *
-* *
-* Description : Marque l'instruction comme ne contenant que du bourrage. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_raw_instruction_mark_as_padding(GRawInstruction *instr, bool is_padding)
-{
- if (is_padding)
- g_arch_instruction_set_flag(G_ARCH_INSTRUCTION(instr), RIF_PADDING);
- else
- g_arch_instruction_unset_flag(G_ARCH_INSTRUCTION(instr), RIF_PADDING);
+ return result;
}
/******************************************************************************
* *
-* Paramètres : instr = instruction à traiter. *
-* is_padding = nouveau statut à associer au contenu. *
+* Paramètres : instr = instruction d'assemblage à consulter. *
* *
-* Description : Indique si le contenu de l'instruction est du bourrage. *
+* Description : Fournit le nom humain de l'instruction manipulée. *
* *
-* Retour : Statut du contenu de l'instruction. *
+* Retour : Mot clef de bas niveau. *
* *
* Remarques : - *
* *
******************************************************************************/
-bool g_raw_instruction_is_padding(const GRawInstruction *instr)
+static char *g_raw_instruction_get_keyword(const GArchInstruction *instr)
{
- bool result; /* Indication à retourner */
-
- result = g_arch_instruction_has_flag(G_ARCH_INSTRUCTION(instr), RIF_PADDING);
-
- return result;
-
-}
+ char *result; /* Désignation à retourner */
+ GArchOperand *operand; /* Octet décodé à afficher */
+ MemoryDataSize size; /* Taille de valeur associée */
+ static char *defines[] = { "dn", "db", "dw", "dd", "dq" };
-/******************************************************************************
-* *
-* Paramètres : instr = instruction à traiter. *
-* is_string = nouveau statut à associer au contenu. *
-* *
-* Description : Marque l'instruction comme contenant une chaîne de texte. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ g_thick_object_lock(G_THICK_OBJECT(instr));
-void g_raw_instruction_mark_as_string(GRawInstruction *instr, bool is_string)
-{
- if (is_string)
- g_arch_instruction_set_flag(G_ARCH_INSTRUCTION(instr), RIF_STRING);
- else
- g_arch_instruction_unset_flag(G_ARCH_INSTRUCTION(instr), RIF_STRING);
-
-}
+ operand = g_arch_instruction_get_operand(instr, 0);
+ /*if (G_IS_TARGET_OPERAND(operand)) FIXME
+ size = g_target_operand_get_size(G_TARGET_OPERAND(operand));
+ else*/
+ size = g_immediate_operand_get_size(G_IMMEDIATE_OPERAND(operand));
-/******************************************************************************
-* *
-* Paramètres : instr = instruction à traiter. *
-* is_string = nouveau statut à associer au contenu. *
-* *
-* Description : Indique si le contenu de l'instruction est un texte. *
-* *
-* Retour : Statut du contenu de l'instruction. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ unref_object(operand);
-bool g_raw_instruction_is_string(const GRawInstruction *instr)
-{
- bool result; /* Indication à retourner */
+ g_thick_object_unlock(G_THICK_OBJECT(instr));
- result = g_arch_instruction_has_flag(G_ARCH_INSTRUCTION(instr), RIF_STRING);
+ result = strdup(defines[MDS_RANGE(size)]);
return result;
diff --git a/src/arch/instructions/raw.h b/src/arch/instructions/raw.h
index 4e92cd4..712f877 100644
--- a/src/arch/instructions/raw.h
+++ b/src/arch/instructions/raw.h
@@ -1,8 +1,8 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * raw.h - prototypes pour les instructions pures vues de l'esprit
+ * raw.h - prototypes pour les instructions de données brutes
*
- * Copyright (C) 2014-2020 Cyrille Bagard
+ * Copyright (C) 2014-2025 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -25,46 +25,24 @@
#define _ARCH_INSTRUCTIONS_RAW_H
-#include <glib-object.h>
-
-
#include "../instruction.h"
#include "../vmpa.h"
+#include "../../analysis/content.h"
+#include "../../glibext/helpers.h"
-/* ------------------------- INSTRUCTION INCONNUE / DONNEES ------------------------- */
-
-
-#define G_TYPE_RAW_INSTRUCTION g_raw_instruction_get_type()
-#define G_RAW_INSTRUCTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_RAW_INSTRUCTION, GRawInstruction))
-#define G_IS_RAW_INSTRUCTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_RAW_INSTRUCTION))
-#define G_RAW_INSTRUCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_RAW_INSTRUCTION, GRawInstructionClass))
-#define G_IS_RAW_INSTRUCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_RAW_INSTRUCTION))
-#define G_RAW_INSTRUCTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_RAW_INSTRUCTION, GRawInstructionClass))
-
+#define G_TYPE_RAW_INSTRUCTION (g_raw_instruction_get_type())
-/* Définition générique d'une instruction brute d'architecture (instance) */
-typedef struct _GRawInstruction GRawInstruction;
+DECLARE_GTYPE(GRawInstruction, g_raw_instruction, G, RAW_INSTRUCTION);
-/* Définition générique d'une instruction brute d'architecture (classe) */
-typedef struct _GRawInstructionClass GRawInstructionClass;
-
-
-/* Indique le type défini pour une instruction inconnue d'architecture. */
-GType g_raw_instruction_get_type(void);
/* Crée une instruction de type 'db/dw/etc' simple. */
-GArchInstruction *g_raw_instruction_new_from_value(const vmpa2t *, MemoryDataSize, uint64_t);
+GArchInstruction *g_raw_instruction_new_from_value(GBinaryPortion *, const vmpa2t *, MemoryDataSize, uint64_t);
-/* Crée une instruction de type 'db/dw/etc' pour un uleb128. */
-GArchInstruction *g_raw_instruction_new_uleb128(const GBinContent *content, vmpa2t *);
+/* Crée une instruction de type 'db/dw/etc' étendue. */
+GArchInstruction *g_raw_instruction_new_array(GBinaryPortion *, vmpa2t *, MemoryDataSize, const GBinContent *, size_t, SourceEndian);
-/* Crée une instruction de type 'db/dw/etc' pour un sleb128. */
-GArchInstruction *g_raw_instruction_new_sleb128(const GBinContent *content, vmpa2t *);
-
-/* Crée une instruction de type 'db/dw/etc' étendue. */
-GArchInstruction *g_raw_instruction_new_array(const GBinContent *, MemoryDataSize, size_t, vmpa2t *, SourceEndian);
/* Drapeaux pour informations complémentaires */
typedef enum _RawInstrFlag
@@ -74,6 +52,7 @@ typedef enum _RawInstrFlag
} RawInstrFlag;
+
/* Marque l'instruction comme ne contenant que du bourrage. */
void g_raw_instruction_mark_as_padding(GRawInstruction *, bool);
diff --git a/src/arch/instructions/undefined-int.h b/src/arch/instructions/undefined-int.h
index a9b7627..faf0b4b 100644
--- a/src/arch/instructions/undefined-int.h
+++ b/src/arch/instructions/undefined-int.h
@@ -1,8 +1,8 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * undefined-int.h - prototypes pour la définition générique interne des instructions au comportement non défini
+ * undefined-int.h - prototypes pour la définition interne des instructions au comportement non défini
*
- * Copyright (C) 2019 Cyrille Bagard
+ * Copyright (C) 2019-2025 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -27,42 +27,18 @@
#include "undefined.h"
#include "../instruction-int.h"
-#include "../../glibext/objhole.h"
-/* Informations glissées dans la structure GObject de GArchInstruction */
-typedef struct _undef_extra_data_t
-{
- /**
- * Le champ uid de la structure parente attendue conduit à une taille
- * alignée sur 2 octets, donc à une taille totale de 4 octets ce qui
- * représente la limite maximale de taille supportée.
- *
- * Pour 3 octets à la base, qui devraient laisser 8 - 1 octets disponbibles
- * en incluant le bit de verrouillage.
- *
- * On reproduit donc la structure instr_extra_data_t ici, en basculant
- * l'énumération InstrExpectedBehavior en champ de bits.
- */
-
- itid_t uid; /* Identifiant unique du type */
- ArchInstrFlag flags; /* Informations complémentaires*/
-
- unsigned int behavior : 2; /* Conséquences réelles */
-
-} undef_extra_data_t;
-
-
/* Définition générique d'une instruction au comportement non défini (instance) */
-struct _GUndefInstruction
+struct _GUndefinedInstruction
{
GArchInstruction parent; /* A laisser en premier */
};
/* Définition générique d'une instruction au comportement non défini (classe) */
-struct _GUndefInstructionClass
+struct _GUndefinedInstructionClass
{
GArchInstructionClass parent; /* A laisser en premier */
@@ -73,15 +49,25 @@ struct _GUndefInstructionClass
* Accès aux informations éventuellement déportées.
*/
-#if 1 //__SIZEOF_INT__ == __SIZEOF_LONG__
+/* Informations glissées dans la structure GObject de GArchInstruction */
+typedef struct _undef_extra_data_t
+{
+ ARCH_INSTRUCTION_EXTRA_DATA
+
+ unsigned int behavior : 2; /* Conséquences réelles */
+
+} undef_extra_data_t;
+
-# define GET_UNDEF_INSTR_EXTRA(ins) ((undef_extra_data_t *)&((GArchInstruction *)ins)->extra)
+#define GET_UNDEF_INSTR_EXTRA(op) \
+ GET_GOBJECT_EXTRA(op, undef_extra_data_t)
-#else
+#define SET_UNDEF_INSTR_EXTRA(op, data) \
+ SET_GOBJECT_EXTRA(op, undef_extra_data_t, data)
-# define GET_UNDEF_INSTR_EXTRA(ins) GET_GOBJECT_EXTRA(G_OBJECT(ins), undef_extra_data_t)
-#endif
+/* Met en place une instruction au comportement indéfini. */
+bool g_undefined_instruction_create(GUndefinedInstruction *, InstrExpectedBehavior);
diff --git a/src/arch/instructions/undefined-ui.c b/src/arch/instructions/undefined-ui.c
new file mode 100644
index 0000000..fbc0452
--- /dev/null
+++ b/src/arch/instructions/undefined-ui.c
@@ -0,0 +1,102 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * undefined-ui.c - opérandes représentant des instructions indéfinies sous forme graphique
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "undefined-ui.h"
+
+
+#include "../instruction.h"
+#include "../../glibext/options/asm.h"
+
+
+
+/* Etablit dans une ligne de rendu le contenu représenté. */
+static void g_undefined_instruction_ui_populate_line(const GTokenGenerator *, size_t, size_t, GBufferLine *, void *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : iface = interface GLib à initialiser. *
+* *
+* Description : Procède à l'initialisation de l'interface de génération. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_undefined_instruction_ui_token_generator_iface_init(GTokenGeneratorInterface *iface)
+{
+ iface->populate = g_undefined_instruction_ui_populate_line;
+
+}
+
+
+/******************************************************************************
+* *
+* 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_undefined_instruction_ui_populate_line(const GTokenGenerator *generator, size_t index, size_t repeat, GBufferLine *line, void *data)
+{
+ GArchInstruction *instr; /* Version spécialisée */
+ GBinContent *content; /* Contenu brut d'origine */
+ mrange_t range; /* Emplacement couvert */
+ char *key; /* Mot clef principal */
+
+ instr = G_ARCH_INSTRUCTION(generator);
+ content = G_BIN_CONTENT(data);
+
+ /* Prologue */
+
+ if (g_arch_instruction_get_range(instr, &range))
+ {
+ g_buffer_line_fill_physical(line, ACO_PHYSICAL, MDS_32_BITS_UNSIGNED, get_mrange_addr(&range));
+
+ g_buffer_line_fill_virtual(line, ACO_VIRTUAL, MDS_32_BITS_UNSIGNED, get_mrange_addr(&range));
+
+ g_buffer_line_fill_content(line, ACO_BINARY, content, &range, VMPA_NO_PHYSICAL);
+
+ }
+
+ /* Instruction proprement dite */
+
+ key = g_arch_instruction_get_keyword(instr);
+
+ g_buffer_line_append_text(line, ACO_ASSEMBLY_HEAD, TRT_ERROR, SL(key), NULL, G_OBJECT(instr));
+
+ free(key);
+
+}
diff --git a/src/arch/instructions/undefined-ui.h b/src/arch/instructions/undefined-ui.h
new file mode 100644
index 0000000..8bc2d67
--- /dev/null
+++ b/src/arch/instructions/undefined-ui.h
@@ -0,0 +1,37 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * undefined-ui.h - prototypes pour les opérandes représentant des instructions indéfinies sous forme graphique
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ARCH_OPERANDS_UNDEFINED_UI_H
+#define _ARCH_OPERANDS_UNDEFINED_UI_H
+
+
+#include "../../glibext/generator-int.h"
+
+
+
+/* Procède à l'initialisation de l'interface de génération. */
+void g_undefined_instruction_ui_token_generator_iface_init(GTokenGeneratorInterface *);
+
+
+
+#endif /* _ARCH_OPERANDS_UNDEFINED_UI_H */
diff --git a/src/arch/instructions/undefined.c b/src/arch/instructions/undefined.c
index 15c63e7..75df493 100644
--- a/src/arch/instructions/undefined.c
+++ b/src/arch/instructions/undefined.c
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* undefined.c - instructions au comportement non défini
*
- * Copyright (C) 2016-2019 Cyrille Bagard
+ * Copyright (C) 2016-2025 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -25,63 +25,42 @@
#include <assert.h>
+#include <string.h>
#include <i18n.h>
#include "undefined-int.h"
-#include "../../core/columns.h"
+#include "../../glibext/serialize-int.h"
+/* ------------------------- INSTRUCTION INCONNUE / DONNEES ------------------------- */
+
+
/* Initialise la classe des instructions non définies. */
-static void g_undef_instruction_class_init(GUndefInstructionClass *);
+static void g_undefined_instruction_class_init(GUndefinedInstructionClass *);
/* Initialise une instance d'instruction non définie. */
-static void g_undef_instruction_init(GUndefInstruction *);
+static void g_undefined_instruction_init(GUndefinedInstruction *);
/* Supprime toutes les références externes. */
-static void g_undef_instruction_dispose(GUndefInstruction *);
+static void g_undefined_instruction_dispose(GObject *);
/* Procède à la libération totale de la mémoire. */
-static void g_undef_instruction_finalize(GUndefInstruction *);
-
-/* Indique l'encodage d'une instruction de façon détaillée. */
-static const char *g_undef_instruction_get_encoding(const GUndefInstruction *);
-
-/* Fournit le nom humain de l'instruction manipulée. */
-static const char *g_undef_instruction_get_keyword(const GUndefInstruction *);
-
-
-
-/* -------------------- CONSERVATION SUR DISQUE DES INSTRUCTIONS -------------------- */
-
-
-/* Charge une instruction depuis une mémoire tampon. */
-static bool g_undef_instruction_unserialize(GUndefInstruction *, GAsmStorage *, GBinFormat *, packed_buffer_t *);
-
-/* Sauvegarde une instruction dans une mémoire tampon. */
-static bool g_undef_instruction_serialize(GUndefInstruction *, GAsmStorage *, packed_buffer_t *);
-
-
-
-/* ------------------------ OFFRE DE CAPACITES DE GENERATION ------------------------ */
-
-
-/* Ajoute à un tampon GLib le contenu de l'instance spécifiée. */
-static void g_undef_instruction_print(GUndefInstruction *, GBufferLine *, size_t, size_t, const GBinContent *);
+static void g_undefined_instruction_finalize(GObject *);
/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
-/* Charge un contenu depuis une mémoire tampon. */
-static bool g_undef_instruction_load(GUndefInstruction *, GObjectStorage *, packed_buffer_t *);
+/* Indique l'encodage d'une instruction de façon détaillée. */
+static char *g_undefined_instruction_get_encoding(const GArchInstruction *);
-/* Sauvegarde un contenu dans une mémoire tampon. */
-static bool g_undef_instruction_store(GUndefInstruction *, GObjectStorage *, packed_buffer_t *);
+/* Fournit le nom humain de l'instruction manipulée. */
+static char *g_undefined_instruction_get_keyword(const GArchInstruction *);
@@ -91,7 +70,9 @@ static bool g_undef_instruction_store(GUndefInstruction *, GObjectStorage *, pac
/* Indique le type défini pour une instruction au comportement non défini. */
-G_DEFINE_TYPE(GUndefInstruction, g_undef_instruction, G_TYPE_ARCH_INSTRUCTION);
+G_DEFINE_TYPE_WITH_CODE(GUndefinedInstruction, g_undefined_instruction, G_TYPE_ARCH_INSTRUCTION,
+ G_IMPLEMENT_INTERFACE_IF_SYM(g_token_generator_get_type, g_undefined_instruction_ui_token_generator_iface_init));
+
/******************************************************************************
@@ -106,28 +87,20 @@ G_DEFINE_TYPE(GUndefInstruction, g_undef_instruction, G_TYPE_ARCH_INSTRUCTION);
* *
******************************************************************************/
-static void g_undef_instruction_class_init(GUndefInstructionClass *klass)
+static void g_undefined_instruction_class_init(GUndefinedInstructionClass *klass)
{
GObjectClass *object; /* Autre version de la classe */
GArchInstructionClass *instr; /* Encore une autre vision... */
object = G_OBJECT_CLASS(klass);
- object->dispose = (GObjectFinalizeFunc/* ! */)g_undef_instruction_dispose;
- object->finalize = (GObjectFinalizeFunc)g_undef_instruction_finalize;
+ object->dispose = g_undefined_instruction_dispose;
+ object->finalize = g_undefined_instruction_finalize;
instr = G_ARCH_INSTRUCTION_CLASS(klass);
- instr->get_encoding = (get_instruction_encoding_fc)g_undef_instruction_get_encoding;
- instr->get_keyword = (get_instruction_keyword_fc)g_undef_instruction_get_keyword;
-
- instr->unserialize = (unserialize_instruction_fc)g_undef_instruction_unserialize;
- instr->serialize = (serialize_instruction_fc)g_undef_instruction_serialize;
-
- instr->print = (print_instruction_fc)g_undef_instruction_print;
-
- instr->load = (load_instruction_fc)g_undef_instruction_load;
- instr->store = (store_instruction_fc)g_undef_instruction_store;
+ instr->get_encoding = g_undefined_instruction_get_encoding;
+ instr->get_keyword = g_undefined_instruction_get_keyword;
}
@@ -144,16 +117,22 @@ static void g_undef_instruction_class_init(GUndefInstructionClass *klass)
* *
******************************************************************************/
-static void g_undef_instruction_init(GUndefInstruction *instr)
+static void g_undefined_instruction_init(GUndefinedInstruction *instr)
{
- GET_UNDEF_INSTR_EXTRA(instr)->behavior = IEB_UNDEFINED;
+ undef_extra_data_t extra; /* Données insérées à consulter*/
+
+ extra = GET_UNDEF_INSTR_EXTRA(instr);
+
+ extra.behavior = IEB_UNDEFINED;
+
+ SET_UNDEF_INSTR_EXTRA(instr, &extra);
}
/******************************************************************************
* *
-* Paramètres : instr = instance d'objet GLib à traiter. *
+* Paramètres : object = instance d'objet GLib à traiter. *
* *
* Description : Supprime toutes les références externes. *
* *
@@ -163,16 +142,16 @@ static void g_undef_instruction_init(GUndefInstruction *instr)
* *
******************************************************************************/
-static void g_undef_instruction_dispose(GUndefInstruction *instr)
+static void g_undefined_instruction_dispose(GObject *object)
{
- G_OBJECT_CLASS(g_undef_instruction_parent_class)->dispose(G_OBJECT(instr));
+ G_OBJECT_CLASS(g_undefined_instruction_parent_class)->dispose(object);
}
/******************************************************************************
* *
-* Paramètres : instr = instance d'objet GLib à traiter. *
+* Paramètres : object = instance d'objet GLib à traiter. *
* *
* Description : Procède à la libération totale de la mémoire. *
* *
@@ -182,9 +161,9 @@ static void g_undef_instruction_dispose(GUndefInstruction *instr)
* *
******************************************************************************/
-static void g_undef_instruction_finalize(GUndefInstruction *instr)
+static void g_undefined_instruction_finalize(GObject *object)
{
- G_OBJECT_CLASS(g_undef_instruction_parent_class)->finalize(G_OBJECT(instr));
+ G_OBJECT_CLASS(g_undefined_instruction_parent_class)->finalize(object);
}
@@ -201,16 +180,14 @@ static void g_undef_instruction_finalize(GUndefInstruction *instr)
* *
******************************************************************************/
-GArchInstruction *g_undef_instruction_new(InstrExpectedBehavior behavior)
+GArchInstruction *g_undefined_instruction_new(InstrExpectedBehavior behavior)
{
GArchInstruction *result; /* Instruction à retourner */
- undef_extra_data_t *extra; /* Données insérées à modifier */
- result = g_object_new(G_TYPE_UNDEF_INSTRUCTION, NULL);
+ result = g_object_new(G_TYPE_UNDEFINED_INSTRUCTION, NULL);
- extra = GET_UNDEF_INSTR_EXTRA(result);
-
- extra->behavior = behavior;
+ if (!g_undefined_instruction_create(G_UNDEFINED_INSTRUCTION(result), behavior))
+ g_clear_object(&result);
return result;
@@ -219,90 +196,10 @@ GArchInstruction *g_undef_instruction_new(InstrExpectedBehavior behavior)
/******************************************************************************
* *
-* Paramètres : instr = instruction quelconque à consulter. *
-* *
-* Description : Indique l'encodage d'une instruction de façon détaillée. *
-* *
-* Retour : Description humaine de l'encodage utilisé. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static const char *g_undef_instruction_get_encoding(const GUndefInstruction *instr)
-{
- const char *result; /* Description à retourner */
-
- result = _("Undefined");
-
- return result;
-
-}
-
-
-/******************************************************************************
+* Paramètres : instr = instance à initialiser pleinement. *
+* behavior = état réel du CPU après une passe de l'instruction.*
* *
-* Paramètres : instr = instruction d'assemblage à consulter. *
-* *
-* Description : Fournit le nom humain de l'instruction manipulée. *
-* *
-* Retour : Mot clef de bas niveau. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-const char *g_undef_instruction_get_keyword(const GUndefInstruction *instr)
-{
- const char *result; /* Désignation à retourner */
- undef_extra_data_t *extra; /* Données insérées à consulter*/
-
- extra = GET_UNDEF_INSTR_EXTRA(instr);
-
- switch (extra->behavior)
- {
- case IEB_NOP:
- result = "nop";
- break;
-
- case IEB_UNDEFINED:
- result = "undefined";
- break;
-
- case IEB_UNPREDICTABLE:
- result = "unpredictable";
- break;
-
- case IEB_RESERVED:
- result = "reserved";
- break;
-
- default:
- assert(false);
- result = NULL;
- break;
-
- }
-
- return result;
-
-}
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* CONSERVATION SUR DISQUE DES INSTRUCTIONS */
-/* ---------------------------------------------------------------------------------- */
-
-
-/******************************************************************************
-* *
-* Paramètres : instr = instruction d'assemblage à consulter. *
-* storage = mécanisme de sauvegarde à manipuler. *
-* format = format binaire chargé associé à l'architecture. *
-* pbuf = zone tampon à remplir. *
-* *
-* Description : Charge une instruction depuis une mémoire tampon. *
+* Description : Met en place une instruction au comportement indéfini. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -310,122 +207,24 @@ const char *g_undef_instruction_get_keyword(const GUndefInstruction *instr)
* *
******************************************************************************/
-static bool g_undef_instruction_unserialize(GUndefInstruction *instr, GAsmStorage *storage, GBinFormat *format, packed_buffer_t *pbuf)
+bool g_undefined_instruction_create(GUndefinedInstruction *instr, InstrExpectedBehavior behavior)
{
bool result; /* Bilan à retourner */
- GArchInstructionClass *parent; /* Classe parente à consulter */
- undef_extra_data_t *extra; /* Données insérées à consulter*/
- uint8_t val; /* Champ de bits manipulé */
-
- parent = G_ARCH_INSTRUCTION_CLASS(g_undef_instruction_parent_class);
+ undef_extra_data_t extra; /* Données insérées à modifier */
- result = parent->unserialize(G_ARCH_INSTRUCTION(instr), storage, format, pbuf);
+ result = true;
- if (result)
- {
- extra = GET_UNDEF_INSTR_EXTRA(instr);
-
- LOCK_GOBJECT_EXTRA(extra);
-
- result = extract_packed_buffer(pbuf, &val, sizeof(uint8_t), false);
- extra->behavior = val;
-
- UNLOCK_GOBJECT_EXTRA(extra);
-
- }
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : instr = instruction d'assemblage à consulter. *
-* storage = mécanisme de sauvegarde à manipuler. *
-* pbuf = zone tampon à remplir. *
-* *
-* Description : Sauvegarde une instruction dans une mémoire tampon. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static bool g_undef_instruction_serialize(GUndefInstruction *instr, GAsmStorage *storage, packed_buffer_t *pbuf)
-{
- bool result; /* Bilan à retourner */
- GArchInstructionClass *parent; /* Classe parente à consulter */
- undef_extra_data_t *extra; /* Données insérées à consulter*/
-
- parent = G_ARCH_INSTRUCTION_CLASS(g_undef_instruction_parent_class);
-
- result = parent->serialize(G_ARCH_INSTRUCTION(instr), storage, pbuf);
-
- if (result)
- {
- extra = GET_UNDEF_INSTR_EXTRA(instr);
-
- LOCK_GOBJECT_EXTRA(extra);
-
- result = extend_packed_buffer(pbuf, (uint8_t []){ extra->behavior }, sizeof(uint8_t), false);
+ extra = GET_UNDEF_INSTR_EXTRA(instr);
- UNLOCK_GOBJECT_EXTRA(extra);
+ extra.behavior = behavior;
- }
+ SET_UNDEF_INSTR_EXTRA(instr, &extra);
return result;
}
-
-/* ---------------------------------------------------------------------------------- */
-/* OFFRE DE CAPACITES DE GENERATION */
-/* ---------------------------------------------------------------------------------- */
-
-
-/******************************************************************************
-* *
-* Paramètres : instr = instruction d'assemblage à représenter. *
-* line = ligne de rendu à compléter. *
-* 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. *
-* *
-* Description : Ajoute à un tampon GLib le contenu de l'instance spécifiée. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_undef_instruction_print(GUndefInstruction *instr, GBufferLine *line, size_t index, size_t repeat, const GBinContent *content)
-{
- GArchInstruction *base; /* Version de base */
- const char *key; /* Mot clef principal */
- size_t klen; /* Taille de ce mot clef */
-
- base = G_ARCH_INSTRUCTION(instr);
-
- g_buffer_line_fill_phys(line, DLC_PHYSICAL, MDS_32_BITS_UNSIGNED, get_mrange_addr(&base->range));
-
- g_buffer_line_fill_virt(line, DLC_VIRTUAL, MDS_32_BITS_UNSIGNED, get_mrange_addr(&base->range));
-
- g_buffer_line_fill_content(line, DLC_BINARY, content, &base->range, VMPA_NO_PHYSICAL);
-
- /* Instruction proprement dite */
-
- key = g_arch_instruction_get_keyword(base);
- klen = strlen(key);
-
- g_buffer_line_append_text(line, DLC_ASSEMBLY_HEAD, key, klen, RTT_ERROR, NULL);
-
-}
-
-
/******************************************************************************
* *
* Paramètres : instr = instruction à consulter. *
@@ -438,18 +237,14 @@ static void g_undef_instruction_print(GUndefInstruction *instr, GBufferLine *lin
* *
******************************************************************************/
-InstrExpectedBehavior g_undef_instruction_get_behavior(const GUndefInstruction *instr)
+InstrExpectedBehavior g_undefined_instruction_get_behavior(const GUndefinedInstruction *instr)
{
InstrExpectedBehavior result; /* Comportement à retourner */
- undef_extra_data_t *extra; /* Données insérées à consulter*/
+ undef_extra_data_t extra; /* Données insérées à consulter*/
extra = GET_UNDEF_INSTR_EXTRA(instr);
- LOCK_GOBJECT_EXTRA(extra);
-
- result = extra->behavior;
-
- UNLOCK_GOBJECT_EXTRA(extra);
+ result = extra.behavior;
return result;
@@ -464,41 +259,21 @@ InstrExpectedBehavior g_undef_instruction_get_behavior(const GUndefInstruction *
/******************************************************************************
* *
-* Paramètres : instr = élément GLib à constuire. *
-* storage = conservateur de données à manipuler ou NULL. *
-* pbuf = zone tampon à lire. *
+* Paramètres : instr = instruction quelconque à consulter. *
* *
-* Description : Charge un contenu depuis une mémoire tampon. *
+* Description : Indique l'encodage d'une instruction de façon détaillée. *
* *
-* Retour : Bilan de l'opération. *
+* Retour : Description humaine de l'encodage utilisé. *
* *
* Remarques : - *
* *
******************************************************************************/
-static bool g_undef_instruction_load(GUndefInstruction *instr, GObjectStorage *storage, packed_buffer_t *pbuf)
+static char *g_undefined_instruction_get_encoding(const GArchInstruction *instr)
{
- bool result; /* Bilan à retourner */
- GArchInstructionClass *parent; /* Classe parente à consulter */
- undef_extra_data_t *extra; /* Données insérées à consulter*/
- uint8_t val; /* Champ de bits manipulé */
-
- parent = G_ARCH_INSTRUCTION_CLASS(g_undef_instruction_parent_class);
-
- result = parent->load(G_ARCH_INSTRUCTION(instr), storage, pbuf);
-
- if (result)
- {
- extra = GET_UNDEF_INSTR_EXTRA(instr);
-
- LOCK_GOBJECT_EXTRA(extra);
+ char *result; /* Description à retourner */
- result = extract_packed_buffer(pbuf, &val, sizeof(uint8_t), false);
- extra->behavior = val;
-
- UNLOCK_GOBJECT_EXTRA(extra);
-
- }
+ result = strdup(_("Undefined"));
return result;
@@ -507,37 +282,45 @@ static bool g_undef_instruction_load(GUndefInstruction *instr, GObjectStorage *s
/******************************************************************************
* *
-* Paramètres : instr = élément GLib à consulter. *
-* storage = conservateur de données à manipuler ou NULL. *
-* pbuf = zone tampon à remplir. *
+* Paramètres : instr = instruction d'assemblage à consulter. *
* *
-* Description : Sauvegarde un contenu dans une mémoire tampon. *
+* Description : Fournit le nom humain de l'instruction manipulée. *
* *
-* Retour : Bilan de l'opération. *
+* Retour : Mot clef de bas niveau. *
* *
* Remarques : - *
* *
******************************************************************************/
-static bool g_undef_instruction_store(GUndefInstruction *instr, GObjectStorage *storage, packed_buffer_t *pbuf)
+static char *g_undefined_instruction_get_keyword(const GArchInstruction *instr)
{
- bool result; /* Bilan à retourner */
- GArchInstructionClass *parent; /* Classe parente à consulter */
- undef_extra_data_t *extra; /* Données insérées à consulter*/
-
- parent = G_ARCH_INSTRUCTION_CLASS(g_undef_instruction_parent_class);
+ char *result; /* Désignation à retourner */
+ undef_extra_data_t extra; /* Données insérées à consulter*/
- result = parent->store(G_ARCH_INSTRUCTION(instr), storage, pbuf);
+ extra = GET_UNDEF_INSTR_EXTRA(instr);
- if (result)
+ switch (extra.behavior)
{
- extra = GET_UNDEF_INSTR_EXTRA(instr);
+ case IEB_NOP:
+ result = strdup("nop");
+ break;
- LOCK_GOBJECT_EXTRA(extra);
+ case IEB_UNDEFINED:
+ result = strdup("undefined");
+ break;
- result = extend_packed_buffer(pbuf, (uint8_t []){ extra->behavior }, sizeof(uint8_t), false);
+ case IEB_UNPREDICTABLE:
+ result = strdup("unpredictable");
+ break;
- UNLOCK_GOBJECT_EXTRA(extra);
+ case IEB_RESERVED:
+ result = strdup("reserved");
+ break;
+
+ default:
+ assert(false);
+ result = NULL;
+ break;
}
diff --git a/src/arch/instructions/undefined.h b/src/arch/instructions/undefined.h
index 8f35f35..d4b35f4 100644
--- a/src/arch/instructions/undefined.h
+++ b/src/arch/instructions/undefined.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* undefined.h - prototypes pour les instructions au comportement non défini
*
- * Copyright (C) 2016-2019 Cyrille Bagard
+ * Copyright (C) 2016-2025 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -25,27 +25,14 @@
#define _ARCH_INSTRUCTIONS_UNDEFINED_H
-#include <glib-object.h>
-
-
#include "../instruction.h"
-#include "../vmpa.h"
-
+#include "../../glibext/helpers.h"
-#define G_TYPE_UNDEF_INSTRUCTION g_undef_instruction_get_type()
-#define G_UNDEF_INSTRUCTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_UNDEF_INSTRUCTION, GUndefInstruction))
-#define G_IS_UNDEF_INSTRUCTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_UNDEF_INSTRUCTION))
-#define G_UNDEF_INSTRUCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_UNDEF_INSTRUCTION, GUndefInstructionClass))
-#define G_IS_UNDEF_INSTRUCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_UNDEF_INSTRUCTION))
-#define G_UNDEF_INSTRUCTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_UNDEF_INSTRUCTION, GUndefInstructionClass))
+#define G_TYPE_UNDEFINED_INSTRUCTION (g_undefined_instruction_get_type())
-/* Définition générique d'une instruction au comportement non défini (instance) */
-typedef struct _GUndefInstruction GUndefInstruction;
-
-/* Définition générique d'une instruction au comportement non défini (classe) */
-typedef struct _GUndefInstructionClass GUndefInstructionClass;
+DECLARE_GTYPE(GUndefinedInstruction, g_undefined_instruction, G, UNDEFINED_INSTRUCTION);
/* Etat précis de l'instruction */
@@ -59,14 +46,11 @@ typedef enum _InstrExpectedBehavior
} InstrExpectedBehavior;
-/* Indique le type défini pour une instruction au comportement non défini. */
-GType g_undef_instruction_get_type(void);
-
/* Crée une instruction au comportement nominalement indéfini. */
-GArchInstruction *g_undef_instruction_new(InstrExpectedBehavior);
+GArchInstruction *g_undefined_instruction_new(InstrExpectedBehavior);
/* Indique le type de conséquences réél de l'instruction. */
-InstrExpectedBehavior g_undef_instruction_get_behavior(const GUndefInstruction *);
+InstrExpectedBehavior g_undefined_instruction_get_behavior(const GUndefinedInstruction *);
diff --git a/src/arch/vmpa.h b/src/arch/vmpa.h
index 8a9b961..7a11deb 100644
--- a/src/arch/vmpa.h
+++ b/src/arch/vmpa.h
@@ -296,4 +296,33 @@ char *mrange_length_to_string(const mrange_t *, MemoryDataSize, char [VMPA_MAX_L
+/* ------------------- DEFINITION D'UN ESPACE RELATIVE EN MEMOIRE ------------------- */
+
+
+/* Couverture mémoire */
+typedef struct _rel_mrange_t
+{
+ uint32_t offset; /* Décalage depuis une ref. */
+ uint16_t length; /* Taille de la couverture */
+
+} rel_mrange_t;
+
+
+#define init_rel_mrange(rr, o, l) \
+ do \
+ { \
+ (rr)->offset = o; \
+ (rr)->length = l; \
+ } \
+ while (0);
+
+
+#define get_rel_mrange_offset(rr) \
+ (rr)->offset
+
+#define get_rel_mrange_length(rr) \
+ (rr)->length
+
+
+
#endif /* _ARCH_VMPA_H */
diff --git a/src/common/Makefile.am b/src/common/Makefile.am
index d09b661..1056cb2 100644
--- a/src/common/Makefile.am
+++ b/src/common/Makefile.am
@@ -47,6 +47,7 @@ endif
libcommon4_la_SOURCES = \
+ array.h array.c \
asm.h asm.c \
bits.h bits.c \
compiler.h \
diff --git a/src/common/cpp.h b/src/common/cpp.h
index 9616db3..4ebad82 100644
--- a/src/common/cpp.h
+++ b/src/common/cpp.h
@@ -48,6 +48,8 @@
*/
#define SL(str) str, strlen(str)
+#define STCSL(str) str, STATIC_STR_SIZE(str)
+
/**
* Détermine la taille de la plus longue chaîne de caractères
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/core/Makefile.am b/src/core/Makefile.am
index 17fd2bf..15ed866 100644
--- a/src/core/Makefile.am
+++ b/src/core/Makefile.am
@@ -20,7 +20,8 @@ libcore4_la_SOURCES = \
logs.h logs.c \
nox.h nox.c \
nproc.h nproc.c \
- paths.h paths.c
+ paths.h paths.c \
+ processors.h processors.c
libcore4_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBSSL_CFLAGS)
diff --git a/src/core/core.c b/src/core/core.c
index 8fe12f5..c730fad 100644
--- a/src/core/core.c
+++ b/src/core/core.c
@@ -25,6 +25,7 @@
#include "global.h"
+#include "processors.h"
@@ -61,6 +62,14 @@ bool load_core_components(AvailableCoreComponent flags)
}
+ if ((flags & ACC_CODE_ANALYSIS) != 0 && (__loaded & ACC_CODE_ANALYSIS) == 0)
+ {
+ register_arch_gtypes();
+
+ init_operands_factory();
+
+ }
+
return result;
}
@@ -80,6 +89,12 @@ bool load_core_components(AvailableCoreComponent flags)
void unload_core_components(AvailableCoreComponent flags)
{
+ if ((flags & ACC_CODE_ANALYSIS) != 0 && (__loaded & ACC_CODE_ANALYSIS) == 0)
+ {
+ exit_operands_factory();
+
+ }
+
if ((flags & ACC_GLOBAL_VARS) != 0 && (__loaded & ACC_GLOBAL_VARS) == 0)
{
set_work_queue(NULL);
@@ -111,7 +126,6 @@ void unload_core_components(AvailableCoreComponent flags)
#include "demanglers.h"
#include "global.h"
#include "params.h"
-#include "processors.h"
#include "queue.h"
#include "../analysis/scan/core.h"
#ifdef INCLUDE_MAGIC_SUPPORT
@@ -195,9 +209,6 @@ bool load_all_core_components(bool cs)
if (result) result = init_segment_content_hash_table();
- register_arch_gtypes();
- init_operands_factory();
-
}
}
@@ -223,8 +234,6 @@ void unload_all_core_components(bool cs)
{
if (cs)
{
- exit_operands_factory();
-
exit_segment_content_hash_table();
unload_demanglers_definitions();
diff --git a/src/core/core.h b/src/core/core.h
index e5f0a60..640476a 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -34,9 +34,10 @@ typedef enum _AvailableCoreComponent
{
ACC_NONE = (0 << 0), /* Statut initial */
ACC_GLOBAL_VARS = (1 << 0), /* Singletons globaux */
- ACC_SCAN_FEATURES = (1 << 1), /* Espace de noms pour scan */
+ ACC_CODE_ANALYSIS = (1 << 1), /* Désassemblage de code */
+ ACC_SCAN_FEATURES = (1 << 2), /* Espace de noms pour scan */
- ACC_ALL_COMPONENTS = (1 << 2) - 1
+ ACC_ALL_COMPONENTS = (1 << 3) - 1
} AvailableCoreComponent;
diff --git a/src/core/processors.c b/src/core/processors.c
index e4a558f..056fc23 100644
--- a/src/core/processors.c
+++ b/src/core/processors.c
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* processors.c - enregistrement et fourniture des architectures supportées
*
- * Copyright (C) 2015-2020 Cyrille Bagard
+ * Copyright (C) 2015-2025 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -29,13 +29,13 @@
#include <pthread.h>
#include <string.h>
-
+#if 0
#include "../arch/instructions/raw.h"
#include "../arch/instructions/undefined.h"
#include "../arch/operands/immediate.h"
#include "../arch/operands/register.h"
#include "../arch/operands/target.h"
-
+#endif
/* Cache des singletons d'opérandes */
@@ -77,12 +77,12 @@ static proc_t *find_processor_by_key(const char *);
void register_arch_gtypes(void)
{
- g_type_ensure(G_TYPE_RAW_INSTRUCTION);
- g_type_ensure(G_TYPE_UNDEF_INSTRUCTION);
+ //g_type_ensure(G_TYPE_RAW_INSTRUCTION);
+ //g_type_ensure(G_TYPE_UNDEF_INSTRUCTION);
- g_type_ensure(G_TYPE_IMM_OPERAND);
- g_type_ensure(G_TYPE_REGISTER_OPERAND);
- g_type_ensure(G_TYPE_TARGET_OPERAND);
+ //g_type_ensure(G_TYPE_IMM_OPERAND);
+ //g_type_ensure(G_TYPE_REGISTER_OPERAND);
+ //g_type_ensure(G_TYPE_TARGET_OPERAND);
}
@@ -126,7 +126,7 @@ GSingletonFactory *get_operands_factory(void)
result = __operands_factory;
- g_object_ref(G_OBJECT(result));
+ ref_object(result);
return result;
@@ -154,7 +154,7 @@ void exit_operands_factory(void)
}
-
+#if 0
/******************************************************************************
* *
* Paramètres : type = type GLib représentant le type à instancier. *
@@ -206,7 +206,7 @@ bool register_processor_type(GType type)
done:
- g_object_unref(G_OBJECT(proc));
+ unref_object(proc);
return result;
@@ -341,3 +341,4 @@ GArchProcessor *get_arch_processor_for_key(const char *key)
return result;
}
+#endif
diff --git a/src/core/processors.h b/src/core/processors.h
index 6aa2d1e..b622305 100644
--- a/src/core/processors.h
+++ b/src/core/processors.h
@@ -29,7 +29,7 @@
#include <stdbool.h>
-#include "../arch/processor.h"
+//#include "../arch/processor.h"
#include "../glibext/singleton.h"
@@ -45,7 +45,7 @@ GSingletonFactory *get_operands_factory(void);
/* Supprime le fournisseur d'instances uniques d'opérandes. */
void exit_operands_factory(void);
-
+#if 0
/* Enregistre un processeur pour une architecture donnée. */
bool register_processor_type(GType);
@@ -57,7 +57,7 @@ char **get_all_processor_keys(size_t *);
/* Fournit le processeur d'architecture correspondant à un nom. */
GArchProcessor *get_arch_processor_for_key(const char *);
-
+#endif
#endif /* _CORE_PROCESSORS_H */
diff --git a/src/data/Makefile.am b/src/data/Makefile.am
new file mode 100644
index 0000000..8cbe67a
--- /dev/null
+++ b/src/data/Makefile.am
@@ -0,0 +1,2 @@
+
+SUBDIRS = images
diff --git a/src/data/images/Makefile.am b/src/data/images/Makefile.am
new file mode 100644
index 0000000..d5ec84f
--- /dev/null
+++ b/src/data/images/Makefile.am
@@ -0,0 +1,33 @@
+
+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 \
+ logs-symbolic.svg
+
+libdataimages_la_SOURCES = \
+ resources.h resources.c
+
+libdataimages_la_CFLAGS = $(LIBGIOUNIX_CFLAGS)
+
+
+devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%)
+
+dev_HEADERS = $(libdataimages_la_SOURCES:%c=)
+
+
+resources.c: gresource.xml $(RES_FILES)
+ glib-compile-resources --target=$@ --sourcedir=$(srcdir) --generate-source --c-name data_images gresource.xml
+
+resources.h: gresource.xml
+ glib-compile-resources --target=$@ --sourcedir=$(srcdir) --generate-header --c-name data_images gresource.xml
+
+
+CLEANFILES = resources.h resources.c
+
+EXTRA_DIST = gresource.xml $(RES_FILES)
diff --git a/src/data/images/dock-station-bottom-symbolic.svg b/src/data/images/dock-station-bottom-symbolic.svg
new file mode 100644
index 0000000..37084ac
--- /dev/null
+++ b/src/data/images/dock-station-bottom-symbolic.svg
@@ -0,0 +1,197 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ width="180"
+ height="180"
+ viewBox="0 0 180 180"
+ version="1.1"
+ id="svg5"
+ inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
+ sodipodi:docname="dock-station-bottom-symbolic.svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+ <sodipodi:namedview
+ id="namedview7"
+ pagecolor="#ffffff"
+ bordercolor="#000000"
+ borderopacity="0.25"
+ inkscape:showpageshadow="2"
+ inkscape:pageopacity="0.0"
+ inkscape:pagecheckerboard="true"
+ inkscape:deskcolor="#d1d1d1"
+ inkscape:document-units="px"
+ showgrid="false"
+ inkscape:zoom="4.2708118"
+ inkscape:cx="87.219952"
+ inkscape:cy="89.444353"
+ inkscape:window-width="1920"
+ inkscape:window-height="1011"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="g3929" />
+ <defs
+ id="defs2">
+ <clipPath
+ id="k">
+ <path
+ d="M 0,0 H 800 V 800 H 0 Z"
+ id="path1320" />
+ </clipPath>
+ <mask
+ id="j">
+ <g
+ filter="url(#a)"
+ id="g1317">
+ <path
+ d="M 0,0 H 16 V 16 H 0 Z"
+ fill-opacity="0.35"
+ id="path1315" />
+ </g>
+ </mask>
+ <filter
+ id="a"
+ height="1"
+ width="1"
+ x="0"
+ y="0">
+ <feColorMatrix
+ in="SourceGraphic"
+ type="matrix"
+ values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"
+ id="feColorMatrix1280" />
+ </filter>
+ <clipPath
+ id="i">
+ <path
+ d="M 0,0 H 800 V 800 H 0 Z"
+ id="path1312" />
+ </clipPath>
+ <mask
+ id="h">
+ <g
+ filter="url(#a)"
+ id="g1309">
+ <path
+ d="M 0,0 H 16 V 16 H 0 Z"
+ fill-opacity="0.35"
+ id="path1307" />
+ </g>
+ </mask>
+ <filter
+ id="filter3652"
+ height="1"
+ width="1"
+ x="0"
+ y="0">
+ <feColorMatrix
+ in="SourceGraphic"
+ type="matrix"
+ values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"
+ id="feColorMatrix3650" />
+ </filter>
+ <clipPath
+ id="g">
+ <path
+ d="M 0,0 H 800 V 800 H 0 Z"
+ id="path1304" />
+ </clipPath>
+ <mask
+ id="f">
+ <g
+ filter="url(#a)"
+ id="g1301">
+ <path
+ d="M 0,0 H 16 V 16 H 0 Z"
+ fill-opacity="0.35"
+ id="path1299" />
+ </g>
+ </mask>
+ <filter
+ id="filter3661"
+ height="1"
+ width="1"
+ x="0"
+ y="0">
+ <feColorMatrix
+ in="SourceGraphic"
+ type="matrix"
+ values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"
+ id="feColorMatrix3659" />
+ </filter>
+ <clipPath
+ id="e">
+ <path
+ d="M 0,0 H 800 V 800 H 0 Z"
+ id="path1296" />
+ </clipPath>
+ <mask
+ id="d">
+ <g
+ filter="url(#a)"
+ id="g1293">
+ <path
+ d="M 0,0 H 16 V 16 H 0 Z"
+ fill-opacity="0.35"
+ id="path1291" />
+ </g>
+ </mask>
+ <filter
+ id="filter3670"
+ height="1"
+ width="1"
+ x="0"
+ y="0">
+ <feColorMatrix
+ in="SourceGraphic"
+ type="matrix"
+ values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"
+ id="feColorMatrix3668" />
+ </filter>
+ <clipPath
+ id="c">
+ <path
+ d="M 0,0 H 800 V 800 H 0 Z"
+ id="path1288" />
+ </clipPath>
+ <mask
+ id="b">
+ <g
+ filter="url(#a)"
+ id="g1285">
+ <path
+ d="M 0,0 H 16 V 16 H 0 Z"
+ fill-opacity="0.3"
+ id="path1283" />
+ </g>
+ </mask>
+ <filter
+ id="filter3679"
+ height="1"
+ width="1"
+ x="0"
+ y="0">
+ <feColorMatrix
+ in="SourceGraphic"
+ type="matrix"
+ values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"
+ id="feColorMatrix3677" />
+ </filter>
+ </defs>
+ <g
+ inkscape:label="Calque 1"
+ inkscape:groupmode="layer"
+ id="g3929">
+ <path
+ id="rect3921"
+ style="fill:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;paint-order:fill markers stroke;fill-opacity:1"
+ d="M 30 15 C 13.380034 15 0 28.380034 0 45 L 0 100 L 0 110 L 0 135 C 0 151.61996 13.380034 165 30 165 L 150 165 C 166.61996 165 180 151.61996 180 135 L 180 110 L 180 100 L 180 45 C 180 28.380034 166.61996 15 150 15 L 30 15 z M 35 35 L 145 35 C 153.30998 35 160 41.690016 160 50 L 160 100 L 20 100 L 20 50 C 20 41.690016 26.690016 35 35 35 z M 20 110 L 160 110 L 160 130 C 160 138.30998 153.30998 145 145 145 L 35 145 C 26.690016 145 20 138.30998 20 130 L 20 110 z " />
+ <path
+ id="rect3923"
+ style="fill:#000000;fill-opacity:0.41999999;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;paint-order:fill markers stroke"
+ d="M 20 110 L 20 130 C 20 138.30999 26.690008 145 35 145 L 145 145 C 153.30999 145 160 138.30999 160 130 L 160 110 L 20 110 z " />
+ </g>
+</svg>
diff --git a/src/data/images/dock-station-left-symbolic.svg b/src/data/images/dock-station-left-symbolic.svg
new file mode 100644
index 0000000..0f90e8f
--- /dev/null
+++ b/src/data/images/dock-station-left-symbolic.svg
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ width="180"
+ height="180"
+ viewBox="0 0 180 180"
+ version="1.1"
+ id="svg5"
+ inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
+ sodipodi:docname="dock-station-left-symbolic.svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+ <sodipodi:namedview
+ id="namedview7"
+ pagecolor="#ffffff"
+ bordercolor="#000000"
+ borderopacity="0.25"
+ inkscape:showpageshadow="2"
+ inkscape:pageopacity="0.0"
+ inkscape:pagecheckerboard="true"
+ inkscape:deskcolor="#d1d1d1"
+ inkscape:document-units="px"
+ showgrid="false"
+ inkscape:zoom="4.4555556"
+ inkscape:cx="88.541146"
+ inkscape:cy="89.999999"
+ inkscape:window-width="1920"
+ inkscape:window-height="1011"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="layer1" />
+ <defs
+ id="defs2" />
+ <g
+ inkscape:label="Calque 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <path
+ id="rect254"
+ style="fill:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;paint-order:fill markers stroke;fill-opacity:1"
+ d="M 30 15 C 13.380034 15 0 28.380034 0 45 L 0 135 C 0 151.61996 13.380034 165 30 165 L 65 165 L 75 165 L 150 165 C 166.61996 165 180 151.61996 180 135 L 180 45 C 180 28.380034 166.61996 15 150 15 L 75 15 L 65 15 L 30 15 z M 35 35 L 65 35 L 65 145 L 35 145 C 26.690016 145 20 138.30998 20 130 L 20 50 C 20 41.690016 26.690016 35 35 35 z M 75 35 L 145 35 C 153.30998 35 160 41.690016 160 50 L 160 130 C 160 138.30998 153.30998 145 145 145 L 75 145 L 75 35 z " />
+ <path
+ id="rect390"
+ style="fill:#000000;fill-opacity:0.41999999;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;paint-order:fill markers stroke"
+ d="M 35 35 C 26.690008 35 20 41.690008 20 50 L 20 130 C 20 138.30999 26.690008 145 35 145 L 65 145 L 65 35 L 35 35 z " />
+ </g>
+</svg>
diff --git a/src/data/images/dock-station-right-symbolic.svg b/src/data/images/dock-station-right-symbolic.svg
new file mode 100644
index 0000000..774476a
--- /dev/null
+++ b/src/data/images/dock-station-right-symbolic.svg
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ width="180"
+ height="180"
+ viewBox="0 0 180 180"
+ version="1.1"
+ id="svg5"
+ inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
+ sodipodi:docname="dock-station-right-symbolic.svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+ <sodipodi:namedview
+ id="namedview7"
+ pagecolor="#ffffff"
+ bordercolor="#000000"
+ borderopacity="0.25"
+ inkscape:showpageshadow="2"
+ inkscape:pageopacity="0.0"
+ inkscape:pagecheckerboard="true"
+ inkscape:deskcolor="#d1d1d1"
+ inkscape:document-units="px"
+ showgrid="false"
+ inkscape:zoom="4.4555556"
+ inkscape:cx="86.408977"
+ inkscape:cy="89.999999"
+ inkscape:window-width="1920"
+ inkscape:window-height="1011"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="layer1" />
+ <defs
+ id="defs2" />
+ <g
+ inkscape:label="Calque 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <path
+ id="rect254"
+ style="fill:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;paint-order:fill markers stroke;fill-opacity:1"
+ d="M 30 15 C 13.380034 15 0 28.380034 0 45 L 0 135 C 0 151.61996 13.380034 165 30 165 L 105 165 L 115 165 L 150 165 C 166.61996 165 180 151.61996 180 135 L 180 45 C 180 28.380034 166.61996 15 150 15 L 115 15 L 105 15 L 30 15 z M 35 35 L 105 35 L 105 145 L 35 145 C 26.690016 145 20 138.30998 20 130 L 20 50 C 20 41.690016 26.690016 35 35 35 z M 115 35 L 145 35 C 153.30998 35 160 41.690016 160 50 L 160 130 C 160 138.30998 153.30998 145 145 145 L 115 145 L 115 35 z " />
+ <path
+ id="rect390"
+ style="fill:#000000;fill-opacity:0.41999999;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;paint-order:fill markers stroke"
+ d="M 115 35 L 115 145 L 145 145 C 153.30999 145 160 138.30999 160 130 L 160 50 C 160 41.690008 153.30999 35 145 35 L 115 35 z " />
+ </g>
+ <g
+ inkscape:groupmode="layer"
+ id="layer2"
+ inkscape:label="Calque 2"
+ style="display:none;opacity:0.700936">
+ <g
+ fill="#2e3436"
+ id="g182"
+ transform="matrix(11.328515,0,0,10.683311,-1.25624,4.6587097)"
+ style="stroke-width:0.0908993">
+ <path
+ d="m 6.5,13.988281 v -12 h -5 v 12 z m 0,0"
+ fill-opacity="0.35"
+ id="path176"
+ style="stroke-width:0.00826268" />
+ <path
+ d="m 3,0.988281 c -1.644531,0 -3,1.355469 -3,3 v 8 c 0,1.644531 1.355469,3 3,3 h 10 c 1.644531,0 3,-1.355469 3,-3 v -8 c 0,-1.644531 -1.355469,-3 -3,-3 z m 0,2 h 10 c 0.570312,0 1,0.429688 1,1 v 8 c 0,0.570313 -0.429688,1 -1,1 H 3 c -0.570312,0 -1,-0.429687 -1,-1 v -8 c 0,-0.570312 0.429688,-1 1,-1 z m 0,0"
+ id="path178"
+ style="stroke-width:0.0908993" />
+ <path
+ d="m 6,1.988281 h 1 v 12 H 6 Z m 0,0"
+ id="path180"
+ style="stroke-width:0.0908993" />
+ </g>
+ </g>
+</svg>
diff --git a/src/data/images/gresource.xml b/src/data/images/gresource.xml
new file mode 100644
index 0000000..25c8274
--- /dev/null
+++ b/src/data/images/gresource.xml
@@ -0,0 +1,12 @@
+<?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>
+ <file compressed="true">dock-station-bottom-symbolic.svg</file>
+ <file compressed="true">logs-symbolic.svg</file>
+ </gresource>
+</gresources>
diff --git a/src/data/images/logs-symbolic.svg b/src/data/images/logs-symbolic.svg
new file mode 100644
index 0000000..f541607
--- /dev/null
+++ b/src/data/images/logs-symbolic.svg
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ width="180"
+ height="180"
+ viewBox="0 0 180 180"
+ version="1.1"
+ id="svg5"
+ inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
+ sodipodi:docname="logs-symbolic.svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+ <sodipodi:namedview
+ id="namedview7"
+ pagecolor="#ffffff"
+ bordercolor="#000000"
+ borderopacity="0.25"
+ inkscape:showpageshadow="2"
+ inkscape:pageopacity="0.0"
+ inkscape:pagecheckerboard="0"
+ inkscape:deskcolor="#d1d1d1"
+ inkscape:document-units="px"
+ showgrid="false"
+ inkscape:zoom="3.9657403"
+ inkscape:cx="110.44596"
+ inkscape:cy="77.413036"
+ inkscape:window-width="1920"
+ inkscape:window-height="1011"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="layer1" />
+ <defs
+ id="defs2" />
+ <g
+ inkscape:label="Calque 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ style="fill:#25ff4c;fill-opacity:1">
+ <path
+ id="rect495"
+ style="opacity:1;fill:#000000;fill-opacity:1;stroke-width:1.99999;stroke-linecap:round;stroke-linejoin:round;paint-order:fill markers stroke"
+ d="M 45 0 C 31.150014 0 20 11.150014 20 25 L 20 155 C 20 168.84999 31.150014 180 45 180 L 155 180 C 168.84999 180 180 168.84999 180 155 L 180 25 C 180 11.150014 168.84999 0 155 0 L 45 0 z M 55 10 L 145 10 C 158.84999 10 170 21.150014 170 35 L 170 145 C 170 158.84999 158.84999 170 145 170 L 55 170 C 41.150014 170 30 158.84999 30 145 L 30 35 C 30 21.150014 41.150014 10 55 10 z " />
+ <rect
+ style="display:inline;opacity:1;fill:#000000;fill-opacity:1;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;paint-order:fill markers stroke"
+ id="rect3619"
+ width="75"
+ height="12"
+ x="62.5"
+ y="84"
+ rx="6"
+ ry="6" />
+ <rect
+ style="display:inline;opacity:1;fill:#000000;fill-opacity:1;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;paint-order:fill markers stroke"
+ id="rect5029"
+ width="75"
+ height="12"
+ x="62.5"
+ y="127"
+ rx="6"
+ ry="6" />
+ <rect
+ style="display:inline;opacity:1;fill:#000000;fill-opacity:1;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;paint-order:fill markers stroke"
+ id="rect5031"
+ width="75"
+ height="12"
+ x="62.5"
+ y="41"
+ rx="6"
+ ry="6" />
+ <rect
+ style="display:inline;opacity:1;fill:#000000;fill-opacity:1;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;paint-order:fill markers stroke"
+ id="rect5049"
+ width="34"
+ height="12"
+ x="8.2744884"
+ y="41"
+ rx="6"
+ ry="6" />
+ <rect
+ style="display:inline;opacity:1;fill:#000000;fill-opacity:1;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;paint-order:fill markers stroke"
+ id="rect5051"
+ width="34"
+ height="12"
+ x="8.2744884"
+ y="127"
+ rx="6"
+ ry="6" />
+ </g>
+</svg>
diff --git a/src/glibext/Makefile.am b/src/glibext/Makefile.am
index f946665..b0a7c31 100644
--- a/src/glibext/Makefile.am
+++ b/src/glibext/Makefile.am
@@ -14,7 +14,6 @@ noinst_LTLIBRARIES = libglibext.la libglibextui.la
# \
# proto.h \
# seq.h seq.c \
-# _signal.h signal.c \
# singleton.h singleton.c \
# linetoken.h linetoken.c \
# umemslice-int.h \
@@ -43,6 +42,8 @@ libglibext_la_SOURCES = \
hashable-int.h \
hashable.h hashable.c \
helpers.h \
+ log-int.h \
+ log.h log.c \
objhole-int.h \
objhole.h objhole.c \
portion-int.h \
@@ -51,6 +52,7 @@ libglibext_la_SOURCES = \
secstorage.h secstorage.c \
serialize-int.h \
serialize.h serialize.c \
+ sigredir.h sigredir.c \
singleton-int.h \
singleton.h singleton.c \
storage-int.h \
diff --git a/src/glibext/bufferline.c b/src/glibext/bufferline.c
index 4862e9f..e3fb27b 100644
--- a/src/glibext/bufferline.c
+++ b/src/glibext/bufferline.c
@@ -24,14 +24,16 @@
#include "bufferline.h"
+#include <assert.h>
+#include <malloc.h>
+
+
#include "bufferline-int.h"
#if 0
-#include <assert.h>
-#include <malloc.h>
#include <string.h>
@@ -273,158 +275,12 @@ bool g_buffer_line_create(GBufferLine *line, size_t col_count)
}
-
-
-
-
-
-
-
-/******************************************************************************
-* *
-* 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. *
-* col = indice de la colonne à constituer. *
-* size = taille souhaitée de l'impression des positions. *
-* addr = localisation physique à venir représenter. *
+* Paramètres : line = ligne à venir compléter. *
+* column = indice de la colonne visée par l'insertion. *
+* size = taille souhaitée de l'impression des positions. *
+* addr = localisation physique à venir représenter. *
* *
* Description : Construit le tronc commun d'une ligne autour de sa position. *
* *
@@ -434,7 +290,7 @@ void g_buffer_line_draw(const GBufferLine *line, cairo_t *cr, size_t column, int
* *
******************************************************************************/
-void g_buffer_line_fill_phys(GBufferLine *line, size_t col, MemoryDataSize size, const vmpa2t *addr)
+void g_buffer_line_fill_physical(GBufferLine *line, size_t column, MemoryDataSize size, const vmpa2t *addr)
{
VMPA_BUFFER(position); /* Emplacement au format texte */
size_t len; /* Taille de l'élément inséré */
@@ -448,20 +304,22 @@ void g_buffer_line_fill_phys(GBufferLine *line, size_t col, MemoryDataSize size,
if (i == len)
i = len - 1;
+ assert(column < line->col_count);
+
if (i > 0)
- g_buffer_line_append_text(line, col, position, i, RTT_PHYS_ADDR_PAD, NULL);
+ g_buffer_line_append_text(line, column, TRT_PHYS_ADDR_PAD, position, i, NULL, NULL);
- g_buffer_line_append_text(line, col, &position[i], len - i, RTT_PHYS_ADDR, NULL);
+ g_buffer_line_append_text(line, column, TRT_PHYS_ADDR, &position[i], len - i, NULL, NULL);
}
/******************************************************************************
* *
-* Paramètres : line = ligne à venir compléter. *
-* col = indice de la colonne à constituer. *
-* size = taille souhaitée de l'impression des positions. *
-* addr = localisation virtuelle à venir représenter. *
+* Paramètres : line = ligne à venir compléter. *
+* column = indice de la colonne visée par l'insertion. *
+* size = taille souhaitée de l'impression des positions. *
+* addr = localisation virtuelle à venir représenter. *
* *
* Description : Construit le tronc commun d'une ligne autour de sa position. *
* *
@@ -471,7 +329,7 @@ void g_buffer_line_fill_phys(GBufferLine *line, size_t col, MemoryDataSize size,
* *
******************************************************************************/
-void g_buffer_line_fill_virt(GBufferLine *line, size_t col, MemoryDataSize size, const vmpa2t *addr)
+void g_buffer_line_fill_virtual(GBufferLine *line, size_t column, MemoryDataSize size, const vmpa2t *addr)
{
VMPA_BUFFER(position); /* Emplacement au format texte */
size_t len; /* Taille de l'élément inséré */
@@ -479,6 +337,8 @@ void g_buffer_line_fill_virt(GBufferLine *line, size_t col, MemoryDataSize size,
vmpa2_virt_to_string(addr, size, position, &len);
+ assert(column < line->col_count);
+
if (has_virt_addr(addr))
{
for (i = 2; i < len; i++)
@@ -488,14 +348,14 @@ void g_buffer_line_fill_virt(GBufferLine *line, size_t col, MemoryDataSize size,
i = len - 1;
if (i > 0)
- g_buffer_line_append_text(line, col, position, i, RTT_VIRT_ADDR_PAD, NULL);
+ g_buffer_line_append_text(line, column, TRT_VIRT_ADDR_PAD, position, i, NULL, NULL);
- g_buffer_line_append_text(line, col, &position[i], len - i, RTT_VIRT_ADDR, NULL);
+ g_buffer_line_append_text(line, column, TRT_VIRT_ADDR, &position[i], len - i, NULL, NULL);
}
else
- g_buffer_line_append_text(line, col, position, len, RTT_VIRT_ADDR_PAD, NULL);
+ g_buffer_line_append_text(line, column, TRT_VIRT_ADDR_PAD, position, len, NULL, NULL);
}
@@ -503,7 +363,7 @@ void g_buffer_line_fill_virt(GBufferLine *line, size_t col, MemoryDataSize size,
/******************************************************************************
* *
* Paramètres : line = ligne à venir compléter. *
-* col = indice de la colonne à constituer. *
+* column = indice de la colonne visée par l'insertion. *
* content = contenu binaire global à venir lire. *
* range = localisation des données à venir lire et présenter.*
* max = taille maximale de la portion binaire en octets. *
@@ -516,7 +376,7 @@ void g_buffer_line_fill_virt(GBufferLine *line, size_t col, MemoryDataSize size,
* *
******************************************************************************/
-void g_buffer_line_fill_content(GBufferLine *line, size_t col, const GBinContent *content, const mrange_t *range, phys_t max)
+void g_buffer_line_fill_content(GBufferLine *line, size_t column, const GBinContent *content, const mrange_t *range, phys_t max)
{
phys_t length; /* Taille de la couverture */
bool truncated; /* Indique si le code est coupé*/
@@ -548,7 +408,7 @@ void g_buffer_line_fill_content(GBufferLine *line, size_t col, const GBinContent
if (required <= sizeof(static_buffer))
bin_code = static_buffer;
else
- bin_code = (char *)calloc(required, sizeof(char));
+ bin_code = calloc(required, sizeof(char));
/* Code brut */
@@ -589,7 +449,7 @@ void g_buffer_line_fill_content(GBufferLine *line, size_t col, const GBinContent
/* Conclusion */
- g_buffer_line_append_text(line, col, bin_code, iter - bin_code, RTT_RAW_CODE, NULL);
+ g_buffer_line_append_text(line, column, TRT_RAW_CODE, bin_code, iter - bin_code, NULL, NULL);
if (bin_code != static_buffer)
free(bin_code);
@@ -599,6 +459,146 @@ void g_buffer_line_fill_content(GBufferLine *line, size_t col, const GBinContent
/******************************************************************************
* *
+* 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 consulter. *
* column = indice de la colonne visée par les recherches. *
* *
diff --git a/src/glibext/bufferline.h b/src/glibext/bufferline.h
index d6a2e2d..e95ee2b 100644
--- a/src/glibext/bufferline.h
+++ b/src/glibext/bufferline.h
@@ -30,6 +30,8 @@
#include "helpers.h"
#include "tokenstyle.h"
+#include "../arch/vmpa.h"
+#include "../analysis/content.h"
@@ -45,8 +47,6 @@
#ifdef INCLUDE_GTK_SUPPORT
# include "widthtracker.h"
#endif
-#include "../analysis/content.h"
-#include "../arch/vmpa.h"
@@ -75,6 +75,9 @@ typedef struct _GBufferLineClass GBufferLineClass;
+
+
+
#define G_TYPE_BUFFER_LINE (g_buffer_line_get_type())
DECLARE_GTYPE(GBufferLine, g_buffer_line, G, BUFFER_LINE);
@@ -98,7 +101,14 @@ typedef enum _BufferLineFlags
/* Crée une nouvelle représentation de fragments de texte. */
GBufferLine *g_buffer_line_new(size_t);
+/* Construit le tronc commun d'une ligne autour de sa position. */
+void g_buffer_line_fill_physical(GBufferLine *, size_t, MemoryDataSize, const vmpa2t *);
+
+/* Construit le tronc commun d'une ligne autour de sa position. */
+void g_buffer_line_fill_virtual(GBufferLine *, size_t, MemoryDataSize, const vmpa2t *);
+/* Construit le tronc commun d'une ligne autour de son contenu. */
+void g_buffer_line_fill_content(GBufferLine *, size_t, const GBinContent *, const mrange_t *, phys_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 *);
diff --git a/src/glibext/log-int.h b/src/glibext/log-int.h
new file mode 100644
index 0000000..3b3208a
--- /dev/null
+++ b/src/glibext/log-int.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * log-int.h - prototypes internes pour la conservation à destination graphique des éléments de journalisation
+ *
+ * Copyright (C) 2025 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GLIBEXT_LOG_INT_H
+#define _GLIBEXT_LOG_INT_H
+
+
+#include <stdbool.h>
+
+
+#include "log.h"
+
+
+
+/* Définition d'une conservation d'objets construits (instance) */
+struct _GLogEntry
+{
+ GObject parent; /* A laisser en premier */
+
+ LogMessageType type; /* Type de message porté */
+ char *msg; /* Contenu du message diffusé */
+
+};
+
+/* Définition d'une conservation d'objets construits (classe) */
+struct _GLogEntryClass
+{
+ GObjectClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place une conservation pour élément de journalisation. */
+bool g_log_entry_create(GLogEntry *, LogMessageType, const char *);
+
+
+
+#endif /* _GLIBEXT_LOG_INT_H */
diff --git a/src/glibext/log.c b/src/glibext/log.c
new file mode 100644
index 0000000..039172c
--- /dev/null
+++ b/src/glibext/log.c
@@ -0,0 +1,306 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * log.c - conservation hors mémoire d'objets choisis
+ *
+ * Copyright (C) 2020-2025 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "log.h"
+
+
+#include <malloc.h>
+#include <string.h>
+
+
+#include "log-int.h"
+
+
+
+/* ---------------------------- ENTREE DE JOURNALISATION ---------------------------- */
+
+
+/* Liste des propriétés */
+
+typedef enum _LogEntryProperty {
+
+ PROP_0, /* Réservé */
+
+ PROP_ICON_NAME, /* Nom d'image de représentat° */
+ PROP_MESSAGE, /* Contenu du message diffusé */
+
+ N_PROPERTIES
+
+} LogEntryProperty;
+
+static GParamSpec *_log_entry_properties[N_PROPERTIES] = { NULL, };
+
+
+/* Initialise la classe des conservations d'objets en place. */
+static void g_log_entry_class_init(GLogEntryClass *);
+
+/* Initialise une instance de conservation d'objets en place. */
+static void g_log_entry_init(GLogEntry *);
+
+/* Supprime toutes les références externes. */
+static void g_log_entry_dispose(GObject *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_log_entry_finalize(GObject *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Fournit la valeur d'une propriété d'instance GObject. */
+static void gtk_log_entry_get_property(GObject *, guint, GValue *, GParamSpec *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* ENTREE DE JOURNALISATION */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une conservation d'objets construits. */
+G_DEFINE_TYPE(GLogEntry, g_log_entry, G_TYPE_OBJECT);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des conservations d'objets en place. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_log_entry_class_init(GLogEntryClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = g_log_entry_dispose;
+ object->finalize = g_log_entry_finalize;
+ object->get_property = gtk_log_entry_get_property;
+
+ _log_entry_properties[PROP_ICON_NAME] =
+ g_param_spec_string("icon-name", NULL, NULL,
+ NULL,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+ _log_entry_properties[PROP_MESSAGE] =
+ g_param_spec_string("message", NULL, NULL,
+ NULL,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties(object, N_PROPERTIES, _log_entry_properties);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : entry = instance à initialiser. *
+* *
+* Description : Initialise une instance de conservation d'objets en place. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_log_entry_init(GLogEntry *entry)
+{
+ entry->type = LMT_COUNT;
+ entry->msg = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_log_entry_dispose(GObject *object)
+{
+ G_OBJECT_CLASS(g_log_entry_parent_class)->dispose(object);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_log_entry_finalize(GObject *object)
+{
+ GLogEntry *entry; /* Version spécialisée */
+
+ entry = G_LOG_ENTRY(object);
+
+ if (entry->msg != NULL)
+ free(entry->msg);
+
+ G_OBJECT_CLASS(g_log_entry_parent_class)->finalize(object);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : type = espèce du message à représenter. *
+* msg = message à faire apparaître à l'écran. *
+* *
+* Description : Crée une conservation pour un élément de journalisation. *
+* *
+* Retour : Conservation mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GLogEntry *g_log_entry_new(LogMessageType type, const char *msg)
+{
+ GLogEntry *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_LOG_ENTRY, NULL);
+
+ if (!g_log_entry_create(result, type, msg))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : entry = instance de conservation à initialiser pleinement. *
+* type = espèce du message à représenter. *
+* msg = message à faire apparaître à l'écran. *
+* *
+* Description : Met en place une conservation pour élément de journalisation.*
+* *
+* Retour : Conservation mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_log_entry_create(GLogEntry *entry, LogMessageType type, const char *msg)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ entry->type = type;
+ entry->msg = strdup(msg);
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* 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_log_entry_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+ GLogEntry *entry; /* Version spécialisée */
+
+ entry = G_LOG_ENTRY(object);
+
+ switch (prop_id)
+ {
+ case PROP_ICON_NAME:
+ switch (entry->type)
+ {
+ case LMT_INFO:
+ g_value_set_string(value, "dialog-information-symbolic");
+ break;
+
+ case LMT_PROCESS:
+ g_value_set_string(value, "system-run-symbolic");
+ break;
+
+ case LMT_WARNING:
+ case LMT_BAD_BINARY:
+ g_value_set_string(value, "dialog-warning-symbolic");
+ break;
+
+ case LMT_ERROR:
+ case LMT_EXT_ERROR:
+ g_value_set_string(value, "computer-fail-symbolic");
+ break;
+
+
+ case LMT_COUNT:
+ g_value_set_string(value, "dialog-question-symbolic");
+ break;
+
+ }
+ break;
+
+ case PROP_MESSAGE:
+ g_value_set_string(value, entry->msg);
+ break;
+
+ }
+
+}
diff --git a/src/glibext/log.h b/src/glibext/log.h
new file mode 100644
index 0000000..472773c
--- /dev/null
+++ b/src/glibext/log.h
@@ -0,0 +1,43 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * log.h - prototypes pour la conservation à destination graphique des éléments de journalisation
+ *
+ * Copyright (C) 2025 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GLIBEXT_LOG_H
+#define _GLIBEXT_LOG_H
+
+
+#include "helpers.h"
+#include "../core/logs.h"
+
+
+
+#define G_TYPE_LOG_ENTRY (g_log_entry_get_type())
+
+DECLARE_GTYPE(GLogEntry, g_log_entry, G, LOG_ENTRY);
+
+
+/* Crée une conservation pour un élément de journalisation. */
+GLogEntry *g_log_entry_new(LogMessageType, const char *);
+
+
+
+#endif /* _GLIBEXT_LOG_H */
diff --git a/src/glibext/options/asm.h b/src/glibext/options/asm.h
index e916083..d7a2c86 100644
--- a/src/glibext/options/asm.h
+++ b/src/glibext/options/asm.h
@@ -1,6 +1,6 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * disass.h - prototypes pour les options de rendus de code désassemblé
+ * asm.h - prototypes pour les options de rendus de code désassemblé
*
* Copyright (C) 2025 Cyrille Bagard
*
@@ -21,8 +21,8 @@
*/
-#ifndef _GLIBEXT_OPTIONS_DISASS_H
-#define _GLIBEXT_OPTIONS_DISASS_H
+#ifndef _GLIBEXT_OPTIONS_ASM_H
+#define _GLIBEXT_OPTIONS_ASM_H
#include "../helpers.h"
@@ -32,14 +32,23 @@
/* Liste des colonnes en options */
typedef enum _DisassColumnOptions
{
- ACO_OFFSET, /* Position */
+ ACO_PHYSICAL, /* Position physique */
+ ACO_VIRTUAL, /* Adresse virtuelle */
+ ACO_BINARY, /* Contenu sous forme binaire */
ACO_COUNT
} DisassColumnOptions;
-#define ACO_ASSEMBLY (ACO_COUNT + 0) /* Code pour assembleur */
+#define ACO_ASSEMBLY_LABEL (ACO_COUNT + 0) /* Etiquette dans les données */
+#define ACO_ASSEMBLY_HEAD (ACO_COUNT + 1) /* Instruction pour assembleur */
+#define ACO_ASSEMBLY (ACO_COUNT + 2) /* Code pour assembleur */
+#define ACO_COMMENTS (ACO_COUNT + 3) /* Commentaires éventuels */
+
+
+
+
#if 0
diff --git a/src/glibext/secstorage.c b/src/glibext/secstorage.c
index b118aa6..161214c 100644
--- a/src/glibext/secstorage.c
+++ b/src/glibext/secstorage.c
@@ -160,7 +160,7 @@ static void g_secret_storage_init(GSecretStorage *storage)
static void g_secret_storage_dispose(GObject *object)
{
- GSecretStorage *storage; /* Gestion de stockage sécurisé*/
+ GSecretStorage *storage; /* Version spécialisée */
storage = G_SECRET_STORAGE(object);
@@ -185,7 +185,7 @@ static void g_secret_storage_dispose(GObject *object)
static void g_secret_storage_finalize(GObject *object)
{
- GSecretStorage *storage; /* Gestion de stockage sécurisé*/
+ GSecretStorage *storage; /* Version spécialisée */
storage = G_SECRET_STORAGE(object);
diff --git a/src/glibext/signal.c b/src/glibext/sigredir.c
index 33290fb..67e8563 100644
--- a/src/glibext/signal.c
+++ b/src/glibext/sigredir.c
@@ -1,8 +1,8 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * signal.c - encadrement des signaux supplémentaire par rapport à celui de la GLib
+ * sigredir.c - encadrement des signaux supplémentaire par rapport à celui de la GLib
*
- * Copyright (C) 2014-2018 Cyrille Bagard
+ * Copyright (C) 2014-2025 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -21,49 +21,55 @@
*/
-#include "signal.h"
+#include "sigredir.h"
#include <assert.h>
#include <malloc.h>
#include <stdarg.h>
#include <stdbool.h>
+#include <gobject/gclosure.h>
#include <gobject/gvaluecollector.h>
-/* Prototype pour le transfert d'exécution. */
-typedef void (* GSignalCallback) (gpointer, ...);
+/* Informations utiles à l'appel final */
+typedef struct _gsignal_wrapper_params_t
+{
+ GClosure *closure; /* Glue pour les appels */
+
+ guint n_params; /* Nombre de paramètres */
+ GValue instance_and_params[0]; /* Instance & paramètres */
+
+} gsignal_wrapper_params_t;
+
+/* Transmet un signal dans le contexte principal. */
+static gboolean to_main_wrapper(gpointer);
+/* Supprime de la mémoire le transporteur d'informations. */
+static void destroy_wrapper_params(gpointer);
/* Informations concernant une diffusion de signal */
-typedef struct _gsignal_wrapper_info
+typedef struct _gsignal_wrapper_info_t
{
gpointer instance; /* Instance GLib initiatrice */
+ gulong id; /* Identifiant de connexion */
GClosure *closure; /* Glue pour les appels */
- GType return_type; /* Type de la valeur retournée */
guint n_params; /* Nombre de paramètres */
- const GType *param_types; /* Type des paramètres associés*/
+ GType param_types[0]; /* Type des paramètres associés*/
- GValue return_value; /* Valeur de retour */
- GValue instance_and_params[0]; /* Instance & paramètres */
-
-} gsignal_wrapper_info;
-
-
-/* Transmet un signal dans le contexte principal. */
-static gboolean to_main_wrapper(gsignal_wrapper_info *);
+} gsignal_wrapper_info_t;
/* Réceptionne un signal et redirige son exécution. */
-static void carry_signal_to_main_thread(gsignal_wrapper_info *, ...);
+static void carry_signal_to_main_thread(gsignal_wrapper_info_t *, ...);
/******************************************************************************
* *
-* Paramètres : info = collecteur d'informations sur la diffusion. *
+* Paramètres : data = collecteur d'informations sur la diffusion. *
* *
* Description : Transmet un signal dans le contexte principal. *
* *
@@ -73,11 +79,17 @@ static void carry_signal_to_main_thread(gsignal_wrapper_info *, ...);
* *
******************************************************************************/
-static gboolean to_main_wrapper(gsignal_wrapper_info *info)
+static gboolean to_main_wrapper(gpointer data)
{
- g_closure_invoke(info->closure, NULL/*&info->return_value*/,
- info->n_params + 1, info->instance_and_params,
- NULL);
+ gsignal_wrapper_params_t *params; /* Informations d'appel */
+
+ params = (gsignal_wrapper_params_t *)data;
+
+ g_closure_invoke(params->closure,
+ NULL /* return_value */,
+ params->n_params + 1,
+ params->instance_and_params,
+ NULL /* invocation_hint */);
return G_SOURCE_REMOVE;
@@ -86,6 +98,35 @@ static gboolean to_main_wrapper(gsignal_wrapper_info *info)
/******************************************************************************
* *
+* Paramètres : data = collecteur d'informations à supprimer. *
+* *
+* Description : Supprime de la mémoire le transporteur d'informations. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void destroy_wrapper_params(gpointer data)
+{
+ gsignal_wrapper_params_t *params; /* Informations d'appel */
+ guint i; /* Boucle de parcours */
+
+ params = (gsignal_wrapper_params_t *)data;
+
+ g_closure_unref(params->closure);
+
+ for (i = 0; i < (params->n_params + 1); i++)
+ g_value_unset(params->instance_and_params + i);
+
+ free(params);
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : info = collecteur d'informations sur la diffusion. *
* ... = arguments poussés par la GLib sur la pile. *
* *
@@ -97,23 +138,26 @@ static gboolean to_main_wrapper(gsignal_wrapper_info *info)
* *
******************************************************************************/
-static void carry_signal_to_main_thread(gsignal_wrapper_info *info, ...)
+static void carry_signal_to_main_thread(gsignal_wrapper_info_t *info, ...)
{
+ gsignal_wrapper_params_t *params; /* Informations d'appel */
GValue *param_values; /* Paramètres d'appel */
va_list ap; /* Liste d'arguments sur pile */
guint i; /* Boucle de parcours */
bool static_scope; /* Portée des arguments */
gchar *error; /* Eventuelle erreur inattendue*/
- //g_value_init(&info->return_value, info->return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE);
+ params = calloc(1, sizeof(gsignal_wrapper_params_t) + sizeof(GValue) * (info->n_params + 1));
+
+ params->closure = info->closure;
+ g_closure_ref(info->closure);
- if (G_IS_VALUE(info->instance_and_params))
- g_value_unset(info->instance_and_params);
+ params->n_params = info->n_params;
- g_value_init(info->instance_and_params, G_TYPE_FROM_INSTANCE(info->instance));
- g_value_set_instance(info->instance_and_params, info->instance);
+ g_value_init(params->instance_and_params, G_TYPE_FROM_INSTANCE(info->instance));
+ g_value_set_instance(params->instance_and_params, info->instance);
- param_values = info->instance_and_params + 1;
+ param_values = params->instance_and_params + 1;
va_start(ap, info);
@@ -121,9 +165,6 @@ static void carry_signal_to_main_thread(gsignal_wrapper_info *info, ...)
for (i = 0; i < info->n_params; i++)
{
- if (G_IS_VALUE(param_values + i))
- g_value_unset(param_values + i);
-
static_scope = info->param_types[i] & G_SIGNAL_TYPE_STATIC_SCOPE;
G_VALUE_COLLECT_INIT(param_values + i,
@@ -143,7 +184,28 @@ static void carry_signal_to_main_thread(gsignal_wrapper_info *info, ...)
va_end(ap);
if (error == NULL)
- g_idle_add_full(G_PRIORITY_HIGH_IDLE, (GSourceFunc)to_main_wrapper, info, NULL);
+ g_idle_add_full(G_PRIORITY_HIGH_IDLE, to_main_wrapper, params, destroy_wrapper_params);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : info = collecteur d'informations à supprimer. *
+* *
+* Description : Déconnecte un signal redirigé vers le contexte principal. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_signal_disconnect_from_main(gsignal_wrapper_info_t *info)
+{
+ g_signal_handler_disconnect(info->instance, info->id);
+
+ free(info);
}
@@ -165,41 +227,44 @@ static void carry_signal_to_main_thread(gsignal_wrapper_info *info, ...)
* *
******************************************************************************/
-gulong _g_signal_connect_to_main(gpointer instance, const gchar *signal, GCallback handler, gpointer data, GClosureMarshal marshal, GConnectFlags flags)
+gsignal_wrapper_info_t *_g_signal_connect_to_main(gpointer instance, const gchar *signal, GCallback handler, gpointer data, GClosureMarshal marshal, GConnectFlags flags)
{
+ gsignal_wrapper_info_t *result; /* Structure à renvoyer */
guint signal_id; /* Identifiant du signal visé */
GSignalQuery query; /* Information sur le signal */
- gsignal_wrapper_info *info; /* Encapsulation des données */
/* Collection d'informations */
signal_id = g_signal_lookup(signal, G_TYPE_FROM_INSTANCE(instance));
g_signal_query(signal_id, &query);
+
assert(query.signal_id != 0);
+ assert(query.return_type == G_TYPE_NONE);
/* Allocation adaptée */
- info = calloc(1, sizeof(gsignal_wrapper_info) + sizeof(GValue) * (query.n_params + 1));
+ result = malloc(sizeof(gsignal_wrapper_info_t) + sizeof(GType) * query.n_params);
- info->instance = instance;
+ result->instance = instance;
if (flags & G_CONNECT_SWAPPED)
- info->closure = g_cclosure_new_swap(handler, data, NULL);
+ result->closure = g_cclosure_new_swap(handler, data, NULL);
else
- info->closure = g_cclosure_new(handler, data, NULL);
+ result->closure = g_cclosure_new(handler, data, NULL);
- g_closure_ref(info->closure);
- g_closure_sink(info->closure);
+ g_closure_ref(result->closure);
+ g_closure_sink(result->closure);
- g_closure_set_marshal(info->closure, marshal);
+ g_closure_set_marshal(result->closure, marshal);
- info->return_type = query.return_type;
- info->n_params = query.n_params;
- info->param_types = query.param_types;
+ result->n_params = query.n_params;
+ memcpy(result->param_types, query.param_types, sizeof(GType) * query.n_params);
- assert(query.return_type == G_TYPE_NONE);
+ /* Connexion au signal */
+
+ result->id = g_signal_connect_swapped(instance, signal, G_CALLBACK(carry_signal_to_main_thread), result);
- return g_signal_connect_swapped(instance, signal, G_CALLBACK(carry_signal_to_main_thread), info);
+ return result;
}
diff --git a/src/glibext/_signal.h b/src/glibext/sigredir.h
index 4f0ab4b..f394d77 100644
--- a/src/glibext/_signal.h
+++ b/src/glibext/sigredir.h
@@ -1,8 +1,8 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * signal.h - prototypes pour un encadrement des signaux supplémentaire par rapport à celui de la GLib
+ * sigredir.h - prototypes pour un encadrement des signaux supplémentaire par rapport à celui de la GLib
*
- * Copyright (C) 2014-2018 Cyrille Bagard
+ * Copyright (C) 2014-2025 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -21,20 +21,23 @@
*/
-#ifndef _GLIBEXT_SIGNAL_H
-#define _GLIBEXT_SIGNAL_H
+#ifndef _GLIBEXT_SIGREDIR_H
+#define _GLIBEXT_SIGREDIR_H
#include <glib-object.h>
-#include <gobject/gclosure.h>
-#include <glib/gdataset.h>
-#include <glib/glist.h>
#include <gobject/gsignal.h>
+/* Informations concernant une diffusion de signal */
+typedef struct _gsignal_wrapper_info_t gsignal_wrapper_info_t;
+
/* Reproduit le comportement de la fonction g_signal_connect(). */
-gulong _g_signal_connect_to_main(gpointer, const gchar *, GCallback, gpointer, GClosureMarshal, GConnectFlags);
+gsignal_wrapper_info_t *_g_signal_connect_to_main(gpointer, const gchar *, GCallback, gpointer, GClosureMarshal, GConnectFlags);
+
+/* Déconnecte un signal redirigé vers le contexte principal. */
+void g_signal_disconnect_from_main(gsignal_wrapper_info_t *);
#define g_signal_connect_to_main(instance, signal, handler, data, marshal) \
@@ -45,4 +48,4 @@ gulong _g_signal_connect_to_main(gpointer, const gchar *, GCallback, gpointer, G
-#endif /* _GLIBEXT_SIGNAL_H */
+#endif /* _GLIBEXT_SIGREDIR_H */
diff --git a/src/glibext/storage-int.h b/src/glibext/storage-int.h
index e4bac7a..d89e1c8 100644
--- a/src/glibext/storage-int.h
+++ b/src/glibext/storage-int.h
@@ -1,6 +1,6 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * storage.h - prototypes internes pour la conservation sur disque d'objets construits
+ * storage-int.h - prototypes internes pour la conservation sur disque d'objets construits
*
* Copyright (C) 2020-2025 Cyrille Bagard
*
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/Makefile.am b/src/gtkext/Makefile.am
index 839ee8f..c6908dd 100644
--- a/src/gtkext/Makefile.am
+++ b/src/gtkext/Makefile.am
@@ -29,6 +29,8 @@ libgtkext_la_CFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS)
IMG_PATH = ../../data/images
RES_FILES = \
+ grid.ui \
+ dockstation.ui \
hexview.css \
hexview.ui \
launcher.ui \
@@ -64,6 +66,9 @@ libgtkext4_la_SOURCES = \
libgtkext4_la_CFLAGS = $(LIBGTK4_CFLAGS)
+libgtkext4_la_LIBADD = \
+ bindings/libgtkextbindings.la
+
devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%)
@@ -71,6 +76,7 @@ dev_HEADERS = $(libgtkext4_la_SOURCES:%c=)
#SUBDIRS = graph
+SUBDIRS = bindings
resources.c: gresource.xml $(RES_FILES)
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/bindings/Makefile.am b/src/gtkext/bindings/Makefile.am
new file mode 100644
index 0000000..71e770d
--- /dev/null
+++ b/src/gtkext/bindings/Makefile.am
@@ -0,0 +1,42 @@
+
+EXTRA_DIST = \
+ generated-enums.c.template \
+ generated-enums.h.template
+
+
+noinst_LTLIBRARIES = libgtkextbindings.la
+
+
+nodist_libgtkextbindings_la_SOURCES = \
+ grid-enums.h grid-enums.c
+
+libgtkextbindings_la_CFLAGS = $(LIBGTK4_CFLAGS)
+
+
+BUILT_SOURCES = $(nodist_libgtkextbindings_la_SOURCES)
+CLEANFILES = $(nodist_libgtkextbindings_la_SOURCES)
+
+
+devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%)
+
+dev_HEADERS = $(nodist_libgtkextbindings_la_SOURCES:%c=)
+
+
+grid-enums.c: ../../gtkext/grid.h generated-enums.c.template
+ $(AM_V_GEN)$(GLIB_MKENUMS) \
+ --fhead "#include \"$(subst .c,.h,$@)\"\n" \
+ --template=$(srcdir)/generated-enums.c.template \
+ --output=$(srcdir)/$@ \
+ $<
+
+grid-enums.h: ../../gtkext/grid.h generated-enums.h.template
+ $(AM_V_GEN)$(GLIB_MKENUMS) \
+ --fhead "#ifndef _GTKEXT_BINDINGS_GRID_ENUM_H\n" \
+ --fhead "#define _GTKEXT_BINDINGS_GRID_ENUM_H\n" \
+ --fhead "\n" \
+ --fhead "#include \"$<\"\n" \
+ --fhead "\n" \
+ --ftail "#endif /* _GTKEXT_BINDINGS_GRID_ENUM_H */\n" \
+ --template=$(srcdir)/generated-enums.h.template \
+ --output=$(srcdir)/$@ \
+ $<
diff --git a/src/gtkext/bindings/generated-enums.c.template b/src/gtkext/bindings/generated-enums.c.template
new file mode 100644
index 0000000..8f54149
--- /dev/null
+++ b/src/gtkext/bindings/generated-enums.c.template
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+// SPDX-FileCopyrightText: 2023 Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
+
+/*** BEGIN file-header ***/
+
+/*** END file-header ***/
+
+/*** BEGIN file-production ***/
+
+/* Enumerations de "@filename@" */
+
+/*** END file-production ***/
+
+/*** BEGIN value-header ***/
+
+GType @enum_name@_get_type(void)
+{
+ static gsize static_g_@type@_type_id;
+
+ if (g_once_init_enter(&static_g_@type@_type_id)) {
+ static const G@Type@Value values[] = {
+/*** END value-header ***/
+
+/*** BEGIN value-production ***/
+ {@VALUENAME@, "@VALUENAME@", "@valuenick@"},
+/*** END value-production ***/
+
+/*** BEGIN value-tail ***/
+ { 0, NULL, NULL }
+ };
+
+ GType g_@type@_type_id = g_@type@_register_static(
+ g_intern_static_string("@EnumName@"), values);
+
+ g_once_init_leave (&static_g_@type@_type_id, g_@type@_type_id);
+ }
+
+ return static_g_@type@_type_id;
+}
+
+/*** END value-tail ***/
diff --git a/src/gtkext/bindings/generated-enums.h.template b/src/gtkext/bindings/generated-enums.h.template
new file mode 100644
index 0000000..58c772d
--- /dev/null
+++ b/src/gtkext/bindings/generated-enums.h.template
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+// SPDX-FileCopyrightText: 2023-2024 Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
+
+/*** BEGIN file-header ***/
+
+G_BEGIN_DECLS
+
+/*** END file-header ***/
+
+/*** BEGIN file-production ***/
+
+/*** END file-production ***/
+
+/*** BEGIN value-header ***/
+GType @enum_name@_get_type(void) G_GNUC_CONST;
+#define @ENUMPREFIX@_@ENUMSHORT@_TYPE (@enum_name@_get_type())
+/*** END value-header ***/
+
+/*** BEGIN file-tail ***/
+
+G_END_DECLS
+
+/*** END file-tail ***/
diff --git a/src/gtkext/dockstation-int.h b/src/gtkext/dockstation-int.h
index a44371a..17ed828 100644
--- a/src/gtkext/dockstation-int.h
+++ b/src/gtkext/dockstation-int.h
@@ -32,19 +32,29 @@
/* Station de réception pour concentration d'éléments (instance) */
struct _GtkDockStation
{
- GtkWidget parent; /* A laisser en premier */
+ GtkBox parent; /* A laisser en premier */
+
+ GtkOrientation orientation; /* Spécification d'orientation */
+
+ GtkWidget *tabs; /* Bascule entre panneaux */
+ GtkWidget *toolbar; /* Boutons d'action */
+ GtkWidget *sep1; /* Séparateur #1 */
+ GtkStack *stack; /* Pile de panneaux affichés */
+ GtkWidget *sep2; /* Séparateur #2 */
+
+ GtkTiledPanel *def_panel; /* Eventuel panneau à maintenir*/
};
/* Station de réception pour concentration d'éléments (classe) */
struct _GtkDockStationClass
{
- GtkWidgetClass parent; /* A laisser en premier */
+ GtkBoxClass parent; /* A laisser en premier */
/* Signaux */
- void (* dock_widget) (GtkDockStation *, GtkWidget *);
- void (* undock_widget) (GtkDockStation *, GtkWidget *);
+ void (* panel_docked) (GtkDockStation *, GtkTiledPanel *);
+ void (* panel_undocked) (GtkDockStation *, GtkTiledPanel *);
void (* switch_widget) (GtkDockStation *, GtkWidget *);
diff --git a/src/gtkext/dockstation.c b/src/gtkext/dockstation.c
index 093f120..80bae75 100644
--- a/src/gtkext/dockstation.c
+++ b/src/gtkext/dockstation.c
@@ -28,6 +28,25 @@
+/* --------------------------- INTERFACE DU COMPOSANT GTK --------------------------- */
+
+
+/* Liste des propriétés */
+
+typedef enum _DockStationProperty {
+
+ PROP_0, /* Réservé */
+
+ /* Interface GtkOrientable */
+ PROP_ORIENTATION,
+
+ N_PROPERTIES = PROP_ORIENTATION
+
+} DockStationProperty;
+
+//static GParamSpec *_dock_station_properties[N_PROPERTIES] = { NULL, };
+
+
/* Procède à l'initialisation de l'afficheur concentré. */
static void gtk_dock_station_class_init(GtkDockStationClass *);
@@ -35,16 +54,31 @@ static void gtk_dock_station_class_init(GtkDockStationClass *);
static void gtk_dock_station_init(GtkDockStation *);
/* Supprime toutes les références externes. */
-static void gtk_dock_station_dispose(GtkDockStation *);
+static void gtk_dock_station_dispose(GObject *);
/* Procède à la libération totale de la mémoire. */
-static void gtk_dock_station_finalize(GtkDockStation *);
+static void gtk_dock_station_finalize(GObject *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Met à jour une propriété d'instance GObject. */
+static void gtk_dock_station_set_property(GObject *, guint, const GValue *, GParamSpec *);
+/* Fournit la valeur d'une propriété d'instance GObject. */
+static void gtk_dock_station_get_property(GObject *, guint, GValue *, GParamSpec *);
+/* ---------------------------------------------------------------------------------- */
+/* INTERFACE DU COMPOSANT GTK */
+/* ---------------------------------------------------------------------------------- */
+
+
/* Détermine le type du composant d'affichage concentré. */
-G_DEFINE_TYPE(GtkDockStation, gtk_dock_station, GTK_TYPE_WIDGET)
+G_DEFINE_TYPE(GtkDockStation, gtk_dock_station, GTK_TYPE_GRID)
/******************************************************************************
@@ -62,28 +96,47 @@ G_DEFINE_TYPE(GtkDockStation, gtk_dock_station, GTK_TYPE_WIDGET)
static void gtk_dock_station_class_init(GtkDockStationClass *class)
{
GObjectClass *object; /* Autre version de la classe */
+ GtkWidgetClass *widget; /* Classe de haut niveau */
object = G_OBJECT_CLASS(class);
- object->dispose = (GObjectFinalizeFunc/* ! */)gtk_dock_station_dispose;
- object->finalize = (GObjectFinalizeFunc)gtk_dock_station_finalize;
+ object->dispose = gtk_dock_station_dispose;
+ object->finalize = gtk_dock_station_finalize;
+ object->set_property = gtk_dock_station_set_property;
+ object->get_property = gtk_dock_station_get_property;
- g_signal_new("dock-widget",
+ //g_object_class_install_properties(object, N_PROPERTIES, _dock_station_properties);
+ g_object_class_override_property(object, PROP_ORIENTATION, "orientation");
+
+ widget = GTK_WIDGET_CLASS(class);
+
+ gtk_widget_class_set_template_from_resource(widget, "/re/chrysalide/framework/gtkext/dockstation.ui");
+
+ //gtk_widget_class_bind_template_callback_full(widget, BUILDER_CB(gtk_status_stack_on_zoom_icon_press));
+
+ gtk_widget_class_bind_template_child(widget, GtkDockStation, tabs);
+ gtk_widget_class_bind_template_child(widget, GtkDockStation, toolbar);
+ gtk_widget_class_bind_template_child(widget, GtkDockStation, sep1);
+ gtk_widget_class_bind_template_child(widget, GtkDockStation, stack);
+ gtk_widget_class_bind_template_child(widget, GtkDockStation, sep2);
+
+ g_signal_new("panel-docked",
GTK_TYPE_DOCK_STATION,
G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET(GtkDockStationClass, dock_widget),
+ G_STRUCT_OFFSET(GtkDockStationClass, panel_docked),
NULL, NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1, GTK_TYPE_WIDGET);
- g_signal_new("undock-widget",
+ g_signal_new("panel-undocked",
GTK_TYPE_DOCK_STATION,
G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET(GtkDockStationClass, undock_widget),
+ G_STRUCT_OFFSET(GtkDockStationClass, panel_undocked),
NULL, NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1, GTK_TYPE_WIDGET);
+ /*
g_signal_new("switch-widget",
GTK_TYPE_DOCK_STATION,
G_SIGNAL_RUN_LAST,
@@ -107,6 +160,7 @@ static void gtk_dock_station_class_init(GtkDockStationClass *class)
NULL, NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1, GTK_TYPE_WIDGET);
+ */
}
@@ -125,57 +179,66 @@ static void gtk_dock_station_class_init(GtkDockStationClass *class)
static void gtk_dock_station_init(GtkDockStation *station)
{
-#if 0
+ gtk_widget_init_template(GTK_WIDGET(station));
- GtkNotebook *notebook; /* Autre version du composant */
- GtkWidget *hbox; /* Division supérieure */
- GtkWidget *button; /* Bouton de contrôle */
+ station->orientation = GTK_ORIENTATION_HORIZONTAL;
- notebook = GTK_NOTEBOOK(station);
+ station->def_panel = NULL;
- gtk_notebook_set_show_border(notebook, FALSE);
- gtk_notebook_set_scrollable(notebook, TRUE);
+}
- /* Définition de la zone de contrôle */
- hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
- gtk_widget_set_valign(hbox, GTK_ALIGN_CENTER);
- gtk_widget_set_margin_end(hbox, 8);
- gtk_widget_show(hbox);
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
- button = qck_create_toggle_button_with_named_img(G_OBJECT(station), "search",
- "edit-find-symbolic", GTK_ICON_SIZE_MENU, NULL,
- G_CALLBACK(on_toggle_revealer), station);
- gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
- gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
+static void gtk_dock_station_dispose(GObject *object)
+{
+ GtkDockStation *station; /* Version spécialisée */
- button = qck_create_button_with_named_img(G_OBJECT(station), "menu",
- "go-down-symbolic", GTK_ICON_SIZE_MENU, NULL,
- G_CALLBACK(on_click_for_menu), station);
- gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
- gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
+ station = GTK_DOCK_STATION(object);
- button = qck_create_button_with_named_img(G_OBJECT(station), "close",
- "window-close-symbolic", GTK_ICON_SIZE_MENU, NULL,
- G_CALLBACK(on_click_for_close), station);
- gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
- gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
+ gtk_widget_dispose_template(GTK_WIDGET(object), GTK_TYPE_DOCK_STATION);
- gtk_notebook_set_action_widget(notebook, hbox, GTK_PACK_END);
+ g_clear_object(&station->def_panel);
- g_signal_connect(notebook, "switch-page",
- G_CALLBACK(gtk_dock_station_switch_panel), station);
+ G_OBJECT_CLASS(gtk_dock_station_parent_class)->dispose(object);
-#endif
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_dock_station_finalize(GObject *object)
+{
+ G_OBJECT_CLASS(gtk_dock_station_parent_class)->finalize(object);
}
/******************************************************************************
* *
-* Paramètres : station = instance d'objet GLib à traiter. *
+* Paramètres : - *
* *
-* Description : Supprime toutes les références externes. *
+* Description : Crée un nouveau composant pour support d'affichage concentré.*
* *
* Retour : - *
* *
@@ -183,18 +246,23 @@ static void gtk_dock_station_init(GtkDockStation *station)
* *
******************************************************************************/
-static void gtk_dock_station_dispose(GtkDockStation *station)
+GtkWidget *gtk_dock_station_new(void)
{
- G_OBJECT_CLASS(gtk_dock_station_parent_class)->dispose(G_OBJECT(station));
+ GtkWidget *result; /* Instance à retourner */
+
+ result = g_object_new(GTK_TYPE_DOCK_STATION, NULL);
+
+ return result;
}
/******************************************************************************
* *
-* Paramètres : station = instance d'objet GLib à traiter. *
+* Paramètres : station = station d'accueil pour panneaux à compléter. *
+* panel = nouveau panneau à afficher. *
* *
-* Description : Procède à la libération totale de la mémoire. *
+* Description : Ajoute un panneau à un groupe de tuiles. *
* *
* Retour : - *
* *
@@ -202,18 +270,33 @@ static void gtk_dock_station_dispose(GtkDockStation *station)
* *
******************************************************************************/
-static void gtk_dock_station_finalize(GtkDockStation *station)
+void gtk_dock_station_add_panel(GtkDockStation *station, GtkTiledPanel *panel)
{
- G_OBJECT_CLASS(gtk_dock_station_parent_class)->finalize(G_OBJECT(station));
+ GtkStackPage *page; /* Nouvelle page insérée */
+
+ page = gtk_stack_add_child(station->stack, GTK_WIDGET(panel));
+
+ if (0) // TODO
+ gtk_stack_page_set_title(page, "settings");
+
+ else
+ gtk_stack_page_set_icon_name(page, "logs-symbolic");
+
+ gtk_stack_set_visible_child(station->stack, GTK_WIDGET(panel));
+
+
+ g_signal_emit_by_name(station, "panel-docked", panel);
+
}
/******************************************************************************
* *
-* Paramètres : - *
+* Paramètres : station = station d'accueil pour panneaux à compléter. *
+* panel = nouveau panneau à afficher. *
* *
-* Description : Crée un nouveau composant pour support d'affichage concentré.*
+* Description : Ajoute un panneau à conserver à un groupe de tuiles. *
* *
* Retour : - *
* *
@@ -221,17 +304,300 @@ static void gtk_dock_station_finalize(GtkDockStation *station)
* *
******************************************************************************/
-GtkWidget *gtk_dock_station_new(void)
+void gtk_dock_station_keep_panel(GtkDockStation *station, GtkTiledPanel *panel)
{
- GtkWidget *result; /* Instance à retourner */
+ bool visible; /* Visibilité des barres */
- result = g_object_new(GTK_TYPE_DOCK_STATION, NULL);
+ g_clear_object(&station->def_panel);
+
+ if (panel != NULL)
+ {
+ station->def_panel = panel;
+ ref_object(panel);
+
+ if (gtk_stack_get_page(station->stack, GTK_WIDGET(panel)) == NULL)
+ gtk_dock_station_add_panel(station, panel);
+
+ }
+
+ visible = (station->def_panel == NULL);
+
+ gtk_widget_set_visible(station->tabs, visible);
+ gtk_widget_set_visible(station->toolbar, visible);
+ gtk_widget_set_visible(station->sep1, visible);
+ gtk_widget_set_visible(station->sep2, visible && station->orientation == GTK_ORIENTATION_HORIZONTAL);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : station = station d'accueil pour panneaux à consulter. *
+* *
+* Description : Indique si la station d'accueil contient au moins un panneau.*
+* *
+* Retour : true si aucun panneau n'est intégré, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool gtk_dock_station_is_empty(const GtkDockStation *station)
+{
+ bool result; /* Bilan à retourner */
+ GtkSelectionModel *model; /* Modèle pour la pile */
+ guint count; /* Nombre de panneaux présents */
+
+ model = gtk_stack_get_pages(station->stack);
+
+ count = g_list_model_get_n_items(G_LIST_MODEL(model));
+
+ result = (count == 0);
+
+ unref_object(model);
return result;
}
+/******************************************************************************
+* *
+* 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 */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* 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 : - *
+* *
+******************************************************************************/
+
+static void gtk_dock_station_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+ GtkDockStation *station; /* Version spécialisée */
+ GtkOrientation orientation; /* Spécification d'orientation */
+ GtkLayoutManager *layout; /* Gestionnaire de disposition */
+ GtkLayoutChild *child_layout; /* Disposition de composant */
+
+ station = GTK_DOCK_STATION(object);
+
+ switch (prop_id)
+ {
+ case PROP_ORIENTATION:
+
+ orientation = g_value_get_enum(value);
+
+ if (station->orientation != orientation)
+ {
+ station->orientation = orientation;
+
+ gtk_orientable_set_orientation(GTK_ORIENTABLE(station->tabs), orientation);
+ gtk_orientable_set_orientation(GTK_ORIENTABLE(station->toolbar), orientation);
+
+ layout = gtk_widget_get_layout_manager(GTK_WIDGET(object));
+
+ if (orientation == GTK_ORIENTATION_VERTICAL)
+ {
+ g_object_set(G_OBJECT(station->tabs),
+ "halign", GTK_ALIGN_START,
+ "valign", GTK_ALIGN_CENTER,
+ NULL);
+
+ g_object_set(G_OBJECT(station->toolbar),
+ "halign", GTK_ALIGN_END,
+ "valign", GTK_ALIGN_CENTER,
+ NULL);
+
+ child_layout = gtk_layout_manager_get_layout_child(layout, station->toolbar);
+
+ g_object_set(G_OBJECT(child_layout),
+ "column", 1,
+ "row", 0,
+ NULL);
+
+ child_layout = gtk_layout_manager_get_layout_child(layout, station->sep1);
+
+ g_object_set(G_OBJECT(child_layout),
+ "column", 0,
+ "row", 1,
+ "column-span", 2,
+ NULL);
+
+ gtk_widget_set_visible(station->sep2, FALSE);
+
+ child_layout = gtk_layout_manager_get_layout_child(layout, GTK_WIDGET(station->stack));
+
+ g_object_set(G_OBJECT(child_layout),
+ "column", 0,
+ "row", 2,
+ "column-span", 2,
+ NULL);
+
+ }
+ else
+ {
+ g_object_set(G_OBJECT(station->tabs),
+ "halign", GTK_ALIGN_START,
+ "valign", GTK_ALIGN_START,
+ NULL);
+
+ g_object_set(G_OBJECT(station->toolbar),
+ "halign", GTK_ALIGN_END,
+ "valign", GTK_ALIGN_START,
+ NULL);
+
+ child_layout = gtk_layout_manager_get_layout_child(layout, station->sep1);
+
+ g_object_set(G_OBJECT(child_layout),
+ "column", 1,
+ "row", 0,
+ "column-span", 1,
+ NULL);
+
+ child_layout = gtk_layout_manager_get_layout_child(layout, GTK_WIDGET(station->stack));
+
+ g_object_set(G_OBJECT(child_layout),
+ "column", 2,
+ "row", 0,
+ "column-span", 1,
+ NULL);
+
+ gtk_widget_set_visible(station->sep2, TRUE);
+
+ child_layout = gtk_layout_manager_get_layout_child(layout, station->sep2);
+
+ g_object_set(G_OBJECT(child_layout),
+ "column", 3,
+ "row", 0,
+ NULL);
+
+ child_layout = gtk_layout_manager_get_layout_child(layout, station->toolbar);
+
+ g_object_set(G_OBJECT(child_layout),
+ "column", 4,
+ "row", 0,
+ NULL);
+
+ }
+
+ g_object_notify_by_pspec(object, pspec);
+
+ }
+
+ 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_dock_station_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+ GtkDockStation *station; /* Version spécialisée */
+
+ station = GTK_DOCK_STATION(object);
+
+ switch (prop_id)
+ {
+ case PROP_ORIENTATION:
+ g_value_set_enum(value, station->orientation);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ break;
+
+ }
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/gtkext/dockstation.h b/src/gtkext/dockstation.h
index a857626..e4c849f 100644
--- a/src/gtkext/dockstation.h
+++ b/src/gtkext/dockstation.h
@@ -28,6 +28,7 @@
#include <gtk/gtk.h>
+#include "panel.h"
#include "../glibext/helpers.h"
@@ -40,7 +41,17 @@ DECLARE_GTYPE(GtkDockStation, gtk_dock_station, GTK, DOCK_STATION);
/* Crée un nouveau composant pour support d'affichage concentré. */
GtkWidget *gtk_dock_station_new(void);
+/* Ajoute un panneau à un groupe de tuiles. */
+void gtk_dock_station_add_panel(GtkDockStation *, GtkTiledPanel *);
+/* Ajoute un panneau à conserver à un groupe de tuiles. */
+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);
diff --git a/src/gtkext/dockstation.ui b/src/gtkext/dockstation.ui
new file mode 100644
index 0000000..4d25134
--- /dev/null
+++ b/src/gtkext/dockstation.ui
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="GtkDockStation" parent="GtkGrid">
+ <property name="orientation">horizontal</property>
+
+ <child>
+ <object class="GtkStackSwitcher" id="tabs">
+ <property name="orientation">horizontal</property>
+ <property name="halign">start</property>
+ <property name="valign">start</property>
+ <property name="margin-start">2</property>
+ <property name="margin-top">2</property>
+ <property name="margin-end">2</property>
+ <property name="margin-bottom">2</property>
+ <property name="stack">stack</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkBox" id="toolbar">
+ <property name="orientation">horizontal</property>
+ <property name="halign">end</property>
+ <property name="valign">start</property>
+
+ <child>
+ <object class="GtkButton">
+ <property name="icon-name">window-close-symbolic</property>
+ <style>
+ <class name="circular"/>
+ <class name="flat"/>
+ <class name="control-button"/>
+ </style>
+ </object>
+ </child>
+
+ <layout>
+ <property name="column">4</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkSeparator" id="sep1">
+ <property name="orientation">horizontal</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ <property name="column-span">1</property>
+ </layout>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkStack" id="stack">
+ <property name="hexpand">true</property>
+ <layout>
+ <property name="column">2</property>
+ <property name="row">0</property>
+ <property name="column-span">1</property>
+ </layout>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkSeparator" id="sep2">
+ <property name="orientation">horizontal</property>
+ <layout>
+ <property name="column">3</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+
+ </template>
+</interface>
diff --git a/src/gtkext/gresource.xml b/src/gtkext/gresource.xml
index 640985f..26943a6 100644
--- a/src/gtkext/gresource.xml
+++ b/src/gtkext/gresource.xml
@@ -1,6 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/re/chrysalide/framework/gtkext">
+ <file compressed="true">dockstation.ui</file>
+ <file compressed="true">grid.ui</file>
<file compressed="true">hexview.css</file>
<file compressed="true">hexview.ui</file>
<file compressed="true">launcher.ui</file>
diff --git a/src/gtkext/grid-int.h b/src/gtkext/grid-int.h
index 5ae48ad..8a2702b 100644
--- a/src/gtkext/grid-int.h
+++ b/src/gtkext/grid-int.h
@@ -25,46 +25,50 @@
#define _GTKEXT_GRID_INT_H
+#include "dockstation.h"
#include "grid.h"
-/* -------------------------- GESTION DES TUILES AFFICHEES -------------------------- */
-
-
-/* Informations concernant une tuile */
-typedef struct _grid_tile_t
+/* Conteneur pour un affichage en tuiles nommées (instance) */
+struct _GtkTilingGrid
{
- struct _grid_tile_t *parent; /* Tuile parente */
+ GtkGrid parent; /* A laisser en premier */
- GtkWidget *widget; /* Support d'affichage */
+ GSettings *settings; /* Configuration du conteneur */
- char *path; /* Chemin d'accès */
+ LayoutReachOptions layout; /* Disposition générale */
- struct _grid_tile_t *children[2]; /* Tuiles encastrées ou 2xNULL */
+ bool visible[TGB_COUNT]; /* Visibilités souhaitées */
-} grid_tile_t;
+ GtkRevealer *top; /* Zone d'accueil #1 */
+ GtkWidget *top_handle; /* Poignée de redimensionnement*/
+ GtkDockStation *top_station; /* Station entière */
+ GtkRevealer *left; /* Zone d'accueil #2 */
+ GtkWidget *left_handle; /* Poignée de redimensionnement*/
+ GtkDockStation *left_station; /* Station entière */
+ GtkDockStation *main_station; /* Zone d'accueil #3 */
-/* --------------------------- INTERFACE DU COMPOSANT GTK --------------------------- */
+ GtkRevealer *right; /* Zone d'accueil #4 */
+ GtkWidget *right_handle; /* Poignée de redimensionnement*/
+ GtkDockStation *right_station; /* Station entière */
+ GtkRevealer *bottom; /* Zone d'accueil #5 */
+ GtkWidget *bottom_handle; /* Poignée de redimensionnement*/
+ GtkDockStation *bottom_station; /* Station entière */
-/* Conteneur pour un affichage en tuiles nommées (instance) */
-struct _GtkTilingGrid
-{
- GtkWidget parent; /* A laisser en premier */
-
- grid_tile_t *tiles; /* Tuiles représentées */
+ GtkGesture *tpad_gesture[TGB_COUNT]; /* Gestionnaires du touchpad */
- GtkTiledPanel *def_panel; /* Panneau principal par défaut*/
+ bool panning; /* Redimensionnement en cours */
};
/* Conteneur pour un affichage en tuiles nommées (classe) */
struct _GtkTilingGridClass
{
- GtkWidgetClass parent; /* A laisser en premier */
+ GtkGridClass parent; /* A laisser en premier */
/* Signaux */
diff --git a/src/gtkext/grid.c b/src/gtkext/grid.c
index 1b9c909..eb3cdf9 100644
--- a/src/gtkext/grid.c
+++ b/src/gtkext/grid.c
@@ -24,29 +24,43 @@
#include "grid.h"
+#include <assert.h>
+#include <malloc.h>
+#include <string.h>
+
+
#include "grid-int.h"
+#include "helpers.h"
+#include "bindings/grid-enums.h"
+
+/* --------------------------- INTERFACE DU COMPOSANT GTK --------------------------- */
-/* -------------------------- GESTION DES TUILES AFFICHEES -------------------------- */
+/* Liste des propriétés */
+typedef enum _TilingGridProperty {
-#define IS_LEAF_TILE(t) \
- ({ \
- bool __result; \
- __result = GTK_IS_DOCK_STATION((t)->widget); \
- assert(__result || GTK_IS_PANED((t)->widget)); \
- __result; \
- })
+ PROP_0, /* Réservé */
+ PROP_LAYOUT, /* Disposition générale */
-/* Supprime une tuile de la mémoire. */
-static void delete_tile(grid_tile_t *);
+ PROP_EMPTY_TOP, /* Vide de la zone supérieure */
+ PROP_EMPTY_LEFT, /* Vide de la zone de gauche */
+ PROP_EMPTY_RIGHT, /* Vide de la zone de droite */
+ PROP_EMPTY_BOTTOM, /* Vide de la zone inférieure */
+ PROP_VISIBLE_TOP, /* Visibilité de zone sup. */
+ PROP_VISIBLE_LEFT, /* Visibilité de zone de gauche*/
+ PROP_VISIBLE_RIGHT, /* Visibilité de zone de droite*/
+ PROP_VISIBLE_BOTTOM, /* Visibilité de zone inf. */
+ N_PROPERTIES
-/* --------------------------- INTERFACE DU COMPOSANT GTK --------------------------- */
+} TilingGridProperty;
+
+static GParamSpec *_tiling_grid_properties[N_PROPERTIES] = { NULL, };
/* Initialise la classe des conteneurs d'affichage en tuiles. */
@@ -56,48 +70,50 @@ static void gtk_tiling_grid_class_init(GtkTilingGridClass *);
static void gtk_tiling_grid_init(GtkTilingGrid *);
/* Supprime toutes les références externes. */
-static void gtk_tiling_grid_dispose(GtkTilingGrid *);
+static void gtk_tiling_grid_dispose(GObject *);
/* Procède à la libération totale de la mémoire. */
-static void gtk_tiling_grid_finalize(GtkTilingGrid *);
+static void gtk_tiling_grid_finalize(GObject *);
+/* Réagit à une intégration ou à un retrait de panneau. */
+static void gtk_tiling_grid_on_panel_un_docked(GtkDockStation *, GtkTiledPanel *, GtkTilingGrid *);
+/* -------------------- REDIMENSIONNEMENT DE ZONES POUR PANNEAUX -------------------- */
-/* ---------------------------------------------------------------------------------- */
-/* GESTION DES TUILES AFFICHEES */
-/* ---------------------------------------------------------------------------------- */
+/* Initie un redimensionnement par drag-and-drop. */
+static void gtk_tiling_grid_on_gesture_drag_begin(GtkGestureDrag *, double, double, GtkTilingGrid *);
-/******************************************************************************
-* *
-* Paramètres : tile = tuile à supprimer. *
-* *
-* Description : Supprime une tuile de la mémoire. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+/* Applique l'effet d'un redimensionnement drag-and-drop donné. */
+static void gtk_tiling_grid_on_gesture_drag_update(GtkTilingGrid *, TilingGridBorder, double, double);
-static void delete_tile(grid_tile_t *tile)
-{
- if (!IS_LEAF_TILE(tile))
- {
- delete_tile(tile->children[0]);
- delete_tile(tile->children[1]);
- }
+/* Actualise l'effet d'un redimensionnement drag-and-drop. */
+static void gtk_tiling_grid_on_top_gesture_drag_update(GtkGestureDrag *, double, double, GtkTilingGrid *);
- else
- free(tile->path);
+/* Actualise l'effet d'un redimensionnement drag-and-drop. */
+static void gtk_tiling_grid_on_left_gesture_drag_update(GtkGestureDrag *, double, double, GtkTilingGrid *);
- unref_object(tile->widget);
+/* Actualise l'effet d'un redimensionnement drag-and-drop. */
+static void gtk_tiling_grid_on_right_gesture_drag_update(GtkGestureDrag *, double, double, GtkTilingGrid *);
- free(tile);
+/* Actualise l'effet d'un redimensionnement drag-and-drop. */
+static void gtk_tiling_grid_on_bottom_gesture_drag_update(GtkGestureDrag *, double, double, GtkTilingGrid *);
-}
+/* Clôture un drag-and-drop de redimensionnement. */
+static void gtk_tiling_grid_on_gesture_drag_end(GtkGestureDrag *, double, double, GtkTilingGrid *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Met à jour une propriété d'instance GObject. */
+static void gtk_tiling_grid_set_property(GObject *, guint, const GValue *, GParamSpec *);
+
+/* Fournit la valeur d'une propriété d'instance GObject. */
+static void gtk_tiling_grid_get_property(GObject *, guint, GValue *, GParamSpec *);
@@ -107,12 +123,12 @@ static void delete_tile(grid_tile_t *tile)
/* Détermine le type du conteneur d'affichage en tuiles nommées. */
-G_DEFINE_TYPE(GtkTilingGrid, gtk_tiling_grid, GTK_TYPE_WIDGET)
+G_DEFINE_TYPE(GtkTilingGrid, gtk_tiling_grid, GTK_TYPE_GRID)
/******************************************************************************
* *
-* Paramètres : klass = classe GTK à initialiser. *
+* Paramètres : class = classe GTK à initialiser. *
* *
* Description : Initialise la classe des conteneurs d'affichage en tuiles. *
* *
@@ -122,14 +138,101 @@ G_DEFINE_TYPE(GtkTilingGrid, gtk_tiling_grid, GTK_TYPE_WIDGET)
* *
******************************************************************************/
-static void gtk_tiling_grid_class_init(GtkTilingGridClass *klass)
+static void gtk_tiling_grid_class_init(GtkTilingGridClass *class)
{
GObjectClass *object; /* Autre version de la classe */
+ GtkWidgetClass *widget; /* Classe de haut niveau */
+
+ object = G_OBJECT_CLASS(class);
+
+ object->dispose = gtk_tiling_grid_dispose;
+ object->finalize = gtk_tiling_grid_finalize;
+ object->set_property = gtk_tiling_grid_set_property;
+ object->get_property = gtk_tiling_grid_get_property;
+
+ _tiling_grid_properties[PROP_LAYOUT] =
+ g_param_spec_flags("layout", NULL, NULL,
+ LAYOUT_REACH_OPTIONS_TYPE,
+ LRO_NONE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
+
+ _tiling_grid_properties[PROP_EMPTY_TOP] =
+ g_param_spec_boolean("empty-top", NULL, NULL,
+ TRUE,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
+
+ _tiling_grid_properties[PROP_EMPTY_LEFT] =
+ g_param_spec_boolean("empty-left", NULL, NULL,
+ TRUE,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
+
+ _tiling_grid_properties[PROP_EMPTY_RIGHT] =
+ g_param_spec_boolean("empty-right", NULL, NULL,
+ TRUE,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
+
+ _tiling_grid_properties[PROP_EMPTY_BOTTOM] =
+ g_param_spec_boolean("empty-bottom", NULL, NULL,
+ TRUE,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
+
+ /**
+ * La valeur initiale des champs suivants est à maintenir synchronisée avec
+ * les initialisations de gtk_tiling_grid_init().
+ */
+
+ _tiling_grid_properties[PROP_VISIBLE_TOP] =
+ g_param_spec_boolean("visible-top", NULL, NULL,
+ TRUE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
+
+ _tiling_grid_properties[PROP_VISIBLE_LEFT] =
+ g_param_spec_boolean("visible-left", NULL, NULL,
+ TRUE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
+
+ _tiling_grid_properties[PROP_VISIBLE_RIGHT] =
+ g_param_spec_boolean("visible-right", NULL, NULL,
+ TRUE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
+
+ _tiling_grid_properties[PROP_VISIBLE_BOTTOM] =
+ g_param_spec_boolean("visible-bottom", NULL, NULL,
+ TRUE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
+
+ g_object_class_install_properties(object, N_PROPERTIES, _tiling_grid_properties);
+
+ widget = GTK_WIDGET_CLASS(class);
+
+ g_type_ensure(GTK_TYPE_DOCK_STATION);
- object = G_OBJECT_CLASS(klass);
+ gtk_widget_class_set_template_from_resource(widget, "/re/chrysalide/framework/gtkext/grid.ui");
- object->dispose = (GObjectFinalizeFunc/* ! */)gtk_tiling_grid_dispose;
- object->finalize = (GObjectFinalizeFunc)gtk_tiling_grid_finalize;
+ gtk_widget_class_bind_template_callback_full(widget, BUILDER_CB(gtk_tiling_grid_on_panel_un_docked));
+ gtk_widget_class_bind_template_callback_full(widget, BUILDER_CB(gtk_tiling_grid_on_gesture_drag_begin));
+ gtk_widget_class_bind_template_callback_full(widget, BUILDER_CB(gtk_tiling_grid_on_top_gesture_drag_update));
+ gtk_widget_class_bind_template_callback_full(widget, BUILDER_CB(gtk_tiling_grid_on_left_gesture_drag_update));
+ gtk_widget_class_bind_template_callback_full(widget, BUILDER_CB(gtk_tiling_grid_on_right_gesture_drag_update));
+ gtk_widget_class_bind_template_callback_full(widget, BUILDER_CB(gtk_tiling_grid_on_bottom_gesture_drag_update));
+ gtk_widget_class_bind_template_callback_full(widget, BUILDER_CB(gtk_tiling_grid_on_gesture_drag_end));
+
+ gtk_widget_class_bind_template_child(widget, GtkTilingGrid, top);
+ gtk_widget_class_bind_template_child(widget, GtkTilingGrid, top_handle);
+ gtk_widget_class_bind_template_child(widget, GtkTilingGrid, top_station);
+ gtk_widget_class_bind_template_child(widget, GtkTilingGrid, left);
+ gtk_widget_class_bind_template_child(widget, GtkTilingGrid, left_handle);
+ gtk_widget_class_bind_template_child(widget, GtkTilingGrid, left_station);
+ gtk_widget_class_bind_template_child(widget, GtkTilingGrid, main_station);
+ gtk_widget_class_bind_template_child(widget, GtkTilingGrid, right);
+ gtk_widget_class_bind_template_child(widget, GtkTilingGrid, right_handle);
+ gtk_widget_class_bind_template_child(widget, GtkTilingGrid, right_station);
+ gtk_widget_class_bind_template_child(widget, GtkTilingGrid, bottom);
+ gtk_widget_class_bind_template_child(widget, GtkTilingGrid, bottom_handle);
+ gtk_widget_class_bind_template_child(widget, GtkTilingGrid, bottom_station);
+
+
+ /////////////
g_signal_new("station-created",
GTK_TYPE_TILING_GRID,
@@ -144,7 +247,7 @@ static void gtk_tiling_grid_class_init(GtkTilingGridClass *klass)
/******************************************************************************
* *
-* Paramètres : tgrid = instance GTK à initialiser. *
+* Paramètres : grid = instance GTK à initialiser. *
* *
* Description : Initialise une instance de conteneur d'affichage en tuiles. *
* *
@@ -154,18 +257,70 @@ static void gtk_tiling_grid_class_init(GtkTilingGridClass *klass)
* *
******************************************************************************/
-static void gtk_tiling_grid_init(GtkTilingGrid *tgrid)
+static void gtk_tiling_grid_init(GtkTilingGrid *grid)
{
- tgrid->tiles = NULL;
+ gtk_widget_init_template(GTK_WIDGET(grid));
+
+ grid->settings = g_settings_new_with_path("re.chrysalide.framework.tiledgrid",
+ "/re/chrysalide/framework/gui/tiles/");
+
+ g_settings_bind(grid->settings, "layout",
+ grid, "layout",
+ G_SETTINGS_BIND_DEFAULT);
+
+ /**
+ * L'initialisation des champs suivants est à maintenir synchronisée avec
+ * les valeurs initiales de gtk_tiling_grid_class_init().
+ */
+
+ grid->visible[TGB_TOP] = true;
+ grid->visible[TGB_LEFT] = true;
+ grid->visible[TGB_RIGHT] = true;
+ grid->visible[TGB_BOTTOM] = true;
+
+ g_settings_bind(grid->settings, "top-request",
+ grid->top_station, "height-request",
+ G_SETTINGS_BIND_DEFAULT);
+
+ g_settings_bind(grid->settings, "top-visibility",
+ grid, "visible-top",
+ G_SETTINGS_BIND_DEFAULT);
+
+ g_settings_bind(grid->settings, "left-request",
+ grid->left_station, "width-request",
+ G_SETTINGS_BIND_DEFAULT);
- tgrid->def_panel = NULL;
+ g_settings_bind(grid->settings, "left-visibility",
+ grid, "visible-left",
+ G_SETTINGS_BIND_DEFAULT);
+
+ g_settings_bind(grid->settings, "right-request",
+ grid->right_station, "width-request",
+ G_SETTINGS_BIND_DEFAULT);
+
+ g_settings_bind(grid->settings, "right-visibility",
+ grid, "visible-right",
+ G_SETTINGS_BIND_DEFAULT);
+
+ g_settings_bind(grid->settings, "bottom-request",
+ grid->bottom_station, "height-request",
+ G_SETTINGS_BIND_DEFAULT);
+
+ g_settings_bind(grid->settings, "bottom-visibility",
+ grid, "visible-bottom",
+ G_SETTINGS_BIND_DEFAULT);
+
+ gtk_widget_set_cursor_from_name(grid->top_handle, "row-resize");
+ gtk_widget_set_cursor_from_name(grid->left_handle, "col-resize");
+ gtk_widget_set_cursor_from_name(grid->right_handle, "col-resize");
+ gtk_widget_set_cursor_from_name(grid->bottom_handle, "row-resize");
}
/******************************************************************************
* *
-* Paramètres : grid = instance d'objet GLib à traiter. *
+* Paramètres : object = instance d'objet GLib à traiter. *
* *
* Description : Supprime toutes les références externes. *
* *
@@ -175,24 +330,24 @@ static void gtk_tiling_grid_init(GtkTilingGrid *tgrid)
* *
******************************************************************************/
-static void gtk_tiling_grid_dispose(GtkTilingGrid *grid)
+static void gtk_tiling_grid_dispose(GObject *object)
{
- if (grid->tiles != NULL)
- {
- delete_tile(grid->tiles);
- grid->tiles = NULL;
- }
+ GtkTilingGrid *grid; /* Version spécialisée */
+
+ gtk_widget_dispose_template(GTK_WIDGET(object), GTK_TYPE_DOCK_STATION);
+
+ grid = GTK_TILING_GRID(object);
- g_clear_object(&grid->def_panel);
+ g_clear_object(&grid->settings);
- G_OBJECT_CLASS(gtk_tiling_grid_parent_class)->dispose(G_OBJECT(grid));
+ G_OBJECT_CLASS(gtk_tiling_grid_parent_class)->dispose(object);
}
/******************************************************************************
* *
-* Paramètres : grid = instance d'objet GLib à traiter. *
+* Paramètres : object = instance d'objet GLib à traiter. *
* *
* Description : Procède à la libération totale de la mémoire. *
* *
@@ -202,9 +357,9 @@ static void gtk_tiling_grid_dispose(GtkTilingGrid *grid)
* *
******************************************************************************/
-static void gtk_tiling_grid_finalize(GtkTilingGrid *grid)
+static void gtk_tiling_grid_finalize(GObject *object)
{
- G_OBJECT_CLASS(gtk_tiling_grid_parent_class)->finalize(G_OBJECT(grid));
+ G_OBJECT_CLASS(gtk_tiling_grid_parent_class)->finalize(object);
}
@@ -232,142 +387,80 @@ GtkWidget *gtk_tiling_grid_new(void)
}
-
-
-
-
-#if 0
-
-
-#include <assert.h>
-#include <ctype.h>
-#include <malloc.h>
-#include <string.h>
-
-
-#include "../core/logs.h"
-
-
-
-/* Valide un chemin d'accès à une tuile. */
-static bool is_valid_tile_path(const char *);
-
-/* Crée une tuile finale d'affichage de panneaux. */
-static grid_tile_t *create_leaf_tile(const char *, GtkTiledGrid *);
-
-/* Crée une tuile intermédiaire d'affichage de panneaux. */
-static grid_tile_t *create_inter_tile(grid_tile_t *, bool, grid_tile_t *, grid_tile_t *);
-
-/* Supprime une tuile de la mémoire. */
-//static void delete_tile(grid_tile_t *);
-
-/* Calcule la taille comme entre un chemin et celui d'une tuile. */
-static size_t compute_tile_score(const grid_tile_t *, const char *);
-
-/* Indique la tuile adaptée pour un chemin donné. */
-static grid_tile_t *find_suitable_tile(grid_tile_t **, const char *, GtkTiledGrid *);
-
-/* Découpe une tuile pour y insérer une zone. */
-static grid_tile_t *split_tile(grid_tile_t **, const char *, char, GtkTiledGrid *);
-
-/* Tente de mettre la main sur une station d'accueil. */
-static grid_tile_t *find_tile_for_widget(grid_tile_t *, GtkWidget *);
-
-/* Retire une moitié de tuile vide au plein profit de l'autre. */
-static void collapse_tile(grid_tile_t *, grid_tile_t *);
-
-
-
-/* --------------------------- INTERFACE DU COMPOSANT GTK --------------------------- */
-
-
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* GESTION DES TUILES AFFICHEES */
-/* ---------------------------------------------------------------------------------- */
-
-
/******************************************************************************
* *
-* Paramètres : path = chemin destiné à sélectionner une tuile. *
+* Paramètres : grid = zone d'affichage en tuiles à manipuler. *
+* border = sélection de la zone à considérer. *
+* visible = nouveau statut de visibilité à appliquer. *
* *
-* Description : Valide un chemin d'accès à une tuile. *
+* Description : Affiche ou masque une zone du conteneur en tuiles. *
* *
-* Retour : true si le chemin est utilisable, false sinon. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-static bool is_valid_tile_path(const char *path)
+void gtk_tiling_grid_set_visible(GtkTilingGrid *grid, TilingGridBorder border, bool visible)
{
- bool result; /* Bilan à retourner */
- size_t len; /* Taille du chemin */
- size_t i; /* Boucle de parcours */
- char c; /* Caractère de chemin analysé */
-
- /**
- * M[NESWnesw]*
- */
-
- len = strlen(path);
+ GtkRevealer *revealer; /* Cible visée par l'opération */
+ GtkDockStation *station; /* Apport d'une contrainte */
- result = (len >= 1);
+ if (grid->visible[border] != visible)
+ {
+ grid->visible[border] = visible;
- if (result)
- result = (path[0] == 'M');
+ switch (border)
+ {
+ case TGB_TOP:
+ revealer = grid->top;
+ station = grid->top_station;
+ break;
+
+ case TGB_LEFT:
+ revealer = grid->left;
+ station = grid->left_station;
+ break;
+
+ case TGB_RIGHT:
+ revealer = grid->right;
+ station = grid->right_station;
+ break;
+
+ case TGB_BOTTOM:
+ revealer = grid->bottom;
+ station = grid->bottom_station;
+ break;
- for (i = 1; i < len && result; i++)
- {
- c = path[i];
+ }
- if (c == '\0')
- break;
+ gtk_revealer_set_reveal_child(revealer, visible && !gtk_dock_station_is_empty(station));
- result = (c == 'N' || c == 'n'
- || c == 'E' || c == 'e'
- || c == 'S' || c == 's'
- || c == 'W' || c == 'w');
+ g_object_notify_by_pspec(G_OBJECT(grid), _tiling_grid_properties[PROP_VISIBLE_TOP + border]);
}
- return result;
-
}
/******************************************************************************
* *
-* Paramètres : path = chemin d'accès à la future tuile. *
-* tgrid = conteneur d'affichage en tuiles à manipuler. *
+* Paramètres : grid = zone d'affichage en tuiles à manipuler. *
+* border = sélection de la zone à considérer. *
* *
-* Description : Crée une tuile finale d'affichage de panneaux. *
+* Description : Fournit la visibilité d'une zone du conteneur en tuiles. *
* *
-* Retour : Structure mise en place. *
+* Retour : Visibilité de la zone considérée. *
* *
* Remarques : - *
* *
******************************************************************************/
-static grid_tile_t *create_leaf_tile(const char *path, GtkTiledGrid *tgrid)
+bool gtk_tiling_grid_get_visible(GtkTilingGrid *grid, TilingGridBorder border)
{
- grid_tile_t *result; /* Structure à retourner */
-
- result = (grid_tile_t *)malloc(sizeof(grid_tile_t));
-
- result->parent = NULL;
-
- result->widget = gtk_dock_station_new();
- gtk_widget_show(result->widget);
+ bool result; /* Statut à retourner */
- result->path = strdup(path);
-
- result->children[0] = NULL;
- result->children[1] = NULL;
-
- g_signal_emit_by_name(tgrid, "station-created", result->widget);
+ result = grid->visible[border];
return result;
@@ -376,333 +469,307 @@ static grid_tile_t *create_leaf_tile(const char *path, GtkTiledGrid *tgrid)
/******************************************************************************
* *
-* Paramètres : parent = tuile parente ou NULL si aucune. *
-* horiz = indique le type d'orientation désiré. *
-* first = première tuile à intégrer. *
-* second = seconde tuile à intégrer. *
+* Paramètres : grid = zone d'affichage en tuiles à manipuler. *
+* panel = nouveau panneau à afficher. *
+* keep = indique si le panneau est à conserver présent. *
* *
-* Description : Crée une tuile intermédiaire d'affichage de panneaux. *
+* Description : Ajoute un panneau à un conteneur en tuiles. *
* *
-* Retour : Structure mise en place. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-static grid_tile_t *create_inter_tile(grid_tile_t *parent, bool horiz, grid_tile_t *first, grid_tile_t *second)
+void gtk_tiling_grid_add_panel(GtkTilingGrid *grid, GtkTiledPanel *panel, bool keep)
{
- grid_tile_t *result; /* Structure à retourner */
- GtkWidget *container; /* Conteneur à vider */
-
- result = (grid_tile_t *)malloc(sizeof(grid_tile_t));
-
- result->parent = parent;
-
- if (horiz)
- result->widget = gtk_paned_new(GTK_ORIENTATION_HORIZONTAL);
- else
- result->widget = gtk_paned_new(GTK_ORIENTATION_VERTICAL);
+ char *path; /* Chemin visé par le panneau */
+ bool static_path; /* Nature du chemin à traiter */
- gtk_widget_show(result->widget);
+ path = gtk_tiled_panel_get_path(panel);
- result->path = NULL;
+ static_path = (path == NULL);
- result->children[0] = first;
- result->children[1] = second;
+ if (static_path)
+ path = "";
- /* Changement de propriétaire */
+ switch (path[0])
+ {
+ case 'N':
+ if (keep)
+ gtk_dock_station_keep_panel(grid->top_station, panel);
+ else
+ gtk_dock_station_add_panel(grid->top_station, panel);
+ break;
- container = gtk_widget_get_parent(first->widget);
+ case 'W':
+ if (keep)
+ gtk_dock_station_keep_panel(grid->left_station, panel);
+ else
+ gtk_dock_station_add_panel(grid->left_station, panel);
+ break;
- if (container != NULL)
- gtk_container_remove(GTK_CONTAINER(container), first->widget);
+ case '\0':
+ case 'M':
+ if (keep)
+ gtk_dock_station_keep_panel(grid->main_station, panel);
+ else
+ gtk_dock_station_add_panel(grid->main_station, panel);
+ break;
- g_object_ref(G_OBJECT(first->widget));
- gtk_paned_pack1(GTK_PANED(result->widget), first->widget, TRUE, FALSE);
+ case 'E':
+ if (keep)
+ gtk_dock_station_keep_panel(grid->right_station, panel);
+ else
+ gtk_dock_station_add_panel(grid->right_station, panel);
+ break;
- container = gtk_widget_get_parent(second->widget);
+ case 'S':
+ if (keep)
+ gtk_dock_station_keep_panel(grid->bottom_station, panel);
+ else
+ gtk_dock_station_add_panel(grid->bottom_station, panel);
+ break;
- if (container != NULL)
- gtk_container_remove(GTK_CONTAINER(container), second->widget);
+ default:
+ break;
- g_object_ref(G_OBJECT(second->widget));
- gtk_paned_pack2(GTK_PANED(result->widget), second->widget, TRUE, FALSE);
+ }
- return result;
+ if (!static_path)
+ free(path);
}
-
/******************************************************************************
* *
-* Paramètres : tile = tuile à analyser. *
-* path = chemin final complet recherché. *
+* 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 : Calcule la taille comme entre un chemin et celui d'une tuile.*
+* Description : Note un ajout ou un retrait de panneau principal. *
* *
-* Retour : Quantité de caractères communs. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-static size_t compute_tile_score(const grid_tile_t *tile, const char *path)
+void gtk_tiling_grid_notify_new_main_panel_state(const GtkTilingGrid *grid, GtkTiledPanel *main, bool activated)
{
- size_t result; /* Nombre de points à renvoyer */
- size_t max; /* Taille du chemin de la tuile*/
- size_t i; /* Boucle de parcours */
- size_t score_0; /* Score du sous-élément #1 */
- size_t score_1; /* Score du sous-élément #2 */
-
- if (IS_LEAF_TILE(tile))
- {
- max = strlen(tile->path);
-
- if (strlen(path) < max)
- result = 0;
-
- else
- {
- result = 0;
-
- for (i = 0; i < max; i++)
- {
- if (tolower((unsigned char)tile->path[i]) == tolower((unsigned char)path[i]))
- result++;
- else
- break;
- }
+ gtk_dock_station_notify_new_main_panel_state(grid->top_station, main, activated);
- }
-
- }
- else
- {
- score_0 = compute_tile_score(tile->children[0], path);
- score_1 = compute_tile_score(tile->children[1], path);
+ gtk_dock_station_notify_new_main_panel_state(grid->left_station, main, activated);
- result = score_0 > score_1 ? score_0 : score_1;
+ 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);
- return result;
+ gtk_dock_station_notify_new_main_panel_state(grid->bottom_station, main, activated);
}
/******************************************************************************
* *
-* Paramètres : tile = tuile ou NULL si aucune. [OUT] *
-* path = chemin d'accès à la tuile visée. *
-* tgrid = conteneur d'affichage en tuiles à manipuler. *
+* Paramètres : station = plateforme GTK ayant connu un changement. *
+* widget = nouvel élément à intégrer. *
+* grid = gestionnaire de placement en tuile concerné. *
* *
-* Description : Indique la tuile adaptée pour un chemin donné. *
+* Description : Réagit à une intégration ou à un retrait de panneau. *
* *
-* Retour : Structure d'acceuil à disposition. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-static grid_tile_t *find_suitable_tile(grid_tile_t **tile, const char *path, GtkTiledGrid *tgrid)
+static void gtk_tiling_grid_on_panel_un_docked(GtkDockStation *station, GtkTiledPanel *panel, GtkTilingGrid *grid)
{
- grid_tile_t *result; /* Structure à renvoyer */
- size_t best_len; /* Taille du chemin associé */
- size_t score_0; /* Score du sous-élément #1 */
- size_t score_1; /* Score du sous-élément #2 */
- char *sub_path; /* Nouvelle tentative d'accès */
- grid_tile_t **best; /* Direction à prendre */
- unsigned char next; /* Prochaine étape */
-
- /* Cas d'école : appel initial */
- if (*tile == NULL)
- {
- assert(path[0] == 'M' && path[1] == '\0');
-
- result = create_leaf_tile("M", tgrid);
- *tile = result;
+ TilingGridBorder border; /* Aire concernée par l'action */
+ GtkRevealer *revealer; /* Cible visée par l'opération */
+ bool new_state; /* Nouveau statut d'affichage */
+ if (station == grid->top_station)
+ {
+ border = TGB_TOP;
+ revealer = grid->top;
}
- else
+ else if (station == grid->left_station)
{
- if (IS_LEAF_TILE(*tile))
- {
- best_len = compute_tile_score(*tile, path);
-
- assert(best_len > 0);
+ border = TGB_LEFT;
+ revealer = grid->left;
+ }
- if (path[best_len] == '\0')
- result = *tile;
+ else if (station == grid->right_station)
+ {
+ border = TGB_RIGHT;
+ revealer = grid->right;
+ }
- else
- result = split_tile(tile, path, path[best_len], tgrid);
+ else if (station == grid->bottom_station)
+ {
+ border = TGB_BOTTOM;
+ revealer = grid->bottom;
+ }
- }
+ else
+ assert(false);
- else
- {
- score_0 = compute_tile_score((*tile)->children[0], path);
- score_1 = compute_tile_score((*tile)->children[1], path);
+ new_state = grid->visible[border] && !gtk_dock_station_is_empty(station);
- assert(score_0 > 0 || score_0 > 0);
+ if (gtk_revealer_get_reveal_child(revealer) != new_state)
+ gtk_revealer_set_reveal_child(revealer, new_state);
- if (score_0 == score_1)
- {
- sub_path = strndup(path, score_0);
+ /**
+ * On ne sait pas si l'état a réellement changé, mais on avertit
+ * d'une mise à jour quand même, au cas où.
+ */
- score_0 = compute_tile_score((*tile)->children[0], sub_path);
- score_1 = compute_tile_score((*tile)->children[1], sub_path);
+ g_object_notify_by_pspec(G_OBJECT(grid), _tiling_grid_properties[PROP_EMPTY_TOP + border]);
- free(sub_path);
+}
- }
- if (score_0 == score_1)
- result = split_tile(tile, path, path[score_0], tgrid);
- else
- {
- if (score_0 > score_1)
- {
- best = &(*tile)->children[0];
- best_len = score_0;
- }
- else
- {
- best = &(*tile)->children[1];
- best_len = score_1;
- }
-
- /**
- * Si on vient de tomber une feuille, trois cas de figure :
- * - soit c'est elle qui est visée.
- * - soit on veut la diviser.
- * - soit on veut la diviser en englobant ses voisines.
- */
-
- if (IS_LEAF_TILE(*best))
- {
- assert(best_len <= strlen(path));
-
- next = path[best_len];
-
- /* Premier cas */
- if (next == '\0')
- result = *best;
-
- else
- {
- /* Second cas */
- if (islower(next))
- result = find_suitable_tile(best, path, tgrid);
-
- /* Troisième cas */
- else
- result = split_tile(tile, path, next, tgrid);
-
- }
-
- }
-
- else
- result = find_suitable_tile(best, path, tgrid);
-
- }
+/* ---------------------------------------------------------------------------------- */
+/* REDIMENSIONNEMENT DE ZONES POUR PANNEAUX */
+/* ---------------------------------------------------------------------------------- */
- }
- }
+/******************************************************************************
+* *
+* Paramètres : gesture = encadrement de déplacement à l'origine de l'appel. *
+* start_x = pointe de départ sur l'axe des abscisses. *
+* start_y = pointe de départ sur l'axe des ordonnées. *
+* grid = gestionnaire de placement en tuile concerné. *
+* *
+* Description : Initie un redimensionnement par drag-and-drop. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
- assert(IS_LEAF_TILE(result));
+static void gtk_tiling_grid_on_gesture_drag_begin(GtkGestureDrag *gesture, double start_x, double start_y, GtkTilingGrid *grid)
+{
+ gtk_gesture_set_state(GTK_GESTURE(gesture), GTK_EVENT_SEQUENCE_CLAIMED);
- return result;
+ grid->panning = true;
}
/******************************************************************************
* *
-* Paramètres : tile = tuile à découper en deux. [OUT] *
-* path = chemin d'accès à la future tuile. *
-* endpoint = désignation de la zone représentée. *
-* tgrid = conteneur d'affichage en tuiles à manipuler. *
+* Paramètres : grid = zone d'affichage en tuiles à manipuler. *
+* border = sélection de la zone à considérer. *
+* offset_x = déplacement sur l'axe des abscisses. *
+* offset_y = déplacement sur l'axe des ordonnées. *
* *
-* Description : Découpe une tuile pour y insérer une zone. *
+* Description : Applique l'effet d'un redimensionnement drag-and-drop donné. *
* *
-* Retour : Structure fille mise en place. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-static grid_tile_t *split_tile(grid_tile_t **tile, const char *path, char endpoint, GtkTiledGrid *tgrid)
+static void gtk_tiling_grid_on_gesture_drag_update(GtkTilingGrid *grid, TilingGridBorder border, double offset_x, double offset_y)
{
- grid_tile_t *result; /* Création à retourner */
- GtkWidget *container; /* Conteneur à vider */
- grid_tile_t *new; /* Nouvelle tuile intermédiaire*/
+ GtkDockStation *station; /* Station entière */
+ int request; /* Taille requise */
+
+ /* Sélection de la poignée adaptée */
+
+ switch (border)
+ {
+ case TGB_TOP:
+ station = grid->top_station;
+ break;
+
+ case TGB_LEFT:
+ station = grid->left_station;
+ break;
- container = gtk_widget_get_parent((*tile)->widget);
+ case TGB_RIGHT:
+ station = grid->right_station;
+ break;
- /* Création */
+ case TGB_BOTTOM:
+ station = grid->bottom_station;
+ break;
- result = create_leaf_tile(path, tgrid);
+ }
- /* Encapsulation */
+ /* Détermination d'une nouvelle position et application */
- switch (endpoint)
+ switch (border)
{
- case 'N':
- case 'n':
- new = create_inter_tile((*tile)->parent, false, result, *tile);
+ case TGB_TOP:
+ case TGB_BOTTOM:
+ g_object_get(G_OBJECT(station), "height-request", &request, NULL);
break;
- case 'E':
- case 'e':
- new = create_inter_tile((*tile)->parent, true, *tile, result);
+ case TGB_LEFT:
+ case TGB_RIGHT:
+ g_object_get(G_OBJECT(station), "width-request", &request, NULL);
break;
- case 'S':
- case 's':
- new = create_inter_tile((*tile)->parent, false, *tile, result);
+ }
+
+ switch (border)
+ {
+ case TGB_TOP:
+ request += offset_y;
break;
- case 'W':
- case 'w':
- new = create_inter_tile((*tile)->parent, true, result, *tile);
+ case TGB_LEFT:
+ request += offset_x;
break;
- default:
- assert(false);
- new = NULL;
+ case TGB_RIGHT:
+ request += -offset_x;
+ break;
+
+ case TGB_BOTTOM:
+ request += -offset_y;
break;
}
- /* Connexions */
+ if (request > 0)
+ {
+ switch (border)
+ {
+ case TGB_TOP:
+ case TGB_BOTTOM:
+ g_object_set(G_OBJECT(station), "height-request", request, NULL);
+ break;
- *tile = new;
+ case TGB_LEFT:
+ case TGB_RIGHT:
+ g_object_set(G_OBJECT(station), "width-request", request, NULL);
+ break;
- result->parent = new;
+ }
- if (container != NULL)
- {
- g_object_ref(G_OBJECT(new->widget));
- gtk_container_add(GTK_CONTAINER(container), new->widget);
}
- return result;
-
}
/******************************************************************************
* *
-* Paramètres : tile = tuile parente, prochaine victime de promotion. *
-* side = côté de tuile amené à disparaître. *
+* Paramètres : gesture = encadrement de déplacement à l'origine de l'appel. *
+* offset_x = déplacement sur l'axe des abscisses. *
+* offset_y = déplacement sur l'axe des ordonnées. *
+* grid = gestionnaire de placement en tuile concerné. *
* *
-* Description : Retire une moitié de tuile vide au plein profit de l'autre. *
+* Description : Actualise l'effet d'un redimensionnement drag-and-drop. *
* *
* Retour : - *
* *
@@ -710,114 +777,65 @@ static grid_tile_t *split_tile(grid_tile_t **tile, const char *path, char endpoi
* *
******************************************************************************/
-static void collapse_tile(grid_tile_t *tile, grid_tile_t *side)
+static void gtk_tiling_grid_on_top_gesture_drag_update(GtkGestureDrag *gesture, double offset_x, double offset_y, GtkTilingGrid *grid)
{
- grid_tile_t *promoted; /* Tuile à faire remonter */
- GtkWidget *container; /* Conteneur à vider */
-
- assert(!IS_LEAF_TILE(tile));
-
- /* Sélection du remplaçant */
-
- if (side == tile->children[0])
- promoted = tile->children[1];
- else
- promoted = tile->children[0];
-
- /* Etablissement d'une place nette */
-
- gtk_container_remove(GTK_CONTAINER(tile->widget), promoted->widget);
-
- container = gtk_widget_get_parent(tile->widget);
- gtk_container_remove(GTK_CONTAINER(container), tile->widget);
-
- delete_tile(side);
-
- /* Promotion effective */
-
- tile->widget = promoted->widget;
-
- tile->path = promoted->path;
-
- tile->children[0] = promoted->children[0];
- tile->children[1] = promoted->children[1];
-
- g_object_ref(G_OBJECT(promoted->widget));
- gtk_container_add(GTK_CONTAINER(container), tile->widget);
-
- free(promoted);
+ gtk_tiling_grid_on_gesture_drag_update(grid, TGB_TOP, offset_x, offset_y);
}
/******************************************************************************
* *
-* Paramètres : tile = point de départ des recherches locales. *
-* widget = composant graphique à retrouver. *
+* Paramètres : gesture = encadrement de déplacement à l'origine de l'appel. *
+* offset_x = déplacement sur l'axe des abscisses. *
+* offset_y = déplacement sur l'axe des ordonnées. *
+* grid = gestionnaire de placement en tuile concerné. *
* *
-* Description : Tente de mettre la main sur une station d'accueil. *
+* Description : Actualise l'effet d'un redimensionnement drag-and-drop. *
* *
-* Retour : Eventuelle tuile trouvée ou NULL. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-static grid_tile_t *find_tile_for_widget(grid_tile_t *tile, GtkWidget *widget)
+static void gtk_tiling_grid_on_left_gesture_drag_update(GtkGestureDrag *gesture, double offset_x, double offset_y, GtkTilingGrid *grid)
{
- grid_tile_t *result; /* Tuile à retourner */
-
- if (IS_LEAF_TILE(tile))
- result = tile->widget == widget ? tile : NULL;
-
- else
- {
- result = find_tile_for_widget(tile->children[0], widget);
-
- if (result == NULL)
- result = find_tile_for_widget(tile->children[1], widget);
-
- }
-
- return result;
+ gtk_tiling_grid_on_gesture_drag_update(grid, TGB_LEFT, offset_x, offset_y);
}
-
-
/******************************************************************************
* *
-* Paramètres : tgrid = conteneur d'affichage en tuiles à consulter. *
+* Paramètres : gesture = encadrement de déplacement à l'origine de l'appel. *
+* offset_x = déplacement sur l'axe des abscisses. *
+* offset_y = déplacement sur l'axe des ordonnées. *
+* grid = gestionnaire de placement en tuile concerné. *
* *
-* Description : Donne le panneau fourni par défaut pour la zone principale. *
+* Description : Actualise l'effet d'un redimensionnement drag-and-drop. *
* *
-* Retour : Panneau d'affichage par défault ou NULL. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-GPanelItem *gtk_tiled_grid_get_default_main_panel(const GtkTiledGrid *tgrid)
+static void gtk_tiling_grid_on_right_gesture_drag_update(GtkGestureDrag *gesture, double offset_x, double offset_y, GtkTilingGrid *grid)
{
- GPanelItem *result; /* Panneau à retourner */
-
- result = tgrid->def_panel;
-
- if (result != NULL)
- g_object_ref(G_OBJECT(result));
-
- return result;
+ gtk_tiling_grid_on_gesture_drag_update(grid, TGB_RIGHT, offset_x, offset_y);
}
/******************************************************************************
* *
-* Paramètres : tgrid = conteneur d'affichage en tuiles à modifier. *
-* panel = panneau d'affichage par défault ou NULL. *
+* Paramètres : gesture = encadrement de déplacement à l'origine de l'appel. *
+* offset_x = déplacement sur l'axe des abscisses. *
+* offset_y = déplacement sur l'axe des ordonnées. *
+* grid = gestionnaire de placement en tuile concerné. *
* *
-* Description : Fournit le panneau par défaut pour la zone principale. *
+* Description : Actualise l'effet d'un redimensionnement drag-and-drop. *
* *
* Retour : - *
* *
@@ -825,56 +843,21 @@ GPanelItem *gtk_tiled_grid_get_default_main_panel(const GtkTiledGrid *tgrid)
* *
******************************************************************************/
-void gtk_tiled_grid_set_default_main_panel(GtkTiledGrid *tgrid, GPanelItem *panel)
+static void gtk_tiling_grid_on_bottom_gesture_drag_update(GtkGestureDrag *gesture, double offset_x, double offset_y, GtkTilingGrid *grid)
{
- GtkWidget *widget; /* Composant GTK à retirer */
- GtkWidget *parent; /* Conteneur à vider */
- grid_tile_t *tile; /* Première tuile d'accueil */
-
- if (tgrid->def_panel != NULL)
- {
- widget = gtk_dockable_build_widget(GTK_DOCKABLE(tgrid->def_panel));
-
- parent = gtk_widget_get_parent(widget);
-
- if (parent != NULL)
- gtk_container_remove(GTK_CONTAINER(parent), widget);
-
- g_object_unref(G_OBJECT(widget));
-
- g_object_unref(G_OBJECT(tgrid->def_panel));
-
- }
-
- tgrid->def_panel = panel;
-
- if (panel != NULL)
- {
- g_object_ref(G_OBJECT(panel));
-
- if (tgrid->tiles == NULL)
- gtk_tiled_grid_add(tgrid, panel);
-
- else
- {
- tile = find_suitable_tile(&tgrid->tiles, "M", tgrid);
-
- if (gtk_notebook_get_n_pages(GTK_NOTEBOOK(tile->widget)) == 0)
- gtk_tiled_grid_add(tgrid, panel);
-
- }
-
- }
+ gtk_tiling_grid_on_gesture_drag_update(grid, TGB_BOTTOM, offset_x, offset_y);
}
/******************************************************************************
* *
-* Paramètres : tgrid = conteneur d'affichage en tuiles à modifier. *
-* panel = panneau d'affichage à intégrer. *
+* Paramètres : gesture = encadrement de déplacement à l'origine de l'appel. *
+* offset_x = déplacement final sur l'axe des abscisses. *
+* offset_y = déplacement final sur l'axe des ordonnées. *
+* grid = gestionnaire de placement en tuile concerné. *
* *
-* Description : Incorpore un nouveau panneau dans le conteneur en tuiles. *
+* Description : Clôture un drag-and-drop de redimensionnement. *
* *
* Retour : - *
* *
@@ -882,66 +865,30 @@ void gtk_tiled_grid_set_default_main_panel(GtkTiledGrid *tgrid, GPanelItem *pane
* *
******************************************************************************/
-void gtk_tiled_grid_add(GtkTiledGrid *tgrid, GPanelItem *panel)
+static void gtk_tiling_grid_on_gesture_drag_end(GtkGestureDrag *gesture, double offset_x, double offset_y, GtkTilingGrid *grid)
{
- char *path; /* Chemin d'accès */
- char *name; /* Nom à donner à l'onglet */
- grid_tile_t *tile; /* Tuile d'accueil */
-
- path = gtk_panel_item_class_get_path(G_PANEL_ITEM_GET_CLASS(panel));
-
- if (!is_valid_tile_path(path))
- {
- name = gtk_dockable_get_name(GTK_DOCKABLE(panel));
- log_variadic_message(LMT_ERROR, _("Invalid path '%s' for panel '%s'"), path, name);
- free(name);
- }
-
+ if (!grid->panning)
+ gtk_gesture_set_state(GTK_GESTURE(gesture), GTK_EVENT_SEQUENCE_DENIED);
else
- {
- tile = find_suitable_tile(&tgrid->tiles, path, tgrid);
- assert(tile != NULL);
-
- gtk_dock_station_add_dockable(GTK_DOCK_STATION(tile->widget), GTK_DOCKABLE(panel));
+ grid->panning = false;
- g_panel_item_set_dock_at_startup(panel, true);
-
- /* Si c'est la toute première fois... */
- if (gtk_widget_get_parent(tile->widget) == NULL)
- {
- assert(tile == tgrid->tiles);
- assert(tile->path[0] == 'M' && tile->path[1] == '\0');
- g_object_ref(G_OBJECT(tile->widget));
- gtk_container_add(GTK_CONTAINER(tgrid), tile->widget);
- }
-
- /* Si on n'a plus besoin du panneau par défaut */
- if (tgrid->def_panel != NULL && tile->path[0] == 'M' && tile->path[1] == '\0')
- {
- /* Si ce n'est pas le panneau qu'on vient de rajouter...*/
- if (panel != tgrid->def_panel)
- {
- /* Enfin : si ce panneau par défaut est réellement en place */
- if (g_panel_item_is_docked(tgrid->def_panel))
- gtk_tiled_grid_remove(tgrid, tgrid->def_panel);
-
- }
-
- }
+}
- }
- free(path);
-}
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
/******************************************************************************
* *
-* Paramètres : tgrid = conteneur d'affichage en tuiles à modifier. *
-* panel = panneau d'affichage à supprimer. *
+* 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 : Retire un panneau dans le conteneur en tuiles. *
+* Description : Met à jour une propriété d'instance GObject. *
* *
* Retour : - *
* *
@@ -949,90 +896,65 @@ void gtk_tiled_grid_add(GtkTiledGrid *tgrid, GPanelItem *panel)
* *
******************************************************************************/
-void gtk_tiled_grid_remove(GtkTiledGrid *tgrid, GPanelItem *panel)
+static void gtk_tiling_grid_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
{
- GtkWidget *station; /* Support courant */
- grid_tile_t *tile; /* Tuile d'accueil */
-
- assert(g_panel_item_is_docked(panel));
-
- gtk_dockable_decompose(GTK_DOCKABLE(panel), &station);
-
- tile = find_tile_for_widget(tgrid->tiles, station);
- assert(tile != NULL);
+ GtkTilingGrid *grid; /* Version spécialisée */
- gtk_dock_station_remove_dockable(GTK_DOCK_STATION(station), GTK_DOCKABLE(panel));
+ grid = GTK_TILING_GRID(object);
- g_panel_item_set_dock_at_startup(panel, false);
-
- if (gtk_notebook_get_n_pages(GTK_NOTEBOOK(station)) == 0)
+ switch (prop_id)
{
- /* Si le panneau par défaut devient nécessaire */
- if (tgrid->def_panel != NULL && tile->path[0] == 'M' && tile->path[1] == '\0')
- gtk_tiled_grid_add(tgrid, tgrid->def_panel);
-
- else
- {
- /* La racine est concernée ! */
- if (tile->parent == NULL)
+ case PROP_LAYOUT:
+ if (grid->layout != g_value_get_flags(value))
{
- assert(tile == tgrid->tiles);
+ grid->layout = g_value_get_flags(value);
- g_object_ref(G_OBJECT(tile->widget));
- gtk_container_remove(GTK_CONTAINER(tgrid), tile->widget);
+ apply_tiling_grid_layout(GTK_GRID(grid), grid->layout, (GtkWidget *[]) {
+ GTK_WIDGET(grid->top), GTK_WIDGET(grid->left),
+ GTK_WIDGET(grid->right), GTK_WIDGET(grid->bottom)
+ });
- delete_tile(tile);
- tgrid->tiles = NULL;
+ g_object_notify_by_pspec(object, pspec);
}
+ break;
- else
- collapse_tile(tile->parent, tile);
-
- }
-
- }
-
-}
-
+ gtk_tiling_grid_set_visible(grid, TGB_TOP, g_value_get_boolean(value));
+ break;
-/******************************************************************************
-* *
-* Paramètres : tgrid = conteneur d'affichage en tuiles à consulter. *
-* station = station d'accueil à retrouver. *
-* *
-* Description : Indique le chemin correspondant à une station intégrée. *
-* *
-* Retour : Copie de chemin trouvé, à libérer ensuite, ou NULL si échec. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ case PROP_VISIBLE_TOP:
+ gtk_tiling_grid_set_visible(grid, TGB_TOP, g_value_get_boolean(value));
+ break;
-char *gtk_tiled_grid_get_path_for_station(const GtkTiledGrid *tgrid, GtkDockStation *station)
-{
- char *result; /* Chemin d'accès à renvoyer */
- grid_tile_t *tile; /* Tuile d'accueil */
+ case PROP_VISIBLE_LEFT:
+ gtk_tiling_grid_set_visible(grid, TGB_LEFT, g_value_get_boolean(value));
+ break;
- tile = find_tile_for_widget(tgrid->tiles, GTK_WIDGET(station));
+ case PROP_VISIBLE_RIGHT:
+ gtk_tiling_grid_set_visible(grid, TGB_RIGHT, g_value_get_boolean(value));
+ break;
- if (tile == NULL)
- result = NULL;
+ case PROP_VISIBLE_BOTTOM:
+ gtk_tiling_grid_set_visible(grid, TGB_BOTTOM, g_value_get_boolean(value));
+ break;
- else
- result = strdup(tile->path);
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ break;
- return result;
+ }
}
/******************************************************************************
* *
-* Paramètres : tgrid = conteneur d'affichage en tuiles à mettre à jour. *
-* config = configuration à consulter. *
+* 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 : Replace les positions des séparateurs de tuiles. *
+* Description : Fournit la valeur d'une propriété d'instance GObject. *
* *
* Retour : - *
* *
@@ -1040,57 +962,68 @@ char *gtk_tiled_grid_get_path_for_station(const GtkTiledGrid *tgrid, GtkDockStat
* *
******************************************************************************/
-void gtk_tiled_grid_restore_positions(const GtkTiledGrid *tgrid, GGenConfig *config)
+static void gtk_tiling_grid_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
{
+ GtkTilingGrid *grid; /* Version spécialisée */
- void visit_tiles_for_restoring(grid_tile_t *tile, const char *vpath)
- {
- GtkOrientation orientation; /* Direction de la tuile */
- char hint; /* Inutile donc indispensable */
- char *key; /* Clef d'accès à un paramètre */
- gint position; /* Nouvelle position de barre */
- size_t i; /* Boucle de parcours */
- char *child_key; /* Clef d'accès des suivants */
-
- if (!IS_LEAF_TILE(tile))
- {
- orientation = gtk_orientable_get_orientation(GTK_ORIENTABLE(tile->widget));
+ grid = GTK_TILING_GRID(object);
- hint = orientation == GTK_ORIENTATION_HORIZONTAL ? 'h' : 'v';
+ switch (prop_id)
+ {
+ case PROP_EMPTY_TOP:
+ g_value_set_boolean(value, gtk_dock_station_is_empty(grid->top_station));
+ break;
- asprintf(&key, "%s%c", vpath, hint);
+ case PROP_EMPTY_LEFT:
+ g_value_set_boolean(value, gtk_dock_station_is_empty(grid->left_station));
+ break;
- if (g_generic_config_get_value(config, key, &position))
- gtk_paned_set_position(GTK_PANED(tile->widget), position);
+ case PROP_EMPTY_RIGHT:
+ g_value_set_boolean(value, gtk_dock_station_is_empty(grid->right_station));
+ break;
- for (i = 0; i < 2; i++)
- {
- asprintf(&child_key, "%s%zu", key, i);
+ case PROP_EMPTY_BOTTOM:
+ g_value_set_boolean(value, gtk_dock_station_is_empty(grid->bottom_station));
+ break;
- visit_tiles_for_restoring(tile->children[i], child_key);
+ case PROP_VISIBLE_TOP:
+ g_value_set_boolean(value, gtk_tiling_grid_get_visible(grid, TGB_TOP));
+ break;
- free(child_key);
+ case PROP_VISIBLE_LEFT:
+ g_value_set_boolean(value, gtk_tiling_grid_get_visible(grid, TGB_LEFT));
+ break;
- }
+ case PROP_VISIBLE_RIGHT:
+ g_value_set_boolean(value, gtk_tiling_grid_get_visible(grid, TGB_RIGHT));
+ break;
- free(key);
+ case PROP_VISIBLE_BOTTOM:
+ g_value_set_boolean(value, gtk_tiling_grid_get_visible(grid, TGB_BOTTOM));
+ break;
- }
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ break;
}
+}
- visit_tiles_for_restoring(tgrid->tiles, "gui.panels.positions.R");
-}
+
+/* ---------------------------------------------------------------------------------- */
+/* FORME GENERIQUE DE MISE EN DISPOSITION */
+/* ---------------------------------------------------------------------------------- */
/******************************************************************************
* *
-* Paramètres : tgrid = conteneur d'affichage en tuiles à consulter. *
-* config = configuration à mettre à jour. *
+* Paramètres : grid = composant GTK dont le contenu est à arranger. *
+* options = options de mise en place. *
+* panels = liste organisée de composants à déplacer. *
* *
-* Description : Sauvegarde les positions des séparateurs de tuiles. *
+* Description : Met en place une disposition particulière de panneaux. *
* *
* Retour : - *
* *
@@ -1098,49 +1031,98 @@ void gtk_tiled_grid_restore_positions(const GtkTiledGrid *tgrid, GGenConfig *con
* *
******************************************************************************/
-void gtk_tiled_grid_save_positions(const GtkTiledGrid *tgrid, GGenConfig *config)
+void apply_tiling_grid_layout(GtkGrid *grid, LayoutReachOptions options, GtkWidget *panels[TGB_COUNT])
{
-
- void visit_tiles_for_saving(grid_tile_t *tile, const char *vpath)
+ int top_panel_span; /* Etendue d'un composant #1 */
+ int left_panel_span; /* Etendue d'un composant #2 */
+ int right_panel_span; /* Etendue d'un composant #3 */
+ int bottom_panel_span; /* Etendue d'un composant #4 */
+ int top_panel_column; /* Position de composant #1 */
+ int left_panel_row; /* Position de composant #2 */
+ int right_panel_row; /* Position de composant #3 */
+ int bottom_panel_column; /* Position de composant #4 */
+ GtkLayoutManager *layout; /* Gestionnaire de disposition */
+ GtkGridLayoutChild *top_panel_layout; /* Disposition de composant #1 */
+ GtkGridLayoutChild *left_panel_layout; /* Disposition de composant #2 */
+ GtkGridLayoutChild *right_panel_layout; /* Disposition de composant #3 */
+ GtkGridLayoutChild *bottom_panel_layout;/* Disposition de composant #4 */
+
+ /* Calcul des placements */
+
+ top_panel_span = 3;
+ left_panel_span = 3;
+ right_panel_span = 3;
+ bottom_panel_span = 3;
+
+ if (options & LRO_LEFT_TOP_REACH)
{
- GtkOrientation orientation; /* Direction de la tuile */
- char hint; /* Inutile donc indispensable */
- char *key; /* Clef d'accès à un paramètre */
- gint position; /* Nouvelle position de barre */
- size_t i; /* Boucle de parcours */
- char *child_key; /* Clef d'accès des suivants */
-
- if (!IS_LEAF_TILE(tile))
- {
- orientation = gtk_orientable_get_orientation(GTK_ORIENTABLE(tile->widget));
-
- hint = orientation == GTK_ORIENTATION_HORIZONTAL ? 'h' : 'v';
+ top_panel_column = 1;
+ top_panel_span--;
+ left_panel_row = 0;
+ }
+ else
+ {
+ top_panel_column = 0;
+ left_panel_row = 1;
+ left_panel_span--;
+ }
- asprintf(&key, "%s%c", vpath, hint);
+ if (options & LRO_LEFT_BOTTOM_REACH)
+ {
+ bottom_panel_column = 1;
+ bottom_panel_span--;
+ }
+ else
+ {
+ left_panel_span--;
+ bottom_panel_column = 0;
+ }
- position = gtk_paned_get_position(GTK_PANED(tile->widget));
- g_generic_config_create_or_udpdate_param(config, key, CPT_INTEGER, -1, position);
+ if (options & LRO_RIGHT_TOP_REACH)
+ {
+ top_panel_span--;
+ right_panel_row = 0;
+ }
+ else
+ {
+ right_panel_row = 1;
+ right_panel_span--;
+ }
- for (i = 0; i < 2; i++)
- {
- asprintf(&child_key, "%s%zu", key, i);
+ if (options & LRO_RIGHT_BOTTOM_REACH)
+ bottom_panel_span--;
+ else
+ right_panel_span--;
- visit_tiles_for_saving(tile->children[i], child_key);
+ /* Mise en application des contraintes */
- free(child_key);
+ layout = gtk_widget_get_layout_manager(GTK_WIDGET(grid));
- }
+ top_panel_layout = GTK_GRID_LAYOUT_CHILD(gtk_layout_manager_get_layout_child(layout, panels[TGB_TOP]));
+ left_panel_layout = GTK_GRID_LAYOUT_CHILD(gtk_layout_manager_get_layout_child(layout, panels[TGB_LEFT]));
+ right_panel_layout = GTK_GRID_LAYOUT_CHILD(gtk_layout_manager_get_layout_child(layout, panels[TGB_RIGHT]));
+ bottom_panel_layout = GTK_GRID_LAYOUT_CHILD(gtk_layout_manager_get_layout_child(layout, panels[TGB_BOTTOM]));
- free(key);
+ g_object_set(G_OBJECT(top_panel_layout),
+ "column", top_panel_column,
+ "column-span", top_panel_span,
+ NULL);
- }
+ g_object_set(G_OBJECT(left_panel_layout),
+ "row", left_panel_row,
+ "row-span", left_panel_span,
+ NULL);
- }
+ g_object_set(G_OBJECT(right_panel_layout),
+ "row", right_panel_row,
+ "row-span", right_panel_span,
+ NULL);
+ g_object_set(G_OBJECT(bottom_panel_layout),
+ "column", bottom_panel_column,
+ "column-span", bottom_panel_span,
+ NULL);
- visit_tiles_for_saving(tgrid->tiles, "gui.panels.positions.R");
+ gtk_layout_manager_layout_changed(layout);
}
-
-
-#endif
diff --git a/src/gtkext/grid.h b/src/gtkext/grid.h
index d9b7ef1..fd98035 100644
--- a/src/gtkext/grid.h
+++ b/src/gtkext/grid.h
@@ -25,10 +25,10 @@
#define _GTKEXT_GRID_H
+#include <stdbool.h>
#include <gtk/gtk.h>
-#include "dockstation.h"
#include "panel.h"
#include "../glibext/helpers.h"
@@ -42,7 +42,51 @@ DECLARE_GTYPE(GtkTilingGrid, gtk_tiling_grid, GTK, TILING_GRID);
/* Crée une nouvelle instance de conteneur avec tuiles. */
GtkWidget *gtk_tiling_grid_new(void);
+/* Liste des zones de bordure */
+typedef enum _TilingGridBorder /*< skip (glib-mkenums) >*/
+{
+ TGB_TOP, /* Zone supérieure */
+ TGB_LEFT, /* Zone de gauche */
+ TGB_RIGHT, /* Zone de droite */
+ TGB_BOTTOM, /* Zone inférieure */
+} TilingGridBorder;
+
+/**
+ * Fixe le nombre de combinaisons sans le rendre visible dans l'énumération.
+ */
+#define TGB_COUNT (TGB_BOTTOM + 1)
+
+/* Affiche ou masque une zone du conteneur en tuiles. */
+void gtk_tiling_grid_set_visible(GtkTilingGrid *, TilingGridBorder, bool);
+
+/* Fournit la visibilité d'une zone du conteneur en tuiles. */
+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 --------------------- */
+
+
+/* Options de dispositions cumulables */
+typedef enum _LayoutReachOptions /*< flags (glib-mkenums) >*/
+{
+ LRO_NONE = (0 << 0), /* Aucune atteinte des bords */
+ LRO_LEFT_TOP_REACH = (1 << 0), /* Atteinte du bord haut à G. */
+ LRO_LEFT_BOTTOM_REACH = (1 << 1), /* Atteinte du bord bas à G. */
+ LRO_RIGHT_TOP_REACH = (1 << 2), /* Atteinte du bord haut à D. */
+ LRO_RIGHT_BOTTOM_REACH = (1 << 3), /* Atteinte du bord bas à D. */
+
+} LayoutReachOptions;
+
+/* Met en place une disposition particulière de panneaux. */
+void apply_tiling_grid_layout(GtkGrid *, LayoutReachOptions, GtkWidget *[TGB_COUNT]);
diff --git a/src/gtkext/grid.ui b/src/gtkext/grid.ui
new file mode 100644
index 0000000..b14ced2
--- /dev/null
+++ b/src/gtkext/grid.ui
@@ -0,0 +1,217 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="GtkTilingGrid" parent="GtkGrid">
+
+ <!-- Zone supérieure -->
+
+ <child>
+ <object class="GtkRevealer" id="top">
+ <property name="transition-type">slide-up</property>
+ <property name="reveal-child">false</property>
+
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+
+ <child>
+ <object class="GtkDockStation" id="top_station">
+ <property name="orientation">vertical</property>
+ <property name="hexpand">true</property>
+ <property name="vexpand">false</property>
+ <property name="height-request">30</property>
+ <signal name="panel-docked" handler="gtk_tiling_grid_on_panel_un_docked"/>
+ <signal name="panel-undocked" handler="gtk_tiling_grid_on_panel_un_docked"/>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkSeparator" id="top_handle">
+ <property name="orientation">vertical</property>
+ <property name="height-request">5</property>
+
+ <child>
+ <object class="GtkGestureDrag">
+ <property name="propagation-phase">capture</property>
+ <signal name="drag-begin" handler="gtk_tiling_grid_on_gesture_drag_begin"/>
+ <signal name="drag-update" handler="gtk_tiling_grid_on_top_gesture_drag_update"/>
+ <signal name="drag-end" handler="gtk_tiling_grid_on_gesture_drag_end"/>
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ <property name="column-span">3</property>
+ </layout>
+ </object>
+ </child>
+
+ <!-- Zone de gauche -->
+
+ <child>
+ <object class="GtkRevealer" id="left">
+ <property name="transition-type">slide-right</property>
+ <property name="reveal-child">false</property>
+
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">horizontal</property>
+
+ <child>
+ <object class="GtkDockStation" id="left_station">
+ <property name="orientation">vertical</property>
+ <property name="hexpand">false</property>
+ <property name="vexpand">true</property>
+ <property name="width-request">300</property>
+ <signal name="panel-docked" handler="gtk_tiling_grid_on_panel_un_docked"/>
+ <signal name="panel-undocked" handler="gtk_tiling_grid_on_panel_un_docked"/>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkSeparator" id="left_handle">
+ <property name="orientation">horizontal</property>
+ <property name="width-request">5</property>
+
+ <child>
+ <object class="GtkGestureDrag">
+ <property name="propagation-phase">capture</property>
+ <signal name="drag-begin" handler="gtk_tiling_grid_on_gesture_drag_begin"/>
+ <signal name="drag-update" handler="gtk_tiling_grid_on_left_gesture_drag_update"/>
+ <signal name="drag-end" handler="gtk_tiling_grid_on_gesture_drag_end"/>
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ <layout>
+ <property name="column">0</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+
+ <!-- Zone centrale -->
+
+ <child>
+ <object class="GtkDockStation" id="main_station">
+ <property name="hexpand">true</property>
+ <property name="vexpand">true</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+
+ <!-- Zone de droite -->
+
+ <child>
+ <object class="GtkRevealer" id="right">
+ <property name="transition-type">slide-left</property>
+ <property name="reveal-child">false</property>
+
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">horizontal</property>
+
+ <child>
+ <object class="GtkSeparator" id="right_handle">
+ <property name="orientation">horizontal</property>
+ <property name="width-request">5</property>
+
+ <child>
+ <object class="GtkGestureDrag">
+ <property name="propagation-phase">capture</property>
+ <signal name="drag-begin" handler="gtk_tiling_grid_on_gesture_drag_begin"/>
+ <signal name="drag-update" handler="gtk_tiling_grid_on_right_gesture_drag_update"/>
+ <signal name="drag-end" handler="gtk_tiling_grid_on_gesture_drag_end"/>
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkDockStation" id="right_station">
+ <property name="orientation">vertical</property>
+ <property name="hexpand">false</property>
+ <property name="vexpand">true</property>
+ <property name="width-request">300</property>
+ <signal name="panel-docked" handler="gtk_tiling_grid_on_panel_un_docked"/>
+ <signal name="panel-undocked" handler="gtk_tiling_grid_on_panel_un_docked"/>
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ <layout>
+ <property name="column">2</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+
+ <!-- Zone inférieure -->
+
+ <child>
+ <object class="GtkRevealer" id="bottom">
+ <property name="transition-type">slide-up</property>
+ <property name="reveal-child">false</property>
+
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+
+ <child>
+ <object class="GtkSeparator" id="bottom_handle">
+ <property name="orientation">vertical</property>
+ <property name="height-request">5</property>
+
+ <child>
+ <object class="GtkGestureDrag">
+ <property name="propagation-phase">capture</property>
+ <signal name="drag-begin" handler="gtk_tiling_grid_on_gesture_drag_begin"/>
+ <signal name="drag-update" handler="gtk_tiling_grid_on_bottom_gesture_drag_update"/>
+ <signal name="drag-end" handler="gtk_tiling_grid_on_gesture_drag_end"/>
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkDockStation" id="bottom_station">
+ <property name="orientation">horizontal</property>
+ <property name="hexpand">true</property>
+ <property name="vexpand">false</property>
+ <property name="height-request">250</property>
+ <signal name="panel-docked" handler="gtk_tiling_grid_on_panel_un_docked"/>
+ <signal name="panel-undocked" handler="gtk_tiling_grid_on_panel_un_docked"/>
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ <layout>
+ <property name="column">0</property>
+ <property name="row">2</property>
+ <property name="column-span">3</property>
+ </layout>
+ </object>
+ </child>
+
+ </template>
+</interface>
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 07ade20..5398e51 100644
--- a/src/gtkext/panel-int.h
+++ b/src/gtkext/panel-int.h
@@ -30,9 +30,14 @@
+/* Indique l'emplacement par défaut pour un affichage. */
+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) (GtkTiledPanel *, bool);
+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) */
@@ -47,8 +52,11 @@ struct _GtkTiledPanelClass
{
GtkBoxClass parent; /* A laisser en premier */
+ 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 de55917..f63cfa1 100644
--- a/src/gtkext/panel.c
+++ b/src/gtkext/panel.c
@@ -137,6 +137,35 @@ static void gtk_tiled_panel_finalize(GtkTiledPanel *panel)
/******************************************************************************
* *
* Paramètres : panel = panneau graphique à consulter. *
+* *
+* Description : Indique l'emplacement attendu pour un affichage. *
+* *
+* Retour : Chemin représenté ou NULL pour l'emplacement "M" par défaut. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+char *gtk_tiled_panel_get_path(const GtkTiledPanel *panel)
+{
+ char *result; /* Chemin à retourner */
+ GtkTiledPanelClass *class; /* Classe à actionner */
+
+ class = GTK_TILED_PANEL_GET_CLASS(panel);
+
+ if (class->get_default_path != NULL)
+ result = class->get_default_path(panel);
+ else
+ result = NULL;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : panel = panneau graphique à consulter. *
* left = indication quant au côté ciblé. *
* *
* Description : Fournit les composants adaptés pour la barre de titre. *
@@ -147,7 +176,7 @@ static void gtk_tiled_panel_finalize(GtkTiledPanel *panel)
* *
******************************************************************************/
-GListStore *gtk_tiled_panel_get_title_widgets(GtkTiledPanel *panel, bool left)
+GListStore *gtk_tiled_panel_get_title_widgets(const GtkTiledPanel *panel, bool left)
{
GListStore *result; /* Composant(s) à retourner */
GtkTiledPanelClass *class; /* Classe à actionner */
@@ -164,6 +193,32 @@ GListStore *gtk_tiled_panel_get_title_widgets(GtkTiledPanel *panel, bool left)
}
+/******************************************************************************
+* *
+* 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 d2259ef..9b00657 100644
--- a/src/gtkext/panel.h
+++ b/src/gtkext/panel.h
@@ -38,9 +38,14 @@
DECLARE_GTYPE(GtkTiledPanel, gtk_tiled_panel, GTK, TILED_PANEL);
+/* Indique l'emplacement attendu pour un affichage. */
+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(GtkTiledPanel *, bool);
+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 2a9e99e..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 */
@@ -84,6 +90,8 @@ struct _GtkStatusStack
guint network_update_tag; /* Identifiant de mise à jour */
+ GtkToggleButton *bottom_toggler; /* Bascule de panneaux inf. */
+
};
/* Gestion de barre de statut adaptable (classe) */
diff --git a/src/gtkext/statusstack.c b/src/gtkext/statusstack.c
index 76dbee8..92c296a 100644
--- a/src/gtkext/statusstack.c
+++ b/src/gtkext/statusstack.c
@@ -41,6 +41,25 @@
/* -------------------------- GESTION GENERALE DES STATUTS -------------------------- */
+/* Liste des propriétés */
+
+typedef enum _StatusStackProperty {
+
+ PROP_0, /* Réservé */
+
+ PROP_SHOW_BOTTOM, /* Affichage de la zone inf. */
+
+ N_PROPERTIES
+
+} 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 *);
@@ -61,6 +80,25 @@ static gboolean gtk_status_stack_update_network_stats(GtkStatusStack *);
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Met à jour une propriété d'instance GObject. */
+static void gtk_status_stack_set_property(GObject *, guint, const GValue *, GParamSpec *);
+
+/* Fournit la valeur d'une propriété d'instance GObject. */
+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 -------------------- */
@@ -89,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 *);
@@ -139,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);
@@ -173,6 +211,15 @@ static void gtk_status_stack_class_init(GtkStatusStackClass *class)
object->dispose = (GObjectFinalizeFunc/* ! */)gtk_status_stack_dispose;
object->finalize = (GObjectFinalizeFunc)gtk_status_stack_finalize;
+ object->set_property = gtk_status_stack_set_property;
+ object->get_property = gtk_status_stack_get_property;
+
+ _status_stack_properties[PROP_SHOW_BOTTOM] =
+ g_param_spec_boolean("show-bottom", NULL, NULL,
+ TRUE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties(object, N_PROPERTIES, _status_stack_properties);
widget = GTK_WIDGET_CLASS(class);
@@ -182,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);
@@ -198,6 +247,8 @@ static void gtk_status_stack_class_init(GtkStatusStackClass *class)
gtk_widget_class_bind_template_child(widget, GtkStatusStack, net_recv_speed);
gtk_widget_class_bind_template_child(widget, GtkStatusStack, net_send_speed);
+ gtk_widget_class_bind_template_child(widget, GtkStatusStack, bottom_toggler);
+
}
@@ -217,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);
@@ -241,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);
+
}
@@ -287,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);
@@ -333,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);
}
@@ -497,6 +561,148 @@ static gboolean gtk_status_stack_update_network_stats(GtkStatusStack *stack)
+
+/* ---------------------------------------------------------------------------------- */
+/* 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 : - *
+* *
+******************************************************************************/
+
+static void gtk_status_stack_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+ GtkStatusStack *stack; /* Version spécialisée */
+
+ stack = GTK_STATUS_STACK(object);
+
+ switch (prop_id)
+ {
+ case PROP_SHOW_BOTTOM:
+ gtk_toggle_button_set_active(stack->bottom_toggler, g_value_get_boolean(value));
+ 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_status_stack_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+ GtkStatusStack *stack; /* Version spécialisée */
+
+ stack = GTK_STATUS_STACK(object);
+
+ switch (prop_id)
+ {
+ case PROP_SHOW_BOTTOM:
+ g_value_set_boolean(value, gtk_toggle_button_get_active(stack->bottom_toggler));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ break;
+
+ }
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* 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 */
/* ---------------------------------------------------------------------------------- */
@@ -628,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". *
* *
@@ -638,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;
@@ -669,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;
}
@@ -869,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);
@@ -936,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);
}
@@ -993,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);
}
@@ -1045,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);
}
@@ -1111,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:
@@ -1125,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é". *
* *
@@ -1135,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);
@@ -1148,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 8469e6e..0b7cd6d 100644
--- a/src/gtkext/statusstack.ui
+++ b/src/gtkext/statusstack.ui
@@ -2,6 +2,8 @@
<interface>
<template class="GtkStatusStack" parent="GtkBox">
+ <!--property name="show-bottom" bind-source="bottom_toggler" bind-property="active" bind-flags="bidirectional|sync-create"/-->
+
<child>
<object class="GtkStack" id="main">
<property name="margin-start">8</property>
@@ -10,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>
@@ -200,7 +205,8 @@
<child>
<object class="GtkToggleButton" id="bottom_toggler">
<property name="has-frame">false</property>
- <property name="icon-name">panel-bottom-symbolic</property>
+ <property name="icon-name">dock-station-bottom-symbolic</property>
+ <property name="action-name">win.toggle-bottom</property>
</object>
</child>
diff --git a/src/gui/core/logs.c b/src/gui/core/logs.c
index 59910f1..cdb2a0d 100644
--- a/src/gui/core/logs.c
+++ b/src/gui/core/logs.c
@@ -24,6 +24,14 @@
#include "logs.h"
+#include <assert.h>
+
+
+#include "panels.h"
+#include "../panels/logs.h"
+#include "../../glibext/log.h"
+
+
/******************************************************************************
* *
@@ -38,26 +46,20 @@
* *
******************************************************************************/
-void do_log_message_alt2(LogMessageType type, const char *msg)
+void do_log_message_alt(LogMessageType type, const char *msg)
{
-#if 0
-
-#ifdef INCLUDE_GTK_SUPPORT
-
- GEditorItem *item; /* Eventuel affichage présent */
+ GLogEntry *entry; /* Nouvel élément de journal */
+ GtkTiledPanel *panel; /* Panneau de journalisation */
- item = find_editor_item_by_type(G_TYPE_LOG_PANEL);
+ entry = g_log_entry_new(type, msg);
- if (item != NULL)
- {
- g_log_panel_add_message(G_LOG_PANEL(item), type, msg);
- g_object_unref(G_OBJECT(item));
- }
+ panel = get_framework_panel_singleton(GTK_TYPE_LOGS_PANEL);
+ assert(panel != NULL);
-#endif
+ g_log_panel_add_message(GTK_LOGS_PANEL(panel), entry);
-#endif
+ unref_object(panel);
- printf("[log GUI] [%u] %s\n", type, msg);
+ unref_object(entry);
}
diff --git a/src/gui/core/panels.c b/src/gui/core/panels.c
index 4c113b8..9fca411 100644
--- a/src/gui/core/panels.c
+++ b/src/gui/core/panels.c
@@ -35,6 +35,7 @@
#include "../panels/binary.h"
#include "../panels/binary-params.h"
+#include "../panels/logs.h"
#include "../panels/welcome.h"
#include "../../gtkext/launcher.h"
@@ -168,10 +169,23 @@ bool load_main_framework_panel_definitions(void)
bool result; /* Bilan à retourner */
panel_info_t info; /* Infos d'enregistrement */
- // TODO register_panel_item(G_TYPE_LOG_PANEL, config);
-
/* Chargement du panneau de rapport au plus tôt */
- // TODO panel = g_panel_item_new(G_TYPE_LOG_PANEL, NULL);
+
+ info.category = NULL;
+
+ info.image = NULL;
+ info.title = _("Logs");
+ info.desc = NULL;
+
+ info.personality = FPP_SINGLETON;
+
+ info.panel_type = GTK_TYPE_LOGS_PANEL;
+ info.params_type = G_TYPE_INVALID;
+
+ result = register_framework_panel_definition(&info);
+ if (!result) goto done;
+
+ /* Chargements des panneaux restants */
info.category = "Main";
@@ -187,6 +201,8 @@ bool load_main_framework_panel_definitions(void)
result = register_framework_panel_definition(&info);
if (!result) goto done;
+ /* --- */
+
info.category = NULL;
info.image = NULL;
@@ -283,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">&lt;span fgcolor='white'&gt;Copyright (C) 2008-2025 Cyrille Bagard&lt;/span&gt;</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/dialogs/preferences.c b/src/gui/dialogs/preferences.c
index 68e7fd9..0369241 100644
--- a/src/gui/dialogs/preferences.c
+++ b/src/gui/dialogs/preferences.c
@@ -34,6 +34,7 @@
#include "preferences-int.h"
+#include "prefs/appearance.h"
#include "prefs/security.h"
#include "../../common/cpp.h"
#include "../../gtkext/tweak.h"
@@ -140,6 +141,8 @@ static void gtk_preferences_dialog_init(GtkPreferencesDialog *dialog)
tweak_info_t infos[] = {
TWEAK_SIMPLE_DEF("root", "Basics",
+ "security-high-symbolic", "appearance", "Appearance", GTK_TYPE_APPEARANCE_TWEAK_PANEL),
+ TWEAK_SIMPLE_DEF("root", "Basics",
"security-high-symbolic", "security", "Security", GTK_TYPE_SECURITY_TWEAK_PANEL),
};
diff --git a/src/gui/dialogs/prefs/Makefile.am b/src/gui/dialogs/prefs/Makefile.am
index fa1af96..50bc3c8 100644
--- a/src/gui/dialogs/prefs/Makefile.am
+++ b/src/gui/dialogs/prefs/Makefile.am
@@ -4,9 +4,12 @@ BUILT_SOURCES = resources.h resources.c
noinst_LTLIBRARIES = libguidialogsprefs.la
UI_FILES = \
+ appearance.ui \
security.ui
libguidialogsprefs_la_SOURCES = \
+ appearance-int.h \
+ appearance.h appearance.c \
resources.h resources.c \
security-int.h \
security.h security.c
diff --git a/src/gui/dialogs/prefs/appearance-int.h b/src/gui/dialogs/prefs/appearance-int.h
new file mode 100644
index 0000000..886a562
--- /dev/null
+++ b/src/gui/dialogs/prefs/appearance-int.h
@@ -0,0 +1,64 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * appearance-int.h - définitions internes pour la configuration des paramètres liés aux apparences
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GUI_DIALOGS_PREFS_APPEARANCE_INT_H
+#define _GUI_DIALOGS_PREFS_APPEARANCE_INT_H
+
+
+#include "appearance.h"
+
+
+
+/* Composant d'édition des paramètres liés aux apparences (instance) */
+struct _GtkAppearanceTweakPanel
+{
+ GtkBox parent; /* A laisser en premier */
+
+ /* Disposition des panneaux */
+
+ GSettings *tiles_settings; /* Configuration sollicitée */
+
+ GtkWidget *layout_preview; /* Zone d'aperçu de dispositon*/
+
+ GtkWidget *top_panel; /* Composant d'aperçu #1 */
+ GtkWidget *left_panel; /* Composant d'aperçu #2 */
+ GtkWidget *right_panel; /* Composant d'aperçu #3 */
+ GtkWidget *bottom_panel; /* Composant d'aperçu #4 */
+
+ GtkCheckButton *left_top_reach; /* Paramètre de disposition #1 */
+ GtkCheckButton *left_bottom_reach; /* Paramètre de disposition #2 */
+ GtkCheckButton *right_top_reach; /* Paramètre de disposition #3 */
+ GtkCheckButton *right_bottom_reach; /* Paramètre de disposition #4 */
+
+};
+
+/* Composant d'édition des paramètres liés aux apparences (classe) */
+struct _GtkAppearanceTweakPanelClass
+{
+ GtkBoxClass parent; /* A laisser en premier */
+
+};
+
+
+
+#endif /* _GUI_DIALOGS_PREFS_APPEARANCE_INT_H */
diff --git a/src/gui/dialogs/prefs/appearance.c b/src/gui/dialogs/prefs/appearance.c
new file mode 100644
index 0000000..a8585fa
--- /dev/null
+++ b/src/gui/dialogs/prefs/appearance.c
@@ -0,0 +1,251 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * appearance.c - configuration des paramètres liés aux apparences
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "appearance.h"
+
+
+#include "appearance-int.h"
+#include "../../../gtkext/grid.h"
+#include "../../../gtkext/helpers.h"
+
+
+
+/* Procède à l'initialisation de classe des configurations. */
+static void gtk_appearance_tweak_panel_class_init(GtkAppearanceTweakPanelClass *);
+
+/* Procède à l'initialisation des configurations de sécurité. */
+static void gtk_appearance_tweak_panel_init(GtkAppearanceTweakPanel *);
+
+/* Supprime toutes les références externes. */
+static void gtk_appearance_tweak_panel_dispose(GObject *);
+
+/* Procède à la libération totale de la mémoire. */
+static void gtk_appearance_tweak_panel_finalize(GObject *);
+
+/* Réagit à un changement de paramètre de configuration. */
+static void gtk_appearance_tweak_panel_on_tiles_settings_changed(GSettings *, const gchar *, GtkAppearanceTweakPanel *);
+
+/* Change la disposition des panneaux de la fenêtre principale. */
+static void gtk_appearance_tweak_panel_on_panel_reach_toggled(GtkCheckButton *, GtkAppearanceTweakPanel *);
+
+
+/* Indique le type du composant de configuration des notes. */
+G_DEFINE_TYPE(GtkAppearanceTweakPanel, gtk_appearance_tweak_panel, GTK_TYPE_BOX);
+
+
+/******************************************************************************
+* *
+* Paramètres : class = classe GTK à initialiser. *
+* *
+* Description : Procède à l'initialisation de classe des configurations. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_appearance_tweak_panel_class_init(GtkAppearanceTweakPanelClass *class)
+{
+ GObjectClass *object; /* Plus haut niveau équivalent */
+ GtkWidgetClass *widget; /* Classe de haut niveau */
+
+ object = G_OBJECT_CLASS(class);
+
+ object->dispose = gtk_appearance_tweak_panel_dispose;
+ object->finalize = gtk_appearance_tweak_panel_finalize;
+
+ widget = GTK_WIDGET_CLASS(class);
+
+ gtk_widget_class_set_template_from_resource(widget, "/re/chrysalide/framework/gui/dialogs/prefs/appearance.ui");
+
+ gtk_widget_class_bind_template_callback_full(widget, BUILDER_CB(gtk_appearance_tweak_panel_on_panel_reach_toggled));
+
+ gtk_widget_class_bind_template_child(widget, GtkAppearanceTweakPanel, layout_preview);
+
+ gtk_widget_class_bind_template_child(widget, GtkAppearanceTweakPanel, top_panel);
+ gtk_widget_class_bind_template_child(widget, GtkAppearanceTweakPanel, left_panel);
+ gtk_widget_class_bind_template_child(widget, GtkAppearanceTweakPanel, right_panel);
+ gtk_widget_class_bind_template_child(widget, GtkAppearanceTweakPanel, bottom_panel);
+
+ gtk_widget_class_bind_template_child(widget, GtkAppearanceTweakPanel, left_top_reach);
+ gtk_widget_class_bind_template_child(widget, GtkAppearanceTweakPanel, left_bottom_reach);
+ gtk_widget_class_bind_template_child(widget, GtkAppearanceTweakPanel, right_top_reach);
+ gtk_widget_class_bind_template_child(widget, GtkAppearanceTweakPanel, right_bottom_reach);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : panel = composant GTK à initialiser. *
+* *
+* Description : Procède à l'initialisation des configurations de sécurité. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_appearance_tweak_panel_init(GtkAppearanceTweakPanel *panel)
+{
+ LayoutReachOptions options; /* Détails de disposition */
+
+ gtk_widget_init_template(GTK_WIDGET(panel));
+
+ panel->tiles_settings = g_settings_new_with_path("re.chrysalide.framework.tiledgrid",
+ "/re/chrysalide/framework/gui/tiles/");
+
+ options = g_settings_get_flags(panel->tiles_settings, "layout");
+
+ gtk_check_button_set_active(panel->left_top_reach, options & LRO_LEFT_TOP_REACH);
+ gtk_check_button_set_active(panel->left_bottom_reach, options & LRO_LEFT_BOTTOM_REACH);
+ gtk_check_button_set_active(panel->right_top_reach, options & LRO_RIGHT_TOP_REACH);
+ gtk_check_button_set_active(panel->right_bottom_reach, options & LRO_RIGHT_BOTTOM_REACH);
+
+ gtk_appearance_tweak_panel_on_tiles_settings_changed(panel->tiles_settings, "layout", panel);
+
+ g_signal_connect(panel->tiles_settings, "changed",
+ G_CALLBACK(gtk_appearance_tweak_panel_on_tiles_settings_changed), panel);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_appearance_tweak_panel_dispose(GObject *object)
+{
+ GtkAppearanceTweakPanel *panel; /* Version spécialisée */
+
+ gtk_widget_dispose_template(GTK_WIDGET(object), GTK_TYPE_APPEARANCE_TWEAK_PANEL);
+
+ panel = GTK_APPEARANCE_TWEAK_PANEL(object);
+
+ g_clear_object(&panel->tiles_settings);
+
+ G_OBJECT_CLASS(gtk_appearance_tweak_panel_parent_class)->dispose(object);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_appearance_tweak_panel_finalize(GObject *object)
+{
+ G_OBJECT_CLASS(gtk_appearance_tweak_panel_parent_class)->finalize(object);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : settings = ensemble de paramètres connaissant une évolution. *
+* key = identifiant du paramètre ayant changé. *
+* panel = panneau de paramétrage concerné par l'appel. *
+* *
+* Description : Réagit à un changement de paramètre de configuration. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_appearance_tweak_panel_on_tiles_settings_changed(GSettings *settings, const gchar *key, GtkAppearanceTweakPanel *panel)
+{
+ LayoutReachOptions options; /* Détails de disposition */
+
+ if (strcmp(key, "layout") == 0)
+ {
+ options = g_settings_get_flags(panel->tiles_settings, "layout");
+
+ apply_tiling_grid_layout(GTK_GRID(panel->layout_preview), options, (GtkWidget *[]) {
+ panel->top_panel, panel->left_panel, panel->right_panel, panel->bottom_panel
+ });
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : button = composant radio dont l'état vient de basculer. *
+* panel = panneau d'édition des préférences courant. *
+* *
+* Description : Change la disposition des panneaux de la fenêtre principale. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_appearance_tweak_panel_on_panel_reach_toggled(GtkCheckButton *button, GtkAppearanceTweakPanel *panel)
+{
+ gboolean left_top_reach; /* Paramètre de disposition #1 */
+ gboolean left_bottom_reach; /* Paramètre de disposition #2 */
+ gboolean right_top_reach; /* Paramètre de disposition #3 */
+ gboolean right_bottom_reach; /* Paramètre de disposition #4 */
+ LayoutReachOptions options; /* Options à appliquer */
+
+ /* Récupération des indications */
+
+ left_top_reach = gtk_check_button_get_active(panel->left_top_reach);
+ left_bottom_reach = gtk_check_button_get_active(panel->left_bottom_reach);
+ right_top_reach = gtk_check_button_get_active(panel->right_top_reach);
+ right_bottom_reach = gtk_check_button_get_active(panel->right_bottom_reach);
+
+ /* Conversion et application */
+
+ options = LRO_NONE;
+
+ if (left_top_reach) options |= LRO_LEFT_TOP_REACH;
+ if (left_bottom_reach) options |= LRO_LEFT_BOTTOM_REACH;
+ if (right_top_reach) options |= LRO_RIGHT_TOP_REACH;
+ if (right_bottom_reach) options |= LRO_RIGHT_BOTTOM_REACH;
+
+ g_settings_set_flags(panel->tiles_settings, "layout", options);
+
+}
diff --git a/src/gui/dialogs/prefs/appearance.h b/src/gui/dialogs/prefs/appearance.h
new file mode 100644
index 0000000..916b194
--- /dev/null
+++ b/src/gui/dialogs/prefs/appearance.h
@@ -0,0 +1,41 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * appearance.h - prototypes pour la configuration des paramètres liés aux apparences
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GUI_DIALOGS_PREFS_APPEARANCE_H
+#define _GUI_DIALOGS_PREFS_APPEARANCE_H
+
+
+#include <gtk/gtk.h>
+
+
+#include "../../../glibext/helpers.h"
+
+
+
+#define GTK_TYPE_APPEARANCE_TWEAK_PANEL (gtk_appearance_tweak_panel_get_type())
+
+DECLARE_GTYPE(GtkAppearanceTweakPanel, gtk_appearance_tweak_panel, GTK, APPEARANCE_TWEAK_PANEL);
+
+
+
+#endif /* _GUI_DIALOGS_PREFS_APPEARANCE_H */
diff --git a/src/gui/dialogs/prefs/appearance.ui b/src/gui/dialogs/prefs/appearance.ui
new file mode 100644
index 0000000..3410115
--- /dev/null
+++ b/src/gui/dialogs/prefs/appearance.ui
@@ -0,0 +1,184 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+
+ <template class="GtkAppearanceTweakPanel" parent="GtkBox">
+
+ <property name="orientation">vertical</property>
+ <property name="margin-start">20</property>
+ <property name="margin-end">20</property>
+ <property name="margin-top">20</property>
+ <property name="margin-bottom">20</property>
+ <property name="spacing">10</property>
+
+ <!-- Disposition des panneaux -->
+
+ <child>
+ <object class="GtkLabel">
+ <property name="label">Layout</property>
+ <property name="use-markup">true</property>
+ <property name="xalign">0</property>
+ <style>
+ <class name="heading"/>
+ </style>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkLabel">
+ <property name="label">Layout defines the global panel organization of the main window.</property>
+ <property name="wrap">true</property>
+ <property name="use-markup">true</property>
+ <property name="xalign">0</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+
+
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">horizontal</property>
+
+ <!-- Aperçu -->
+
+ <child>
+ <object class="GtkGrid" id="layout_preview">
+ <property name="margin-start">20</property>
+ <property name="margin-end">20</property>
+ <property name="margin-top">10</property>
+ <property name="margin-bottom">10</property>
+ <property name="row-spacing">5</property>
+ <property name="column-spacing">5</property>
+ <property name="hexpand">false</property>
+ <property name="vexpand">false</property>
+ <property name="height-request">200</property>
+ <property name="width-request">300</property>
+
+ <child>
+ <object class="GtkFrame" id="top_panel">
+ <property name="hexpand">true</property>
+ <property name="vexpand">false</property>
+ <property name="height-request">20</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ <property name="column-span">3</property>
+ </layout>
+ <style>
+ <class name="view"/>
+ </style>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkFrame" id="left_panel">
+ <property name="hexpand">false</property>
+ <property name="vexpand">true</property>
+ <property name="width-request">50</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">1</property>
+ </layout>
+ <style>
+ <class name="view"/>
+ </style>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkFrame">
+ <property name="hexpand">true</property>
+ <property name="vexpand">true</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">1</property>
+ </layout>
+ <style>
+ <class name="view"/>
+ </style>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkFrame" id="right_panel">
+ <property name="hexpand">false</property>
+ <property name="vexpand">true</property>
+ <property name="width-request">50</property>
+ <layout>
+ <property name="column">2</property>
+ <property name="row">1</property>
+ </layout>
+ <style>
+ <class name="view"/>
+ </style>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkFrame" id="bottom_panel">
+ <property name="hexpand">true</property>
+ <property name="vexpand">false</property>
+ <property name="height-request">50</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">2</property>
+ <property name="column-span">3</property>
+ </layout>
+ <style>
+ <class name="view"/>
+ </style>
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ <!-- Options -->
+
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+ <property name="valign">center</property>
+ <property name="spacing">10</property>
+
+ <child>
+ <object class="GtkCheckButton" id="left_top_reach">
+ <property name="label">Left panels reach the top of the window</property>
+ <property name="active">false</property>
+ <signal name="toggled" handler="gtk_appearance_tweak_panel_on_panel_reach_toggled"/>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkCheckButton" id="left_bottom_reach">
+ <property name="label">Left panels reach the bottom of the window</property>
+ <property name="active">false</property>
+ <signal name="toggled" handler="gtk_appearance_tweak_panel_on_panel_reach_toggled"/>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkCheckButton" id="right_top_reach">
+ <property name="label">Right panels reach the top of the window</property>
+ <property name="active">false</property>
+ <signal name="toggled" handler="gtk_appearance_tweak_panel_on_panel_reach_toggled"/>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkCheckButton" id="right_bottom_reach">
+ <property name="label">Right panels reach the bottom of the window</property>
+ <property name="active">false</property>
+ <signal name="toggled" handler="gtk_appearance_tweak_panel_on_panel_reach_toggled"/>
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ </template>
+</interface>
diff --git a/src/gui/dialogs/prefs/gresource.xml b/src/gui/dialogs/prefs/gresource.xml
index 7b18143..ad0f97f 100644
--- a/src/gui/dialogs/prefs/gresource.xml
+++ b/src/gui/dialogs/prefs/gresource.xml
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/re/chrysalide/framework/gui/dialogs/prefs">
+ <file compressed="true">appearance.ui</file>
<file compressed="true">security.ui</file>
</gresource>
</gresources>
diff --git a/src/gui/panels/Makefile.am b/src/gui/panels/Makefile.am
index 2765405..ecff6c7 100644
--- a/src/gui/panels/Makefile.am
+++ b/src/gui/panels/Makefile.am
@@ -11,7 +11,6 @@ UI_FILES = \
errors.ui \
glance.ui \
history.ui \
- log.ui \
regedit.ui \
strings.ui \
symbols.ui
@@ -22,7 +21,6 @@ libguipanels_la_SOURCES = \
errors.h errors.c \
glance.h glance.c \
history.h history.c \
- log.h log.c \
regedit.h regedit.c \
resources.h resources.c \
strings.h strings.c \
@@ -40,6 +38,9 @@ RES_FILES = \
binary.ui \
binary-params.ui \
$(IMG_PATH)/binfile-symbolic.svg \
+ logs.ui \
+ logs-col-icon.ui \
+ logs-col-message.ui \
welcome.ui \
welcome-hints.txt \
$(IMG_PATH)/tipoftheday-symbolic.svg
@@ -49,6 +50,8 @@ libguipanels4_la_SOURCES = \
binary.h binary.c \
binary-params-int.h \
binary-params.h binary-params.c \
+ logs-int.h \
+ logs.h logs.c \
resources.h resources.c \
welcome-int.h \
welcome.h welcome.c
diff --git a/src/gui/panels/gresource.xml b/src/gui/panels/gresource.xml
index f49a16f..2765b25 100644
--- a/src/gui/panels/gresource.xml
+++ b/src/gui/panels/gresource.xml
@@ -3,6 +3,9 @@
<gresource prefix="/re/chrysalide/framework/gui/panels">
<file compressed="true">binary.ui</file>
<file compressed="true">binary-params.ui</file>
+ <file compressed="true">logs.ui</file>
+ <file compressed="true">logs-col-icon.ui</file>
+ <file compressed="true">logs-col-message.ui</file>
<file compressed="true">welcome.ui</file>
<file compressed="true">welcome-hints.txt</file>
</gresource>
diff --git a/src/gui/panels/log.c b/src/gui/panels/log.c
deleted file mode 100644
index d11fbd2..0000000
--- a/src/gui/panels/log.c
+++ /dev/null
@@ -1,451 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * log.c - panneau d'affichage des messages système
- *
- * Copyright (C) 2012-2019 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 this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-#include "log.h"
-
-
-#include <malloc.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-#include <gtk/gtk.h>
-
-
-#include "../panel-int.h"
-#include "../core/panels.h"
-#include "../../gtkext/easygtk.h"
-#include "../../gtkext/named.h"
-
-
-
-/* Colonnes de la liste des messages */
-typedef enum _LogColumn
-{
- LGC_PICTURE, /* Image de représentation */
- LGC_STRING, /* Chaîne de caractères */
-
- LGC_COUNT /* Nombre de colonnes */
-
-} LogColumn;
-
-
-/* Paramètres à transmettre pour un affichage */
-typedef struct _log_data
-{
- GPanelItem *item; /* Intermédiaire mis en place */
- LogMessageType type; /* Type de message à afficher */
- char *msg; /* Contenu du message */
-
-} log_data;
-
-
-/* Panneau d'accueil (instance) */
-struct _GLogPanel
-{
- GPanelItem parent; /* A laisser en premier */
-
-};
-
-
-/* Panneau d'accueil (classe) */
-struct _GLogPanelClass
-{
- GPanelItemClass parent; /* A laisser en premier */
-
-};
-
-
-/* Initialise la classe des panneaux d'affichage des messages. */
-static void g_log_panel_class_init(GLogPanelClass *);
-
-/* Initialise une instance de panneau d'affichage des messages. */
-static void g_log_panel_init(GLogPanel *);
-
-/* Supprime toutes les références externes. */
-static void g_log_panel_dispose(GLogPanel *);
-
-/* Procède à la libération totale de la mémoire. */
-static void g_log_panel_finalize(GLogPanel *);
-
-/* Fournit le nom interne attribué à l'élément réactif. */
-static char *g_log_panel_class_get_key(const GLogPanelClass *);
-
-/* Fournit une indication sur la personnalité du panneau. */
-static PanelItemPersonality g_log_panel_class_get_personality(const GLogPanelClass *);
-
-/* Indique le chemin initial de la localisation d'un panneau. */
-static char *g_log_panel_class_get_path(const GLogPanelClass *);
-
-/* Indique la définition d'un éventuel raccourci clavier. */
-static char *g_log_panel_class_get_key_bindings(const GLogPanelClass *);
-
-/* Affiche un message dans le journal des messages système. */
-static gboolean log_message(log_data *);
-
-
-
-/* Indique le type défini pour un panneau d'affichage de messages. */
-G_DEFINE_TYPE(GLogPanel, g_log_panel, G_TYPE_PANEL_ITEM);
-
-
-/******************************************************************************
-* *
-* Paramètres : class = classe à initialiser. *
-* *
-* Description : Initialise la classe des panneaux d'affichage des messages. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_log_panel_class_init(GLogPanelClass *class)
-{
- GObjectClass *object; /* Autre version de la classe */
- GEditorItemClass *item; /* Encore une autre vision... */
- GPanelItemClass *panel; /* Version parente de la classe*/
-
- object = G_OBJECT_CLASS(class);
-
- object->dispose = (GObjectFinalizeFunc/* ! */)g_log_panel_dispose;
- object->finalize = (GObjectFinalizeFunc)g_log_panel_finalize;
-
- item = G_EDITOR_ITEM_CLASS(class);
-
- item->get_key = (get_item_key_fc)g_log_panel_class_get_key;
-
- panel = G_PANEL_ITEM_CLASS(class);
-
- panel->get_personality = (get_panel_personality_fc)g_log_panel_class_get_personality;
- panel->get_path = (get_panel_path_fc)g_log_panel_class_get_path;
- panel->get_bindings = (get_panel_bindings_fc)g_log_panel_class_get_key_bindings;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : panel = instance à initialiser. *
-* *
-* Description : Initialise une instance de panneau d'affichage des messages. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_log_panel_init(GLogPanel *panel)
-{
- GPanelItem *pitem; /* Version parente du panneau */
-
- /* Eléments de base */
-
- pitem = G_PANEL_ITEM(panel);
-
- pitem->widget = G_NAMED_WIDGET(gtk_built_named_widget_new_for_panel(_("Messages"),
- _("Misc information"),
- PANEL_LOG_ID));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : panel = instance d'objet GLib à traiter. *
-* *
-* Description : Supprime toutes les références externes. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_log_panel_dispose(GLogPanel *panel)
-{
- G_OBJECT_CLASS(g_log_panel_parent_class)->dispose(G_OBJECT(panel));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : panel = instance d'objet GLib à traiter. *
-* *
-* Description : Procède à la libération totale de la mémoire. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_log_panel_finalize(GLogPanel *panel)
-{
- G_OBJECT_CLASS(g_log_panel_parent_class)->finalize(G_OBJECT(panel));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : class = classe à consulter. *
-* *
-* Description : Fournit le nom interne attribué à l'élément réactif. *
-* *
-* Retour : Désignation (courte) de l'élément de l'éditeur. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static char *g_log_panel_class_get_key(const GLogPanelClass *class)
-{
- char *result; /* Description à renvoyer */
-
- result = strdup(PANEL_LOG_ID);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : class = classe à consulter. *
-* *
-* Description : Fournit une indication sur la personnalité du panneau. *
-* *
-* Retour : Identifiant lié à la nature unique du panneau. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static PanelItemPersonality g_log_panel_class_get_personality(const GLogPanelClass *class)
-{
- PanelItemPersonality result; /* Personnalité à retourner */
-
- result = PIP_PERSISTENT_SINGLETON;
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : class = classe à consulter. *
-* *
-* Description : Indique le chemin initial de la localisation d'un panneau. *
-* *
-* Retour : Chemin fixé associé à la position initiale. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static char *g_log_panel_class_get_path(const GLogPanelClass *class)
-{
- char *result; /* Emplacement à retourner */
-
- result = strdup("Ms");
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : class = classe à consulter. *
-* *
-* Description : Indique la définition d'un éventuel raccourci clavier. *
-* *
-* Retour : Description d'un raccourci ou NULL si aucun de défini. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static char *g_log_panel_class_get_key_bindings(const GLogPanelClass *class)
-{
- char *result; /* Emplacement à retourner */
-
- result = strdup("<Shift>F1");
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : - *
-* *
-* Description : Crée un panneau d'affichage des messages système. *
-* *
-* Retour : Adresse de la structure mise en place. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GPanelItem *g_log_panel_new(void)
-{
- GPanelItem *result; /* Structure à retourner */
-
- result = g_object_new(G_TYPE_LOG_PANEL, NULL);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : panel = instance d'objet GLib à traiter. *
-* type = espèce du message à ajouter. *
-* msg = message à faire apparaître à l'écran. *
-* *
-* Description : Affiche un message dans le journal des messages système. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_log_panel_add_message(GLogPanel *panel, LogMessageType type, const char *msg)
-{
- log_data *data; /* Paramètres à joindre */
-
- data = calloc(1, sizeof(log_data));
-
- data->item = G_PANEL_ITEM(panel);
- data->type = type;
- data->msg = strdup(msg);
-
- g_object_ref(G_OBJECT(data->item));
-
- g_main_context_invoke(NULL, (GSourceFunc)log_message, data);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : data = paramètres destinés à l'affichage d'un message. *
-* *
-* Description : Affiche un message dans le journal des messages système. *
-* *
-* Retour : - *
-* *
-* Remarques : Cette fonction, et c'est tout son intérêt, est toujours *
-* exécutée dans le contexte GTK principal. *
-* *
-******************************************************************************/
-
-static gboolean log_message(log_data *data)
-{
- GtkBuilder *builder; /* Constructeur utilisé */
- GtkListStore *store; /* Modèle de gestion */
- GtkTreeIter iter; /* Point d'insertion */
- GtkTreeView *treeview; /* Affichage de la liste */
-
- builder = gtk_built_named_widget_get_builder(GTK_BUILT_NAMED_WIDGET(G_PANEL_ITEM(data->item)->widget));
-
- /* Mise en place du message */
-
- store = GTK_LIST_STORE(gtk_builder_get_object(builder, "store"));
-
- gtk_list_store_append(store, &iter);
-
- switch (data->type)
- {
- case LMT_INFO:
- gtk_list_store_set(store, &iter,
- LGC_PICTURE, "gtk-info",
- LGC_STRING, data->msg,
- -1);
- break;
-
- case LMT_PROCESS:
- gtk_list_store_set(store, &iter,
- LGC_PICTURE, "gtk-execute",
- LGC_STRING, data->msg,
- -1);
- break;
-
- case LMT_WARNING:
- gtk_list_store_set(store, &iter,
- LGC_PICTURE, "gtk-dialog-warning",
- LGC_STRING, data->msg,
- -1);
- break;
-
- case LMT_BAD_BINARY:
- gtk_list_store_set(store, &iter,
- LGC_PICTURE, "gtk-dialog-warning",
- LGC_STRING, data->msg,
- -1);
- break;
-
- case LMT_ERROR:
- case LMT_EXT_ERROR:
- gtk_list_store_set(store, &iter,
- LGC_PICTURE, "gtk-dialog-error",
- LGC_STRING, data->msg,
- -1);
- break;
-
- default:
- gtk_list_store_set(store, &iter,
- LGC_STRING, data->msg,
- -1);
- break;
-
- }
-
- /* Défilement pour pointer à l'affichage */
-
- treeview = GTK_TREE_VIEW(gtk_builder_get_object(builder, "treeview"));
-
- scroll_to_treeview_iter(treeview, GTK_TREE_MODEL(store), &iter);
-
- g_object_unref(G_OBJECT(builder));
-
- /* Nettoyage de la mémoire */
-
- g_object_unref(G_OBJECT(data->item));
-
- free(data->msg);
-
- free(data);
-
- return G_SOURCE_REMOVE;
-
-}
diff --git a/src/gui/panels/log.h b/src/gui/panels/log.h
deleted file mode 100644
index 4d155a2..0000000
--- a/src/gui/panels/log.h
+++ /dev/null
@@ -1,67 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * log.h - prototypes pour le panneau d'affichage des messages système
- *
- * Copyright (C) 2012-2019 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 this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-#ifndef _GUI_PANELS_LOG_H
-#define _GUI_PANELS_LOG_H
-
-
-#include <i18n.h>
-
-
-#include "../panel.h"
-#include "../../core/logs.h"
-
-
-
-#define PANEL_LOG_ID "log"
-
-
-#define G_TYPE_LOG_PANEL g_log_panel_get_type()
-#define G_LOG_PANEL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_log_panel_get_type(), GLogPanel))
-#define G_IS_LOG_PANEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_log_panel_get_type()))
-#define G_LOG_PANEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_LOG_PANEL, GLogPanelClass))
-#define G_IS_LOG_PANEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_LOG_PANEL))
-#define G_LOG_PANEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_LOG_PANEL, GLogPanelClass))
-
-
-/* Panneau d'affichage de messages (instance) */
-typedef struct _GLogPanel GLogPanel;
-
-/* Panneau d'affichage de messages (classe) */
-typedef struct _GLogPanelClass GLogPanelClass;
-
-
-
-/* Indique le type défini pour un panneau d'affichage de messages. */
-GType g_log_panel_get_type(void);
-
-/* Crée un panneau d'affichage des messages système. */
-GPanelItem *g_log_panel_new(void);
-
-/* Affiche un message dans le journal des messages système. */
-void g_log_panel_add_message(GLogPanel *, LogMessageType, const char *);
-
-
-
-#endif /* _GUI_PANELS_LOG_H */
diff --git a/src/gui/panels/log.ui b/src/gui/panels/log.ui
deleted file mode 100644
index 4ffe96c..0000000
--- a/src/gui/panels/log.ui
+++ /dev/null
@@ -1,59 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.21.0 -->
-<interface>
- <requires lib="gtk+" version="3.20"/>
- <object class="GtkListStore" id="store">
- <columns>
- <!-- column-name picture -->
- <column type="gchararray"/>
- <!-- column-name string -->
- <column type="gchararray"/>
- </columns>
- </object>
- <object class="GtkOffscreenWindow">
- <property name="can_focus">False</property>
- <child>
- <object class="GtkScrolledWindow" id="box">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="shadow_type">in</property>
- <child>
- <object class="GtkTreeView" id="treeview">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="model">store</property>
- <property name="headers_visible">False</property>
- <child internal-child="selection">
- <object class="GtkTreeSelection"/>
- </child>
- <child>
- <object class="GtkTreeViewColumn">
- <property name="title" translatable="yes">picture</property>
- <child>
- <object class="GtkCellRendererPixbuf"/>
- <attributes>
- <attribute name="stock-id">0</attribute>
- </attributes>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkTreeViewColumn">
- <property name="title" translatable="yes">string</property>
- <child>
- <object class="GtkCellRendererText"/>
- <attributes>
- <attribute name="markup">1</attribute>
- </attributes>
- </child>
- </object>
- </child>
- </object>
- </child>
- </object>
- </child>
- <child type="titlebar">
- <placeholder/>
- </child>
- </object>
-</interface>
diff --git a/src/gui/panels/logs-col-icon.ui b/src/gui/panels/logs-col-icon.ui
new file mode 100644
index 0000000..6463e84
--- /dev/null
+++ b/src/gui/panels/logs-col-icon.ui
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+
+ <template class="GtkListItem">
+ <property name="child">
+ <object class="GtkImage">
+ <binding name="icon-name">
+ <lookup name="icon-name" type="GLogEntry">
+ <lookup name="item">GtkListItem</lookup>
+ </lookup>
+ </binding>
+ </object>
+ </property>
+
+ </template>
+
+</interface>
diff --git a/src/gui/panels/logs-col-message.ui b/src/gui/panels/logs-col-message.ui
new file mode 100644
index 0000000..49839e4
--- /dev/null
+++ b/src/gui/panels/logs-col-message.ui
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+
+ <template class="GtkListItem">
+ <property name="child">
+ <object class="GtkLabel">
+ <property name="xalign">0</property>
+ <property name="use-markup">true</property>
+ <binding name="label">
+ <lookup name="message" type="GLogEntry">
+ <lookup name="item">GtkListItem</lookup>
+ </lookup>
+ </binding>
+ </object>
+ </property>
+
+ </template>
+
+</interface>
diff --git a/src/gui/panels/logs-int.h b/src/gui/panels/logs-int.h
new file mode 100644
index 0000000..692c1b4
--- /dev/null
+++ b/src/gui/panels/logs-int.h
@@ -0,0 +1,53 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * logs-int.h - prototypes internes pour le panneau d'affichage des messages système
+ *
+ * Copyright (C) 2025 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _GUI_PANELS_LOGS_INT_H
+#define _GUI_PANELS_LOGS_INT_H
+
+
+#include "logs.h"
+#include "../../gtkext/panel-int.h"
+
+
+
+/* Panneau d'affichage de messages (instance) */
+struct _GtkLogsPanel
+{
+ GtkTiledPanel parent; /* A laisser en premier */
+
+ GListStore *store; /* Liste des eléments conservés*/
+ GtkWidget *list; /* Composant d'affichage */
+
+};
+
+/* Panneau d'affichage de messages (classe) */
+struct _GtkLogsPanelClass
+{
+ GtkTiledPanelClass parent; /* A laisser en premier */
+
+};
+
+
+
+#endif /* _GUI_PANELS_LOGS_INT_H */
diff --git a/src/gui/panels/logs.c b/src/gui/panels/logs.c
new file mode 100644
index 0000000..399c4c0
--- /dev/null
+++ b/src/gui/panels/logs.c
@@ -0,0 +1,227 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * logs.c - panneau d'affichage des messages système
+ *
+ * Copyright (C) 2012-2025 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "logs.h"
+
+
+#include <assert.h>
+#include <string.h>
+
+
+#include "logs-int.h"
+#include "../../gtkext/helpers.h"
+
+
+
+/* ------------------------- COEUR D'UN PANNEAU D'AFFICHAGE ------------------------- */
+
+
+/* Initialise la classe des panneaux d'affichage des journaux. */
+static void gtk_logs_panel_class_init(GtkLogsPanelClass *);
+
+/* Initialise une instance de panneau d'affichage des journaux. */
+static void gtk_logs_panel_init(GtkLogsPanel *);
+
+/* Supprime toutes les références externes. */
+static void gtk_logs_panel_dispose(GObject *);
+
+/* Procède à la libération totale de la mémoire. */
+static void gtk_logs_panel_finalize(GObject *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Indique l'emplacement par défaut pour un affichage. */
+static char *gtk_logs_panel_get_default_path(const GtkTiledPanel *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* COEUR D'UN PANNEAU D'AFFICHAGE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour un panneau d'accueil. */
+G_DEFINE_TYPE(GtkLogsPanel, gtk_logs_panel, GTK_TYPE_TILED_PANEL);
+
+
+/******************************************************************************
+* *
+* Paramètres : class = classe à initialiser. *
+* *
+* Description : Initialise la classe des panneaux d'affichage des journaux. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_logs_panel_class_init(GtkLogsPanelClass *class)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GtkWidgetClass *widget; /* Classe de haut niveau */
+ GtkTiledPanelClass *panel; /* Classe parente */
+
+ object = G_OBJECT_CLASS(class);
+
+ object->dispose = gtk_logs_panel_dispose;
+ object->finalize = gtk_logs_panel_finalize;
+
+ widget = GTK_WIDGET_CLASS(class);
+
+ g_type_ensure(G_TYPE_LOG_ENTRY);
+
+ gtk_widget_class_set_template_from_resource(widget, "/re/chrysalide/framework/gui/panels/logs.ui");
+
+ //gtk_widget_class_bind_template_callback_full(widget, BUILDER_CB(gtk_logs_panel_on_selected_rows_changed));
+
+ gtk_widget_class_bind_template_child(widget, GtkLogsPanel, store);
+ gtk_widget_class_bind_template_child(widget, GtkLogsPanel, list);
+
+ panel = GTK_TILED_PANEL_CLASS(class);
+
+ panel->get_default_path = gtk_logs_panel_get_default_path;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : panel = instance à initialiser. *
+* *
+* Description : Initialise une instance de panneau d'affichage des journaux. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_logs_panel_init(GtkLogsPanel *panel)
+{
+ GtkWidget *headers; /* Composant à cacher */
+
+ gtk_widget_init_template(GTK_WIDGET(panel));
+
+ /**
+ * Retrait des entêtes de colonne de l'affichage.
+ */
+
+ headers = gtk_widget_get_first_child(panel->list);
+
+ gtk_widget_set_visible(headers, FALSE);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_logs_panel_dispose(GObject *object)
+{
+ gtk_widget_dispose_template(GTK_WIDGET(object), GTK_TYPE_LOGS_PANEL);
+
+ G_OBJECT_CLASS(gtk_logs_panel_parent_class)->dispose(object);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_logs_panel_finalize(GObject *object)
+{
+ G_OBJECT_CLASS(gtk_logs_panel_parent_class)->finalize(object);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : panel = instance d'objet GLib à traiter. *
+* entry = élément de journalisation à intégrer. *
+* *
+* Description : Affiche un message dans le journal des messages système. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_log_panel_add_message(GtkLogsPanel *panel, GLogEntry *entry)
+{
+ g_list_store_append(panel->store, entry);
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : panel = panneau graphique à consulter. *
+* *
+* Description : Indique l'emplacement par défaut pour un affichage. *
+* *
+* Retour : Chemin représenté ou NULL pour l'emplacement "M" par défaut. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *gtk_logs_panel_get_default_path(const GtkTiledPanel *panel)
+{
+ char *result; /* Chemin à retourner */
+
+ result = strdup("S");
+
+ return result;
+
+}
diff --git a/src/gui/panels/logs.h b/src/gui/panels/logs.h
new file mode 100644
index 0000000..a8b902b
--- /dev/null
+++ b/src/gui/panels/logs.h
@@ -0,0 +1,47 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * logs.h - prototypes pour le panneau d'affichage des messages système
+ *
+ * Copyright (C) 2012-2025 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _GUI_PANELS_LOGS_H
+#define _GUI_PANELS_LOGS_H
+
+
+#include <gtk/gtk.h>
+
+
+#include "../../glibext/helpers.h"
+#include "../../glibext/log.h"
+
+
+
+#define GTK_TYPE_LOGS_PANEL (gtk_logs_panel_get_type())
+
+DECLARE_GTYPE(GtkLogsPanel, gtk_logs_panel, GTK, LOGS_PANEL);
+
+
+/* Affiche un message dans le journal des messages système. */
+void g_log_panel_add_message(GtkLogsPanel *, GLogEntry *);
+
+
+
+#endif /* _GUI_PANELS_LOGS_H */
diff --git a/src/gui/panels/logs.ui b/src/gui/panels/logs.ui
new file mode 100644
index 0000000..ba920cd
--- /dev/null
+++ b/src/gui/panels/logs.ui
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+
+ <object class="GtkNoSelection" id="noselection">
+ <property name="model">
+ <object class="GListStore" id="store">
+ <property name="item-type">GLogEntry</property>
+ </object>
+ </property>
+ </object>
+
+ <template class="GtkLogsPanel" parent="GtkTiledPanel">
+
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="hscrollbar-policy">automatic</property>
+ <property name="vscrollbar-policy">automatic</property>
+ <property name="hexpand">true</property>
+ <property name="vexpand">true</property>
+ <property name="has-frame">0</property>
+
+ <child>
+ <object class="GtkColumnView" id="list">
+ <property name="vexpand">true</property>
+ <property name="model">noselection</property>
+
+ <child>
+ <object class="GtkColumnViewColumn">
+ <property name="title"></property>
+ <property name="factory">
+ <object class="GtkBuilderListItemFactory">
+ <property name="resource">/re/chrysalide/framework/gui/panels/logs-col-icon.ui</property>
+ </object>
+ </property>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkColumnViewColumn">
+ <property name="expand">true</property>
+ <property name="title">Message</property>
+ <property name="factory">
+ <object class="GtkBuilderListItemFactory">
+ <property name="resource">/re/chrysalide/framework/gui/panels/logs-col-message.ui</property>
+ </object>
+ </property>
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ </template>
+
+</interface>
diff --git a/src/gui/style.css b/src/gui/style.css
index 9078310..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 */
@@ -61,3 +57,15 @@ grid.hints > box {
min-width: 130px;
}
+
+
+/* dockstation.css */
+
+.control-button {
+
+ min-height: 0;
+ min-width: 0;
+
+ padding: 6px;
+
+}
diff --git a/src/gui/window-int.h b/src/gui/window-int.h
index d79e189..4f3dd57 100644
--- a/src/gui/window-int.h
+++ b/src/gui/window-int.h
@@ -37,7 +37,10 @@ struct _GtkFrameworkWindow
GSettings *settings; /* Paramètres globaux */
- GtkStack *grid; /* Réceptacle de panneaux */
+ 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 f45cec9..e14ecf7 100644
--- a/src/gui/window.c
+++ b/src/gui/window.c
@@ -29,9 +29,10 @@
#include "core/panels.h"
#include "dialogs/about.h"
#include "dialogs/preferences.h"
+#include "panels/logs.h"
#include "panels/welcome.h"
+#include "../gtkext/grid.h"
#include "../gtkext/helpers.h"
-#include "../gtkext/statusstack.h"
@@ -42,10 +43,25 @@ static void gtk_framework_window_class_init(GtkFrameworkWindowClass *);
static void gtk_framework_window_init(GtkFrameworkWindow *);
/* Supprime toutes les références externes. */
-static void gtk_framework_window_dispose(GtkFrameworkWindow *);
+static void gtk_framework_window_dispose(GObject *);
/* Procède à la libération totale de la mémoire. */
-static void gtk_framework_window_finalize(GtkFrameworkWindow *);
+static void gtk_framework_window_finalize(GObject *);
+
+/* Bascule l'affichage d'un panneau de bordure. */
+static void gtk_framework_window_toggle_pannel_visibility(GtkFrameworkWindow *, TilingGridBorder);
+
+/* Réagit à une activation de bascule du panneau supérieur. */
+static void gtk_framework_window_activate_toggle_top(GSimpleAction *, GVariant *, gpointer);
+
+/* Réagit à une activation de bascule du panneau de gauche. */
+static void gtk_framework_window_activate_toggle_left(GSimpleAction *action, GVariant *, gpointer);
+
+/* Réagit à une activation de bascule du panneau de droite. */
+static void gtk_framework_window_activate_toggle_right(GSimpleAction *, GVariant *, gpointer);
+
+/* Réagit à une activation de bascule du panneau inférieur. */
+static void gtk_framework_window_activate_toggle_bottom(GSimpleAction *, GVariant *, gpointer);
/* Réagit à une activation du menu "Préférences" de la fenetre. */
static void gtk_framework_window_activate_preferences(GSimpleAction *, GVariant *, gpointer);
@@ -83,11 +99,13 @@ static void gtk_framework_window_class_init(GtkFrameworkWindowClass *class)
widget = GTK_WIDGET_CLASS(class);
+ g_type_ensure(GTK_TYPE_TILING_GRID);
g_type_ensure(GTK_TYPE_STATUS_STACK);
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);
@@ -111,7 +129,13 @@ static void gtk_framework_window_class_init(GtkFrameworkWindowClass *class)
static void gtk_framework_window_init(GtkFrameworkWindow *window)
{
+ GAction *action; /* Action mise en place */
+
static GActionEntry app_entries[] = {
+ { "toggle-top", gtk_framework_window_activate_toggle_top, NULL, NULL, NULL },
+ { "toggle-left", gtk_framework_window_activate_toggle_left, NULL, NULL, NULL },
+ { "toggle-right", gtk_framework_window_activate_toggle_right, NULL, NULL, NULL },
+ { "toggle-bottom", gtk_framework_window_activate_toggle_bottom, NULL, NULL, NULL },
{ "preferences", gtk_framework_window_activate_preferences, NULL, NULL, NULL },
{ "about", gtk_framework_window_activate_about, NULL, NULL, NULL },
};
@@ -124,16 +148,47 @@ 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);
+ /**
+ * Définition de l'accès aux actions pour obtenir un effet de bord sur
+ * l'accès aux boutons graphiques de déclenchement.
+ */
+
+ action = g_action_map_lookup_action(G_ACTION_MAP(window), "toggle-top");
+
+ g_object_bind_property(G_OBJECT(window->grid), "empty-top",
+ G_OBJECT(action), "enabled",
+ G_BINDING_SYNC_CREATE | G_BINDING_INVERT_BOOLEAN);
+
+ action = g_action_map_lookup_action(G_ACTION_MAP(window), "toggle-left");
+
+ g_object_bind_property(G_OBJECT(window->grid), "empty-left",
+ G_OBJECT(action), "enabled",
+ G_BINDING_SYNC_CREATE | G_BINDING_INVERT_BOOLEAN);
+
+ action = g_action_map_lookup_action(G_ACTION_MAP(window), "toggle-right");
+
+ g_object_bind_property(G_OBJECT(window->grid), "empty-right",
+ G_OBJECT(action), "enabled",
+ G_BINDING_SYNC_CREATE | G_BINDING_INVERT_BOOLEAN);
+
+ action = g_action_map_lookup_action(G_ACTION_MAP(window), "toggle-bottom");
+
+ g_object_bind_property(G_OBJECT(window->grid), "empty-bottom",
+ G_OBJECT(action), "enabled",
+ G_BINDING_SYNC_CREATE | G_BINDING_INVERT_BOOLEAN);
+
}
/******************************************************************************
* *
-* Paramètres : window = instance d'objet GLib à traiter. *
+* Paramètres : object = instance d'objet GLib à traiter. *
* *
* Description : Supprime toutes les références externes. *
* *
@@ -143,20 +198,26 @@ static void gtk_framework_window_init(GtkFrameworkWindow *window)
* *
******************************************************************************/
-static void gtk_framework_window_dispose(GtkFrameworkWindow *window)
+static void gtk_framework_window_dispose(GObject *object)
{
+ GtkFrameworkWindow *window; /* Version spécialisée */
+
+ window = GTK_FRAMEWORK_WINDOW(object);
+
gtk_widget_dispose_template(GTK_WIDGET(window), GTK_TYPE_FRAMEWORK_WINDOW);
g_clear_object(&window->settings);
- G_OBJECT_CLASS(gtk_framework_window_parent_class)->dispose(G_OBJECT(window));
+ g_clear_object(&window->main);
+
+ G_OBJECT_CLASS(gtk_framework_window_parent_class)->dispose(object);
}
/******************************************************************************
* *
-* Paramètres : window = instance d'objet GLib à traiter. *
+* Paramètres : object = instance d'objet GLib à traiter. *
* *
* Description : Procède à la libération totale de la mémoire. *
* *
@@ -166,9 +227,9 @@ static void gtk_framework_window_dispose(GtkFrameworkWindow *window)
* *
******************************************************************************/
-static void gtk_framework_window_finalize(GtkFrameworkWindow *window)
+static void gtk_framework_window_finalize(GObject *object)
{
- G_OBJECT_CLASS(gtk_framework_window_parent_class)->finalize(G_OBJECT(window));
+ G_OBJECT_CLASS(gtk_framework_window_parent_class)->finalize(object);
}
@@ -228,6 +289,14 @@ bool gtk_framework_window_create(GtkFrameworkWindow *window, GtkApplication *app
gtk_framework_window_add(window, panel);
+ if (1/* FIXME : first time */)
+ {
+ panel = get_framework_panel_singleton(GTK_TYPE_LOGS_PANEL);
+
+ gtk_framework_window_add(window, panel);
+
+ }
+
/* Chargement des extensions de thème */
css = gtk_css_provider_new();
@@ -257,6 +326,116 @@ bool gtk_framework_window_create(GtkFrameworkWindow *window, GtkApplication *app
/******************************************************************************
* *
+* Paramètres : window = instance de fenêtre principale à manipuler. *
+* border = sélection de la zone à considérer. *
+* *
+* Description : Bascule l'affichage d'un panneau de bordure. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_framework_window_toggle_pannel_visibility(GtkFrameworkWindow *window, TilingGridBorder border)
+{
+ bool state; /* Etat courant à basculer */
+
+ state = gtk_tiling_grid_get_visible(window->grid, border);
+
+ state = !state;
+
+ gtk_tiling_grid_set_visible(window->grid, border, state);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : action = désignation de l'action concernée par l'appel. *
+* unused = adresse non utilisée ici. *
+* _window = instance de fenêtre principale à manipuler. *
+* *
+* Description : Réagit à une activation de bascule du panneau supérieur. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_framework_window_activate_toggle_top(GSimpleAction *action, GVariant *unused, gpointer _window)
+{
+ gtk_framework_window_toggle_pannel_visibility(_window, TGB_TOP);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : action = désignation de l'action concernée par l'appel. *
+* unused = adresse non utilisée ici. *
+* _window = instance de fenêtre principale à manipuler. *
+* *
+* Description : Réagit à une activation de bascule du panneau de gauche. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_framework_window_activate_toggle_left(GSimpleAction *action, GVariant *unused, gpointer _window)
+{
+ gtk_framework_window_toggle_pannel_visibility(_window, TGB_LEFT);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : action = désignation de l'action concernée par l'appel. *
+* unused = adresse non utilisée ici. *
+* _window = instance de fenêtre principale à manipuler. *
+* *
+* Description : Réagit à une activation de bascule du panneau de droite. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_framework_window_activate_toggle_right(GSimpleAction *action, GVariant *unused, gpointer _window)
+{
+ gtk_framework_window_toggle_pannel_visibility(_window, TGB_RIGHT);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : action = désignation de l'action concernée par l'appel. *
+* unused = adresse non utilisée ici. *
+* _window = instance de fenêtre principale à manipuler. *
+* *
+* Description : Réagit à une activation de bascule du panneau inférieur. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_framework_window_activate_toggle_bottom(GSimpleAction *action, GVariant *unused, gpointer _window)
+{
+ gtk_framework_window_toggle_pannel_visibility(_window, TGB_BOTTOM);
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : action = désignation de l'action concernée par l'appel. *
* unused = adresse non utilisée ici. *
* _window = instance de fenêtre principale à manipuler. *
@@ -313,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. *
* *
@@ -331,10 +535,12 @@ 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 */
+
+
- gtk_stack_add_child(window->grid, GTK_WIDGET(panel));
+ gtk_tiling_grid_add_panel(window->grid, panel, G_OBJECT_TYPE(panel) == GTK_TYPE_WELCOME_PANEL);
- gtk_stack_set_visible_child(window->grid, GTK_WIDGET(panel));
@@ -362,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 */
diff --git a/src/gui/window.ui b/src/gui/window.ui
index 363ea54..1c6a89a 100644
--- a/src/gui/window.ui
+++ b/src/gui/window.ui
@@ -22,6 +22,23 @@
<child type="titlebar">
<object class="GtkHeaderBar">
+
+ <child type="start">
+ <object class="GtkToggleButton">
+ <property name="icon-name">dock-station-left-symbolic</property>
+ <property name="action-name">win.toggle-left</property>
+ <property name="active" bind-source="grid" bind-property="visible-left" bind-flags="sync-create"/>
+ </object>
+ </child>
+
+ <child type="end">
+ <object class="GtkToggleButton">
+ <property name="icon-name">dock-station-right-symbolic</property>
+ <property name="action-name">win.toggle-right</property>
+ <property name="active" bind-source="grid" bind-property="visible-right" bind-flags="sync-create"/>
+ </object>
+ </child>
+
<child type="end">
<object class="GtkMenuButton">
<property name="icon-name">open-menu-symbolic</property>
@@ -37,7 +54,7 @@
<property name="orientation">vertical</property>
<child>
- <object class="GtkStack" id="grid">
+ <object class="GtkTilingGrid" id="grid">
<property name="vexpand">TRUE</property>
</object>
</child>
@@ -50,6 +67,7 @@
<child>
<object class="GtkStatusStack" id="status">
+ <property name="show-bottom" bind-source="grid" bind-property="visible-bottom" bind-flags="sync-create"/>
</object>
</child>
diff --git a/src/rost.c b/src/rost.c
index 4a052c3..b94b367 100644
--- a/src/rost.c
+++ b/src/rost.c
@@ -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/src/schemas/re.chrysalide.framework.gschema.xml b/src/schemas/re.chrysalide.framework.gschema.xml
index 80a20db..534f735 100644
--- a/src/schemas/re.chrysalide.framework.gschema.xml
+++ b/src/schemas/re.chrysalide.framework.gschema.xml
@@ -3,6 +3,7 @@
<schema id="re.chrysalide.framework" path="/re/chrysalide/framework/">
<child schema="re.chrysalide.framework.paths" name="paths"/>
<child schema="re.chrysalide.framework.gui" name="gui"/>
+ <child schema="re.chrysalide.framework.tiledgrid" name="tiles"/>
<child schema="re.chrysalide.framework.secstorage" name="secstorage"/>
</schema>
@@ -28,6 +29,71 @@
</key>
</schema>
+ <flags id="re.chrysalide.framework.tiledgrid.LayoutReachOptions">
+ <value nick="left-top-reach" value="1"/>
+ <value nick="left-bottom-reach" value="2"/>
+ <value nick="right-top-reach" value="4"/>
+ <value nick="right-bottom-reach" value="8"/>
+ </flags>
+
+ <schema id="re.chrysalide.framework.tiledgrid">
+
+ <key name="layout" flags="re.chrysalide.framework.tiledgrid.LayoutReachOptions">
+ <default>["left-top-reach","right-top-reach"]</default>
+ <summary>Main panel layout</summary>
+ <description>Layout details describing the border panel locations</description>
+ </key>
+
+ <key name="top-visibility" type="b">
+ <default>false</default>
+ <summary>Top panel visibility</summary>
+ <description>Visbility of the panel located at the top of a tiling grid</description>
+ </key>
+
+ <key name="top-request" type="u">
+ <default>300</default>
+ <summary>Top panel height</summary>
+ <description>Height request for the panel located at the top of a tiling grid</description>
+ </key>
+
+ <key name="left-visibility" type="b">
+ <default>false</default>
+ <summary>Left panel visibility</summary>
+ <description>Visbility of the panel located at the left of a tiling grid</description>
+ </key>
+
+ <key name="left-request" type="u">
+ <default>300</default>
+ <summary>Left panel height</summary>
+ <description>Width request for the panel located at the left of a tiling grid</description>
+ </key>
+
+ <key name="right-visibility" type="b">
+ <default>false</default>
+ <summary>Right panel visibility</summary>
+ <description>Visbility of the panel located at the right of a tiling grid</description>
+ </key>
+
+ <key name="right-request" type="u">
+ <default>300</default>
+ <summary>Right panel height</summary>
+ <description>Width request for the panel located at the right of a tiling grid</description>
+ </key>
+
+ <key name="bottom-visibility" type="b">
+ <default>false</default>
+ <summary>Bottom panel visibility</summary>
+ <description>Visbility of the panel located at the bottom of a tiling grid</description>
+ </key>
+
+ <key name="bottom-request" type="u">
+ <default>250</default>
+ <summary>Bottom panel height</summary>
+ <description>Height request for the panel located at the bottom of a tiling grid</description>
+ </key>
+
+ </schema>
+
<schema id="re.chrysalide.framework.secstorage" path="/re/chrysalide/framework/secstorage/">
<key name="salt" type="ay">
<default>[]</default>
diff --git a/tests/arch/instruction.py b/tests/arch/instruction.py
new file mode 100644
index 0000000..da4d8c1
--- /dev/null
+++ b/tests/arch/instruction.py
@@ -0,0 +1,52 @@
+
+import pychrysalide
+from chrysacase import ChrysalideTestCase
+from pychrysalide.arch import ArchInstruction
+
+
+class TestProcessor(ChrysalideTestCase):
+ """TestCase for arch.ArchProcessor."""
+
+
+ def testAbstractClass(self):
+ """Forbid instruction class instance."""
+
+ with self.assertRaisesRegex(RuntimeError, 'pychrysalide.arch.ArchInstruction is an abstract class'):
+ ins = ArchInstruction()
+
+
+ def testInstructionBasicImplementation(self):
+ """Implement basic custom instructions."""
+
+
+ class TodoInstruction(ArchInstruction):
+
+ def __init__(self):
+ super().__init__(0x123)
+
+
+ ins = TodoInstruction()
+
+ with self.assertRaisesRegex(NotImplementedError, 'unexpected NULL value as encoding'):
+ print(ins.encoding)
+
+ with self.assertRaisesRegex(NotImplementedError, 'unexpected NULL value as keyword'):
+ print(ins.keyword)
+
+
+ class CustomInstruction(ArchInstruction):
+
+ def __init__(self):
+ super().__init__(0x123)
+
+ def _get_encoding(self):
+ return 'custom'
+
+ def _get_keyword(self):
+ return 'kw'
+
+
+ ins = CustomInstruction()
+
+ self.assertEqual('custom', ins.encoding)
+ self.assertEqual('kw', ins.keyword)
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
new file mode 100644
index 0000000..0585fe6
--- /dev/null
+++ b/tools/about/courier-10-pitch-bold_EQ97V.zip
Binary files differ
diff --git a/tools/about/courier10point.zip b/tools/about/courier10point.zip
new file mode 100644
index 0000000..82cd0de
--- /dev/null
+++ b/tools/about/courier10point.zip
Binary files differ
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
new file mode 100644
index 0000000..9bf9969
--- /dev/null
+++ b/tools/about/logo.png
Binary files differ
diff --git a/tools/about/noise.png b/tools/about/noise.png
new file mode 100644
index 0000000..b5d6b91
--- /dev/null
+++ b/tools/about/noise.png
Binary files differ
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