From 932ea7c83c07d3982fee605c6dd9895fd2753874 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Fri, 30 Dec 2016 11:38:52 +0100 Subject: Rewritten the line buffers using generators and on-demand building to save memory. --- ChangeLog | 220 ++++ configure.ac | 5 +- plugins/Makefile.am | 3 +- plugins/pychrysa/analysis/binary.c | 16 +- plugins/pychrysa/glibext/Makefile.am | 2 +- plugins/pychrysa/glibext/buffercache.c | 165 +++ plugins/pychrysa/glibext/buffercache.h | 42 + plugins/pychrysa/glibext/codebuffer.c | 161 --- plugins/pychrysa/glibext/codebuffer.h | 42 - plugins/pychrysa/glibext/module.c | 4 +- plugins/pychrysa/gtkext/Makefile.am | 4 +- plugins/pychrysa/gtkext/blockdisplay.c | 109 ++ plugins/pychrysa/gtkext/blockdisplay.h | 42 + plugins/pychrysa/gtkext/blockview.c | 108 -- plugins/pychrysa/gtkext/blockview.h | 42 - plugins/pychrysa/gtkext/bufferdisplay.c | 109 ++ plugins/pychrysa/gtkext/bufferdisplay.h | 42 + plugins/pychrysa/gtkext/bufferview.c | 108 -- plugins/pychrysa/gtkext/bufferview.h | 42 - plugins/pychrysa/gtkext/module.c | 8 +- plugins/ropgadgets/select.c | 23 +- src/analysis/Makefile.am | 3 +- src/analysis/binary.c | 29 +- src/analysis/binary.h | 7 +- src/analysis/content.c | 2 +- src/analysis/db/items/bookmark.c | 4 +- src/analysis/db/items/comment.c | 335 +++++- src/analysis/db/items/comment.h | 9 - src/analysis/db/items/move.h | 2 +- src/analysis/db/items/switcher.c | 5 +- src/analysis/disass/area.h | 1 + src/analysis/disass/disassembler.c | 127 +-- src/analysis/disass/disassembler.h | 2 +- src/analysis/disass/output.c | 183 +--- src/analysis/disass/output.h | 8 +- src/analysis/human/Makefile.am | 19 + src/analysis/human/asm/Makefile.am | 17 + src/analysis/human/asm/lang.c | 221 ++++ src/analysis/human/asm/lang.h | 58 + src/analysis/human/lang-int.h | 58 + src/analysis/human/lang.c | 167 +++ src/analysis/human/lang.h | 58 + src/analysis/project.c | 18 +- src/arch/dalvik/link.c | 5 + src/arch/instruction-int.h | 2 +- src/arch/instruction.c | 293 +++-- src/arch/instruction.h | 4 - src/arch/raw.c | 45 +- src/arch/undefined.c | 23 +- src/arch/vmpa.h | 4 +- src/format/dex/dex.c | 4 +- src/format/dex/pool.h | 1 + src/format/dwarf/v2/dwarf.h | 3 +- src/format/dwarf/v3/dwarf.h | 3 +- src/format/dwarf/v4/dwarf.h | 3 +- src/format/elf/symbols.h | 1 + src/format/format-int.h | 5 +- src/format/java/java.h | 2 +- src/format/pe/pe.h | 2 +- src/format/symbol.c | 221 +++- src/format/symbol.h | 12 + src/glibext/Makefile.am | 9 +- src/glibext/gbinportion.c | 345 ++++-- src/glibext/gbinportion.h | 4 - src/glibext/gbuffercache.c | 1625 ++++++++++++++++++++++++++++ src/glibext/gbuffercache.h | 121 +++ src/glibext/gbufferline.c | 176 ++- src/glibext/gbufferline.h | 9 + src/glibext/gbufferview.c | 810 ++++++-------- src/glibext/gbufferview.h | 47 +- src/glibext/gcodebuffer.c | 1778 ------------------------------- src/glibext/gcodebuffer.h | 155 --- src/glibext/generator-int.h | 52 + src/glibext/generators/Makefile.am | 15 + src/glibext/generators/prologue.c | 359 +++++++ src/glibext/generators/prologue.h | 58 + src/glibext/generators/rborder.c | 361 +++++++ src/glibext/generators/rborder.h | 60 ++ src/glibext/gwidthtracker.c | 59 +- src/glibext/gwidthtracker.h | 10 +- src/glibext/linecolumn.c | 2 +- src/glibext/linegen-int.h | 67 ++ src/glibext/linegen.c | 208 ++++ src/glibext/linegen.h | 68 ++ src/glibext/linesegment.c | 9 + src/glibext/linesegment.h | 9 +- src/gtkext/Makefile.am | 29 +- src/gtkext/graph/cluster.c | 48 +- src/gtkext/graph/cluster.h | 4 +- src/gtkext/graph/edge.c | 27 + src/gtkext/graph/edge.h | 3 + src/gtkext/gtkblockdisplay.c | 337 ++++++ src/gtkext/gtkblockdisplay.h | 56 + src/gtkext/gtkblockview.c | 289 ----- src/gtkext/gtkblockview.h | 56 - src/gtkext/gtkbufferdisplay-int.h | 68 ++ src/gtkext/gtkbufferdisplay.c | 1104 +++++++++++++++++++ src/gtkext/gtkbufferdisplay.h | 70 ++ src/gtkext/gtkbufferview-int.h | 73 -- src/gtkext/gtkbufferview.c | 1243 --------------------- src/gtkext/gtkbufferview.h | 70 -- src/gtkext/gtkdisplaypanel-int.h | 6 - src/gtkext/gtkdisplaypanel.c | 16 +- src/gtkext/gtkgraphdisplay.c | 1226 +++++++++++++++++++++ src/gtkext/gtkgraphdisplay.h | 64 ++ src/gtkext/gtkgraphview.c | 1371 ------------------------ src/gtkext/gtkgraphview.h | 64 -- src/gtkext/gtksourceview.c | 156 --- src/gtkext/gtksourceview.h | 56 - src/gui/dialogs/export.c | 11 +- src/gui/dialogs/gotox.c | 3 +- src/gui/editem-int.h | 1 - src/gui/editem.c | 11 +- src/gui/editor.c | 6 +- src/gui/menus/edition.c | 1 - src/gui/menus/view.c | 75 +- src/gui/status.c | 15 +- src/gui/tb/Makefile.am | 1 - src/gui/tb/source.c | 321 ------ src/gui/tb/source.h | 56 - src/plugins/plugin.h | 1 + 121 files changed, 9163 insertions(+), 7454 deletions(-) create mode 100644 plugins/pychrysa/glibext/buffercache.c create mode 100644 plugins/pychrysa/glibext/buffercache.h delete mode 100644 plugins/pychrysa/glibext/codebuffer.c delete mode 100644 plugins/pychrysa/glibext/codebuffer.h create mode 100644 plugins/pychrysa/gtkext/blockdisplay.c create mode 100644 plugins/pychrysa/gtkext/blockdisplay.h delete mode 100644 plugins/pychrysa/gtkext/blockview.c delete mode 100644 plugins/pychrysa/gtkext/blockview.h create mode 100644 plugins/pychrysa/gtkext/bufferdisplay.c create mode 100644 plugins/pychrysa/gtkext/bufferdisplay.h delete mode 100644 plugins/pychrysa/gtkext/bufferview.c delete mode 100644 plugins/pychrysa/gtkext/bufferview.h create mode 100755 src/analysis/human/Makefile.am create mode 100755 src/analysis/human/asm/Makefile.am create mode 100644 src/analysis/human/asm/lang.c create mode 100644 src/analysis/human/asm/lang.h create mode 100644 src/analysis/human/lang-int.h create mode 100644 src/analysis/human/lang.c create mode 100644 src/analysis/human/lang.h create mode 100644 src/glibext/gbuffercache.c create mode 100644 src/glibext/gbuffercache.h delete mode 100644 src/glibext/gcodebuffer.c delete mode 100644 src/glibext/gcodebuffer.h create mode 100644 src/glibext/generator-int.h create mode 100644 src/glibext/generators/Makefile.am create mode 100644 src/glibext/generators/prologue.c create mode 100644 src/glibext/generators/prologue.h create mode 100644 src/glibext/generators/rborder.c create mode 100644 src/glibext/generators/rborder.h create mode 100644 src/glibext/linegen-int.h create mode 100644 src/glibext/linegen.c create mode 100644 src/glibext/linegen.h create mode 100644 src/gtkext/gtkblockdisplay.c create mode 100644 src/gtkext/gtkblockdisplay.h delete mode 100644 src/gtkext/gtkblockview.c delete mode 100644 src/gtkext/gtkblockview.h create mode 100644 src/gtkext/gtkbufferdisplay-int.h create mode 100644 src/gtkext/gtkbufferdisplay.c create mode 100644 src/gtkext/gtkbufferdisplay.h delete mode 100644 src/gtkext/gtkbufferview-int.h delete mode 100644 src/gtkext/gtkbufferview.c delete mode 100644 src/gtkext/gtkbufferview.h create mode 100644 src/gtkext/gtkgraphdisplay.c create mode 100644 src/gtkext/gtkgraphdisplay.h delete mode 100644 src/gtkext/gtkgraphview.c delete mode 100644 src/gtkext/gtkgraphview.h delete mode 100644 src/gtkext/gtksourceview.c delete mode 100644 src/gtkext/gtksourceview.h delete mode 100644 src/gui/tb/source.c delete mode 100644 src/gui/tb/source.h diff --git a/ChangeLog b/ChangeLog index 68ece4c..3130325 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,223 @@ +16-12-30 Cyrille Bagard + + * configure.ac: + Extend AC_CONFIG_COMMANDS. Add the new Makefiles from the + 'src/analysis/human', 'src/analysis/human/asm' and + 'src/glibext/generators' directories. + + * plugins/Makefile.am: + Remove the 'androhelpers' plugin from the compilation process. + + * plugins/pychrysa/analysis/binary.c: + Move from buffer to cache. + + * plugins/pychrysa/glibext/Makefile.am: + Replace 'codebuffer.[ch]' by 'buffercache.[ch]' in + libpychrysaglibext_la_SOURCES. + + * plugins/pychrysa/glibext/buffercache.c: + * plugins/pychrysa/glibext/buffercache.h: + * plugins/pychrysa/glibext/codebuffer.c: + * plugins/pychrysa/glibext/codebuffer.h: + Renamed entries. + + * plugins/pychrysa/glibext/module.c: + Update code. + + * plugins/pychrysa/gtkext/Makefile.am: + Replace 'blockview.[ch]' by 'blockdisplay.[ch]' and 'bufferview.[ch]' + by 'bufferdisplay.[ch]' in libpychrysagtkext_la_SOURCES. + + * plugins/pychrysa/gtkext/blockdisplay.c: + * plugins/pychrysa/gtkext/blockdisplay.h: + * plugins/pychrysa/gtkext/blockview.c: + * plugins/pychrysa/gtkext/blockview.h: + * plugins/pychrysa/gtkext/bufferdisplay.c: + * plugins/pychrysa/gtkext/bufferdisplay.h: + * plugins/pychrysa/gtkext/bufferview.c: + * plugins/pychrysa/gtkext/bufferview.h: + Renamed entries. + + * plugins/pychrysa/gtkext/module.c: + Update code. + + * plugins/ropgadgets/select.c: + Print lines using the new generation interface. + + * src/analysis/Makefile.am: + Add 'human/libanalysishuman.la' to libanalysis_la_LIBADD and 'human' + to SUBDIRS. + + * src/analysis/binary.c: + * src/analysis/binary.h: + Move from buffer to cache. Remove the source view. + + * src/analysis/content.c: + Typo. + + * src/analysis/db/items/bookmark.c: + Disable the item action. + + * src/analysis/db/items/comment.c: + * src/analysis/db/items/comment.h: + Print comments using the new generation interface. + + * src/analysis/db/items/move.h: + Typo. + + * src/analysis/db/items/switcher.c: + Disable the item action. + + * src/analysis/disass/area.h: + * src/analysis/disass/disassembler.c: + * src/analysis/disass/disassembler.h: + * src/analysis/disass/output.c: + * src/analysis/disass/output.h: + Use the new defined generators and update the code. + + * src/analysis/human/Makefile.am: + * src/analysis/human/asm/Makefile.am: + * src/analysis/human/asm/lang.c: + * src/analysis/human/asm/lang.h: + * src/analysis/human/lang-int.h: + * src/analysis/human/lang.c: + * src/analysis/human/lang.h: + New entries: prepare ASM-like comments. + + * src/analysis/project.c: + Update code and remove the source view. + + * src/arch/dalvik/link.c: + Fix code to build local comments. + + * src/arch/instruction-int.h: + * src/arch/instruction.c: + * src/arch/instruction.h: + * src/arch/raw.c: + * src/arch/undefined.c: + Define instructions as generators. + + * src/arch/vmpa.h: + Create is_invalid_vmpa(). + + * src/format/dex/dex.c: + * src/format/dex/pool.h: + * src/format/dwarf/v2/dwarf.h: + * src/format/dwarf/v3/dwarf.h: + * src/format/dwarf/v4/dwarf.h: + * src/format/elf/symbols.h: + * src/format/format-int.h: + * src/format/java/java.h: + * src/format/pe/pe.h: + Update code. + + * src/format/symbol.c: + * src/format/symbol.h: + Define symbols as generators. + + * src/glibext/Makefile.am: + Replace 'gcodebuffer.[ch]' by 'gbuffercache.[ch]' and add 'linegen*[ch]' + in libglibext_la_SOURCES. Add 'generators/libglibextgenerators.la' to + libglibext_la_LIBADD and 'generators' to SUBDIRS. + + * src/glibext/gbinportion.c: + * src/glibext/gbinportion.h: + Define portions as generators. + + * src/glibext/gbuffercache.c: + * src/glibext/gbuffercache.h: + Renamed entries. + + * src/glibext/gbufferline.c: + * src/glibext/gbufferline.h: + Update code. + + * src/glibext/gbufferview.c: + * src/glibext/gbufferview.h: + Rewrite the line buffers using generators and on-demand building to save + memory. + + * src/glibext/gcodebuffer.c: + * src/glibext/gcodebuffer.h: + Renamed entries. + + * src/glibext/generator-int.h: + * src/glibext/generators/Makefile.am: + * src/glibext/generators/prologue.c: + * src/glibext/generators/prologue.h: + * src/glibext/generators/rborder.c: + * src/glibext/generators/rborder.h: + New entries: provide some useful basic generators. + + * src/glibext/gwidthtracker.c: + * src/glibext/gwidthtracker.h: + Update code. + + * src/glibext/linecolumn.c: + Improve one assertion. + + * src/glibext/linegen-int.h: + * src/glibext/linegen.c: + * src/glibext/linegen.h: + New entries: define an interface to deal with line content. + + * src/glibext/linesegment.c: + * src/glibext/linesegment.h: + Extend CSS definitions. + + * src/gtkext/Makefile.am: + Update libgtkext_la_SOURCES. + + * src/gtkext/graph/cluster.c: + * src/gtkext/graph/cluster.h: + * src/gtkext/graph/edge.c: + * src/gtkext/graph/edge.h: + Update code. + + * src/gtkext/gtkblockdisplay.c: + * src/gtkext/gtkblockdisplay.h: + * src/gtkext/gtkblockview.c: + * src/gtkext/gtkblockview.h: + * src/gtkext/gtkbufferdisplay-int.h: + * src/gtkext/gtkbufferdisplay.c: + * src/gtkext/gtkbufferdisplay.h: + * src/gtkext/gtkbufferview-int.h: + * src/gtkext/gtkbufferview.c: + * src/gtkext/gtkbufferview.h: + * src/gtkext/gtkdisplaypanel-int.h: + * src/gtkext/gtkdisplaypanel.c: + * src/gtkext/gtkgraphdisplay.c: + * src/gtkext/gtkgraphdisplay.h: + * src/gtkext/gtkgraphview.c: + * src/gtkext/gtkgraphview.h: + Renamed entries. + + * src/gtkext/gtksourceview.c: + * src/gtkext/gtksourceview.h: + Deleted entries. + + * src/gui/dialogs/export.c: + * src/gui/dialogs/gotox.c: + Disable code. + + * src/gui/editem-int.h: + * src/gui/editem.c: + * src/gui/editor.c: + * src/gui/menus/edition.c: + * src/gui/menus/view.c: + * src/gui/status.c: + Update code. + + * src/gui/tb/Makefile.am: + Remove 'source.[ch]' from libguitb_la_SOURCES. + + * src/gui/tb/source.c: + * src/gui/tb/source.h: + Deleted entries. + + * src/plugins/plugin.h: + Update code. + 16-12-29 Cyrille Bagard * src/analysis/disass/limit.c: diff --git a/configure.ac b/configure.ac index d6a96b7..04be709 100644 --- a/configure.ac +++ b/configure.ac @@ -309,7 +309,7 @@ AC_SUBST(LIBPYGOBJECT_LIBS) AC_CONFIG_FILES([stamp-h po/Makefile.in], [echo timestamp > stamp-h]) -AC_CONFIG_COMMANDS([marshal], [echo -e "VOID:UINT64\nVOID:UINT64,UINT64\nVOID:INT,UINT64,INT\nVOID:OBJECT,OBJECT\nVOID:ENUM,OBJECT\nVOID:ENUM,ENUM" > src/glibext/chrysamarshal.list]) +AC_CONFIG_COMMANDS([marshal], [echo -e "VOID:UINT64\nVOID:UINT64,UINT64\nVOID:INT,UINT64,INT\nVOID:OBJECT,OBJECT\nVOID:ENUM,OBJECT\nVOID:ENUM,ENUM\nVOID:BOOLEAN,ULONG,ULONG" > src/glibext/chrysamarshal.list]) AC_CONFIG_FILES([Makefile pixmaps/Makefile @@ -355,6 +355,8 @@ AC_CONFIG_FILES([Makefile src/analysis/db/misc/Makefile src/analysis/decomp/Makefile src/analysis/disass/Makefile + src/analysis/human/Makefile + src/analysis/human/asm/Makefile src/analysis/types/Makefile src/arch/Makefile src/arch/arm/Makefile @@ -393,6 +395,7 @@ AC_CONFIG_FILES([Makefile src/format/mangling/itanium/Makefile src/format/pe/Makefile src/glibext/Makefile + src/glibext/generators/Makefile src/gtkext/Makefile src/gtkext/graph/Makefile src/gui/Makefile diff --git a/plugins/Makefile.am b/plugins/Makefile.am index 0500b07..9b5cd17 100644 --- a/plugins/Makefile.am +++ b/plugins/Makefile.am @@ -3,4 +3,5 @@ if HAVE_PYTHON3_CONFIG PYTHON3_SUBDIRS = pychrysa python endif -SUBDIRS = androhelpers devdbg libcsem mobicore $(PYTHON3_SUBDIRS) readdex readelf ropgadgets stackvars +# androhelpers +SUBDIRS = devdbg libcsem mobicore $(PYTHON3_SUBDIRS) readdex readelf ropgadgets stackvars diff --git a/plugins/pychrysa/analysis/binary.c b/plugins/pychrysa/analysis/binary.c index 32e4a71..5b857d5 100644 --- a/plugins/pychrysa/analysis/binary.c +++ b/plugins/pychrysa/analysis/binary.c @@ -55,7 +55,7 @@ static PyObject *py_loaded_binary_get_format(PyObject *, void *); static PyObject *py_loaded_binary_get_processor(PyObject *, void *); /* Fournit le tampon associé au contenu assembleur d'un binaire. */ -static PyObject *py_loaded_binary_get_disassembled_buffer(PyObject *, void *); +static PyObject *py_loaded_binary_get_disassembled_cache(PyObject *, void *); @@ -234,16 +234,18 @@ static PyObject *py_loaded_binary_get_processor(PyObject *self, void *closure) * * ******************************************************************************/ -static PyObject *py_loaded_binary_get_disassembled_buffer(PyObject *self, void *closure) +static PyObject *py_loaded_binary_get_disassembled_cache(PyObject *self, void *closure) { PyObject *result; /* Trouvailles à retourner */ GLoadedBinary *binary; /* Version native */ - GCodeBuffer *buffer; /* Tampon à récupérer */ + GBufferCache *cache; /* Tampon à récupérer */ binary = G_LOADED_BINARY(pygobject_get(self)); - buffer = g_loaded_binary_get_disassembled_buffer(binary); + cache = g_loaded_binary_get_disassembled_cache(binary); - result = pygobject_new(G_OBJECT(buffer)); + result = pygobject_new(G_OBJECT(cache)); + + g_object_unref(G_OBJECT(cache)); return result; @@ -288,8 +290,8 @@ PyTypeObject *get_python_loaded_binary_type(void) "Handler for the current binary processor.", NULL }, { - "disassembled_buffer", py_loaded_binary_get_disassembled_buffer, NULL, - "Disassembled code buffer.", NULL + "disassembled_cache", py_loaded_binary_get_disassembled_cache, NULL, + "Disassembled buffer cache.", NULL }, { NULL } }; diff --git a/plugins/pychrysa/glibext/Makefile.am b/plugins/pychrysa/glibext/Makefile.am index 74def8a..b53f4b0 100644 --- a/plugins/pychrysa/glibext/Makefile.am +++ b/plugins/pychrysa/glibext/Makefile.am @@ -2,8 +2,8 @@ noinst_LTLIBRARIES = libpychrysaglibext.la libpychrysaglibext_la_SOURCES = \ + buffercache.h buffercache.c \ bufferline.h bufferline.c \ - codebuffer.h codebuffer.c \ configuration.h configuration.c \ module.h module.c diff --git a/plugins/pychrysa/glibext/buffercache.c b/plugins/pychrysa/glibext/buffercache.c new file mode 100644 index 0000000..c79fda2 --- /dev/null +++ b/plugins/pychrysa/glibext/buffercache.c @@ -0,0 +1,165 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * buffercache.c - équivalent Python du fichier "glibext/gbuffercache.h" + * + * Copyright (C) 2012 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 "buffercache.h" + + +#include + + +#include + + +#include "../arch/vmpa.h" +#include "../helpers.h" + + + +#if 0 +/* Retrouve une ligne au sein d'un tampon avec une adresse. */ +static PyObject *py_code_buffer_find_line_by_addr(PyObject *, PyObject *); + + + +/****************************************************************************** +* * +* Paramètres : self = classe représentant un tampon de code. * +* args = arguments fournis à l'appel. * +* * +* Description : Retrouve une ligne au sein d'un tampon avec une adresse. * +* * +* Retour : Instance de la ligne trouvée. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_code_buffer_find_line_by_addr(PyObject *self, PyObject *args) +{ + PyObject *result; /* Trouvailles à retourner */ + PyObject *py_vmpa; /* Localisation version Python */ + int ret; /* Bilan de lecture des args. */ + vmpa2t *addr; /* Adresse visée par l'opérat° */ + GBuffercache *buffer; /* Version native */ + GBufferLine *line; /* Ligne trouvée */ + + ret = PyArg_ParseTuple(args, "O", &py_vmpa); + if (!ret) return NULL; + + ret = PyObject_IsInstance(py_vmpa, (PyObject *)get_python_vmpa_type()); + if (!ret) return NULL; + + addr = get_internal_vmpa(py_vmpa); + if (addr == NULL) return NULL; + + buffer = G_CODE_BUFFER(pygobject_get(self)); + + line = g_code_buffer_find_line_by_addr(buffer, addr, 0, NULL); + if (line == NULL) Py_RETURN_NONE; + + result = pygobject_new(G_OBJECT(line)); + + return result; + +} +#endif + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Fournit un accès à une définition de type à diffuser. * +* * +* Retour : Définition d'objet pour Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyTypeObject *get_python_buffer_cache_type(void) +{ + static PyMethodDef py_buffer_cache_methods[] = { +#if 0 + { + "find_line_by_addr", (PyCFunction)py_buffer_cache_find_line_by_addr, + METH_VARARGS, + "find_line_by_addr($self, addr, /)\n--\n\nFind a buffer line with a given address." + }, +#endif + { NULL } + }; + + static PyGetSetDef py_buffer_cache_getseters[] = { + { NULL } + }; + + static PyTypeObject py_buffer_cache_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.glibext.Buffercache", + .tp_basicsize = sizeof(PyGObject), + + .tp_flags = Py_TPFLAGS_DEFAULT, + + .tp_doc = "PyChrysalide code buffer", + + .tp_methods = py_buffer_cache_methods, + .tp_getset = py_buffer_cache_getseters, + + }; + + return &py_buffer_cache_type; + +} + + +/****************************************************************************** +* * +* Paramètres : module = module dont la définition est à compléter. * +* * +* Description : Prend en charge l'objet 'pychrysalide.glibext.BufferCache'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool register_python_buffer_cache(PyObject *module) +{ + PyTypeObject *py_buffer_cache_type; /* Type Python 'BufferCache' */ + PyObject *dict; /* Dictionnaire du module */ + + py_buffer_cache_type = get_python_buffer_cache_type(); + + dict = PyModule_GetDict(module); + + if (!register_class_for_pygobject(dict, G_TYPE_BUFFER_CACHE, py_buffer_cache_type, &PyGObject_Type)) + return false; + + return true; + +} diff --git a/plugins/pychrysa/glibext/buffercache.h b/plugins/pychrysa/glibext/buffercache.h new file mode 100644 index 0000000..6476f5f --- /dev/null +++ b/plugins/pychrysa/glibext/buffercache.h @@ -0,0 +1,42 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * buffercache.h - prototypes pour l'équivalent Python du fichier "glibext/buffercache.h" + * + * Copyright (C) 2012 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_PYCHRYSA_GLIBEXT_BUFFERCACHE_H +#define _PLUGINS_PYCHRYSA_GLIBEXT_BUFFERCACHE_H + + +#include +#include + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_buffer_cache_type(void); + +/* Prend en charge l'objet 'pychrysalide.glibext.CodeBuffer'. */ +bool register_python_buffer_cache(PyObject *); + + + +#endif /* _PLUGINS_PYCHRYSA_GLIBEXT_BUFFERCACHE_H */ diff --git a/plugins/pychrysa/glibext/codebuffer.c b/plugins/pychrysa/glibext/codebuffer.c deleted file mode 100644 index 7ca9435..0000000 --- a/plugins/pychrysa/glibext/codebuffer.c +++ /dev/null @@ -1,161 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * codebuffer.c - équivalent Python du fichier "glibext/gcodebuffer.h" - * - * Copyright (C) 2012 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 "codebuffer.h" - - -#include - - -#include - - -#include "../arch/vmpa.h" -#include "../helpers.h" - - - -/* Retrouve une ligne au sein d'un tampon avec une adresse. */ -static PyObject *py_code_buffer_find_line_by_addr(PyObject *, PyObject *); - - - -/****************************************************************************** -* * -* Paramètres : self = classe représentant un tampon de code. * -* args = arguments fournis à l'appel. * -* * -* Description : Retrouve une ligne au sein d'un tampon avec une adresse. * -* * -* Retour : Instance de la ligne trouvée. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static PyObject *py_code_buffer_find_line_by_addr(PyObject *self, PyObject *args) -{ - PyObject *result; /* Trouvailles à retourner */ - PyObject *py_vmpa; /* Localisation version Python */ - int ret; /* Bilan de lecture des args. */ - vmpa2t *addr; /* Adresse visée par l'opérat° */ - GCodeBuffer *buffer; /* Version native */ - GBufferLine *line; /* Ligne trouvée */ - - ret = PyArg_ParseTuple(args, "O", &py_vmpa); - if (!ret) return NULL; - - ret = PyObject_IsInstance(py_vmpa, (PyObject *)get_python_vmpa_type()); - if (!ret) return NULL; - - addr = get_internal_vmpa(py_vmpa); - if (addr == NULL) return NULL; - - buffer = G_CODE_BUFFER(pygobject_get(self)); - - line = g_code_buffer_find_line_by_addr(buffer, addr, 0, NULL); - if (line == NULL) Py_RETURN_NONE; - - result = pygobject_new(G_OBJECT(line)); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : - * -* * -* Description : Fournit un accès à une définition de type à diffuser. * -* * -* Retour : Définition d'objet pour Python. * -* * -* Remarques : - * -* * -******************************************************************************/ - -PyTypeObject *get_python_code_buffer_type(void) -{ - static PyMethodDef py_code_buffer_methods[] = { - { - "find_line_by_addr", (PyCFunction)py_code_buffer_find_line_by_addr, - METH_VARARGS, - "find_line_by_addr($self, addr, /)\n--\n\nFind a buffer line with a given address." - }, - { NULL } - }; - - static PyGetSetDef py_code_buffer_getseters[] = { - { NULL } - }; - - static PyTypeObject py_code_buffer_type = { - - PyVarObject_HEAD_INIT(NULL, 0) - - .tp_name = "pychrysalide.glibext.CodeBuffer", - .tp_basicsize = sizeof(PyGObject), - - .tp_flags = Py_TPFLAGS_DEFAULT, - - .tp_doc = "PyChrysalide code buffer", - - .tp_methods = py_code_buffer_methods, - .tp_getset = py_code_buffer_getseters, - - }; - - return &py_code_buffer_type; - -} - - -/****************************************************************************** -* * -* Paramètres : module = module dont la définition est à compléter. * -* * -* Description : Prend en charge l'objet 'pychrysalide.glibext.CodeBuffer'. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool register_python_code_buffer(PyObject *module) -{ - PyTypeObject *py_code_buffer_type; /* Type Python 'CodeBuffer' */ - PyObject *dict; /* Dictionnaire du module */ - - py_code_buffer_type = get_python_code_buffer_type(); - - dict = PyModule_GetDict(module); - - if (!register_class_for_pygobject(dict, G_TYPE_CODE_BUFFER, py_code_buffer_type, &PyGObject_Type)) - return false; - - return true; - -} diff --git a/plugins/pychrysa/glibext/codebuffer.h b/plugins/pychrysa/glibext/codebuffer.h deleted file mode 100644 index e806e36..0000000 --- a/plugins/pychrysa/glibext/codebuffer.h +++ /dev/null @@ -1,42 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * codebuffer.h - prototypes pour l'équivalent Python du fichier "glibext/codebuffer.h" - * - * Copyright (C) 2012 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_PYCHRYSA_GLIBEXT_CODEBUFFER_H -#define _PLUGINS_PYCHRYSA_GLIBEXT_CODEBUFFER_H - - -#include -#include - - - -/* Fournit un accès à une définition de type à diffuser. */ -PyTypeObject *get_python_code_buffer_type(void); - -/* Prend en charge l'objet 'pychrysalide.glibext.CodeBuffer'. */ -bool register_python_code_buffer(PyObject *); - - - -#endif /* _PLUGINS_PYCHRYSA_GLIBEXT_CODEBUFFER_H */ diff --git a/plugins/pychrysa/glibext/module.c b/plugins/pychrysa/glibext/module.c index 2306c44..847e6d6 100644 --- a/plugins/pychrysa/glibext/module.c +++ b/plugins/pychrysa/glibext/module.c @@ -28,8 +28,8 @@ #include +#include "buffercache.h" #include "bufferline.h" -#include "codebuffer.h" #include "configuration.h" @@ -80,8 +80,8 @@ bool add_glibext_module_to_python_module(PyObject *super) result = true; + result &= register_python_buffer_cache(module); result &= register_python_buffer_line(module); - result &= register_python_code_buffer(module); result &= register_python_config_param(module); result &= register_python_config_param_iterator(module); result &= register_python_generic_config(module); diff --git a/plugins/pychrysa/gtkext/Makefile.am b/plugins/pychrysa/gtkext/Makefile.am index e7303e8..fee2032 100644 --- a/plugins/pychrysa/gtkext/Makefile.am +++ b/plugins/pychrysa/gtkext/Makefile.am @@ -2,8 +2,8 @@ noinst_LTLIBRARIES = libpychrysagtkext.la libpychrysagtkext_la_SOURCES = \ - blockview.h blockview.c \ - bufferview.h bufferview.c \ + blockdisplay.h blockdisplay.c \ + bufferdisplay.h bufferdisplay.c \ displaypanel.h displaypanel.c \ module.h module.c diff --git a/plugins/pychrysa/gtkext/blockdisplay.c b/plugins/pychrysa/gtkext/blockdisplay.c new file mode 100644 index 0000000..8262aa7 --- /dev/null +++ b/plugins/pychrysa/gtkext/blockdisplay.c @@ -0,0 +1,109 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * blockdisplay.c - prototypes pour l'équivalent Python du fichier "gtkext/gtkblockdisplay.c" + * + * Copyright (C) 2012 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 "blockdisplay.h" + + +#include + + +#include + + +#include "bufferdisplay.h" +#include "../helpers.h" + + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Fournit un accès à une définition de type à diffuser. * +* * +* Retour : Définition d'objet pour Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyTypeObject *get_python_block_display_type(void) +{ + static PyMethodDef py_block_display_methods[] = { + { NULL } + }; + + static PyGetSetDef py_block_display_getseters[] = { + { NULL } + }; + + static PyTypeObject py_block_display_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.gtkext.BlockDisplay", + .tp_basicsize = sizeof(PyGObject), + + .tp_flags = Py_TPFLAGS_DEFAULT, + + .tp_doc = "PyChrysalide block display.", + + .tp_methods = py_block_display_methods, + .tp_getset = py_block_display_getseters + + }; + + return &py_block_display_type; + +} + + +/****************************************************************************** +* * +* Paramètres : module = module dont la définition est à compléter. * +* * +* Description : Prend en charge l'objet 'pychrysalide.gtkext.BlockDisplay'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool register_python_block_display(PyObject *module) +{ + PyTypeObject *py_block_display_type; /* Type Python 'BlockDisplay' */ + PyObject *dict; /* Dictionnaire du module */ + + py_block_display_type = get_python_block_display_type(); + + dict = PyModule_GetDict(module); + + if (!register_class_for_pygobject(dict, GTK_TYPE_BLOCK_DISPLAY, + py_block_display_type, get_python_buffer_display_type())) + return false; + + return true; + +} diff --git a/plugins/pychrysa/gtkext/blockdisplay.h b/plugins/pychrysa/gtkext/blockdisplay.h new file mode 100644 index 0000000..1a45e15 --- /dev/null +++ b/plugins/pychrysa/gtkext/blockdisplay.h @@ -0,0 +1,42 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * blockdisplay.h - prototypes pour l'équivalent Python du fichier "gtkext/gtkblockdisplay.h" + * + * Copyright (C) 2012 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_PYCHRYSA_GTKEXT_BLOCKDISPLAY_H +#define _PLUGINS_PYCHRYSA_GTKEXT_BLOCKDISPLAY_H + + +#include +#include + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_block_display_type(void); + +/* Prend en charge l'objet 'pychrysalide.gtkext.BlockDisplay'. */ +bool register_python_block_display(PyObject *module); + + + +#endif /* _PLUGINS_PYCHRYSA_GTKEXT_BLOCKDISPLAY_H */ diff --git a/plugins/pychrysa/gtkext/blockview.c b/plugins/pychrysa/gtkext/blockview.c deleted file mode 100644 index 73095b2..0000000 --- a/plugins/pychrysa/gtkext/blockview.c +++ /dev/null @@ -1,108 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * blockview.c - prototypes pour l'équivalent Python du fichier "gtkext/gtkblockview.c" - * - * Copyright (C) 2012 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 "blockview.h" - - -#include - - -#include - - -#include "bufferview.h" -#include "../helpers.h" - - - -/****************************************************************************** -* * -* Paramètres : - * -* * -* Description : Fournit un accès à une définition de type à diffuser. * -* * -* Retour : Définition d'objet pour Python. * -* * -* Remarques : - * -* * -******************************************************************************/ - -PyTypeObject *get_python_block_view_type(void) -{ - static PyMethodDef py_block_view_methods[] = { - { NULL } - }; - - static PyGetSetDef py_block_view_getseters[] = { - { NULL } - }; - - static PyTypeObject py_block_view_type = { - - PyVarObject_HEAD_INIT(NULL, 0) - - .tp_name = "pychrysalide.gtkext.BlockView", - .tp_basicsize = sizeof(PyGObject), - - .tp_flags = Py_TPFLAGS_DEFAULT, - - .tp_doc = "PyChrysalide block view.", - - .tp_methods = py_block_view_methods, - .tp_getset = py_block_view_getseters - - }; - - return &py_block_view_type; - -} - - -/****************************************************************************** -* * -* Paramètres : module = module dont la définition est à compléter. * -* * -* Description : Prend en charge l'objet 'pychrysalide.gtkext.BlockView'. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool register_python_block_view(PyObject *module) -{ - PyTypeObject *py_block_view_type; /* Type Python 'BlockView' */ - PyObject *dict; /* Dictionnaire du module */ - - py_block_view_type = get_python_block_view_type(); - - dict = PyModule_GetDict(module); - - if (!register_class_for_pygobject(dict, GTK_TYPE_BLOCK_VIEW, py_block_view_type, get_python_buffer_view_type())) - return false; - - return true; - -} diff --git a/plugins/pychrysa/gtkext/blockview.h b/plugins/pychrysa/gtkext/blockview.h deleted file mode 100644 index acb97a9..0000000 --- a/plugins/pychrysa/gtkext/blockview.h +++ /dev/null @@ -1,42 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * blockview.h - prototypes pour l'équivalent Python du fichier "gtkext/gtkblockview.h" - * - * Copyright (C) 2012 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_PYCHRYSA_GTKEXT_BLOCKVIEW_H -#define _PLUGINS_PYCHRYSA_GTKEXT_BLOCKVIEW_H - - -#include -#include - - - -/* Fournit un accès à une définition de type à diffuser. */ -PyTypeObject *get_python_block_view_type(void); - -/* Prend en charge l'objet 'pychrysalide.gtkext.BlockView'. */ -bool register_python_block_view(PyObject *module); - - - -#endif /* _PLUGINS_PYCHRYSA_GTKEXT_BLOCKVIEW_H */ diff --git a/plugins/pychrysa/gtkext/bufferdisplay.c b/plugins/pychrysa/gtkext/bufferdisplay.c new file mode 100644 index 0000000..d26d9d9 --- /dev/null +++ b/plugins/pychrysa/gtkext/bufferdisplay.c @@ -0,0 +1,109 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * bufferdisplay.c - prototypes pour l'équivalent Python du fichier "gtkext/gtkbufferdisplay.c" + * + * Copyright (C) 2012 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 "bufferdisplay.h" + + +#include + + +#include + + +#include "displaypanel.h" +#include "../helpers.h" + + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Fournit un accès à une définition de type à diffuser. * +* * +* Retour : Définition d'objet pour Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyTypeObject *get_python_buffer_display_type(void) +{ + static PyMethodDef py_buffer_display_methods[] = { + { NULL } + }; + + static PyGetSetDef py_buffer_display_getseters[] = { + { NULL } + }; + + static PyTypeObject py_buffer_display_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.gtkext.BufferDisplay", + .tp_basicsize = sizeof(PyGObject), + + .tp_flags = Py_TPFLAGS_DEFAULT, + + .tp_doc = "PyChrysalide buffer display.", + + .tp_methods = py_buffer_display_methods, + .tp_getset = py_buffer_display_getseters + + }; + + return &py_buffer_display_type; + +} + + +/****************************************************************************** +* * +* Paramètres : module = module dont la définition est à compléter. * +* * +* Description : Prend en charge l'objet 'pychrysalide.gtkext.Bufferdisplay'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool register_python_buffer_display(PyObject *module) +{ + PyTypeObject *py_buffer_display_type; /* Type Python 'Bufferdisplay' */ + PyObject *dict; /* Dictionnaire du module */ + + py_buffer_display_type = get_python_buffer_display_type(); + + dict = PyModule_GetDict(module); + + if (!register_class_for_pygobject(dict, GTK_TYPE_BUFFER_DISPLAY, + py_buffer_display_type, get_python_display_panel_type())) + return false; + + return true; + +} diff --git a/plugins/pychrysa/gtkext/bufferdisplay.h b/plugins/pychrysa/gtkext/bufferdisplay.h new file mode 100644 index 0000000..332f402 --- /dev/null +++ b/plugins/pychrysa/gtkext/bufferdisplay.h @@ -0,0 +1,42 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * bufferdisplay.h - prototypes pour l'équivalent Python du fichier "gtkext/gtkbufferdisplay.h" + * + * Copyright (C) 2012 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_PYCHRYSA_GTKEXT_BUFFERDISPLAY_H +#define _PLUGINS_PYCHRYSA_GTKEXT_BUFFERDISPLAY_H + + +#include +#include + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_buffer_display_type(void); + +/* Prend en charge l'objet 'pychrysalide.gtkext.BufferDisplay'. */ +bool register_python_buffer_display(PyObject *module); + + + +#endif /* _PLUGINS_PYCHRYSA_GTKEXT_BUFFERDISPLAY_H */ diff --git a/plugins/pychrysa/gtkext/bufferview.c b/plugins/pychrysa/gtkext/bufferview.c deleted file mode 100644 index 3be54fd..0000000 --- a/plugins/pychrysa/gtkext/bufferview.c +++ /dev/null @@ -1,108 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * bufferview.c - prototypes pour l'équivalent Python du fichier "gtkext/gtkbufferview.c" - * - * Copyright (C) 2012 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 "bufferview.h" - - -#include - - -#include - - -#include "displaypanel.h" -#include "../helpers.h" - - - -/****************************************************************************** -* * -* Paramètres : - * -* * -* Description : Fournit un accès à une définition de type à diffuser. * -* * -* Retour : Définition d'objet pour Python. * -* * -* Remarques : - * -* * -******************************************************************************/ - -PyTypeObject *get_python_buffer_view_type(void) -{ - static PyMethodDef py_buffer_view_methods[] = { - { NULL } - }; - - static PyGetSetDef py_buffer_view_getseters[] = { - { NULL } - }; - - static PyTypeObject py_buffer_view_type = { - - PyVarObject_HEAD_INIT(NULL, 0) - - .tp_name = "pychrysalide.gtkext.Bufferview", - .tp_basicsize = sizeof(PyGObject), - - .tp_flags = Py_TPFLAGS_DEFAULT, - - .tp_doc = "PyChrysalide buffer view.", - - .tp_methods = py_buffer_view_methods, - .tp_getset = py_buffer_view_getseters - - }; - - return &py_buffer_view_type; - -} - - -/****************************************************************************** -* * -* Paramètres : module = module dont la définition est à compléter. * -* * -* Description : Prend en charge l'objet 'pychrysalide.gtkext.Bufferview'. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool register_python_buffer_view(PyObject *module) -{ - PyTypeObject *py_buffer_view_type; /* Type Python 'Bufferview' */ - PyObject *dict; /* Dictionnaire du module */ - - py_buffer_view_type = get_python_buffer_view_type(); - - dict = PyModule_GetDict(module); - - if (!register_class_for_pygobject(dict, GTK_TYPE_BUFFER_VIEW, py_buffer_view_type, get_python_display_panel_type())) - return false; - - return true; - -} diff --git a/plugins/pychrysa/gtkext/bufferview.h b/plugins/pychrysa/gtkext/bufferview.h deleted file mode 100644 index d4a1581..0000000 --- a/plugins/pychrysa/gtkext/bufferview.h +++ /dev/null @@ -1,42 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * bufferview.h - prototypes pour l'équivalent Python du fichier "gtkext/gtkbufferview.h" - * - * Copyright (C) 2012 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_PYCHRYSA_GTKEXT_BUFFERVIEW_H -#define _PLUGINS_PYCHRYSA_GTKEXT_BUFFERVIEW_H - - -#include -#include - - - -/* Fournit un accès à une définition de type à diffuser. */ -PyTypeObject *get_python_buffer_view_type(void); - -/* Prend en charge l'objet 'pychrysalide.gtkext.Bufferview'. */ -bool register_python_buffer_view(PyObject *module); - - - -#endif /* _PLUGINS_PYCHRYSA_GTKEXT_BUFFERVIEW_H */ diff --git a/plugins/pychrysa/gtkext/module.c b/plugins/pychrysa/gtkext/module.c index 2230ed0..d826814 100644 --- a/plugins/pychrysa/gtkext/module.c +++ b/plugins/pychrysa/gtkext/module.c @@ -28,8 +28,8 @@ #include -#include "blockview.h" -#include "bufferview.h" +#include "blockdisplay.h" +#include "bufferdisplay.h" #include "displaypanel.h" @@ -81,8 +81,8 @@ bool add_gtkext_module_to_python_module(PyObject *super) result = true; result &= register_python_display_panel(module); - result &= register_python_buffer_view(module); - result &= register_python_block_view(module); + result &= register_python_buffer_display(module); + result &= register_python_block_display(module); agmtpm_exit: diff --git a/plugins/ropgadgets/select.c b/plugins/ropgadgets/select.c index 881cd39..0fedfb1 100644 --- a/plugins/ropgadgets/select.c +++ b/plugins/ropgadgets/select.c @@ -1746,11 +1746,7 @@ static gboolean filter_visible_rop_gadgets(GtkTreeModel *model, GtkTreeIter *ite static void add_new_gadgets_for_category(GExeFormat *format, GtkComboBoxText *combo, GtkTreeStore *store, const char *category, GArchInstruction **gadgets, size_t count) { - const char *target; /* Sous-traitance requise */ - GArchProcessor *proc; /* Architecture du binaire */ - MemoryDataSize msize; /* Taille du bus d'adresses */ const GBinContent *content; /* Contenu binaire global */ - GCodeBuffer *buffer; /* Tampon de rassemblement */ size_t i; /* Boucle de parcours */ GArchInstruction *instr; /* Elément de liste de gadgets */ GBufferLine *line; /* Ligne présente à l'adresse */ @@ -1762,21 +1758,10 @@ static void add_new_gadgets_for_category(GExeFormat *format, GtkComboBoxText *co char *content_markup; /* Contenu assemblé de chaîne */ GtkTreeIter iter; /* Point d'insertion */ - /* Définition de l'écosystème nécessaire */ - - target = g_exe_format_get_target_machine(format); - proc = get_arch_processor_for_type(target); - - msize = g_arch_processor_get_memory_size(proc); - - g_object_unref(G_OBJECT(proc)); - content = g_binary_format_get_content(G_BIN_FORMAT(format)); /* Conversion en contenu textuel */ - buffer = g_code_buffer_new(BLC_ASSEMBLY); - for (i = 0; i < count; i++) { /* Parcours des différentes lignes */ @@ -1788,8 +1773,8 @@ static void add_new_gadgets_for_category(GExeFormat *format, GtkComboBoxText *co for (instr = gadgets[i]; instr != NULL; instr = g_arch_instruction_get_next_iter(gadgets[i], instr, ~0)) { - line = g_arch_instruction_print(instr, buffer, msize, content, ASX_INTEL); - if (line == NULL) continue; + line = g_buffer_line_new(NULL, BLC_ASSEMBLY); + g_line_generator_print(G_LINE_GENERATOR(instr), line, -1, 0); if (instr == gadgets[i]) { @@ -1800,6 +1785,8 @@ static void add_new_gadgets_for_category(GExeFormat *format, GtkComboBoxText *co partial_raw = g_buffer_line_get_text(line, BLC_ASSEMBLY_HEAD, BLC_COUNT, false); partial_markup = g_buffer_line_get_text(line, BLC_ASSEMBLY_HEAD, BLC_COUNT, true); + g_object_unref(G_OBJECT(line)); + if (content_raw != NULL) content_raw = stradd(content_raw, " ; "); @@ -1836,8 +1823,6 @@ static void add_new_gadgets_for_category(GExeFormat *format, GtkComboBoxText *co } - g_object_unref(G_OBJECT(buffer)); - g_object_unref(G_OBJECT(content)); /* Rajout de la catégorie et filtre au besoin */ diff --git a/src/analysis/Makefile.am b/src/analysis/Makefile.am index 8b346f9..a8b1538 100755 --- a/src/analysis/Makefile.am +++ b/src/analysis/Makefile.am @@ -20,6 +20,7 @@ libanalysis_la_LIBADD = \ db/libanalysisdb.la \ db/libanalysiskeys.la \ disass/libanalysisdisass.la \ + human/libanalysishuman.la \ types/libanalysistypes.la # decomp/libanalysisdecomp.la @@ -31,4 +32,4 @@ AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) -SUBDIRS = blocks contents db disass types +SUBDIRS = blocks contents db disass human types diff --git a/src/analysis/binary.c b/src/analysis/binary.c index 3af62cf..ac8863e 100644 --- a/src/analysis/binary.c +++ b/src/analysis/binary.c @@ -37,7 +37,7 @@ #include "routine.h" #include "db/client.h" -#include "decomp/decompiler.h" +//#include "decomp/decompiler.h" #include "disass/disassembler.h" #include "../common/extstr.h" #include "../common/cpp.h" @@ -78,8 +78,9 @@ struct _GLoadedBinary GDbgFormat *debug; /* Informations de débogage */ //// REMME GArchProcessor *proc; /* Architecture du binaire */ - GCodeBuffer *disass_buffer; /* Instructions lisibles */ - GCodeBuffer **dec_buffers; /* Sources sous forme de texte */ + + GBufferCache *disass_cache; /* Instructions lisibles */ + //GCodeBuffer **dec_buffers; /* Sources sous forme de texte */ size_t decbuf_count; /* Taille des tableaux */ size_t defsrc; /* Fichier source principal */ @@ -220,9 +221,6 @@ static void g_loaded_binary_init(GLoadedBinary *binary) binary->col_display[BVW_GRAPH][BLC_PHYSICAL] = false; binary->col_display[BVW_GRAPH][BLC_VIRTUAL] = false; binary->col_display[BVW_GRAPH][BLC_BINARY] = false; - binary->col_display[BVW_SOURCE][BLC_PHYSICAL] = false; - binary->col_display[BVW_SOURCE][BLC_VIRTUAL] = false; - binary->col_display[BVW_SOURCE][BLC_BINARY] = false; binary->lines_display = true; @@ -1377,7 +1375,7 @@ void g_loaded_binary_analyse(GLoadedBinary *binary) g_loaded_binary_connect_internal(binary); - disassemble_binary(binary, &binary->disass_buffer, ack_completed_disassembly); + disassemble_binary(binary, &binary->disass_cache, ack_completed_disassembly); @@ -1508,9 +1506,16 @@ GArchProcessor *g_loaded_binary_get_processor(const GLoadedBinary *binary) * * ******************************************************************************/ -GCodeBuffer *g_loaded_binary_get_disassembled_buffer(const GLoadedBinary *binary) +GBufferCache *g_loaded_binary_get_disassembled_cache(const GLoadedBinary *binary) { - return binary->disass_buffer; + GBufferCache *result; /* Instance à retourner */ + + result = binary->disass_cache; + + if (result != NULL) + g_object_ref(G_OBJECT(result)); + + return result; } @@ -1527,7 +1532,7 @@ GCodeBuffer *g_loaded_binary_get_disassembled_buffer(const GLoadedBinary *binary * Remarques : - * * * ******************************************************************************/ - +#if 0 GCodeBuffer *g_loaded_binary_get_decompiled_buffer(const GLoadedBinary *binary, size_t index) { GCodeBuffer *result; /* Tampon à retourner */ @@ -1544,6 +1549,7 @@ GCodeBuffer *g_loaded_binary_get_decompiled_buffer(const GLoadedBinary *binary, return result; } +#endif /****************************************************************************** @@ -1659,6 +1665,7 @@ void ack_completed_disassembly(GDelayedDisassembly *disass, GLoadedBinary *binar files = g_binary_format_get_source_files(G_BIN_FORMAT(binary->format), &binary->decbuf_count, &binary->defsrc); +#if 0 if (binary->decbuf_count > 0) { binary->dec_buffers = (GCodeBuffer **)calloc(binary->decbuf_count, sizeof(GCodeBuffer *)); @@ -1668,7 +1675,7 @@ void ack_completed_disassembly(GDelayedDisassembly *disass, GLoadedBinary *binar binary->dec_buffers[i] = decompile_all_from_file(binary, files[i]); */ } - +#endif diff --git a/src/analysis/binary.h b/src/analysis/binary.h index 41c7f7a..501ffe6 100644 --- a/src/analysis/binary.h +++ b/src/analysis/binary.h @@ -36,7 +36,7 @@ #include "../common/xml.h" #include "../format/debuggable.h" #include "../format/executable.h" -#include "../glibext/gcodebuffer.h" +#include "../glibext/gbuffercache.h" @@ -76,7 +76,6 @@ typedef enum _BinaryView { BVW_BLOCK, /* Version basique */ BVW_GRAPH, /* Affichage en graphique */ - BVW_SOURCE, /* Code décompilé */ BVW_COUNT @@ -181,10 +180,10 @@ GExeFormat *g_loaded_binary_get_format(const GLoadedBinary *); GArchProcessor *g_loaded_binary_get_processor(const GLoadedBinary *); /* Fournit le tampon associé au contenu assembleur d'un binaire. */ -GCodeBuffer *g_loaded_binary_get_disassembled_buffer(const GLoadedBinary *); +GBufferCache *g_loaded_binary_get_disassembled_cache(const GLoadedBinary *); /* Fournit le tampon associé au contenu d'un fichier source. */ -GCodeBuffer *g_loaded_binary_get_decompiled_buffer(const GLoadedBinary *, size_t); +//GCodeBuffer *g_loaded_binary_get_decompiled_buffer(const GLoadedBinary *, size_t); /* Définit si une colonne donnée doit apparaître dans le rendu. */ void g_loaded_binary_set_column_display(GLoadedBinary *, BinaryView, BufferLineColumn, bool); diff --git a/src/analysis/content.c b/src/analysis/content.c index 484599f..09f293c 100644 --- a/src/analysis/content.c +++ b/src/analysis/content.c @@ -47,7 +47,7 @@ G_DEFINE_INTERFACE(GBinContent, g_binary_content, G_TYPE_OBJECT) /****************************************************************************** * * -* Paramètres : iface = interface GTK à initialiser. * +* Paramètres : iface = interface GLib à initialiser. * * * * Description : Procède à l'initialisation de l'interface de rassemblement. * * * diff --git a/src/analysis/db/items/bookmark.c b/src/analysis/db/items/bookmark.c index 086b9f2..18e4bb5 100644 --- a/src/analysis/db/items/bookmark.c +++ b/src/analysis/db/items/bookmark.c @@ -409,6 +409,8 @@ static void g_db_bookmark_build_label(GDbBookmark *bookmark) static bool g_db_bookmark_run(GDbBookmark *bookmark, GLoadedBinary *binary, bool *prev, bool set) { + return false; +#if 0 bool result; /* Bilan à faire remonter */ GCodeBuffer *buffer; /* Tampon de lignes à traiter */ GBufferLine *line; /* Ligne de tampon à marquer */ @@ -437,7 +439,7 @@ static bool g_db_bookmark_run(GDbBookmark *bookmark, GLoadedBinary *binary, bool exit: return result; - +#endif } diff --git a/src/analysis/db/items/comment.c b/src/analysis/db/items/comment.c index 55893d1..3517f38 100644 --- a/src/analysis/db/items/comment.c +++ b/src/analysis/db/items/comment.c @@ -35,7 +35,10 @@ #include "../collection-int.h" #include "../item-int.h" +#include "../../human/asm/lang.h" #include "../../../common/io.h" +#include "../../../common/extstr.h" +#include "../../../glibext/linegen-int.h" @@ -52,6 +55,9 @@ struct _GDbComment rle_string text; /* Contenu du commentaire */ + char **lines; /* Lignes brutes à représenter */ + size_t count; /* Quantité de ces lignes */ + bool inlined; /* Intégration dans une ligne ?*/ union @@ -60,7 +66,9 @@ struct _GDbComment bool before; /* Zone dédiée au dessus ? */ }; - GDbComment **oldies; /* Commentaires d'origine ? */ + GLineGenerator *previous; /* Commentaire remplacé */ + + GLineGenerator **old_inlined; /* Commentaires d'origine ? */ size_t old_count; /* Nombre de places à restaurer*/ }; @@ -112,6 +120,29 @@ static bool g_db_comment_prepare_db_statement(const GDbComment *, bound_value ** /* Charge les valeurs utiles pour un commentaire. */ static bool g_db_comment_load(GDbComment *, const bound_value *, size_t); +/* Définit le commentaire associé à un commentaire. */ +static void g_db_comment_set_text(GDbComment *, const char *); + + + +/* ------------------------ OFFRE DE CAPACITES DE GENERATION ------------------------ */ + + +/* Indique le nombre de ligne prêtes à être générées. */ +static size_t g_db_comment_count_lines(const GDbComment *); + +/* Retrouve l'emplacement correspondant à une position donnée. */ +static void g_db_comment_compute_addr(const GDbComment *, gint, vmpa2t *, size_t, size_t); + +/* Détermine si le conteneur s'inscrit dans une plage donnée. */ +static int g_db_comment_contains_addr(const GDbComment *, const vmpa2t *, size_t, size_t); + +/* Renseigne sur les propriétés liées à un générateur. */ +static BufferLineFlags g_db_comment_get_flags(const GDbComment *, size_t, size_t); + +/* Imprime dans une ligne de rendu le contenu représenté. */ +static void g_db_comment_print(GDbComment *, GBufferLine *, size_t, size_t); + /* ---------------------- DEFINITION DE LA COLLECTION ASSOCIEE ---------------------- */ @@ -138,6 +169,9 @@ static void g_comment_collection_class_init(GCommentCollectionClass *); /* Initialise un commentaire sous forme de zone de texte. */ static void g_comment_collection_init(GCommentCollection *); +/* Procède à l'initialisation de l'interface de génération. */ +static void g_db_comment_interface_init(GLineGeneratorInterface *); + /* Supprime toutes les références externes. */ static void g_comment_collection_dispose(GCommentCollection *); @@ -161,7 +195,8 @@ static GDbItem *g_comment_collection_has_key(GCommentCollection *, va_list); /* Indique le type défini pour un commentaire à l'intérieur d'une zone de texte. */ -G_DEFINE_TYPE(GDbComment, g_db_comment, G_TYPE_DB_ITEM); +G_DEFINE_TYPE_WITH_CODE(GDbComment, g_db_comment, G_TYPE_DB_ITEM, + G_IMPLEMENT_INTERFACE(G_TYPE_LINE_GENERATOR, g_db_comment_interface_init)); /****************************************************************************** @@ -219,6 +254,31 @@ static void g_db_comment_class_init(GDbCommentClass *klass) static void g_db_comment_init(GDbComment *comment) { + comment->lines = NULL; + comment->count = 0; + +} + + +/****************************************************************************** +* * +* Paramètres : iface = interface GLib à initialiser. * +* * +* Description : Procède à l'initialisation de l'interface de génération. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_db_comment_interface_init(GLineGeneratorInterface *iface) +{ + iface->count = (linegen_count_lines_fc)g_db_comment_count_lines; + iface->compute = (linegen_compute_fc)g_db_comment_compute_addr; + iface->contains = (linegen_contains_fc)g_db_comment_contains_addr; + iface->get_flags = (linegen_get_flags_fc)g_db_comment_get_flags; + iface->print = (linegen_print_fc)g_db_comment_print; } @@ -239,11 +299,17 @@ static void g_db_comment_dispose(GDbComment *comment) { size_t i; /* Boucle de parcours */ + for (i = 0; i < comment->count; i++) + free(comment->lines[i]); + + if (comment->lines != NULL) + free(comment->lines); + for (i = 0; i < comment->old_count; i++) - g_object_unref(G_OBJECT(comment->oldies[i])); + g_object_unref(G_OBJECT(comment->old_inlined[i])); - if (comment->oldies != NULL) - free(comment->oldies); + if (comment->old_inlined != NULL) + free(comment->old_inlined); G_OBJECT_CLASS(g_db_comment_parent_class)->dispose(G_OBJECT(comment)); @@ -516,6 +582,134 @@ static void g_db_comment_build_label(GDbComment *comment) static bool g_db_comment_run(GDbComment *comment, GLoadedBinary *binary, bool apply) { bool result; /* Bilan à faire remonter */ + GBufferCache *cache; /* Ensemble de lignes à traiter*/ + size_t index; /* Point d'insertion */ + GArchProcessor *proc; /* Propriétaire d'instructions */ + GArchInstruction *instr; /* Instruction à traiter */ + instr_link_t *sources; /* Instructions diverses liées */ + size_t scount; /* Nbre de sources affichées */ + size_t i; /* Boucle de parcours */ + const mrange_t *range; /* Emplacement d'instruction */ + size_t linked; /* Indice lié à traiter */ + + result = true; + + cache = g_loaded_binary_get_disassembled_cache(binary); + + index = g_buffer_cache_find_index_by_addr(cache, &comment->addr, true); + + index = g_buffer_cache_look_for_flag(cache, index, BLF_HAS_CODE); + + if (comment->inlined) + { + +#define RUN_INLINED_COMMENT(idx, new, old) \ + if (apply) \ + { \ + old = g_buffer_cache_delete_type_at(cache, idx, G_TYPE_DB_COMMENT, false, false); \ + \ + g_buffer_cache_insert_at(cache, idx, G_LINE_GENERATOR(new), false, false); \ + \ + } \ + else \ + { \ + g_buffer_cache_delete_type_at(cache, idx, G_TYPE_DB_COMMENT, false, false); \ + \ + if (old != NULL) \ + { \ + g_buffer_cache_insert_at(cache, idx, old, false, false); \ + g_object_unref(G_OBJECT(old)); \ + } \ + \ + } + + /* Commentaire principal */ + + RUN_INLINED_COMMENT(index, comment, comment->previous); + + /* Renvois répétés */ + + if (comment->repeatable) + { + proc = g_loaded_binary_get_processor(binary); + + instr = g_arch_processor_find_instr_by_address(proc, &comment->addr); + assert(instr != NULL); + + scount = g_arch_instruction_get_sources(instr, &sources); + + if (apply) + { + comment->old_count = scount; + comment->old_inlined = (GLineGenerator **)realloc(comment->old_inlined, + comment->old_count * sizeof(GLineGenerator *)); + } + + for (i = 0; i < scount && result; i++) + { + range = g_arch_instruction_get_range(sources[i].linked); + + /** + * On recherche ici une ligne potentiellement BLF_HAS_CODE ou BLF_IS_LABEL. + * Comme on ne peut pas traiter les deux cas, on prend la première qui vient + * avec BLF_NONE. + */ + + linked = g_buffer_cache_find_index_by_addr(cache, get_mrange_addr(range), true); + assert(linked != g_buffer_cache_count_lines(cache)); + + RUN_INLINED_COMMENT(linked, comment, comment->old_inlined[i]); + + } + + if (!apply) + { + free(comment->old_inlined); + + comment->old_inlined = NULL; + comment->old_count = 0; + + } + + g_object_unref(G_OBJECT(proc)); + + } + + + + } + + else + { + + + + + + + + + + } + + + //void g_buffer_cache_insert_at(GBufferCache *cache, size_t index, GLineGenerator *generator, bool before, bool after) + + //GLineGenerator *g_buffer_cache_delete_type_at(GBufferCache *cache, size_t index, GType type, bool before, bool after) + + + + + g_object_unref(G_OBJECT(cache)); + + return result; + + + + +#if 0 + + bool result; /* Bilan à faire remonter */ GCodeBuffer *buffer; /* Tampon de lignes à traiter */ GBufferLine *line; /* Ligne de tampon à marquer */ GArchProcessor *proc; /* Propriétaire d'instructions */ @@ -658,7 +852,7 @@ static bool g_db_comment_run(GDbComment *comment, GLoadedBinary *binary, bool ap /* TODO g_object_unref(G_OBJECT(buffer));*/ return result; - +#endif } @@ -884,10 +1078,137 @@ const char *g_db_comment_get_text(const GDbComment *comment) * * ******************************************************************************/ -void g_db_comment_set_text(GDbComment *comment, const char *text) +static void g_db_comment_set_text(GDbComment *comment, const char *text) { + GCodingLanguage *lang; /* Langage de sortie préféré */ + set_rle_string(&comment->text, text); + lang = g_asm_language_new(); + + comment->lines = strtoka(text, "\n", &comment->count); + + g_coding_language_encapsulate_comments(lang, &comment->lines, &comment->count); + + g_object_unref(G_OBJECT(lang)); + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* OFFRE DE CAPACITES DE GENERATION */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : comment = générateur à consulter. * +* * +* Description : Indique le nombre de ligne prêtes à être générées. * +* * +* Retour : Nombre de lignes devant apparaître au final. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static size_t g_db_comment_count_lines(const GDbComment *comment) +{ + return comment->count; + +} + + +/****************************************************************************** +* * +* Paramètres : comment = générateur à consulter. * +* x = position géographique sur la ligne concernée. * +* addr = position en mémoire à analyser. * +* index = indice de cette même ligne dans le tampon global. * +* repeat = indice d'utilisations successives du générateur. * +* * +* Description : Retrouve l'emplacement correspondant à une position donnée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_db_comment_compute_addr(const GDbComment *comment, gint x, vmpa2t *addr, size_t index, size_t repeat) +{ + copy_vmpa(addr, &comment->addr); + +} + + +/****************************************************************************** +* * +* Paramètres : comment = générateur à consulter. * +* addr = position en mémoire à analyser. * +* index = indice de cette même ligne dans le tampon global. * +* repeat = indice d'utilisations successives du générateur. * +* * +* 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_db_comment_contains_addr(const GDbComment *comment, const vmpa2t *addr, size_t index, size_t repeat) +{ + int result; /* Conclusion à retourner */ + + result = cmp_vmpa(addr, &comment->addr); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : comment = 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_db_comment_get_flags(const GDbComment *comment, size_t index, size_t repeat) +{ + return BLF_NONE; + +} + + +/****************************************************************************** +* * +* Paramètres : comment = 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. * +* * +* Description : Imprime dans une ligne de rendu le contenu représenté. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_db_comment_print(GDbComment *comment, GBufferLine *line, size_t index, size_t repeat) +{ + g_buffer_line_append_text(line, BLC_COMMENTS, SL(comment->lines[repeat]), RTT_COMMENT, NULL); + } diff --git a/src/analysis/db/items/comment.h b/src/analysis/db/items/comment.h index c5bd335..16046bc 100644 --- a/src/analysis/db/items/comment.h +++ b/src/analysis/db/items/comment.h @@ -69,15 +69,6 @@ const vmpa2t *g_db_comment_get_address(GDbComment *); /* Fournit le commentaire associé à un commentaire. */ const char *g_db_comment_get_text(const GDbComment *); -/* Définit le commentaire associé à un commentaire. */ -void g_db_comment_set_text(GDbComment *, const char *); - - - - - - - /* ---------------------- DEFINITION DE LA COLLECTION ASSOCIEE ---------------------- */ diff --git a/src/analysis/db/items/move.h b/src/analysis/db/items/move.h index a9d6d8d..115bdc8 100644 --- a/src/analysis/db/items/move.h +++ b/src/analysis/db/items/move.h @@ -96,4 +96,4 @@ GMoveCollection *g_move_collection_new(void); -#endif /* _ANALYSIS_DB_ITEMS_SWITCH_H */ +#endif /* _ANALYSIS_DB_ITEMS_MOVE_H */ diff --git a/src/analysis/db/items/switcher.c b/src/analysis/db/items/switcher.c index 748c934..3d5841c 100644 --- a/src/analysis/db/items/switcher.c +++ b/src/analysis/db/items/switcher.c @@ -496,6 +496,9 @@ static void g_db_switcher_build_label(GDbSwitcher *switcher) static bool g_db_switcher_run(GDbSwitcher *switcher, GLoadedBinary *binary, ImmOperandDisplay *old, ImmOperandDisplay new) { + return false; + +#if 0 bool result; /* Bilan à faire remonter */ GArchProcessor *proc; /* Propriétaire d'instructions */ GArchInstruction *instr; /* Instruction à traiter */ @@ -568,7 +571,7 @@ static bool g_db_switcher_run(GDbSwitcher *switcher, GLoadedBinary *binary, ImmO g_object_unref(G_OBJECT(proc)); return result; - +#endif } diff --git a/src/analysis/disass/area.h b/src/analysis/disass/area.h index d5f910b..155db7c 100644 --- a/src/analysis/disass/area.h +++ b/src/analysis/disass/area.h @@ -28,6 +28,7 @@ #include "../binary.h" #include "../../arch/instruction.h" #include "../../format/symbol.h" +#include "../../glibext/delayed.h" #include "../../gtkext/gtkstatusstack.h" diff --git a/src/analysis/disass/disassembler.c b/src/analysis/disass/disassembler.c index 5326c36..246a5b2 100644 --- a/src/analysis/disass/disassembler.c +++ b/src/analysis/disass/disassembler.c @@ -39,11 +39,16 @@ #include "routines.h" #include "../../format/format.h" #include "../../glibext/delayed-int.h" +#include "../../glibext/generators/prologue.h" #include "../../gui/panels/log.h" #include "../../plugins/pglist.h" +#include "../human/asm/lang.h" // TODO : REMME -> format ! + + + /* ------------------------ DESASSEMBLAGE DE BINAIRE DIFFERE ------------------------ */ @@ -54,8 +59,9 @@ struct _GDelayedDisassembly GLoadedBinary *binary; /* Destinataire final */ GExeFormat *format; /* Format du binaire représenté*/ + GCodingLanguage *lang; /* Traduction en ASM préférée */ - GCodeBuffer *buffer; /* Tampon pour le rendu */ + GBufferCache *cache; /* Tampon pour le rendu */ }; @@ -80,7 +86,7 @@ static void g_delayed_disassembly_dispose(GDelayedDisassembly *); static void g_delayed_disassembly_finalize(GDelayedDisassembly *); /* Crée une tâche de désassemblage différé. */ -static GDelayedDisassembly *g_delayed_disassembly_new(GLoadedBinary *, GCodeBuffer *); +static GDelayedDisassembly *g_delayed_disassembly_new(GLoadedBinary *, GBufferCache *); /* Opère sur toutes les instructions. */ static void process_all_instructions(wgroup_id_t, GtkStatusStack *, const char *, ins_fallback_cb, GArchProcessor *, GProcContext *, GExeFormat *); @@ -97,7 +103,7 @@ static void g_delayed_disassembly_process(GDelayedDisassembly *, GtkStatusStack /* Construit la description d'introduction du désassemblage. */ -static void build_disass_prologue(GCodeBuffer *, const char *, const char *); +static void build_disass_prologue(GBufferCache *, const GCodingLanguage *, const char *, const char *); @@ -172,6 +178,7 @@ static void g_delayed_disassembly_init(GDelayedDisassembly *disass) static void g_delayed_disassembly_dispose(GDelayedDisassembly *disass) { g_object_unref(G_OBJECT(disass->format)); + g_object_unref(G_OBJECT(disass->lang)); G_OBJECT_CLASS(g_delayed_disassembly_parent_class)->dispose(G_OBJECT(disass)); @@ -211,7 +218,7 @@ static void g_delayed_disassembly_finalize(GDelayedDisassembly *disass) * * ******************************************************************************/ -static GDelayedDisassembly *g_delayed_disassembly_new(GLoadedBinary *binary, GCodeBuffer *buffer) +static GDelayedDisassembly *g_delayed_disassembly_new(GLoadedBinary *binary, GBufferCache *cache) { GDelayedDisassembly *result; /* Tâche à retourner */ @@ -219,8 +226,9 @@ static GDelayedDisassembly *g_delayed_disassembly_new(GLoadedBinary *binary, GCo result->binary = binary; result->format = g_loaded_binary_get_format(binary); + result->lang = g_asm_language_new(); - result->buffer = buffer; + result->cache = cache; return result; @@ -568,7 +576,7 @@ static void g_delayed_disassembly_process(GDelayedDisassembly *disass, GtkStatus - print_disassembled_instructions(disass->buffer, disass->format, proc, status); + print_disassembled_instructions(disass->cache, disass->lang, disass->binary, status); @@ -612,10 +620,10 @@ static void g_delayed_disassembly_process(GDelayedDisassembly *disass, GtkStatus /****************************************************************************** * * -* Paramètres : buffer = tampon de destination pour le texte. * +* Paramètres : cache = tampon de destination pour le texte. * +* lang = trauducteur pour l'impression finale. * * filename = nom du fichier ciblé à décompiler. * -* data = données en mémoire pour l'empreinte. * -* length = quantité de données à prendre en compte. * +* checksum = empreinte identifiant le binaire chargé. * * * * Description : Construit la description d'introduction du désassemblage. * * * @@ -625,96 +633,32 @@ static void g_delayed_disassembly_process(GDelayedDisassembly *disass, GtkStatus * * ******************************************************************************/ -static void build_disass_prologue(GCodeBuffer *buffer, const char *filename, const char *checksum) +static void build_disass_prologue(GBufferCache *cache, const GCodingLanguage *lang, const char *filename, const char *checksum) { -#if 0 - GLangOutput *output; /* Modèle de sortie adéquat */ - GBufferLine *line; /* Ligne de destination */ - bool managed; /* Groupe déjà défini ? */ - size_t len; /* Taille du texte */ - char *content; /* Contenu textuel d'une ligne */ - - output = g_asm_output_new(); + char **text; /* Contenu brute à imprimer */ + GIntroGenerator *generator; /* Générateur constitué */ - line = g_lang_output_start_comments(output, buffer); - if (line != NULL) - { - g_buffer_line_start_merge_at(line, BLC_PHYSICAL); - g_buffer_line_add_flag(line, BLF_WIDTH_MANAGER); - - g_code_buffer_append_new_line(buffer, line); - - } - - managed = (line != NULL); + text = calloc(4, sizeof(char *)); /* Introduction */ - line = g_lang_output_continue_comments(output, buffer, - SL(_("Disassembly generated by Chrysalide"))); - g_buffer_line_start_merge_at(line, BLC_PHYSICAL); - - if (!managed) - g_buffer_line_add_flag(line, BLF_WIDTH_MANAGER); - - g_code_buffer_append_new_line(buffer, line); - - line = g_lang_output_continue_comments(output, buffer, - SL(_("Chrysalide is free software - © 2008-2015 Cyrille Bagard"))); - g_buffer_line_start_merge_at(line, BLC_PHYSICAL); - - g_code_buffer_append_new_line(buffer, line); - - line = g_lang_output_continue_comments(output, buffer, NULL, 0); - g_buffer_line_start_merge_at(line, BLC_PHYSICAL); - - g_code_buffer_append_new_line(buffer, line); + text[0] = strdup(_("Disassembly generated by Chrysalide")); + text[1] = strdup(_("Chrysalide is free software - © 2008-2016 Cyrille Bagard")); /* Fichier */ - len = strlen(_("File: ")) + strlen(filename) + 1; - content = (char *)calloc(len, sizeof(char)); - - snprintf(content, len, "%s%s", _("File: "), filename); - - line = g_lang_output_continue_comments(output, buffer, content, len - 1); - g_buffer_line_start_merge_at(line, BLC_PHYSICAL); - - g_code_buffer_append_new_line(buffer, line); - - free(content); + asprintf(&text[2], "%s%s", _("File: "), filename); /* Checksum SHA256 */ - len = strlen(_("Sha256: ")) + strlen(checksum); - content = (char *)calloc(len + 1, sizeof(char)); - - snprintf(content, len + 1, "%s%s", _("Sha256: "), checksum); - - line = g_lang_output_continue_comments(output, buffer, content, len - 1); - g_buffer_line_start_merge_at(line, BLC_PHYSICAL); - - g_code_buffer_append_new_line(buffer, line); + asprintf(&text[3], "%s%s", _("Sha256: "), checksum); - free(content); + /* Intégration finale */ - /* Ligne de séparation */ + generator = g_intro_generator_new(lang, text, 4); - line = g_lang_output_continue_comments(output, buffer, NULL, 0); - g_buffer_line_start_merge_at(line, BLC_PHYSICAL); - g_code_buffer_append_new_line(buffer, line); + g_buffer_cache_append(cache, G_LINE_GENERATOR(generator), BLF_NONE); - /* Conclusion */ - - line = g_lang_output_end_comments(output, buffer); - if (line != NULL) - { - g_buffer_line_start_merge_at(line, BLC_PHYSICAL); - g_code_buffer_append_new_line(buffer, line); - } - - g_object_unref(G_OBJECT(output)); -#endif } @@ -724,7 +668,7 @@ static void build_disass_prologue(GCodeBuffer *buffer, const char *filename, con * parts = parties binaires à désassembler. * * count = nombre de parties à traiter. * * instrs = liste des instructions chargées. [OUT] * -* buffer = tampon de code mis en place. [OUT] * +* cache = tampon de code mis en place. [OUT] * * ack = fonction à appeler une fois l'opération terminée. * * * * Description : Procède au désassemblage d'un contenu binaire donné. * @@ -735,30 +679,35 @@ static void build_disass_prologue(GCodeBuffer *buffer, const char *filename, con * * ******************************************************************************/ -void disassemble_binary(GLoadedBinary *binary, GCodeBuffer **buffer, disassembly_ack_fc ack) +void disassemble_binary(GLoadedBinary *binary, GBufferCache **cache, disassembly_ack_fc ack) { GBinFormat *format; /* Format associé au binaire */ + GCodingLanguage *lang; /* Langage de sortie préféré */ GBinContent *content; /* Contenu bianire manipulé */ const gchar *checksum; /* Identifiant de binaire */ GDelayedDisassembly *disass; /* Désassemblage à mener */ GWorkQueue *queue; /* Gestionnaire de différés */ - *buffer = g_code_buffer_new(BLC_ASSEMBLY); + *cache = g_buffer_cache_new(); format = G_BIN_FORMAT(g_loaded_binary_get_format(binary)); + lang = g_asm_language_new(); + content = g_binary_format_get_content(format); checksum = g_binary_content_get_checksum(content); g_object_unref(G_OBJECT(content)); g_object_unref(G_OBJECT(format)); - build_disass_prologue(*buffer, g_binary_content_describe(content, true), checksum); + build_disass_prologue(*cache, lang, g_binary_content_describe(content, true), checksum); - disass = g_delayed_disassembly_new(binary, *buffer); + disass = g_delayed_disassembly_new(binary, *cache); g_signal_connect(disass, "work-completed", G_CALLBACK(ack), binary); queue = get_work_queue(); g_work_queue_schedule_work(queue, G_DELAYED_WORK(disass), DEFAULT_WORK_GROUP); + g_object_unref(G_OBJECT(lang)); + } diff --git a/src/analysis/disass/disassembler.h b/src/analysis/disass/disassembler.h index 9151d23..20c7bdd 100644 --- a/src/analysis/disass/disassembler.h +++ b/src/analysis/disass/disassembler.h @@ -59,7 +59,7 @@ GType g_delayed_disassembly_get_type(void); typedef void (* disassembly_ack_fc) (GDelayedDisassembly *, GLoadedBinary *); /* Procède à la décompilation des routines d'un fichier donné. */ -void disassemble_binary(GLoadedBinary *, GCodeBuffer **, disassembly_ack_fc); +void disassemble_binary(GLoadedBinary *, GBufferCache **, disassembly_ack_fc); diff --git a/src/analysis/disass/output.c b/src/analysis/disass/output.c index fe4d705..6c044be 100644 --- a/src/analysis/disass/output.c +++ b/src/analysis/disass/output.c @@ -27,27 +27,18 @@ #include -#include "../../arch/processor.h" -#include "../../common/extstr.h" #include "../../format/format.h" +#include "../../glibext/generators/rborder.h" #include "../../gui/panels/log.h" -#define ROUTINE_INTRO_MSG "; --------------- BEGIN OF PROCEDURE ---------------" - -#define ROUTINE_OUTRO_MSG "; ---------------- END OF PROCEDURE ----------------" - - - /****************************************************************************** * * -* Paramètres : buffer = tampon de récueil des résultats d'impression. * -* format = format du binaire traité. * -* instrs = ensemble d'instructions à traiter. * -* routines = liste de routines intervenant dans le flot. * -* count = quantité de ces routines. * -* status = barre de statut avec progression à mettre à jour. * +* Paramètres : cache = tampon de récueil des résultats d'impression. * +* lang = langage de haut niveau préféré pour l'impression. * +* binary = tampon de récueil des résultats d'impression. * +* status = barre de statut avec progression à mettre à jour. * * * * Description : Transcrit du code désassemblé en texte humainement lisible. * * * @@ -57,8 +48,10 @@ * * ******************************************************************************/ -void print_disassembled_instructions(GCodeBuffer *buffer, GExeFormat *format, GArchProcessor *proc, GtkStatusStack *status) +void print_disassembled_instructions(GBufferCache *cache, GCodingLanguage *lang, GLoadedBinary *binary, GtkStatusStack *status) { + GExeFormat *format; /* Format associé au binaire */ + GArchProcessor *proc; /* Processeur de l'architecture*/ GBinPortion *root; /* Couche première de portions */ GBinPortion **portions; /* Morceaux d'encadrement */ size_t portions_count; /* Taille de cette liste */ @@ -74,22 +67,21 @@ void print_disassembled_instructions(GCodeBuffer *buffer, GExeFormat *format, GA size_t i; /* Boucle de parcours */ GArchInstruction *instr; /* Instruction à traiter */ const vmpa2t *iaddr; /* Adresse d'instruction */ - vmpa2t outro_addr; /* Adresse de fin de code */ - GBufferLine *line; + GBorderGenerator *border; /* Délimitation de routine */ const vmpa2t *paddr; /* Adresse de portion */ + GLineGenerator *generator; /* Générateur de contenu ajouté*/ const vmpa2t *saddr; /* Adresse de symbole */ int compared; /* Bilan d'une comparaison */ SymbolType stype; /* Type de symbole trouvé */ - const char *label; /* Etiquette ciblant un symbole*/ - mrange_t range; /* Couverture sans surface */ + vmpa2t intro_addr; /* Adresse de début de code */ + vmpa2t outro_addr; /* Adresse de fin de code */ + BufferLineFlags flags; /* Propriétés pour la ligne */ + //mrange_t range; /* Couverture sans surface */ GDbComment *comment; /* Commentaire à ajouter */ - const char *text; - - char *prefixed; @@ -98,6 +90,8 @@ void print_disassembled_instructions(GCodeBuffer *buffer, GExeFormat *format, GA + format = g_loaded_binary_get_format(binary); + proc = g_loaded_binary_get_processor(binary); bool collect_all_portions(GBinPortion *portion, GBinPortion *parent, BinaryPortionVisit visit, void *unused) { @@ -149,29 +143,8 @@ void print_disassembled_instructions(GCodeBuffer *buffer, GExeFormat *format, GA { expect_outro = false; - init_mrange(&range, &outro_addr, 0); - - line = g_code_buffer_prepare_new_line(buffer, &range); - g_buffer_line_add_flag(line, BLF_IS_LABEL); - g_buffer_line_fill_mrange(line, msize, msize); - - g_code_buffer_append_new_line(buffer, line); - - line = g_code_buffer_prepare_new_line(buffer, &range); - g_buffer_line_add_flag(line, BLF_IS_LABEL); - g_buffer_line_fill_mrange(line, msize, msize); - - g_buffer_line_start_merge_at(line, BLC_ASSEMBLY_HEAD); - g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, - ROUTINE_OUTRO_MSG, strlen(ROUTINE_OUTRO_MSG), RTT_COMMENT, NULL); - - g_code_buffer_append_new_line(buffer, line); - - line = g_code_buffer_prepare_new_line(buffer, &range); - g_buffer_line_add_flag(line, BLF_IS_LABEL); - g_buffer_line_fill_mrange(line, msize, msize); - - g_code_buffer_append_new_line(buffer, line); + border = g_border_generator_new(lang, &outro_addr, false, msize); + g_buffer_cache_append(cache, G_LINE_GENERATOR(border), BLF_NONE); } @@ -184,7 +157,11 @@ void print_disassembled_instructions(GCodeBuffer *buffer, GExeFormat *format, GA if (cmp_vmpa_by_phy(iaddr, paddr) != 0) break; - g_binary_portion_print(portions[portion_index], buffer, msize); + generator = G_LINE_GENERATOR(portions[portion_index]); + + /* Si elle comporte une description ! */ + if (g_line_generator_count_lines(generator) > 0) + g_buffer_cache_append(cache, generator, BLF_NONE); portion_index++; @@ -192,7 +169,10 @@ void print_disassembled_instructions(GCodeBuffer *buffer, GExeFormat *format, GA /* Début d'un nouveau symbole ? */ - if (sym_index < sym_count) + if (sym_index == sym_count) + compared = -1; + + else { iaddr = get_mrange_addr(g_arch_instruction_get_range(instr)); saddr = get_mrange_addr(g_binary_symbol_get_range(symbols[sym_index])); @@ -225,29 +205,10 @@ void print_disassembled_instructions(GCodeBuffer *buffer, GExeFormat *format, GA { /* Impression de la marque de début */ - init_mrange(&range, get_mrange_addr(g_binary_symbol_get_range(symbols[sym_index])), 0); - - line = g_code_buffer_prepare_new_line(buffer, &range); - g_buffer_line_add_flag(line, BLF_IS_LABEL); - g_buffer_line_fill_mrange(line, msize, msize); - - g_code_buffer_append_new_line(buffer, line); - - line = g_code_buffer_prepare_new_line(buffer, &range); - g_buffer_line_add_flag(line, BLF_IS_LABEL); - g_buffer_line_fill_mrange(line, msize, msize); - - g_buffer_line_start_merge_at(line, BLC_ASSEMBLY_HEAD); - g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, - ROUTINE_INTRO_MSG, strlen(ROUTINE_INTRO_MSG), RTT_COMMENT, NULL); - - g_code_buffer_append_new_line(buffer, line); + copy_vmpa(&intro_addr, get_mrange_addr(g_binary_symbol_get_range(symbols[sym_index]))); - line = g_code_buffer_prepare_new_line(buffer, &range); - g_buffer_line_add_flag(line, BLF_IS_LABEL); - g_buffer_line_fill_mrange(line, msize, msize); - - g_code_buffer_append_new_line(buffer, line); + border = g_border_generator_new(lang, &intro_addr, true, msize); + g_buffer_cache_append(cache, G_LINE_GENERATOR(border), BLF_NONE); /* Mémorisation de la fin */ @@ -259,23 +220,10 @@ void print_disassembled_instructions(GCodeBuffer *buffer, GExeFormat *format, GA /* Etiquette ? */ - label = g_binary_symbol_get_label(symbols[sym_index]); - - if (label != NULL) - { - init_mrange(&range, get_mrange_addr(g_binary_symbol_get_range(symbols[sym_index])), 0); - - line = g_code_buffer_prepare_new_line(buffer, &range); - g_buffer_line_add_flag(line, BLF_IS_LABEL); - g_buffer_line_fill_mrange(line, msize, msize); - - g_buffer_line_start_merge_at(line, BLC_ASSEMBLY_HEAD); - g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, label, strlen(label), RTT_LABEL, NULL); - g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, ":", 1, RTT_PUNCT, NULL); - - g_code_buffer_append_new_line(buffer, line); + generator = g_binary_symbol_produce_label(symbols[sym_index]); - } + if (generator != NULL) + g_buffer_cache_append(cache, generator, BLF_NONE); } @@ -283,64 +231,37 @@ void print_disassembled_instructions(GCodeBuffer *buffer, GExeFormat *format, GA no_more_symbol_finally: + flags = BLF_NONE; - - line = g_arch_instruction_print(instr, buffer, msize, content, ASX_INTEL); - - - if (g_arch_instruction_get_flags(instr) & AIF_RETURN_POINT) - g_buffer_line_add_flag(line, BLF_BOOKMARK); - - - if (sym_index < sym_count) + if (compared == 0) { - iaddr = get_mrange_addr(g_arch_instruction_get_range(instr)); - saddr = get_mrange_addr(g_binary_symbol_get_range(symbols[sym_index])); - - if (cmp_vmpa(iaddr, saddr) == 0) - { - /* Point d'entrée ? */ - - if (g_binary_symbol_get_target_type(symbols[sym_index]) == STP_ENTRY_POINT) - g_buffer_line_add_flag(line, BLF_ENTRYPOINT); + /* Point d'entrée ? */ - /* Début d'un groupe bien cohérent avec les alignements ? */ + if (g_binary_symbol_get_target_type(symbols[sym_index]) == STP_ENTRY_POINT) + flags |= BLF_ENTRYPOINT; - if (g_binary_symbol_is_block_start(symbols[sym_index])) - g_buffer_line_add_flag(line, BLF_WIDTH_MANAGER); + /* Début d'un groupe bien cohérent avec les alignements ? */ - /* Commentaire ? */ - - comment = g_binary_symbol_get_comment(symbols[sym_index]); - - if (comment != NULL) - { + if (g_binary_symbol_is_block_start(symbols[sym_index])) + flags |= BLF_WIDTH_MANAGER; - /* FIXME : appliquer ! */ - - text = g_db_comment_get_text(comment); - - - prefixed = strdup("; "); - prefixed = stradd(prefixed, text); - - - - g_buffer_line_append_text(line, BLC_COMMENTS, prefixed, strlen(prefixed), RTT_COMMENT, NULL); + } + g_buffer_cache_append(cache, G_LINE_GENERATOR(instr), flags); - free(prefixed); + if (compared == 0) + { + /* Commentaire ? */ - } + comment = g_binary_symbol_get_comment(symbols[sym_index]); - sym_index++; + if (comment != NULL) + g_db_item_apply(G_DB_ITEM(comment), binary); - } + sym_index++; } - g_code_buffer_append_new_line(buffer, line); - g_object_unref(G_OBJECT(instr)); gtk_status_stack_update_activity_value(status, id, 1); @@ -356,6 +277,10 @@ void print_disassembled_instructions(GCodeBuffer *buffer, GExeFormat *format, GA if (portions != NULL) free(portions); + g_object_unref(G_OBJECT(proc)); + g_object_unref(G_OBJECT(format)); + + fprintf(stderr, "MISSING :: %u symbols\n", _missing); diff --git a/src/analysis/disass/output.h b/src/analysis/disass/output.h index 801d3f4..35a0108 100644 --- a/src/analysis/disass/output.h +++ b/src/analysis/disass/output.h @@ -25,15 +25,15 @@ #define _ANALYSIS_DISASS_OUTPUT_H -#include "../../arch/processor.h" -#include "../../format/executable.h" -#include "../../glibext/gcodebuffer.h" +#include "../binary.h" +#include "../human/lang.h" +#include "../../glibext/gbuffercache.h" #include "../../gtkext/gtkstatusstack.h" /* Transcrit du code désassemblé en texte humainement lisible. */ -void print_disassembled_instructions(GCodeBuffer *, GExeFormat *, GArchProcessor *, GtkStatusStack *); +void print_disassembled_instructions(GBufferCache *, GCodingLanguage *, GLoadedBinary *, GtkStatusStack *); diff --git a/src/analysis/human/Makefile.am b/src/analysis/human/Makefile.am new file mode 100755 index 0000000..0cfc4e3 --- /dev/null +++ b/src/analysis/human/Makefile.am @@ -0,0 +1,19 @@ + +noinst_LTLIBRARIES = libanalysishuman.la + + +libanalysishuman_la_SOURCES = \ + lang-int.h \ + lang.h lang.c + +libanalysishuman_la_LIBADD = \ + asm/libanalysishumanasm.la + +libanalysishuman_la_LDFLAGS = + + +AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBARCHIVE_CFLAGS) $(LIBSQLITE_CFLAGS) + +AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) + +SUBDIRS = asm diff --git a/src/analysis/human/asm/Makefile.am b/src/analysis/human/asm/Makefile.am new file mode 100755 index 0000000..da94071 --- /dev/null +++ b/src/analysis/human/asm/Makefile.am @@ -0,0 +1,17 @@ + +noinst_LTLIBRARIES = libanalysishumanasm.la + + +libanalysishumanasm_la_SOURCES = \ + lang.h lang.c + +libanalysishumanasm_la_LIBADD = + +libanalysishumanasm_la_LDFLAGS = + + +AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBARCHIVE_CFLAGS) $(LIBSQLITE_CFLAGS) + +AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) + +SUBDIRS = diff --git a/src/analysis/human/asm/lang.c b/src/analysis/human/asm/lang.c new file mode 100644 index 0000000..27a26dd --- /dev/null +++ b/src/analysis/human/asm/lang.c @@ -0,0 +1,221 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * lang.c - traduction en language d'assembleur classique + * + * Copyright (C) 2016 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 . + */ + + +#include "lang.h" + + +#include "../lang-int.h" +#include "../../../common/extstr.h" + + + +/* Traduction d'éléments en language d'assembleur (instance) */ +struct _GAsmLanguage +{ + GCodingLanguage parent; /* A laisser en premier */ + +}; + +/* Traduction d'éléments en language d'assembleur (classe) */ +struct _GAsmLanguageClass +{ + GCodingLanguageClass parent; /* A laisser en premier */ + +}; + + +/* Initialise la classe des traductions en langage d'assembleur. */ +static void g_asm_language_class_init(GAsmLanguageClass *); + +/* Initialise une traduction d'éléments en langage d'assembleur. */ +static void g_asm_language_init(GAsmLanguage *); + +/* Supprime toutes les références externes. */ +static void g_asm_language_dispose(GAsmLanguage *); + +/* Procède à la libération totale de la mémoire. */ +static void g_asm_language_finalize(GAsmLanguage *); + +/* Complète du texte pour en faire un vrai commentaire. */ +static void g_asm_language_encapsulate_comment(const GAsmLanguage *, char **); + +/* Complète du texte pour en faire de vrais commentaires. */ +static void g_asm_language_encapsulate_comments(const GAsmLanguage *, char ***, size_t *); + + + +/* Indique le type défini pour une traduction en langage d'assembleur. */ +G_DEFINE_TYPE(GAsmLanguage, g_asm_language, G_TYPE_CODING_LANGUAGE); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des traductions en langage d'assembleur.* +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_asm_language_class_init(GAsmLanguageClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + GCodingLanguageClass *lang; /* Encore une autre vision... */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_asm_language_dispose; + object->finalize = (GObjectFinalizeFunc)g_asm_language_finalize; + + lang = G_CODING_LANGUAGE_CLASS(klass); + + lang->encaps_comment = (encapsulate_comment_fc)g_asm_language_encapsulate_comment; + lang->encaps_comments = (encapsulate_comments_fc)g_asm_language_encapsulate_comments; + +} + + +/****************************************************************************** +* * +* Paramètres : lang = instance à initialiser. * +* * +* Description : Initialise une traduction d'éléments en langage d'assembleur.* +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_asm_language_init(GAsmLanguage *lang) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : lang = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_asm_language_dispose(GAsmLanguage *lang) +{ + G_OBJECT_CLASS(g_asm_language_parent_class)->dispose(G_OBJECT(lang)); + +} + + +/****************************************************************************** +* * +* Paramètres : lang = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_asm_language_finalize(GAsmLanguage *lang) +{ + G_OBJECT_CLASS(g_asm_language_parent_class)->finalize(G_OBJECT(lang)); + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Crée une instance de traduction en langage d'assembleur. * +* * +* Retour : Instance mis en place et prête à emploi. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GCodingLanguage *g_asm_language_new(void) +{ + GAsmLanguage *result; /* Instance à retourner */ + + result = g_object_new(G_TYPE_ASM_LANGUAGE, NULL); + + return G_CODING_LANGUAGE(result); + +} + + +/****************************************************************************** +* * +* Paramètres : lang = langage de haut niveau à manipuler. * +* text = adresse de la ligne à compléter. [OUT] * +* * +* Description : Complète du texte pour en faire un vrai commentaire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_asm_language_encapsulate_comment(const GAsmLanguage *lang, char **text) +{ + *text = strprep(*text, "; "); + +} + + +/****************************************************************************** +* * +* Paramètres : lang = langage de haut niveau à manipuler. * +* text = adresse du tableau de lignes à conserver. [OUT] * +* count = adresse de la taille du tableau fourni. [OUT] * +* * +* Description : Complète du texte pour en faire de vrais commentaires. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_asm_language_encapsulate_comments(const GAsmLanguage *lang, char ***text, size_t *count) +{ + size_t i; /* Boucle de parcours */ + + for (i = 0; i < *count; i++) + (*text)[i] = strprep((*text)[i], "; "); + +} diff --git a/src/analysis/human/asm/lang.h b/src/analysis/human/asm/lang.h new file mode 100644 index 0000000..7381048 --- /dev/null +++ b/src/analysis/human/asm/lang.h @@ -0,0 +1,58 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * lang.h - prototypes pour la traduction en language d'assembleur classique + * + * Copyright (C) 2016 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 . + */ + + +#ifndef _ANALYSIS_HUMAN_ASM_LANG_H +#define _ANALYSIS_HUMAN_ASM_LANG_H + + +#include + + +#include "../lang.h" + + + +#define G_TYPE_ASM_LANGUAGE g_asm_language_get_type() +#define G_ASM_LANGUAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_asm_language_get_type(), GAsmLanguage)) +#define G_IS_ASM_LANGUAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_asm_language_get_type())) +#define G_ASM_LANGUAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ASM_LANGUAGE, GAsmLanguageClass)) +#define G_IS_ASM_LANGUAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ASM_LANGUAGE)) +#define G_ASM_LANGUAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ASM_LANGUAGE, GAsmLanguageClass)) + + +/* Traduction d'éléments en language d'assembleur (instance) */ +typedef struct _GAsmLanguage GAsmLanguage; + +/* Traduction d'éléments en language d'assembleur (classe) */ +typedef struct _GAsmLanguageClass GAsmLanguageClass; + + +/* Indique le type défini pour une traduction en langage d'assembleur. */ +GType g_asm_language_get_type(void); + +/* Crée une instance de traduction en langage d'assembleur. */ +GCodingLanguage *g_asm_language_new(void); + + + +#endif /* _ANALYSIS_HUMAN_ASM_LANG_H */ diff --git a/src/analysis/human/lang-int.h b/src/analysis/human/lang-int.h new file mode 100644 index 0000000..c20bc8a --- /dev/null +++ b/src/analysis/human/lang-int.h @@ -0,0 +1,58 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * lang-int.h - prototypes utiles aux traductions en langages de haut niveau + * + * Copyright (C) 2016 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 . + */ + + +#ifndef _ANALYSIS_HUMAN_LANG_INT_H +#define _ANALYSIS_HUMAN_LANG_INT_H + + +#include "lang.h" + + + +/* Complète du texte pour en faire un vrai commentaire. */ +typedef void (* encapsulate_comment_fc) (const GCodingLanguage *, char **); + +/* Complète du texte pour en faire de vrais commentaires. */ +typedef void (* encapsulate_comments_fc) (const GCodingLanguage *, char ***, size_t *); + + +/* Traduction générique en langage humain (instance) */ +struct _GCodingLanguage +{ + GObject parent; /* A laisser en premier */ + +}; + +/* Traduction générique en langage humain (classe) */ +struct _GCodingLanguageClass +{ + GObjectClass parent; /* A laisser en premier */ + + encapsulate_comment_fc encaps_comment; /* Encadrement de commentaire */ + encapsulate_comments_fc encaps_comments;/* Encadrement de commentaires */ + +}; + + + +#endif /* _ANALYSIS_HUMAN_LANG_INT_H */ diff --git a/src/analysis/human/lang.c b/src/analysis/human/lang.c new file mode 100644 index 0000000..72002d3 --- /dev/null +++ b/src/analysis/human/lang.c @@ -0,0 +1,167 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * lang.c - traduction en langages de haut niveau + * + * Copyright (C) 2016 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 . + */ + + +#include "lang.h" + + +#include "lang-int.h" + + + +/* Initialise la classe des traductions en langage humain. */ +static void g_coding_language_class_init(GCodingLanguageClass *); + +/* Initialise une instance de traduction en langage humain. */ +static void g_coding_language_init(GCodingLanguage *); + +/* Supprime toutes les références externes. */ +static void g_coding_language_dispose(GCodingLanguage *); + +/* Procède à la libération totale de la mémoire. */ +static void g_coding_language_finalize(GCodingLanguage *); + + + +/* Indique le type défini pour une traduction en langage humain. */ +G_DEFINE_TYPE(GCodingLanguage, g_coding_language, G_TYPE_OBJECT); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des traductions en langage humain. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_coding_language_class_init(GCodingLanguageClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_coding_language_dispose; + object->finalize = (GObjectFinalizeFunc)g_coding_language_finalize; + +} + + +/****************************************************************************** +* * +* Paramètres : lang = instance à initialiser. * +* * +* Description : Initialise une instance de traduction en langage humain. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_coding_language_init(GCodingLanguage *lang) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : lang = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_coding_language_dispose(GCodingLanguage *lang) +{ + G_OBJECT_CLASS(g_coding_language_parent_class)->dispose(G_OBJECT(lang)); + +} + + +/****************************************************************************** +* * +* Paramètres : lang = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_coding_language_finalize(GCodingLanguage *lang) +{ + G_OBJECT_CLASS(g_coding_language_parent_class)->finalize(G_OBJECT(lang)); + +} + + +/****************************************************************************** +* * +* Paramètres : lang = langage de haut niveau à manipuler. * +* text = adresse de la ligne à compléter. [OUT] * +* * +* Description : Complète du texte pour en faire un vrai commentaire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_coding_language_encapsulate_comment(const GCodingLanguage *lang, char **text) +{ + G_CODING_LANGUAGE_GET_CLASS(lang)->encaps_comment(lang, text); + +} + + +/****************************************************************************** +* * +* Paramètres : lang = langage de haut niveau à manipuler. * +* text = adresse du tableau de lignes à conserver. [OUT] * +* count = adresse de la taille du tableau fourni. [OUT] * +* * +* Description : Complète du texte pour en faire de vrais commentaires. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_coding_language_encapsulate_comments(const GCodingLanguage *lang, char ***text, size_t *count) +{ + G_CODING_LANGUAGE_GET_CLASS(lang)->encaps_comments(lang, text, count); + +} diff --git a/src/analysis/human/lang.h b/src/analysis/human/lang.h new file mode 100644 index 0000000..dc8e398 --- /dev/null +++ b/src/analysis/human/lang.h @@ -0,0 +1,58 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * lang.h - prototypes pour les traductions en langages de haut niveau + * + * Copyright (C) 2016 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 . + */ + + +#ifndef _ANALYSIS_HUMAN_LANG_H +#define _ANALYSIS_HUMAN_LANG_H + + +#include + + + +#define G_TYPE_CODING_LANGUAGE g_coding_language_get_type() +#define G_CODING_LANGUAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_CODING_LANGUAGE, GCodingLanguage)) +#define G_IS_CODING_LANGUAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_CODING_LANGUAGE)) +#define G_CODING_LANGUAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_CODING_LANGUAGE, GCodingLanguageClass)) +#define G_IS_CODING_LANGUAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_CODING_LANGUAGE)) +#define G_CODING_LANGUAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_CODING_LANGUAGE, GCodingLanguageClass)) + + +/* Traduction générique en langage humain (instance) */ +typedef struct _GCodingLanguage GCodingLanguage; + +/* Traduction générique en langage humain (classe) */ +typedef struct _GCodingLanguageClass GCodingLanguageClass; + + +/* Indique le type défini pour une traduction en langage humain. */ +GType g_coding_language_get_type(void); + +/* Complète du texte pour en faire un vrai commentaire. */ +void g_coding_language_encapsulate_comment(const GCodingLanguage *, char **); + +/* Complète du texte pour en faire de vrais commentaires. */ +void g_coding_language_encapsulate_comments(const GCodingLanguage *, char ***, size_t *); + + + +#endif /* _ANALYSIS_HUMAN_LANG_H */ diff --git a/src/analysis/project.c b/src/analysis/project.c index dce55b6..4251dcc 100644 --- a/src/analysis/project.c +++ b/src/analysis/project.c @@ -39,9 +39,8 @@ #include "../glibext/signal.h" #include "../gtkext/easygtk.h" #include "../glibext/delayed-int.h" -#include "../gtkext/gtkblockview.h" -#include "../gtkext/gtkgraphview.h" -#include "../gtkext/gtksourceview.h" +#include "../gtkext/gtkblockdisplay.h" +#include "../gtkext/gtkgraphdisplay.h" #include "../gui/core/panels.h" #include "../gui/panels/log.h" #include "../gui/panels/panel.h" @@ -836,13 +835,10 @@ GPanelItem *_setup_new_panel_item_for_binary(GStudyProject *project, GLoadedBina switch (i) { case BVW_BLOCK: - display = gtk_block_view_new(); + display = gtk_block_display_new(); break; case BVW_GRAPH: - display = gtk_graph_view_new(); - break; - case BVW_SOURCE: - display = gtk_source_view_new(); + display = gtk_graph_display_new(); break; default: /* GCC ! */ break; @@ -894,9 +890,6 @@ GPanelItem *_setup_new_panel_item_for_binary(GStudyProject *project, GLoadedBina case BVW_GRAPH: g_object_set_data(G_OBJECT(displays[i]), "graph_alt_view", displays[j]); break; - case BVW_SOURCE: - g_object_set_data(G_OBJECT(displays[i]), "source_alt_view", displays[j]); - break; default: /* GCC ! */ break; } @@ -1033,9 +1026,6 @@ GtkDisplayPanel *get_alt_view_for_view_panel(GtkDisplayPanel *panel, BinaryView case BVW_GRAPH: result = GTK_DISPLAY_PANEL(g_object_get_data(G_OBJECT(panel), "graph_alt_view")); break; - case BVW_SOURCE: - result = GTK_DISPLAY_PANEL(g_object_get_data(G_OBJECT(panel), "source_alt_view")); - break; default: assert(false); result = NULL; diff --git a/src/arch/dalvik/link.c b/src/arch/dalvik/link.c index 694ec65..3f9ab8c 100644 --- a/src/arch/dalvik/link.c +++ b/src/arch/dalvik/link.c @@ -58,6 +58,9 @@ typedef struct _case_comment } case_comment; +/* REMME */ +#define COMMENT_LINE_SEP "\n" + /****************************************************************************** * * @@ -262,6 +265,7 @@ void handle_dalvik_packed_switch_links(GArchInstruction *instr, GArchProcessor * for (k = 0; k < comment->count; k++) { if (k > 0) + /* FIXME : encapsuler ! */ msg = stradd(msg, COMMENT_LINE_SEP); asprintf(&int_val, _("Case %d:"), comment->keys[k]); @@ -280,6 +284,7 @@ void handle_dalvik_packed_switch_links(GArchInstruction *instr, GArchProcessor * msg = strdup(_("Defaut case:")); else { + /* FIXME : encapsuler ! */ msg = stradd(msg, COMMENT_LINE_SEP); msg = stradd(msg, _("Defaut case")); } diff --git a/src/arch/instruction-int.h b/src/arch/instruction-int.h index c7f32e7..dbb2f2c 100644 --- a/src/arch/instruction-int.h +++ b/src/arch/instruction-int.h @@ -38,7 +38,7 @@ typedef void (* get_instruction_rw_regs_fc) (const GArchInstruction *, GArchRegi typedef const char * (* get_instruction_encoding_fc) (const GArchInstruction *); /* Ajoute à un tampon GLib le contenu de l'instance spécifiée. */ -typedef GBufferLine * (* print_instruction_fc) (const GArchInstruction *, GCodeBuffer *, MemoryDataSize, const GBinContent *, AsmSyntax); +typedef GBufferLine * (* print_instruction_fc) (const GArchInstruction *, GBufferLine *, size_t, size_t); /* Fournit le nom humain de l'instruction manipulée. */ typedef const char * (* get_instruction_keyword_fc) (GArchInstruction *, AsmSyntax ); diff --git a/src/arch/instruction.c b/src/arch/instruction.c index 5f35db4..fc474ea 100644 --- a/src/arch/instruction.c +++ b/src/arch/instruction.c @@ -30,6 +30,7 @@ #include "instruction-int.h" +#include "../glibext/linegen-int.h" @@ -39,6 +40,9 @@ 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_interface_init(GLineGeneratorInterface *); + /* Supprime toutes les références externes. */ static void g_arch_instruction_dispose(GArchInstruction *); @@ -47,16 +51,32 @@ static void g_arch_instruction_finalize(GArchInstruction *); -/* --------------------- CONVERSIONS DU FORMAT DES INSTRUCTIONS --------------------- */ +/* ------------------------ OFFRE DE CAPACITES DE GENERATION ------------------------ */ + + +/* Indique le nombre de ligne prêtes à être générées. */ +static size_t g_arch_instruction_count_lines(const GArchInstruction *); + +/* Retrouve l'emplacement correspondant à une position donnée. */ +static void g_arch_instruction_compute_addr(const GArchInstruction *, gint, vmpa2t *, size_t, size_t); +/* Détermine si le conteneur s'inscrit dans une plage donnée. */ +static int g_arch_instruction_contains_addr(const GArchInstruction *, const vmpa2t *, size_t, size_t); + +/* 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); /* Ajoute à un tampon GLib le contenu de l'instance spécifiée. */ -static GBufferLine *_g_arch_instruction_print(GArchInstruction *, GCodeBuffer *, MemoryDataSize, const GBinContent *, AsmSyntax); +static void _g_arch_instruction_print(GArchInstruction *, GBufferLine *, size_t, size_t); + +/* Imprime dans une ligne de rendu le contenu représenté. */ +static void g_arch_instruction_print(GArchInstruction *, GBufferLine *, size_t, size_t); /* Indique le type défini pour une instruction d'architecture. */ -G_DEFINE_TYPE(GArchInstruction, g_arch_instruction, G_TYPE_OBJECT); +G_DEFINE_TYPE_WITH_CODE(GArchInstruction, g_arch_instruction, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE(G_TYPE_LINE_GENERATOR, g_arch_instruction_interface_init)); /****************************************************************************** @@ -116,6 +136,29 @@ static void g_arch_instruction_init(GArchInstruction *instr) /****************************************************************************** * * +* Paramètres : iface = interface GLib à initialiser. * +* * +* Description : Procède à l'initialisation de l'interface de génération. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_arch_instruction_interface_init(GLineGeneratorInterface *iface) +{ + iface->count = (linegen_count_lines_fc)g_arch_instruction_count_lines; + iface->compute = (linegen_compute_fc)g_arch_instruction_compute_addr; + iface->contains = (linegen_contains_fc)g_arch_instruction_contains_addr; + iface->get_flags = (linegen_get_flags_fc)g_arch_instruction_get_flags2; + iface->print = (linegen_print_fc)g_arch_instruction_print; + +} + + +/****************************************************************************** +* * * Paramètres : instr = instance d'objet GLib à traiter. * * * * Description : Supprime toutes les références externes. * @@ -897,84 +940,6 @@ void g_arch_instruction_set_displayed_max_length(GArchInstruction *instr, phys_t } -/****************************************************************************** -* * -* Paramètres : instr = instruction d'assemblage à représenter. * -* buffer = espace où placer ledit contenu. * -* msize = taille idéale des positions et adresses; * -* content = contenu binaire global à venir lire. * -* syntax = type de représentation demandée. * -* * -* Description : Ajoute à un tampon GLib le contenu de l'instance spécifiée. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static GBufferLine *_g_arch_instruction_print(GArchInstruction *instr, GCodeBuffer *buffer, MemoryDataSize msize, const GBinContent *content, AsmSyntax syntax) -{ - GBufferLine *result; /* Ligne de destination */ - const char *key; /* Mot clef principal */ - size_t klen; /* Taille de ce mot clef */ - size_t i; /* Boucle de parcours */ - - result = g_code_buffer_prepare_new_line(buffer, &instr->range); - - g_buffer_line_add_flag(result, BLF_HAS_CODE); - - g_buffer_line_fill_for_instr(result, msize/* TODO ! */, msize, content, instr->max_displayed_len); - - /* Instruction proprement dite */ - - key = g_arch_instruction_get_keyword(instr, syntax); - klen = strlen(key); - - g_buffer_line_append_text(result, BLC_ASSEMBLY_HEAD, key, klen, RTT_INSTRUCTION, NULL); - - if (instr->operands_count > 0) - { - g_arch_operand_print(instr->operands[0], result, syntax); - - for (i = 1; i < instr->operands_count; i++) - { - g_buffer_line_append_text(result, BLC_ASSEMBLY, ",", 1, RTT_PUNCT, NULL); - g_buffer_line_append_text(result, BLC_ASSEMBLY, " ", 1, RTT_RAW, NULL); - - g_arch_operand_print(instr->operands[i], result, syntax); - - } - - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : instr = instruction d'assemblage à représenter. * -* buffer = espace où placer ledit contenu. * -* msize = taille idéale des positions et adresses; * -* content = contenu binaire global à venir lire. * -* syntax = type de représentation demandée. * -* * -* Description : Ajoute à un tampon GLib le contenu de l'instance spécifiée. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -GBufferLine *g_arch_instruction_print(const GArchInstruction *instr, GCodeBuffer *buffer, MemoryDataSize msize, const GBinContent *content, AsmSyntax syntax) -{ - return G_ARCH_INSTRUCTION_GET_CLASS(instr)->print(instr, buffer, msize, content, syntax); - -} - /* ---------------------------------------------------------------------------------- */ /* TRAITEMENT DES INSTRUCTIONS PAR ENSEMBLE */ @@ -1110,3 +1075,169 @@ GArchInstruction *g_arch_instruction_find_by_address(GArchInstruction *list, con return result; } + + + +/* ---------------------------------------------------------------------------------- */ +/* OFFRE DE CAPACITES DE GENERATION */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* 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 : - * +* * +******************************************************************************/ + +static size_t g_arch_instruction_count_lines(const GArchInstruction *instr) +{ + return 1; + +} + + +/****************************************************************************** +* * +* Paramètres : instr = générateur à consulter. * +* x = position géographique sur la ligne concernée. * +* addr = position en mémoire à analyser. * +* index = indice de cette même ligne dans le tampon global. * +* repeat = indice d'utilisations successives du générateur. * +* * +* Description : Retrouve l'emplacement correspondant à une position donnée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_arch_instruction_compute_addr(const GArchInstruction *instr, gint x, vmpa2t *addr, size_t index, size_t repeat) +{ + copy_vmpa(addr, get_mrange_addr(&instr->range)); + +} + + +/****************************************************************************** +* * +* Paramètres : instr = générateur à consulter. * +* addr = position en mémoire à analyser. * +* index = indice de cette même ligne dans le tampon global. * +* repeat = indice d'utilisations successives du générateur. * +* * +* 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_contains_addr(const GArchInstruction *instr, const vmpa2t *addr, size_t index, size_t repeat) +{ + int result; /* Conclusion à retourner */ + + result = cmp_mrange_with_vmpa(&instr->range, addr); + + return result; + +} + + +/****************************************************************************** +* * +* 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. * +* * +* 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_get_flags2(const GArchInstruction *instr, size_t index, size_t repeat) +{ + return BLF_HAS_CODE; + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instruction d'assemblage à représenter. * +* buffer = espace où placer ledit contenu. * +* msize = taille idéale des positions et adresses; * +* content = contenu binaire global à venir lire. * +* syntax = type de représentation demandée. * +* * +* Description : Ajoute à un tampon GLib le contenu de l'instance spécifiée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void _g_arch_instruction_print(GArchInstruction *instr, GBufferLine *line, size_t index, size_t repeat) +{ + const char *key; /* Mot clef principal */ + size_t klen; /* Taille de ce mot clef */ + size_t i; /* Boucle de parcours */ + + g_buffer_line_fill_vmpa(line, get_mrange_addr(&instr->range), MDS_32_BITS_UNSIGNED, MDS_32_BITS_UNSIGNED); + + /* Instruction proprement dite */ + + key = g_arch_instruction_get_keyword(instr, 0/*, syntax*/); + klen = strlen(key); + + g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, key, klen, RTT_INSTRUCTION, NULL); + + if (instr->operands_count > 0) + { + g_arch_operand_print(instr->operands[0], line, 0/*syntax*/); + + for (i = 1; i < instr->operands_count; i++) + { + g_buffer_line_append_text(line, BLC_ASSEMBLY, ",", 1, RTT_PUNCT, NULL); + g_buffer_line_append_text(line, BLC_ASSEMBLY, " ", 1, RTT_RAW, NULL); + + g_arch_operand_print(instr->operands[i], line, 0/*syntax*/); + + } + + } + +} + + +/****************************************************************************** +* * +* 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. * +* * +* Description : Imprime dans une ligne de rendu le contenu représenté. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_arch_instruction_print(GArchInstruction *instr, GBufferLine *line, size_t index, size_t repeat) +{ + G_ARCH_INSTRUCTION_GET_CLASS(instr)->print(instr, line, index, repeat); + +} diff --git a/src/arch/instruction.h b/src/arch/instruction.h index 54778b5..814cc86 100644 --- a/src/arch/instruction.h +++ b/src/arch/instruction.h @@ -35,7 +35,6 @@ #include "../analysis/content.h" #include "../analysis/type.h" #include "../format/executable.h" -#include "../glibext/gcodebuffer.h" @@ -222,9 +221,6 @@ phys_t g_arch_instruction_get_displayed_max_length(const GArchInstruction *); /* Définit la quantité maximale de code affiché. */ void g_arch_instruction_set_displayed_max_length(GArchInstruction *, phys_t); -/* Ajoute à un tampon GLib le contenu de l'instance spécifiée. */ -GBufferLine *g_arch_instruction_print(const GArchInstruction *, GCodeBuffer *, MemoryDataSize, const GBinContent *, AsmSyntax); - /* -------------------- TRAITEMENT DES INSTRUCTIONS PAR ENSEMBLE -------------------- */ diff --git a/src/arch/raw.c b/src/arch/raw.c index 61a37e0..d0348c9 100644 --- a/src/arch/raw.c +++ b/src/arch/raw.c @@ -78,7 +78,7 @@ static const char *g_raw_instruction_get_encoding(const GRawInstruction *); static const char *g_raw_instruction_get_keyword(const GRawInstruction *, AsmSyntax); /* Ajoute à un tampon GLib le contenu de l'instance spécifiée. */ -static GBufferLine *g_raw_instruction_print(GRawInstruction *, GCodeBuffer *, MemoryDataSize, const GBinContent *, AsmSyntax); +static void g_raw_instruction_print(GRawInstruction *, GBufferLine *, size_t, size_t); @@ -444,11 +444,11 @@ static const char *g_raw_instruction_get_keyword(const GRawInstruction *instr, A /****************************************************************************** * * -* Paramètres : instr = instruction d'assemblage à représenter. * -* buffer = espace où placer ledit contenu. * +* Paramètres : instr = instruction d'assemblage à représenter. * +* buffer = espace où placer ledit contenu. * * msize = taille idéale des positions et adresses; * * content = contenu binaire global à venir lire. * -* syntax = type de représentation demandée. * +* syntax = type de représentation demandée. * * * * Description : Ajoute à un tampon GLib le contenu de l'instance spécifiée. * * * @@ -458,9 +458,8 @@ static const char *g_raw_instruction_get_keyword(const GRawInstruction *instr, A * * ******************************************************************************/ -static GBufferLine *g_raw_instruction_print(GRawInstruction *instr, GCodeBuffer *buffer, MemoryDataSize msize, const GBinContent *content, AsmSyntax syntax) +static void g_raw_instruction_print(GRawInstruction *instr, GBufferLine *line, size_t index, size_t repeat) { - GBufferLine *result; /* Ligne de destination */ GArchInstruction *base; /* Autre version de l'instance */ const char *key; /* Mot clef principal */ size_t klen; /* Taille de ce mot clef */ @@ -474,25 +473,21 @@ static GBufferLine *g_raw_instruction_print(GRawInstruction *instr, GCodeBuffer base = G_ARCH_INSTRUCTION(instr); if (!instr->is_padding && !instr->is_string) - result = G_ARCH_INSTRUCTION_CLASS(g_raw_instruction_parent_class)->print(base, buffer, msize, content, syntax); + G_ARCH_INSTRUCTION_CLASS(g_raw_instruction_parent_class)->print(base, line, index, repeat); else { - result = g_code_buffer_prepare_new_line(buffer, &base->range); - - g_buffer_line_add_flag(result, BLF_HAS_CODE); - - g_buffer_line_fill_mrange(result, msize/* TODO ! */, msize); + g_buffer_line_fill_vmpa(line, get_mrange_addr(&base->range), MDS_32_BITS_UNSIGNED, MDS_32_BITS_UNSIGNED); /* Instruction proprement dite */ - key = g_arch_instruction_get_keyword(base, syntax); + key = g_arch_instruction_get_keyword(base, 0/*, syntax*/); klen = strlen(key); - g_buffer_line_append_text(result, BLC_ASSEMBLY_HEAD, key, klen, RTT_INSTRUCTION, NULL); + g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, key, klen, RTT_INSTRUCTION, NULL); if (instr->is_padding) - g_buffer_line_append_text(result, BLC_ASSEMBLY, "...", 3, RTT_RAW, NULL); + g_buffer_line_append_text(line, BLC_ASSEMBLY, "...", 3, RTT_RAW, NULL); else /*if (instr->is_string)*/ { @@ -516,15 +511,15 @@ static GBufferLine *g_raw_instruction_print(GRawInstruction *instr, GCodeBuffer { if (!first) { - g_buffer_line_append_text(result, BLC_ASSEMBLY, ",", 1, RTT_PUNCT, NULL); - g_buffer_line_append_text(result, BLC_ASSEMBLY, " ", 1, RTT_RAW, NULL); + g_buffer_line_append_text(line, BLC_ASSEMBLY, ",", 1, RTT_PUNCT, NULL); + g_buffer_line_append_text(line, BLC_ASSEMBLY, " ", 1, RTT_RAW, NULL); } else first = false; string[iter++] = '"'; - g_buffer_line_append_text(result, BLC_ASSEMBLY, string, iter, RTT_STRING, NULL); + g_buffer_line_append_text(line, BLC_ASSEMBLY, string, iter, RTT_STRING, NULL); iter = 1; @@ -534,13 +529,13 @@ static GBufferLine *g_raw_instruction_print(GRawInstruction *instr, GCodeBuffer if (!first) { - g_buffer_line_append_text(result, BLC_ASSEMBLY, ",", 1, RTT_PUNCT, NULL); - g_buffer_line_append_text(result, BLC_ASSEMBLY, " ", 1, RTT_RAW, NULL); + g_buffer_line_append_text(line, BLC_ASSEMBLY, ",", 1, RTT_PUNCT, NULL); + g_buffer_line_append_text(line, BLC_ASSEMBLY, " ", 1, RTT_RAW, NULL); } else first = false; - g_arch_operand_print(base->operands[i], result, syntax); + g_arch_operand_print(base->operands[i], line, 0/*, syntax*/); } @@ -554,15 +549,15 @@ static GBufferLine *g_raw_instruction_print(GRawInstruction *instr, GCodeBuffer { if (!first) { - g_buffer_line_append_text(result, BLC_ASSEMBLY, ",", 1, RTT_PUNCT, NULL); - g_buffer_line_append_text(result, BLC_ASSEMBLY, " ", 1, RTT_RAW, NULL); + g_buffer_line_append_text(line, BLC_ASSEMBLY, ",", 1, RTT_PUNCT, NULL); + g_buffer_line_append_text(line, BLC_ASSEMBLY, " ", 1, RTT_RAW, NULL); } else first = false; string[iter++] = '"'; - g_buffer_line_append_text(result, BLC_ASSEMBLY, string, iter, RTT_STRING, NULL); + g_buffer_line_append_text(line, BLC_ASSEMBLY, string, iter, RTT_STRING, NULL); } @@ -572,8 +567,6 @@ static GBufferLine *g_raw_instruction_print(GRawInstruction *instr, GCodeBuffer } - return result; - } diff --git a/src/arch/undefined.c b/src/arch/undefined.c index 0957764..d239dd5 100644 --- a/src/arch/undefined.c +++ b/src/arch/undefined.c @@ -70,7 +70,7 @@ static const char *g_undef_instruction_get_encoding(const GUndefInstruction *); static const char *g_undef_instruction_get_keyword(const GUndefInstruction *, AsmSyntax); /* Ajoute à un tampon GLib le contenu de l'instance spécifiée. */ -static GBufferLine *g_undef_instruction_print(GUndefInstruction *, GCodeBuffer *, MemoryDataSize, const GBinContent *, AsmSyntax); +static void g_undef_instruction_print(GUndefInstruction *, GBufferLine *, size_t, size_t); @@ -262,11 +262,11 @@ const char *g_undef_instruction_get_keyword(const GUndefInstruction *instr, AsmS /****************************************************************************** * * -* Paramètres : instr = instruction d'assemblage à représenter. * -* buffer = espace où placer ledit contenu. * +* Paramètres : instr = instruction d'assemblage à représenter. * +* buffer = espace où placer ledit contenu. * * msize = taille idéale des positions et adresses; * * content = contenu binaire global à venir lire. * -* syntax = type de représentation demandée. * +* syntax = type de représentation demandée. * * * * Description : Ajoute à un tampon GLib le contenu de l'instance spécifiée. * * * @@ -276,29 +276,22 @@ const char *g_undef_instruction_get_keyword(const GUndefInstruction *instr, AsmS * * ******************************************************************************/ -static GBufferLine *g_undef_instruction_print(GUndefInstruction *instr, GCodeBuffer *buffer, MemoryDataSize msize, const GBinContent *content, AsmSyntax syntax) +static void g_undef_instruction_print(GUndefInstruction *instr, GBufferLine *line, size_t index, size_t repeat) { - GBufferLine *result; /* Ligne de destination */ GArchInstruction *base; /* Version de base */ const char *key; /* Mot clef principal */ size_t klen; /* Taille de ce mot clef */ base = G_ARCH_INSTRUCTION(instr); - result = g_code_buffer_prepare_new_line(buffer, &base->range); - - g_buffer_line_add_flag(result, BLF_HAS_CODE); - - g_buffer_line_fill_for_instr(result, msize/* TODO ! */, msize, content, base->max_displayed_len); + g_buffer_line_fill_vmpa(line, get_mrange_addr(&base->range), MDS_32_BITS_UNSIGNED, MDS_32_BITS_UNSIGNED); /* Instruction proprement dite */ - key = g_arch_instruction_get_keyword(base, syntax); + key = g_arch_instruction_get_keyword(base, 0/*, syntax*/); klen = strlen(key); - g_buffer_line_append_text(result, BLC_ASSEMBLY_HEAD, key, klen, RTT_ERROR, NULL); - - return result; + g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, key, klen, RTT_ERROR, NULL); } diff --git a/src/arch/vmpa.h b/src/arch/vmpa.h index 1e17f17..16fada4 100644 --- a/src/arch/vmpa.h +++ b/src/arch/vmpa.h @@ -104,7 +104,9 @@ int cmp_vmpa(const vmpa2t *, const vmpa2t *); #define has_phys_addr(a) ((a)->physical != VMPA_NO_PHYSICAL) #define has_virt_addr(a) ((a)->virtual != VMPA_NO_VIRTUAL) -#define dup_vmpa(src) \ +#define is_invalid_vmpa(a) (!has_phys_addr(a) && !has_virt_addr(a)) + +#define dup_vmpa(src) \ make_vmpa(get_phy_addr(src), get_virt_addr(src)) /* Décalle une position d'une certaine quantité. */ diff --git a/src/format/dex/dex.c b/src/format/dex/dex.c index df920b2..d93346a 100755 --- a/src/format/dex/dex.c +++ b/src/format/dex/dex.c @@ -79,7 +79,7 @@ static bool g_dex_format_get_section_range_by_name(const GDexFormat *, const cha //static void g_dex_format_find_all_sources(GDexFormat *); /* Procède à la décompilation complète du format. */ -static void g_dex_format_decompile(const GDexFormat *, GCodeBuffer *, const char *); +static void g_dex_format_decompile(const GDexFormat *, void/*GCodeBuffer*/ *, const char *); @@ -470,7 +470,7 @@ static void g_dex_format_find_all_sources(GDexFormat *format) * * ******************************************************************************/ -static void g_dex_format_decompile(const GDexFormat *format, GCodeBuffer *buffer, const char *filename) +static void g_dex_format_decompile(const GDexFormat *format, void/*GCodeBuffer*/ *buffer, const char *filename) { #if 0 diff --git a/src/format/dex/pool.h b/src/format/dex/pool.h index 38065fa..b819156 100644 --- a/src/format/dex/pool.h +++ b/src/format/dex/pool.h @@ -29,6 +29,7 @@ #include "dex.h" #include "method.h" #include "../../analysis/routine.h" +#include "../../glibext/delayed.h" diff --git a/src/format/dwarf/v2/dwarf.h b/src/format/dwarf/v2/dwarf.h index 54c6b37..867ae39 100644 --- a/src/format/dwarf/v2/dwarf.h +++ b/src/format/dwarf/v2/dwarf.h @@ -28,8 +28,7 @@ #include -#include "../../executable.h" -#include "../../format.h" +#include "../../../core/formats.h" diff --git a/src/format/dwarf/v3/dwarf.h b/src/format/dwarf/v3/dwarf.h index e95ed16..bac5ccc 100644 --- a/src/format/dwarf/v3/dwarf.h +++ b/src/format/dwarf/v3/dwarf.h @@ -28,8 +28,7 @@ #include -#include "../../executable.h" -#include "../../format.h" +#include "../../../core/formats.h" diff --git a/src/format/dwarf/v4/dwarf.h b/src/format/dwarf/v4/dwarf.h index 29059b5..6eda64e 100644 --- a/src/format/dwarf/v4/dwarf.h +++ b/src/format/dwarf/v4/dwarf.h @@ -28,8 +28,7 @@ #include -#include "../../executable.h" -#include "../../format.h" +#include "../../../core/formats.h" diff --git a/src/format/elf/symbols.h b/src/format/elf/symbols.h index d1b0fae..90e2f61 100644 --- a/src/format/elf/symbols.h +++ b/src/format/elf/symbols.h @@ -28,6 +28,7 @@ #include "elf.h" +#include "../../glibext/delayed.h" #include "../../gtkext/gtkstatusstack.h" diff --git a/src/format/format-int.h b/src/format/format-int.h index e11e378..ea6b770 100644 --- a/src/format/format-int.h +++ b/src/format/format-int.h @@ -28,6 +28,9 @@ #include "format.h" +#include "../gtkext/gtkstatusstack.h" + + /* ------------------------ TRAITEMENT INDIVIDUEL DE FORMATS ------------------------ */ @@ -36,7 +39,7 @@ typedef SourceEndian (* format_get_endian_fc) (const GBinFormat *); /* Procède à la décompilation complète du format. */ -typedef void (* format_decompile_fc) (const GBinFormat *, GCodeBuffer *, const char *); +typedef void (* format_decompile_fc) (const GBinFormat *, void/*GCodeBuffer*/ *, const char *); /* Rythme des allocations pour les entrées de code */ diff --git a/src/format/java/java.h b/src/format/java/java.h index 074c797..a33870f 100755 --- a/src/format/java/java.h +++ b/src/format/java/java.h @@ -30,7 +30,7 @@ #include -#include "../format.h" +#include "../../core/formats.h" diff --git a/src/format/pe/pe.h b/src/format/pe/pe.h index 3ac5f49..d6c8dde 100644 --- a/src/format/pe/pe.h +++ b/src/format/pe/pe.h @@ -30,7 +30,7 @@ #include -#include "../format.h" +#include "../../core/formats.h" diff --git a/src/format/symbol.c b/src/format/symbol.c index 97ff114..82321c2 100644 --- a/src/format/symbol.c +++ b/src/format/symbol.c @@ -28,6 +28,12 @@ #include +#include "../glibext/linegen-int.h" + + + +/* --------------------- FONCTIONNALITES BASIQUES POUR SYMBOLES --------------------- */ + /* Symbole d'exécutable (instance) */ struct _GBinSymbol @@ -64,6 +70,9 @@ static void g_binary_symbol_class_init(GBinSymbolClass *); /* Initialise une instance de symbole d'exécutable. */ static void g_binary_symbol_init(GBinSymbol *); +/* Procède à l'initialisation de l'interface de génération. */ +static void g_binary_symbol_interface_init(GLineGeneratorInterface *); + /* Supprime toutes les références externes. */ static void g_binary_symbol_dispose(GBinSymbol *); @@ -72,8 +81,34 @@ static void g_binary_symbol_finalize(GBinSymbol *); +/* ------------------------ OFFRE DE CAPACITES DE GENERATION ------------------------ */ + + +/* Indique le nombre de ligne prêtes à être générées. */ +static size_t g_binary_symbol_count_lines(const GBinSymbol *); + +/* Retrouve l'emplacement correspondant à une position donnée. */ +static void g_binary_symbol_compute_addr(const GBinSymbol *, gint, vmpa2t *, size_t, size_t); + +/* Détermine si le conteneur s'inscrit dans une plage donnée. */ +static int g_binary_symbol_contains_addr(const GBinSymbol *, const vmpa2t *, size_t, size_t); + +/* Renseigne sur les propriétés liées à un générateur. */ +static BufferLineFlags g_binary_symbol_get_flags(const GBinSymbol *, size_t, size_t); + +/* Imprime dans une ligne de rendu le contenu représenté. */ +static void g_binary_symbol_print(GBinSymbol *, GBufferLine *, size_t, size_t); + + + +/* ---------------------------------------------------------------------------------- */ +/* FONCTIONNALITES BASIQUES POUR SYMBOLES */ +/* ---------------------------------------------------------------------------------- */ + + /* Indique le type défini pour un symbole d'exécutable. */ -G_DEFINE_TYPE(GBinSymbol, g_binary_symbol, G_TYPE_OBJECT); +G_DEFINE_TYPE_WITH_CODE(GBinSymbol, g_binary_symbol, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE(G_TYPE_LINE_GENERATOR, g_binary_symbol_interface_init)); /****************************************************************************** @@ -120,6 +155,29 @@ static void g_binary_symbol_init(GBinSymbol *symbol) /****************************************************************************** * * +* Paramètres : iface = interface GLib à initialiser. * +* * +* Description : Procède à l'initialisation de l'interface de génération. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_binary_symbol_interface_init(GLineGeneratorInterface *iface) +{ + iface->count = (linegen_count_lines_fc)g_binary_symbol_count_lines; + iface->compute = (linegen_compute_fc)g_binary_symbol_compute_addr; + iface->contains = (linegen_contains_fc)g_binary_symbol_contains_addr; + iface->get_flags = (linegen_get_flags_fc)g_binary_symbol_get_flags; + iface->print = (linegen_print_fc)g_binary_symbol_print; + +} + + +/****************************************************************************** +* * * Paramètres : symbol = instance d'objet GLib à traiter. * * * * Description : Supprime toutes les références externes. * @@ -665,3 +723,164 @@ GDbComment *g_binary_symbol_get_comment(const GBinSymbol *symbol) return symbol->comment; } + + + +/* ---------------------------------------------------------------------------------- */ +/* OFFRE DE CAPACITES DE GENERATION */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : symbol = générateur à consulter pour futur usage. * +* * +* Description : Détermine si un symbole pour faire office de générateur. * +* * +* Retour : Instance de générateur si les capacités sont là. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GLineGenerator *g_binary_symbol_produce_label(GBinSymbol *symbol) +{ + GLineGenerator *result; /* Instance à retourner */ + const char *label; /* Etiquette à insérer */ + + label = g_binary_symbol_get_label(symbol); + + result = (label != NULL ? G_LINE_GENERATOR(symbol) : NULL); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : symbol = générateur à consulter. * +* * +* Description : Indique le nombre de ligne prêtes à être générées. * +* * +* Retour : Nombre de lignes devant apparaître au final. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static size_t g_binary_symbol_count_lines(const GBinSymbol *symbol) +{ + return 1; + +} + + +/****************************************************************************** +* * +* Paramètres : symbol = générateur à consulter. * +* x = position géographique sur la ligne concernée. * +* addr = position en mémoire à analyser. * +* index = indice de cette même ligne dans le tampon global. * +* repeat = indice d'utilisations successives du générateur. * +* * +* Description : Retrouve l'emplacement correspondant à une position donnée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_binary_symbol_compute_addr(const GBinSymbol *symbol, gint x, vmpa2t *addr, size_t index, size_t repeat) +{ + const mrange_t *range; /* Emplacement à manipuler */ + + range = g_binary_symbol_get_range(symbol); + + copy_vmpa(addr, get_mrange_addr(range)); + +} + + +/****************************************************************************** +* * +* Paramètres : symbol = générateur à consulter. * +* addr = position en mémoire à analyser. * +* index = indice de cette même ligne dans le tampon global. * +* repeat = indice d'utilisations successives du générateur. * +* * +* 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_binary_symbol_contains_addr(const GBinSymbol *symbol, const vmpa2t *addr, size_t index, size_t repeat) +{ + int result; /* Conclusion à retourner */ + const mrange_t *range; /* Emplacement à manipuler */ + + range = g_binary_symbol_get_range(symbol); + + result = cmp_mrange_with_vmpa(range, addr); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : symbol = 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_binary_symbol_get_flags(const GBinSymbol *symbol, size_t index, size_t repeat) +{ + return BLF_IS_LABEL; + +} + + +/****************************************************************************** +* * +* Paramètres : symbol = 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. * +* * +* Description : Imprime dans une ligne de rendu le contenu représenté. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_binary_symbol_print(GBinSymbol *symbol, GBufferLine *line, size_t index, size_t repeat) +{ + const mrange_t *range; /* Emplacement à manipuler */ + const char *label; /* Etiquette à insérer */ + + range = g_binary_symbol_get_range(symbol); + + g_buffer_line_fill_vmpa(line, get_mrange_addr(range), MDS_32_BITS_UNSIGNED, MDS_32_BITS_UNSIGNED); + + label = g_binary_symbol_get_label(symbol); + + g_buffer_line_start_merge_at(line, BLC_ASSEMBLY_HEAD); + g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, SL(label), RTT_LABEL, NULL); + g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, ":", 1, RTT_PUNCT, NULL); + +} diff --git a/src/format/symbol.h b/src/format/symbol.h index 78741cb..e73bb27 100644 --- a/src/format/symbol.h +++ b/src/format/symbol.h @@ -32,9 +32,13 @@ #include "../analysis/db/item.h" #include "../analysis/db/items/comment.h" #include "../arch/instruction.h" +#include "../glibext/linegen.h" +/* --------------------- FONCTIONNALITES BASIQUES POUR SYMBOLES --------------------- */ + + /* Types de symbole */ typedef enum _SymbolType { @@ -164,4 +168,12 @@ GDbComment *g_binary_symbol_get_comment(const GBinSymbol *); +/* ------------------------ OFFRE DE CAPACITES DE GENERATION ------------------------ */ + + +/* Détermine si un symbole pour faire office de générateur. */ +GLineGenerator *g_binary_symbol_produce_label(GBinSymbol *); + + + #endif /* _FORMAT_SYMBOL_H */ diff --git a/src/glibext/Makefile.am b/src/glibext/Makefile.am index aa7a9a3..fe7565a 100644 --- a/src/glibext/Makefile.am +++ b/src/glibext/Makefile.am @@ -9,16 +9,21 @@ libglibext_la_SOURCES = \ delayed-int.h \ delayed.h delayed.c \ gbinportion.h gbinportion.c \ + gbuffercache.h gbuffercache.c \ gbufferline.h gbufferline.c \ gbufferview.h gbufferview.c \ - gcodebuffer.h gcodebuffer.c \ gnhash.h gnhash.c \ gwidthtracker.h gwidthtracker.c \ linecolumn.h linecolumn.c \ + linegen-int.h \ + linegen.h linegen.c \ linesegment.h linesegment.c \ proto.h \ signal.h signal.c +libglibext_la_LIBADD = \ + generators/libglibextgenerators.la + libglibext_la_LDFLAGS = @@ -26,7 +31,7 @@ AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) -SUBDIRS = +SUBDIRS = generators chrysamarshal.h: chrysamarshal.list diff --git a/src/glibext/gbinportion.c b/src/glibext/gbinportion.c index 4137763..eec9651 100644 --- a/src/glibext/gbinportion.c +++ b/src/glibext/gbinportion.c @@ -26,6 +26,7 @@ #include #include +#include #include #include @@ -33,8 +34,10 @@ #include +#include "../analysis/human/asm/lang.h" // TODO : REMME -> format ! #include "../common/extstr.h" #include "../common/sort.h" +#include "../glibext/linegen-int.h" @@ -49,6 +52,8 @@ struct _GBinPortion char *code; /* Code de la couleur de fond */ char *desc; /* Désignation humaine */ + char **text; /* Lignes brutes à représenter */ + size_t lcount; /* Quantité de ces lignes */ mrange_t range; /* Emplacement dans le code */ @@ -73,6 +78,9 @@ static void g_binary_portion_class_init(GBinPortionClass *); /* Initialise une instance de portion de données binaires. */ static void g_binary_portion_init(GBinPortion *); +/* Procède à l'initialisation de l'interface de génération. */ +static void g_binary_portion_interface_init(GLineGeneratorInterface *); + /* Supprime toutes les références externes. */ static void g_binary_portion_dispose(GBinPortion *); @@ -84,6 +92,26 @@ static bool g_binary_portion_compute_sub_area(const GBinPortion *, phys_t, const +/* ------------------------ OFFRE DE CAPACITES DE GENERATION ------------------------ */ + + +/* Indique le nombre de ligne prêtes à être générées. */ +static size_t g_binary_portion_count_lines(const GBinPortion *); + +/* Retrouve l'emplacement correspondant à une position donnée. */ +static void g_binary_portion_compute_addr(const GBinPortion *, gint, vmpa2t *, size_t, size_t); + +/* Détermine si le conteneur s'inscrit dans une plage donnée. */ +static int g_binary_portion_contains_addr(const GBinPortion *, const vmpa2t *, size_t, size_t); + +/* Renseigne sur les propriétés liées à un générateur. */ +static BufferLineFlags g_binary_portion_get_flags(const GBinPortion *, size_t, size_t); + +/* Imprime dans une ligne de rendu le contenu représenté. */ +static void g_binary_portion_print(GBinPortion *, GBufferLine *, size_t, size_t); + + + /* ------------------------ PARCOURS D'ENSEMBLES DE PORTIONS ------------------------ */ @@ -98,7 +126,8 @@ static bool g_portion_layer_contains_addr(const GBinPortion *, const vmpa2t *); /* Indique le type défini par la GLib pour les portions de données binaires. */ -G_DEFINE_TYPE(GBinPortion, g_binary_portion, G_TYPE_OBJECT); +G_DEFINE_TYPE_WITH_CODE(GBinPortion, g_binary_portion, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE(G_TYPE_LINE_GENERATOR, g_binary_portion_interface_init)); /****************************************************************************** @@ -140,6 +169,32 @@ static void g_binary_portion_class_init(GBinPortionClass *klass) static void g_binary_portion_init(GBinPortion *portion) { + portion->desc = NULL; + portion->text = NULL; + portion->lcount = 0; + +} + + +/****************************************************************************** +* * +* Paramètres : iface = interface GLib à initialiser. * +* * +* Description : Procède à l'initialisation de l'interface de génération. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_binary_portion_interface_init(GLineGeneratorInterface *iface) +{ + iface->count = (linegen_count_lines_fc)g_binary_portion_count_lines; + iface->compute = (linegen_compute_fc)g_binary_portion_compute_addr; + iface->contains = (linegen_contains_fc)g_binary_portion_contains_addr; + iface->get_flags = (linegen_get_flags_fc)g_binary_portion_get_flags; + iface->print = (linegen_print_fc)g_binary_portion_print; } @@ -177,11 +232,19 @@ static void g_binary_portion_dispose(GBinPortion *portion) static void g_binary_portion_finalize(GBinPortion *portion) { + size_t i; /* Boucle de parcours */ + free(portion->code); if (portion->desc != NULL) free(portion->desc); + for (i = 0; i < portion->lcount; i++) + free(portion->text[i]); + + if (portion->text != NULL) + free(portion->text); + G_OBJECT_CLASS(g_binary_portion_parent_class)->finalize(G_OBJECT(portion)); } @@ -260,9 +323,66 @@ int g_binary_portion_compare(const GBinPortion **a, const GBinPortion **b) void g_binary_portion_set_desc(GBinPortion *portion, const char *desc) { - if (portion->desc != NULL) free(portion->desc); + size_t i; /* Boucle de parcours */ + GCodingLanguage *lang; /* Langage de sortie préféré */ + + if (portion->desc != NULL) + { + free(portion->desc); + + for (i = 0; i < portion->lcount; i++) + free(portion->text[i]); + + if (portion->text != NULL) + { + free(portion->text); + portion->text = NULL; + } + + } + + if (desc == NULL) + portion->desc = NULL; + + else + { + portion->desc = strdup(desc); + + /* Constitution du rendu */ + + portion->text = calloc(4, sizeof(char *)); + portion->lcount = 4; + + portion->text[0] = strdup("======================================================"); + portion->text[1] = strdup(""); + + asprintf(&portion->text[2], "%s (%s%s%s%s)", portion->desc, _("rights: "), + portion->rights & PAC_READ ? "r" : "-", + portion->rights & PAC_WRITE ? "w" : "-", + portion->rights & PAC_EXEC ? "x" : "-"); - portion->desc = strdup(desc); + portion->text[3] = strdup(""); + portion->text[4] = strdup("======================================================"); + + /* Ajout de la touche "commentaires" */ + + lang = g_asm_language_new(); + + g_coding_language_encapsulate_comments(lang, &portion->text, &portion->lcount); + + g_object_unref(G_OBJECT(lang)); + + /* Ajout de deux bordures vides */ + + portion->lcount += 2; + portion->text = realloc(portion->text, portion->lcount * sizeof(char *)); + + memmove(&portion->text[1], &portion->text[0], (portion->lcount - 2) * sizeof(char *)); + + portion->text[0] = NULL; + portion->text[portion->lcount - 1] = NULL; + + } } @@ -346,98 +466,6 @@ PortionAccessRights g_binary_portion_get_rights(const GBinPortion *portion) /****************************************************************************** * * -* Paramètres : portion = description de partie à consulter. * -* buffer = espace où placer ledit contenu. * -* msize = taille idéale des positions et adresses; * -* * -* Description : Insère dans un tampon une description de portion. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_binary_portion_print(const GBinPortion *portion, GCodeBuffer *buffer, MemoryDataSize msize) -{ - mrange_t range; /* Couverture à fournir */ - GBufferLine *line; /* Nouvelle ligne à éditer */ - char rights[64]; /* Traduction en texte */ - - /* On ne traite pas les portions anonymes ! */ - if (portion->desc == NULL) return; - - init_mrange(&range, get_mrange_addr(&portion->range), 0); - - line = g_code_buffer_prepare_new_line(buffer, &range); - g_buffer_line_fill_mrange(line, msize, msize); - - g_buffer_line_add_flag(line, BLF_WIDTH_MANAGER); - - g_code_buffer_append_new_line(buffer, line); - - /* Séparation */ - - line = g_code_buffer_prepare_new_line(buffer, &range); - g_buffer_line_fill_mrange(line, msize, msize); - - g_buffer_line_start_merge_at(line, BLC_ASSEMBLY_HEAD); - g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, - "; ======================================================", 56, RTT_COMMENT, NULL); - - g_code_buffer_append_new_line(buffer, line); - - /* Retour à la ligne */ - - line = g_code_buffer_prepare_new_line(buffer, &range); - g_buffer_line_fill_mrange(line, msize, msize); - - g_buffer_line_start_merge_at(line, BLC_ASSEMBLY_HEAD); - g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, "; ", 2, RTT_COMMENT, NULL); - - g_code_buffer_append_new_line(buffer, line); - - /* Description */ - - line = g_code_buffer_prepare_new_line(buffer, &range); - g_buffer_line_fill_mrange(line, msize, msize); - - g_buffer_line_start_merge_at(line, BLC_ASSEMBLY_HEAD); - - g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, "; ", 2, RTT_COMMENT, NULL); - - g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, portion->desc, strlen(portion->desc), RTT_COMMENT, NULL); - - snprintf(rights, sizeof(rights), " (%s%s%s%s)", - _("rights: "), - portion->rights & PAC_READ ? "r" : "-", - portion->rights & PAC_WRITE ? "w" : "-", - portion->rights & PAC_EXEC ? "x" : "-"); - - g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, rights, strlen(rights), RTT_COMMENT, NULL); - - g_code_buffer_append_new_line(buffer, line); - - /* Retour à la ligne */ - - line = g_code_buffer_prepare_new_line(buffer, &range); - g_buffer_line_fill_mrange(line, msize, msize); - - g_buffer_line_start_merge_at(line, BLC_ASSEMBLY_HEAD); - g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, "; ", 2, RTT_COMMENT, NULL); - - g_code_buffer_append_new_line(buffer, line); - - line = g_code_buffer_prepare_new_line(buffer, &range); - g_buffer_line_fill_mrange(line, msize, msize); - g_code_buffer_append_new_line(buffer, line); - - -} - - -/****************************************************************************** -* * * Paramètres : portion = description de partie à mettre à jour. * * tooltip = astuce à compléter. [OUT] * * * @@ -724,6 +752,133 @@ bool g_binary_portion_visit(GBinPortion *portion, visit_portion_fc visitor, void /* ---------------------------------------------------------------------------------- */ +/* OFFRE DE CAPACITES DE GENERATION */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : portion = générateur à consulter. * +* * +* Description : Indique le nombre de ligne prêtes à être générées. * +* * +* Retour : Nombre de lignes devant apparaître au final. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static size_t g_binary_portion_count_lines(const GBinPortion *portion) +{ + return portion->lcount; + +} + + +/****************************************************************************** +* * +* Paramètres : portion = générateur à consulter. * +* x = position géographique sur la ligne concernée. * +* addr = position en mémoire à analyser. * +* index = indice de cette même ligne dans le tampon global. * +* repeat = indice d'utilisations successives du générateur. * +* * +* Description : Retrouve l'emplacement correspondant à une position donnée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_binary_portion_compute_addr(const GBinPortion *portion, gint x, vmpa2t *addr, size_t index, size_t repeat) +{ + copy_vmpa(addr, get_mrange_addr(&portion->range)); + +} + + +/****************************************************************************** +* * +* Paramètres : portion = générateur à consulter. * +* addr = position en mémoire à analyser. * +* index = indice de cette même ligne dans le tampon global. * +* repeat = indice d'utilisations successives du générateur. * +* * +* 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_binary_portion_contains_addr(const GBinPortion *portion, const vmpa2t *addr, size_t index, size_t repeat) +{ + int result; /* Conclusion à retourner */ + + result = cmp_vmpa(addr, get_mrange_addr(&portion->range)); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : portion = 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_binary_portion_get_flags(const GBinPortion *portion, size_t index, size_t repeat) +{ + return (repeat == 0 ? BLF_WIDTH_MANAGER : BLF_HAS_CODE); + +} + + +/****************************************************************************** +* * +* Paramètres : portion = 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. * +* * +* Description : Imprime dans une ligne de rendu le contenu représenté. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_binary_portion_print(GBinPortion *portion, GBufferLine *line, size_t index, size_t repeat) +{ + assert(repeat < portion->lcount); + + g_buffer_line_fill_vmpa(line, get_mrange_addr(&portion->range), MDS_32_BITS_UNSIGNED, MDS_32_BITS_UNSIGNED); + + if (portion->text[repeat] != NULL) + { + g_buffer_line_start_merge_at(line, BLC_ASSEMBLY_HEAD); + + g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, SL(portion->text[repeat]), RTT_COMMENT, NULL); + + } + +} + + + +/* ---------------------------------------------------------------------------------- */ /* PARCOURS D'ENSEMBLES DE PORTIONS */ /* ---------------------------------------------------------------------------------- */ diff --git a/src/glibext/gbinportion.h b/src/glibext/gbinportion.h index 2aa5e1a..4f4b3be 100644 --- a/src/glibext/gbinportion.h +++ b/src/glibext/gbinportion.h @@ -30,7 +30,6 @@ #include -#include "gcodebuffer.h" #include "../arch/vmpa.h" #include "../common/fnv1a.h" @@ -100,9 +99,6 @@ void g_binary_portion_set_rights(GBinPortion *, PortionAccessRights); /* Fournit les droits associés à une partie de code. */ PortionAccessRights g_binary_portion_get_rights(const GBinPortion *); -/* Insère dans un tampon une description de portion. */ -void g_binary_portion_print(const GBinPortion *, GCodeBuffer *, MemoryDataSize); - /* Prépare une astuce concernant une portion pour son affichage. */ void g_binary_portion_query_tooltip(GBinPortion *, GtkTooltip *); diff --git a/src/glibext/gbuffercache.c b/src/glibext/gbuffercache.c new file mode 100644 index 0000000..57a9487 --- /dev/null +++ b/src/glibext/gbuffercache.c @@ -0,0 +1,1625 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * gbuffercache.c - affichage à la demande d'un ensemble de lignes + * + * Copyright (C) 2016 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 . + */ + + +#include "gbuffercache.h" + + +#include +#include +#include + + +#include "chrysamarshal.h" + + + +/* --------------------- FONCTIONS AUXILIAIRES DE MANIPULATIONS --------------------- */ + + +/* Informations rattachées à la génération d'une ligne */ +typedef struct _generator_link +{ + GLineGenerator *instance; /* Fournisseur de contenu */ + size_t repeat; /* Compteur de successions */ + +} generator_link; + +/* Suivi interne de l'état d'une ligne */ +typedef struct _cache_info +{ + union + { + generator_link generator; /* Générateur unique */ + generator_link *generators; /* Liste de générateurs */ + }; + size_t count; /* Taille de cette liste */ + + GBufferLine *line; /* Ligne en place ou NULL */ + + BufferLineFlags extra_flags; /* Propriétés supplémentaires */ + +} cache_info; + + +/* Gros verrou global pour alléger les structures... */ +G_LOCK_DEFINE_STATIC(_line_update); + + +/* Met en place un nouvel ensemble d'information sur une ligne. */ +static void init_cache_info(cache_info *, GLineGenerator *, size_t, BufferLineFlags); + +/* Libère la mémoire occupée par des informations sur une ligne. */ +static void release_cache_info(cache_info *); + +/* Ajoute un générateur aux informations sur une ligne. */ +static void extend_cache_info(cache_info *, GLineGenerator *); + +/* Retire un générateur aux informations d'une ligne. */ +static void remove_from_cache_info(cache_info *, GLineGenerator *); + +/* Retrouve l'emplacement correspondant à une position de ligne. */ +static void get_cache_info_addr(const cache_info *, size_t, gint, vmpa2t *); + +/* Suivit les variations du compteur de références d'une ligne. */ +static void on_line_ref_toggle(cache_info *, GBufferLine *, gboolean); + +/* Fournit la ligne de tampon correspondant aux générateurs. */ +static GBufferLine *get_cache_info_line(cache_info *, size_t); + +/* Force la réinitialisation d'une éventuelle ligne cachée. */ +static void reset_cache_info_line(cache_info *); + + + +/* -------------------------- TAMPON POUR CODE DESASSEMBLE -------------------------- */ + + +/* Tampon pour gestion de lignes optimisée (instance) */ +struct _GBufferCache +{ + GObject parent; /* A laisser en premier */ + + cache_info *lines; /* Liste des lignes intégrées */ + size_t count; /* Quantité en cache */ + size_t used; /* Quantité utilisée */ + + GWidthTracker *tracker; /* Suivi des largeurs */ + +}; + +/* Tampon pour gestion de lignes optimisée (classe) */ +struct _GBufferCacheClass +{ + GObjectClass parent; /* A laisser en premier */ + + gint line_height; /* Hauteur maximale des lignes */ + gint left_margin; /* Marge gauche + espace */ + gint text_pos; /* Début d'impression du code */ + + /* Signaux */ + + void (* size_changed) (GBufferCache *, bool, size_t, size_t); + +}; + + +/* Taille des allocations de masse */ +#define LINE_ALLOC_BULK 1000 + + +/* Procède à l'initialisation d'une classe de tampon de lignes. */ +static void g_buffer_cache_class_init(GBufferCacheClass *); + +/* Procède à l'initialisation d'un tampon de gestion de lignes. */ +static void g_buffer_cache_init(GBufferCache *); + +/* Supprime toutes les références externes. */ +static void g_buffer_cache_dispose(GBufferCache *); + +/* Procède à la libération totale de la mémoire. */ +static void g_buffer_cache_finalize(GBufferCache *); + +/* Calcule l'indice d'apparition d'un générateur dans le tampon. */ +static size_t g_buffer_cache_compute_repetition(GBufferCache *, size_t, GLineGenerator *); + + + +/* ---------------------------------------------------------------------------------- */ +/* FONCTIONS AUXILIAIRES DE MANIPULATIONS */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : info = informations concernant une ligne à constituer. * +* generator = générateur à associer à toutes les lignes. * +* repeat = compteur de répétition entre les lignes. * +* flags = propriétés supplémentaires à associer à la ligne.* +* * +* Description : Met en place un nouvel ensemble d'information sur une ligne. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void init_cache_info(cache_info *info, GLineGenerator *generator, size_t repeat, BufferLineFlags flags) +{ + info->generator.instance = generator; + info->generator.repeat = repeat; + + g_object_ref(G_OBJECT(generator)); + + info->count = 1; + + info->line = NULL; + + info->extra_flags = flags; + +} + + +/****************************************************************************** +* * +* Paramètres : info = informations concernant une ligne à constituer. * +* * +* Description : Libère la mémoire occupée par des informations sur une ligne.* +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void release_cache_info(cache_info *info) +{ + size_t i; /* Boucle de parcours */ + + if (info->count == 1) + g_object_unref(G_OBJECT(info->generator.instance)); + + else + for (i = 0; i < info->count; i++) + g_object_unref(G_OBJECT(info->generators[i].instance)); + + reset_cache_info_line(info); + +} + + +/****************************************************************************** +* * +* Paramètres : info = informations concernant une ligne à actualiser. * +* generator = générateur à associer à toutes les lignes. * +* * +* Description : Ajoute un générateur aux informations sur une ligne. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void extend_cache_info(cache_info *info, GLineGenerator *generator) +{ + generator_link first; /* Générateur déjà en place */ + generator_link *new; /* Nouveau générateur placé */ + + if (info->count == 1) + { + first = info->generator; + + info->generators = (generator_link *)calloc(2, sizeof(generator_link)); + + info->generators[0] = first; + info->count = 2; + + new = &info->generators[1]; + + } + else + { + info->generators = (generator_link *)realloc(info->generators, + ++info->count * sizeof(generator_link)); + + new = &info->generators[info->count - 1]; + + } + + new->instance = generator; + new->repeat = 0; + + g_object_ref(G_OBJECT(generator)); + + reset_cache_info_line(info); + +} + + +/****************************************************************************** +* * +* Paramètres : info = informations concernant une ligne à actualiser. * +* generator = générateur à dissocier de toutes les lignes. * +* * +* Description : Retire un générateur aux informations d'une ligne. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void remove_from_cache_info(cache_info *info, GLineGenerator *generator) +{ + generator_link *link; /* Accès simplifié */ + size_t i; /* Boucle de parcours */ + generator_link *old; /* Mémorisation avant opérat° */ + + if (info->count == 1) + { + link = &info->generator; + + assert(link->instance == generator); + + g_object_unref(G_OBJECT(generator)); + + info->count = 0; + + } + + else + { + for (i = 0; i < info->count; i++) + { + link = &info->generators[i]; + + if (link->instance == generator) + { + if ((i + 1) < info->count) + memmove(&info->generators[i], &info->generators[i + 1], + (info->count - i - 1) * sizeof(generator_link)); + + if (info->count == 2) + { + old = info->generators; + + info->count = 1; + info->generator = info->generators[0]; + + free(old); + + } + else + info->generators = (generator_link *)realloc(info->generators, + --info->count * sizeof(generator_link)); + + break; + + } + + } + +#ifndef NDEBUG + + /** + * Attention : si l'élément était en dernière position, + * l'indice de parcours est désormais égal au nombre de générateurs présents ! + */ + assert(i <= info->count); + + for ( ; i < info->count; i++) + { + link = &info->generators[i]; + + assert(link->instance != generator); + + } + +#endif + + } + + reset_cache_info_line(info); + +} + + +/****************************************************************************** +* * +* Paramètres : info = informations sur une ligne à venir consulter. * +* index = indice de la ligne visée par la consultation. * +* x = position géographique sur la ligne concernée. * +* addr = adresse à renseigner. [OUT] * +* * +* Description : Retrouve l'emplacement correspondant à une position de ligne.* +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void get_cache_info_addr(const cache_info *info, size_t index, gint x, vmpa2t *addr) +{ + const generator_link *generator; /* Générateur retenu */ + + if (info->count == 1) + generator = &info->generator; + else + generator = &info->generators[0]; + + g_line_generator_compute_addr(generator->instance, x, addr, index, generator->repeat); + +} + + +/****************************************************************************** +* * +* Paramètres : info = informations sur une ligne à venir manipuler. * +* line = tampon de lignes à venir supprimer au besoin. * +* last = indication sur la valeur du compteur de références. * +* * +* Description : Suivit les variations du compteur de références d'une ligne. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void on_line_ref_toggle(cache_info *info, GBufferLine *line, gboolean last) +{ + if (last) + { + G_LOCK(_line_update); + + assert(info->line != NULL); + + info->line = NULL; + + G_UNLOCK(_line_update); + + } + +} + + +/****************************************************************************** +* * +* Paramètres : info = informations sur une ligne à venir manipuler. * +* index = indice de la ligne à constituer. * +* * +* Description : Fournit la ligne de tampon correspondant aux générateurs. * +* * +* Retour : Ligne déjà en place ou créée pour le besoin. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GBufferLine *get_cache_info_line(cache_info *info, size_t index) +{ + GBufferLine *result; /* Construction à retourner */ + size_t i; /* Boucle de parcours */ + + G_LOCK(_line_update); + + result = info->line; + + if (result == NULL) + { + result = g_buffer_line_new((mrange_t []){ { { 0 }, 0 } }, 0/* !! */); + + g_object_add_toggle_ref(G_OBJECT(result), (GToggleNotify)on_line_ref_toggle, info); + + if (info->count == 1) + g_line_generator_print(info->generator.instance, result, index, info->generator.repeat); + + else + for (i = 0; i < info->count; i++) + g_line_generator_print(info->generators[i].instance, result, index, info->generators[i].repeat); + + info->line = result; + + } + + else + g_object_ref(G_OBJECT(result)); + + G_UNLOCK(_line_update); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : info = informations sur une ligne à venir manipuler. * +* * +* Description : Force la réinitialisation d'une éventuelle ligne cachée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void reset_cache_info_line(cache_info *info) +{ + G_LOCK(_line_update); + + if (info->line != NULL) + { + g_object_remove_toggle_ref(G_OBJECT(info->line), (GToggleNotify)on_line_ref_toggle, info); + + g_object_unref(G_OBJECT(info->line)); + + info->line = NULL; + + } + + G_UNLOCK(_line_update); + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* TAMPON POUR CODE DESASSEMBLE */ +/* ---------------------------------------------------------------------------------- */ + + +/* Détermine le type du composant de tampon pour gestion de lignes optimisée. */ +G_DEFINE_TYPE(GBufferCache, g_buffer_cache, G_TYPE_OBJECT); + + +/****************************************************************************** +* * +* Paramètres : class = classe de composant GLib à initialiser. * +* * +* Description : Procède à l'initialisation d'une classe de tampon de lignes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_buffer_cache_class_init(GBufferCacheClass *class) +{ + GObjectClass *object; /* Autre version de la classe */ + + object = G_OBJECT_CLASS(class); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_buffer_cache_dispose; + object->finalize = (GObjectFinalizeFunc)g_buffer_cache_finalize; + + class->line_height = 17; + class->left_margin = 2 * class->line_height; + class->text_pos = 2.5 * class->line_height; + + /* Signaux */ + + g_signal_new("size-changed", + G_TYPE_BUFFER_CACHE, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(GBufferCacheClass, size_changed), + NULL, NULL, + g_cclosure_user_marshal_VOID__BOOLEAN_ULONG_ULONG, + G_TYPE_NONE, 3, G_TYPE_BOOLEAN, G_TYPE_ULONG, G_TYPE_ULONG); + +} + + +/****************************************************************************** +* * +* Paramètres : cache = composant GLib à initialiser. * +* * +* Description : Procède à l'initialisation d'un tampon de gestion de lignes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_buffer_cache_init(GBufferCache *cache) +{ + cache->tracker = g_width_tracker_new(cache); + +} + + +/****************************************************************************** +* * +* Paramètres : cache = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_buffer_cache_dispose(GBufferCache *cache) +{ + size_t i; /* Boucle de parcours #1 */ + cache_info *info; /* Accès directe à une ligne */ + size_t j; /* Boucle de parcours #2 */ + + for (i = 0; i < cache->used; i++) + { + info = &cache->lines[i]; + + if (info->count == 1) + g_object_unref(G_OBJECT(info->generator.instance)); + + else + for (j = 0; j < info->count; j++) + g_object_unref(G_OBJECT(info->generators[j].instance)); + + if (info->line) + g_object_unref(G_OBJECT(info->line)); + + } + + g_object_unref(G_OBJECT(cache->tracker)); + + G_OBJECT_CLASS(g_buffer_cache_parent_class)->dispose(G_OBJECT(cache)); + +} + + +/****************************************************************************** +* * +* Paramètres : cache = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_buffer_cache_finalize(GBufferCache *cache) +{ + size_t i; /* Boucle de parcours */ + cache_info *info; /* Accès directe à une ligne */ + + for (i = 0; i < cache->used; i++) + { + info = &cache->lines[i]; + + if (info->count > 1) + free(info->generators); + + } + + if (cache->lines != NULL) + free(cache->lines); + + G_OBJECT_CLASS(g_buffer_cache_parent_class)->finalize(G_OBJECT(cache)); + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Crée un nouveau composant de tampon pour code désassemblé. * +* * +* Retour : Composant GLib créé. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBufferCache *g_buffer_cache_new(void) +{ + GBufferCache *result; /* Composant à retourner */ + + result = g_object_new(G_TYPE_BUFFER_CACHE, NULL); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : cache = tampon de lignes à consulter. * +* * +* Description : Fournit la hauteur d'impression d'une ligne visualisée. * +* * +* Retour : Hauteur de ligne en pixels. * +* * +* Remarques : - * +* * +******************************************************************************/ + +gint g_buffer_cache_get_line_height(const GBufferCache *cache) +{ + GBufferCacheClass *class; /* Classe des tampons */ + + class = G_BUFFER_CACHE_GET_CLASS(cache); + + return class->line_height; + +} + + +/****************************************************************************** +* * +* Paramètres : cache = tampon de lignes à consulter. * +* * +* Description : Fournit la taille réservée pour la marge gauche. * +* * +* Retour : Largeur en pixels. * +* * +* Remarques : - * +* * +******************************************************************************/ + +gint g_buffer_cache_get_left_margin(const GBufferCache *cache) +{ + GBufferCacheClass *class; /* Classe des tampons */ + + class = G_BUFFER_CACHE_GET_CLASS(cache); + + return class->left_margin; + +} + + +/****************************************************************************** +* * +* Paramètres : cache = tampon de lignes à consulter. * +* * +* Description : Fournit la position de départ pour l'impression de texte. * +* * +* Retour : Position en pixels. * +* * +* Remarques : - * +* * +******************************************************************************/ + +gint g_buffer_cache_get_text_position(const GBufferCache *cache) +{ + GBufferCacheClass *class; /* Classe des tampons */ + + class = G_BUFFER_CACHE_GET_CLASS(cache); + + return class->text_pos; + +} + + +/****************************************************************************** +* * +* Paramètres : cache = instance GLib à consulter. * +* * +* Description : Compte le nombre de lignes rassemblées dans un tampon. * +* * +* Retour : Nombre de lignes constituant le tampon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +size_t g_buffer_cache_count_lines(const GBufferCache *cache) +{ + return cache->used; + +} + + +/****************************************************************************** +* * +* Paramètres : cache = composant GLib à consulter. * +* * +* Description : Fournit un lien vers la structure de suivi de largeurs. * +* * +* Retour : Gestionnaire de largeurs de lignes. * +* * +* Remarques : - * +* * +******************************************************************************/ + +const GWidthTracker *g_buffer_cache_get_width_tracker(const GBufferCache *cache) +{ + return cache->tracker; + +} + + + + + +/****************************************************************************** +* * +* Paramètres : cache = instance GLib à consulter. * +* index = indice de la ligne où se trouve le générateur. * +* generator = générateur associé à au moins une ligne. * +* * +* Description : Calcule l'indice d'apparition d'un générateur dans le tampon.* +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static size_t g_buffer_cache_compute_repetition(GBufferCache *cache, size_t index, GLineGenerator *generator) +{ + size_t result; /* Compteur à retourner */ + cache_info *info; /* Accès directe à une ligne */ + size_t i; /* Boucle de parcours */ + + result = 0; + + if (index > 0) + { + info = &cache->lines[index - 1]; + + if (info->count == 1) + { + if (info->generator.instance == generator) + result = info->generator.repeat + 1; + + } + + else + for (i = 0; i < info->count; i++) + if (info->generators[i].instance == generator) + { + result = info->generators[i].repeat + 1; + break; + } + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : cache = instance GLib à modifier. * +* index = point d'insertion, puis de sauvegarde. * +* generator = générateur à insérer dans les lignes. * +* before = précise l'emplacement final des nouvelles lignes.* +* after = précise l'emplacement final des nouvelles lignes.* +* * +* Description : Insère un générateur dans des lignes à une position donnée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_buffer_cache_insert_at(GBufferCache *cache, size_t index, GLineGenerator *generator, bool before, bool after) +{ +#ifndef NDEBUG + vmpa2t gen_addr; /* Position du générateur */ + vmpa2t line_addr; /* Position de la ligne */ +#endif + size_t needed; /* Emplacements nécessaires */ + size_t i; /* Boucle de parcours */ + + assert(index < cache->used); + + assert(!(before && after)); + +#ifndef NDEBUG + + g_line_generator_compute_addr(generator, 0, &gen_addr, index, 0); + + get_cache_info_addr(&cache->lines[index], index, 0, &line_addr); + + /////////////////////////////////////// + if (cmp_vmpa(&gen_addr, &line_addr) != 0) return; + + assert(cmp_vmpa(&gen_addr, &line_addr) == 0); + +#endif + + /* Cas particulier d'ajout en fin de cache... */ + if (after && (index + 1) == cache->used) + { + g_buffer_cache_append(cache, generator, BLF_NONE); + goto gbcia_done; + } + + /* Adaptation de l'espace */ + + needed = g_line_generator_count_lines(generator); + + if (before || after) + { + if ((cache->used + needed) >= cache->count) + { + cache->count += needed + LINE_ALLOC_BULK; + cache->lines = (cache_info *)realloc(cache->lines, cache->count * sizeof(cache_info)); + } + } +#ifndef NDEBUG + else + assert(needed == 1); +#endif + + /* Insertion du générateur */ + + if (after) + index++; + + if (before || after) + { + memmove(&cache->lines[index], &cache->lines[index + needed], (cache->used - index) * sizeof(cache_info)); + + for (i = 0; i < needed; i++) + init_cache_info(&cache->lines[index + i], generator, i, BLF_NONE); + + cache->used += needed; + + g_width_tracker_update_added(cache->tracker, index, needed); + + g_signal_emit_by_name(cache, "size-changed", true, index, needed); + + } + + else + { + extend_cache_info(&cache->lines[index], generator); + + g_width_tracker_update(cache->tracker, index); + + g_signal_emit_by_name(cache, "size-changed", true, index, 1); + + } + + gbcia_done: + + ; + +} + + +/****************************************************************************** +* * +* Paramètres : cache = instance GLib à modifier. * +* index = point d'insertion, puis de sauvegarde. * +* type = type de générateurs à retirer des lignes visées. * +* before = précise l'emplacement final de l'élément visé. * +* after = précise l'emplacement final de l'élément visé. * +* * +* Description : Retire un type de générateur de lignes. * +* * +* Retour : Générateur éventuellement trouvé ou NULL si aucun. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GLineGenerator *g_buffer_cache_delete_type_at(GBufferCache *cache, size_t index, GType type, bool before, bool after) +{ + GLineGenerator *result; /* Prédécesseur à retourner */ + cache_info *info; /* Accès directe à une ligne */ + generator_link *link; /* Accès simplifié */ + size_t i; /* Boucle de parcours */ + size_t count; /* Emplacements occupés */ + size_t delete; /* Indice de suppression */ + + assert(index < cache->used); + + assert(!(before && after)); + + result = NULL; + + /* Recherche d'un générateur correspondant */ + + if (before) + info = &cache->lines[index - 1]; + else if (after) + info = &cache->lines[index + 1]; + else + info = &cache->lines[index]; + + if (info->count == 1) + { + link = &info->generator; + + if (G_OBJECT_TYPE(link->instance) == type) + result = link->instance; + + } + + else + for (i = 0; i < info->count && result == NULL; i++) + { + link = &info->generators[i]; + + if (G_OBJECT_TYPE(link->instance) == type) + result = link->instance; + + } + + /* Retrait de l'instance trouvée */ + + if (result != NULL) + { + count = g_line_generator_count_lines(result); + +#ifndef NDEBUG + if (!before && !after) + assert(count == 1); +#endif + + g_object_ref(G_OBJECT(result)); + + /* Suppression de l'élément */ + + for (i = 0; i < count; i++) + { + if (before) + info = &cache->lines[index - 1 - i]; + else if (after) + info = &cache->lines[index + 1 + i]; + else + info = &cache->lines[index]; + + remove_from_cache_info(info, result); + + } + + /* Suppression des lignes associées */ + + for (i = 0; i < count; i++) + { + if (before) + delete = index - 1; + else if (after) + delete = index + 1; + else + delete = index; + + info = &cache->lines[delete]; + + if (info->count == 0) + { + release_cache_info(info); + + if ((delete + 1) < cache->used) + memmove(&cache->lines[delete], &cache->lines[delete + 1], + (cache->used - delete - 1) * sizeof(cache_info)); + + cache->used--; + + g_width_tracker_update_deleted(cache->tracker, delete, delete); + + g_signal_emit_by_name(cache, "size-changed", false, delete, 1); + + } + + } + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : cache = instance GLib à modifier. * +* generator = générateur à associer à toutes les lignes. * +* flags = propriétés supplémentaires à associer à la ligne.* +* * +* Description : Ajoute en fin de tampon un générateur de lignes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_buffer_cache_append(GBufferCache *cache, GLineGenerator *generator, BufferLineFlags flags) +{ + size_t count; /* Nombre de lignes générées */ + size_t index; /* Point d'insertion */ + size_t i; /* Boucle de parcours */ + cache_info *info; /* Accès directe à une ligne */ + + count = g_line_generator_count_lines(generator); + + assert(count > 0); + + assert((flags != BLF_NONE && count == 1) || flags == BLF_NONE); + + if ((cache->used + count) > cache->count) + { + cache->count += count + LINE_ALLOC_BULK; + cache->lines = (cache_info *)realloc(cache->lines, cache->count * sizeof(cache_info)); + } + + index = cache->used; + + for (i = 0; i < count; i++) + { + info = &cache->lines[index + i]; + + info->generator.instance = generator; + info->generator.repeat = g_buffer_cache_compute_repetition(cache, index + i, generator); + + g_object_ref(G_OBJECT(generator)); + + info->count = 1; + + info->line = NULL; + + info->extra_flags = flags; + + } + + cache->used += count; + + g_object_unref(G_OBJECT(generator)); + + g_width_tracker_update_added(cache->tracker, index, count); + + g_signal_emit_by_name(cache, "size-changed", true, index, count); + +} + + +/****************************************************************************** +* * +* Paramètres : cache = instance GLib à modifier. * +* count = quantité totale de lignes à avoir à disposition. * +* generator = générateur à associer à toutes les lignes. * +* * +* Description : Etend un tampon avec un générateur de lignes unique. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_buffer_cache_extend_with(GBufferCache *cache, size_t count, GLineGenerator *generator) +{ + size_t index; /* Point d'insertion */ + size_t i; /* Boucle de parcours */ + cache_info *info; /* Accès directe à une ligne */ + size_t added; /* Nombre d'ajouts effectués */ + + assert(count >= cache->used); + + if (count > cache->count) + { + cache->lines = (cache_info *)realloc(cache->lines, count * sizeof(cache_info)); + cache->count = count; + } + + index = cache->used; + + for (i = index; i < count; i++) + { + info = &cache->lines[i]; + + info->generator.instance = generator; + info->generator.repeat = g_buffer_cache_compute_repetition(cache, i, generator); + + g_object_ref(G_OBJECT(generator)); + + info->count = 1; + + info->line = NULL; + + } + + added = count - cache->used; + + cache->used = count; + + g_object_unref(G_OBJECT(generator)); + + if (added > 0) + { + g_width_tracker_update_added(cache->tracker, index, added); + + g_signal_emit_by_name(cache, "size-changed", true, index, added); + + } + +} + + +/****************************************************************************** +* * +* Paramètres : cache = instance GLib à modifier. * +* max = nombre maximal de lignes à conserver. * +* * +* Description : Réduit le tampon à une quantité de lignes précise. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_buffer_cache_truncate(GBufferCache *cache, size_t max) +{ + size_t i; /* Boucle de parcours #1 */ + cache_info *info; /* Accès directe à une ligne */ + size_t j; /* Boucle de parcours #2 */ + size_t removed; /* Nombre de retraits effectués*/ + + assert(max <= cache->used); + + for (i = max; i < cache->used; i++) + { + info = &cache->lines[i]; + + if (info->count == 1) + g_object_unref(G_OBJECT(info->generator.instance)); + + else + { + for (j = 0; j < info->count; j++) + g_object_unref(G_OBJECT(info->generators[j].instance)); + + free(info->generators); + + } + + reset_cache_info_line(info); + + } + + removed = cache->used - max; + + cache->used = max - 1; + + if (removed > 0) + { + g_width_tracker_update_deleted(cache->tracker, max, max + removed - 1); + + g_signal_emit_by_name(cache, "size-changed", false, max, removed); + + } + +} + + +/****************************************************************************** +* * +* Paramètres : cache = tampon de lignes à venir consulter. * +* index = indice de la ligne visée par la consultation. * +* x = position géographique sur la ligne concernée. * +* addr = adresse à renseigner. [OUT] * +* * +* Description : Retrouve l'emplacement correspondant à une position de ligne.* +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_buffer_cache_get_line_addr(const GBufferCache *cache, size_t index, gint x, vmpa2t *addr) +{ + assert(index < cache->used); + + get_cache_info_addr(&cache->lines[index], index, x, addr); + +} + + +/****************************************************************************** +* * +* Paramètres : cache = tampon de lignes à venir consulter. * +* index = indice de la ligne visée par la consultation. * +* * +* Description : Détermine l'ensemble des propriétés attachées à une ligne. * +* * +* Retour : Somme de toutes les propriétés enregistrées. * +* * +* Remarques : - * +* * +******************************************************************************/ + +BufferLineFlags g_buffer_cache_get_line_flags(const GBufferCache *cache, size_t index) +{ + BufferLineFlags result; /* Somme à renvoyer */ + cache_info *info; /* Accès directe à une ligne */ + const generator_link *generator; /* Générateur retenu */ + size_t i; /* Boucle de parcours */ + + assert(index < cache->used); + + info = &cache->lines[index]; + + result = info->extra_flags; + + if (info->count == 1) + { + generator = &info->generator; + result |= g_line_generator_get_flags(generator->instance, index, generator->repeat); + } + + else + for (i = 0; i < info->count; i++) + { + generator = &info->generators[i]; + result |= g_line_generator_get_flags(generator->instance, index, generator->repeat); + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : cache = tampon de lignes à consulter. * +* index = indice de la ligne recherchée. * +* * +* Description : Retrouve une ligne au sein d'un tampon avec un indice. * +* * +* Retour : Line retrouvée ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBufferLine *g_buffer_cache_find_line_by_index(const GBufferCache *cache, size_t index) +{ + GBufferLine *result; /* Ligne trouvée à retourner */ + + if (index < cache->used) + result = get_cache_info_line(&cache->lines[index], index); + else + result = NULL; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : cache = tampon de lignes à venir consulter. * +* index = indice de la ligne à mesurer. * +* summary = largeurs maximales à faire évoluer. * +* * +* Description : Fait remonter les largeurs requises par une ligne donnée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_buffer_cache_collect_widths(GBufferCache *cache, size_t index, line_width_summary *summary) +{ + GBufferLine *line; /* Ligne éphémère à mesurer */ + + line = get_cache_info_line(&cache->lines[index], index); + + g_buffer_line_collect_widths(line, summary); + + g_object_unref(G_OBJECT(line)); + +} + + +/****************************************************************************** +* * +* Paramètres : cache = visualisation à représenter. * +* cr = contexte graphique dédié à la procédure. * +* first = première ligne à dessiner. * +* last = dernière ligne à dessiner. * +* area = position et surface à traiter. * +* display = règles d'affichage des colonnes modulables. * +* selected = ordonnée d'une ligne sélectionnée ou NULL. * +* list = liste de contenus à mettre en évidence. * +* * +* Description : Imprime une partie choisie du tampon contenant des lignes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_buffer_cache_draw(const GBufferCache *cache, cairo_t *cr, size_t first, size_t last, const cairo_rectangle_int_t *area, const bool *display, const gint *selected, const segcnt_list *list) +{ + GBufferCacheClass *class; /* Classe des tampons */ + gint y; /* Point de départ en ordonnée */ + bool wait_selection; /* Sélection déjà passée ? */ + size_t i; /* Boucle de parcours */ + cache_info *info; /* Accès directe à une ligne */ + line_width_summary summary; /* Résumé concis des largeurs */ + GBufferLine *line; /* Ligne à venir dessiner */ + + class = G_BUFFER_CACHE_GET_CLASS(cache); + + y = 0; + + wait_selection = true; + + if (cache->used > 0) + for (i = first; i <= last; i++) + { + /* Si sélection, on sousligne la ligne concernée */ + if (wait_selection && selected != NULL && *selected == y) + { + cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.05); + + cairo_rectangle(cr, area->x, y, area->width, class->line_height); + cairo_fill(cr); + + wait_selection = false; + + } + + info = &cache->lines[i]; + + if (i == first || (g_buffer_cache_get_line_flags(cache, i) & BLF_WIDTH_MANAGER)) + g_width_tracker_get_local_width_summary(cache->tracker, i, &summary); + + line = get_cache_info_line(info, i); + + g_buffer_line_draw(line, cr, &summary, class->text_pos, y, display, list); + + g_object_unref(G_OBJECT(line)); + + y += class->line_height; + + } + +} + + +/****************************************************************************** +* * +* Paramètres : cache = tampon de lignes à consulter. * +* addr = adresse à retrouver dans le tampon. * +* first = indique si on l'arrête à la première ou la dernière. * +* start = borne inférieure des recherches (incluse). * +* end = borne supérieure des recherches (incluse). * +* * +* Description : Indique l'indice correspondant à une adresse donnée. * +* * +* Retour : Indice des infos à l'adresse demandée, ou nombre de lignes. * +* * +* Remarques : - * +* * +******************************************************************************/ + +size_t _g_buffer_cache_find_index_by_addr(const GBufferCache *cache, const vmpa2t *addr, bool first, size_t start, size_t end) +{ + size_t result; /* Indice à retourner */ + cache_info *found; /* Eventuel élément trouvé */ + + int find_containing_generator(const vmpa2t *a, const cache_info *i) + { + const generator_link *generator; /* Générateur retenu */ + + if (i->count == 1) + generator = &i->generator; + else + generator = &i->generators[0]; + + return g_line_generator_contains_addr(generator->instance, addr, + i - cache->lines, generator->repeat); + + } + + found = (cache_info *)bsearch(addr, &cache->lines[start], end - start + 1, + sizeof(cache_info), (__compar_fn_t)find_containing_generator); + + if (found == NULL) + result = cache->used; + + else + { + result = (found - cache->lines); + assert(start <= result && result <= end); + + /* On s'assure d'un arrêt sur la bonne ligne */ + + if (first) + for (; result > start; result--) + { + found = &cache->lines[result - 1]; + + if (find_containing_generator(addr, found) != 0) + break; + + } + + else + for (; result < end; result++) + { + found = &cache->lines[result + 1]; + + if (find_containing_generator(addr, found) != 0) + break; + + } + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : cache = tampon de lignes à consulter. * +* addr = adresse à retrouver dans le tampon. * +* first = indique si on l'arrête à la première ou la dernière. * +* * +* Description : Indique l'indice correspondant à une adresse donnée. * +* * +* Retour : Indice des infos à l'adresse demandée, ou nombre de lignes. * +* * +* Remarques : - * +* * +******************************************************************************/ + +size_t g_buffer_cache_find_index_by_addr(const GBufferCache *cache, const vmpa2t *addr, bool first) +{ + size_t result; /* Indice à retourner */ + + if (cache->used == 0) + result = 0; + else + result = _g_buffer_cache_find_index_by_addr(cache, addr, first, 0, cache->used - 1); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : cache = tampon de lignes à consulter. * +* start = point de départ du parcours. * +* flag = propriétés à retrouver si possible. * +* * +* Description : Avance autant que possible vers une ligne idéale. * +* * +* Retour : Indice de la ligne recherchée, si elle existe. * +* * +* Remarques : - * +* * +******************************************************************************/ + +size_t g_buffer_cache_look_for_flag(const GBufferCache *cache, size_t start, BufferLineFlags flag) +{ + size_t result; /* Indice de ligne à retourner */ + vmpa2t start_addr; /* Localisation de départ */ + size_t i; /* Boucle de parcours */ + vmpa2t addr; /* Localisation suivante */ + + assert(start < cache->used); + + result = start; + + get_cache_info_addr(&cache->lines[start], start, 0, &start_addr); + + for (i = start + 1; i < cache->used; i++) + { + get_cache_info_addr(&cache->lines[i], i, 0, &addr); + + if (cmp_vmpa(&start_addr, &addr) != 0) + break; + + if ((g_buffer_cache_get_line_flags(cache, i) & flag) != 0) + { + result = i; + break; + } + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : cache = tampon de lignes à consulter. * +* addr = adresse à présenter à l'écran. * +* first = borne inférieure des recherches (incluse). * +* last = borne supérieure des recherches (incluse). * +* code = s'arrête si possible à une ligne avec code. * +* x = position horizontale au sein du composant. [OUT] * +* y = position verticale au sein du composant. [OUT] * +* * +* Description : Indique la position d'affichage d'une adresse donnée. * +* * +* Retour : true si l'adresse fait partie du composant, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_buffer_cache_get_address_coordinates(const GBufferCache *cache, const vmpa2t *addr, size_t first, size_t last, bool code, gint *x, gint *y) +{ + bool result; /* Bilan à retourner */ + size_t index; /* Indice de correspondance */ + gint lheight; /* Hauteur d'une ligne */ + const cache_info *info; /* Infos sur une ligne donnée */ + const generator_link *generator; /* Générateur retenu */ + + index = _g_buffer_cache_find_index_by_addr(cache, addr, true, first, last); + + result = (index < cache->used); + + if (result) + { + lheight = G_BUFFER_CACHE_GET_CLASS(cache)->line_height; + + *x = 0; + *y = (index - first) * G_BUFFER_CACHE_GET_CLASS(cache)->line_height; + + for (; code && index <= last; index++) + { + if (g_buffer_cache_get_line_flags(cache, index) & BLF_HAS_CODE) + break; + + if (index == last) + break; + + info = &cache->lines[index + 1]; + + if (info->count == 1) + generator = &info->generator; + else + generator = &info->generators[0]; + + if (!g_line_generator_contains_addr(generator->instance, addr, index + 1, generator->repeat)) + break; + + *y += lheight; + + } + + } + + return result; + +} diff --git a/src/glibext/gbuffercache.h b/src/glibext/gbuffercache.h new file mode 100644 index 0000000..6e9c314 --- /dev/null +++ b/src/glibext/gbuffercache.h @@ -0,0 +1,121 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * gbuffercache.h - prototypes pour l'affichage à la demande d'un ensemble de lignes + * + * Copyright (C) 2016 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 . + */ + + +#ifndef _GLIBEXT_GBUFFERCACHE_H +#define _GLIBEXT_GBUFFERCACHE_H + + +#include +#include +#include + + +#include "gwidthtracker.h" +#include "linegen.h" + + + +/* -------------------------- TAMPON POUR CODE DESASSEMBLE -------------------------- */ + + +#define G_TYPE_BUFFER_CACHE (g_buffer_cache_get_type()) +#define G_BUFFER_CACHE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_CODE_BUFFER, GBufferCache)) +#define G_BUFFER_CACHE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_CODE_BUFFER, GBufferCacheClass)) +#define G_IS_BUFFER_CACHE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_CODE_BUFFER)) +#define G_IS_BUFFER_CACHE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_CODE_BUFFER)) +#define G_BUFFER_CACHE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_CODE_BUFFER, GBufferCacheClass)) + + +/* Tampon pour gestion de lignes optimisée (instance) */ +typedef struct _GBufferCache GBufferCache; + +/* Tampon pour gestion de lignes optimisée (classe) */ +typedef struct _GBufferCacheClass GBufferCacheClass; + + +/* Détermine le type du composant de tampon pour gestion de lignes optimisée. */ +GType g_buffer_cache_get_type(void); + +/* Crée un nouveau composant de tampon pour code désassemblé. */ +GBufferCache *g_buffer_cache_new(void); + +/* Fournit la hauteur d'impression d'une ligne visualisée. */ +gint g_buffer_cache_get_line_height(const GBufferCache *); + +/* Fournit la taille réservée pour la marge gauche. */ +gint g_buffer_cache_get_left_margin(const GBufferCache *); + +/* Fournit la position de départ pour l'impression de texte. */ +gint g_buffer_cache_get_text_position(const GBufferCache *); + +/* Compte le nombre de lignes rassemblées dans un tampon. */ +size_t g_buffer_cache_count_lines(const GBufferCache *); + +/* Fournit un lien vers la structure de suivi de largeurs. */ +const GWidthTracker *g_buffer_cache_get_width_tracker(const GBufferCache *); + +/* Insère un générateur dans des lignes à une position donnée. */ +void g_buffer_cache_insert_at(GBufferCache *, size_t, GLineGenerator *, bool, bool); + +/* Retire un type de générateur de lignes. */ +GLineGenerator *g_buffer_cache_delete_type_at(GBufferCache *, size_t, GType, bool, bool); + +/* Ajoute en fin de tampon un générateur de lignes. */ +void g_buffer_cache_append(GBufferCache *, GLineGenerator *, BufferLineFlags); + +/* Etend un tampon avec un générateur de lignes unique. */ +void g_buffer_cache_extend_with(GBufferCache *, size_t, GLineGenerator *); + +/* Réduit le tampon à une quantité de lignes précise. */ +void g_buffer_cache_truncate(GBufferCache *, size_t); + +/* Retrouve l'emplacement correspondant à une position de ligne. */ +void g_buffer_cache_get_line_addr(const GBufferCache *, size_t, gint, vmpa2t *); + +/* Détermine l'ensemble des propriétés attachées à une ligne. */ +BufferLineFlags g_buffer_cache_get_line_flags(const GBufferCache *, size_t); + +/* Retrouve une ligne au sein d'un tampon avec un indice. */ +GBufferLine *g_buffer_cache_find_line_by_index(const GBufferCache *, size_t); + +/* Fait remonter les largeurs requises par une ligne donnée. */ +void g_buffer_cache_collect_widths(GBufferCache *, size_t, line_width_summary *); + +/* Imprime une partie choisie du tampon contenant des lignes. */ +void g_buffer_cache_draw(const GBufferCache *, cairo_t *, size_t, size_t, const cairo_rectangle_int_t *, const bool *, const gint *, const segcnt_list *); + +/* Indique l'indice correspondant à une adresse donnée. */ +size_t _g_buffer_cache_find_index_by_addr(const GBufferCache *, const vmpa2t *, bool, size_t, size_t); + +/* Indique l'indice correspondant à une adresse donnée. */ +size_t g_buffer_cache_find_index_by_addr(const GBufferCache *, const vmpa2t *, bool); + +/* Avance autant que possible vers une ligne idéale. */ +size_t g_buffer_cache_look_for_flag(const GBufferCache *, size_t, BufferLineFlags); + +/* Indique la position d'affichage d'une adresse donnée. */ +bool g_buffer_cache_get_address_coordinates(const GBufferCache *, const vmpa2t *, size_t, size_t, bool, gint *, gint *); + + + +#endif /* _GLIBEXT_GBUFFERCACHE_H */ diff --git a/src/glibext/gbufferline.c b/src/glibext/gbufferline.c index 5f1756d..768cbca 100644 --- a/src/glibext/gbufferline.c +++ b/src/glibext/gbufferline.c @@ -56,7 +56,7 @@ struct _GBufferLine mrange_t range; /* Couverture geographique */ BufferLineColumn main_column; /* Colonne principale */ - line_column columns[BLC_COUNT]; /* Répartition du texte */ + line_column columns[BLC_COUNT]; /* Répartition du texte */ BufferLineColumn merge_start; /* Début de la zone globale */ BufferLineColumn last_used; /* Dernière colonne utilisée */ @@ -72,7 +72,6 @@ struct _GBufferLine gint max_widths[BLC_COUNT]; /* Taille cachée des colonnes */ gint merged_width; /* Largeur cumulée avant fusion*/ }; - GBufferLine *manager; /* Représentante d'un groupe */ }; }; @@ -214,9 +213,6 @@ static void g_buffer_line_dispose(GBufferLine *line) { size_t i; /* Boucle de parcours */ - if (line->flags & BLF_WIDTH_MANAGER) - g_object_unref(G_OBJECT(line->manager)); - for (i = 0; i < line->ocount; i++) g_object_unref(G_OBJECT(line->origins[i].creator)); @@ -298,9 +294,9 @@ const mrange_t *g_buffer_line_get_range(const GBufferLine *line) /****************************************************************************** * * -* Paramètres : line = ligne à venir compléter. * -* psize = taille souhaitée de l'impression des positions. * -* vsize = taille souhaitée de l'impression des adresses. * +* Paramètres : line = ligne à venir compléter. * +* 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. * * * @@ -310,61 +306,105 @@ const mrange_t *g_buffer_line_get_range(const GBufferLine *line) * * ******************************************************************************/ -void g_buffer_line_fill_mrange(GBufferLine *line, MemoryDataSize psize, MemoryDataSize vsize) +void g_buffer_line_fill_phys(GBufferLine *line, MemoryDataSize size, const vmpa2t *addr) { + VMPA_BUFFER(position); /* Emplacement au format texte */ size_t len; /* Taille de l'élément inséré */ - VMPA_BUFFER(address); /* Adresse au format texte */ - size_t i; /* Boucle de parcours */ + size_t i; /* Boucle de parcours #1 */ - /* Position physique */ + vmpa2_phys_to_string(addr, size, position, &len); - if (has_phys_addr(get_mrange_addr(&line->range))) - { - mrange_phys_to_string(&line->range, psize, true, address, &len); + for (i = 2; i < len; i++) + if (position[i] != '0') break; - for (i = 2; i < len; i++) - if (address[i] != '0') break; + if (i == len) + i = len - 1; - if (i == len) - g_buffer_line_append_text(line, BLC_PHYSICAL, address, len, RTT_PHYS_ADDR_PAD, NULL); + if (i > 0) + g_buffer_line_append_text(line, BLC_PHYSICAL, position, i, RTT_PHYS_ADDR_PAD, NULL); - else - { - g_buffer_line_append_text(line, BLC_PHYSICAL, address, 2, RTT_PHYS_ADDR, NULL); + g_buffer_line_append_text(line, BLC_PHYSICAL, &position[i], len - i, RTT_PHYS_ADDR, NULL); - if (i > 2) - g_buffer_line_append_text(line, BLC_PHYSICAL, &address[2], i - 2, RTT_PHYS_ADDR_PAD, NULL); +} - g_buffer_line_append_text(line, BLC_PHYSICAL, &address[i], len - i, RTT_PHYS_ADDR, NULL); - } +/****************************************************************************** +* * +* Paramètres : line = ligne à venir compléter. * +* 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. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ - } +void g_buffer_line_fill_virt(GBufferLine *line, MemoryDataSize size, const vmpa2t *addr) +{ + VMPA_BUFFER(position); /* Emplacement au format texte */ + size_t len; /* Taille de l'élément inséré */ + size_t i; /* Boucle de parcours #1 */ + + vmpa2_virt_to_string(addr, size, position, &len); + + for (i = 2; i < len; i++) + if (position[i] != '0') break; + + if (i == len) + i = len - 1; + + if (i > 0) + g_buffer_line_append_text(line, BLC_VIRTUAL, position, i, RTT_PHYS_ADDR_PAD, NULL); - /* Adresse virtuelle */ + g_buffer_line_append_text(line, BLC_VIRTUAL, &position[i], len - i, RTT_PHYS_ADDR, NULL); + +} - if (has_virt_addr(get_mrange_addr(&line->range))) - { - mrange_virt_to_string(&line->range, vsize, true, address, &len); - for (i = 2; i < len; i++) - if (address[i] != '0') break; +/****************************************************************************** +* * +* Paramètres : line = ligne à venir compléter. * +* addr = localisation à afficher. * +* psize = taille souhaitée de l'impression des positions. * +* vsize = taille souhaitée de l'impression des adresses. * +* * +* Description : Construit le tronc commun d'une ligne autour de sa position. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ - if (i == len) - g_buffer_line_append_text(line, BLC_VIRTUAL, address, len, RTT_VIRT_ADDR_PAD, NULL); +void g_buffer_line_fill_vmpa(GBufferLine *line, const vmpa2t *addr, MemoryDataSize psize, MemoryDataSize vsize) +{ + g_buffer_line_fill_phys(line, psize, addr); - else - { - g_buffer_line_append_text(line, BLC_VIRTUAL, address, 2, RTT_VIRT_ADDR, NULL); + g_buffer_line_fill_virt(line, vsize, addr); - if (i > 2) - g_buffer_line_append_text(line, BLC_VIRTUAL, &address[2], i - 2, RTT_VIRT_ADDR_PAD, NULL); +} - g_buffer_line_append_text(line, BLC_VIRTUAL, &address[i], len - i, RTT_VIRT_ADDR, NULL); - } +/****************************************************************************** +* * +* Paramètres : line = ligne à venir compléter. * +* psize = taille souhaitée de l'impression des positions. * +* vsize = taille souhaitée de l'impression des adresses. * +* * +* Description : Construit le tronc commun d'une ligne autour de sa position. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ - } +void g_buffer_line_fill_mrange(GBufferLine *line, MemoryDataSize psize, MemoryDataSize vsize) +{ + g_buffer_line_fill_vmpa(line, get_mrange_addr(&line->range), psize, vsize); } @@ -531,7 +571,7 @@ void g_buffer_line_append_text(GBufferLine *line, BufferLineColumn column, const assert(length > 0); if (column == BLC_MAIN) - column = line->main_column; + column = BLC_ASSEMBLY;//line->main_column; if (column == BLC_LAST_USED) column = line->last_used; @@ -938,6 +978,13 @@ void g_buffer_line_collect_widths(GBufferLine *line, line_width_summary *summary { width = get_column_width(&line->columns[i]); + + /* + if (i == BLC_ASSEMBLY_HEAD) + assert(width > 0); + */ + + if (i < line->merge_start) summary->max_widths[i] = MAX(summary->max_widths[i], width); @@ -1008,7 +1055,10 @@ const line_segment *g_buffer_line_get_segment_from_coord(const GBufferLine *line { line_segment *result; /* Trouvaille à retourner */ - result = get_line_column_content_from_index(&line->columns[coord->column], coord->index); + if (coord->column < BLC_COUNT) + result = get_line_column_content_from_index(&line->columns[coord->column], coord->index); + else + result = false; return result; @@ -1069,6 +1119,9 @@ bool g_buffer_line_get_coord_at(const GBufferLine *line, const line_width_summar { width = g_buffer_line_compute_max_width(line, i, summary); + /* Si la colonne n'est absolument pas visible, on ne s'arrête pas dessus ! */ + if (width == 0) continue; + if ((i + 1) < BLC_COUNT) limit = width + COL_MARGIN / 2; else limit = width; @@ -1139,7 +1192,10 @@ bool g_buffer_line_get_coord_at(const GBufferLine *line, const line_width_summar if ((i - 1) < line->merge_start) { width = g_buffer_line_compute_max_width(line, i - 1, summary); - *base += (width + COL_MARGIN); + + if (width > 0) + *base += (width + COL_MARGIN); + } else *base += get_column_width(&line->columns[i - 1]); @@ -1183,8 +1239,19 @@ bool g_buffer_line_get_coord_at(const GBufferLine *line, const line_width_summar } } + + /* Il n'y a rien sur la ligne ! */ else - result = false; + { + result = true; + + *base = 0; + *offset = 0; + + coord->column = BLC_COUNT; + coord->index = -1; + + } } else @@ -1305,6 +1372,7 @@ bool g_buffer_line_find_near_coord(const GBufferLine *line, col_coord_t *coord, BufferLineColumn i; /* Boucle de parcours #1 */ bool displayed; /* Confort de lecture */ BufferLineColumn k; /* Boucle de parcours #2 */ + gint width; /* Largeur d'une colonne donnée*/ result = false; @@ -1381,8 +1449,14 @@ bool g_buffer_line_find_near_coord(const GBufferLine *line, col_coord_t *coord, if (displayed) { - *offset += g_buffer_line_compute_max_width(line, k, summary); - if (k < line->merge_start) *offset += COL_MARGIN; + width = g_buffer_line_compute_max_width(line, k, summary); + + if (width > 0) + { + *offset += width; + if (k < line->merge_start) *offset += COL_MARGIN; + } + } } @@ -1469,10 +1543,8 @@ void g_buffer_line_draw(GBufferLine *line, cairo_t *cairo, const line_width_summ { max_width = g_buffer_line_compute_max_width(line, i, summary); - x += max_width; - if (max_width > 0) - x += COL_MARGIN; + x += max_width + COL_MARGIN; } diff --git a/src/glibext/gbufferline.h b/src/glibext/gbufferline.h index be7e138..a8d2f3f 100644 --- a/src/glibext/gbufferline.h +++ b/src/glibext/gbufferline.h @@ -109,6 +109,15 @@ GBufferLine *g_buffer_line_new(const mrange_t *, BufferLineColumn); const mrange_t *g_buffer_line_get_range(const GBufferLine *); /* Construit le tronc commun d'une ligne autour de sa position. */ +void g_buffer_line_fill_phys(GBufferLine *, MemoryDataSize, const vmpa2t *); + +/* Construit le tronc commun d'une ligne autour de sa position. */ +void g_buffer_line_fill_virt(GBufferLine *, MemoryDataSize, const vmpa2t *); + +/* Construit le tronc commun d'une ligne autour de sa position. */ +void g_buffer_line_fill_vmpa(GBufferLine *, const vmpa2t *, MemoryDataSize, MemoryDataSize); + +/* Construit le tronc commun d'une ligne autour de sa position. */ void g_buffer_line_fill_mrange(GBufferLine *, MemoryDataSize, MemoryDataSize); /* Construit le tronc commun d'une ligne d'instruction. */ diff --git a/src/glibext/gbufferview.c b/src/glibext/gbufferview.c index 20d60ed..cd17191 100644 --- a/src/glibext/gbufferview.c +++ b/src/glibext/gbufferview.c @@ -24,14 +24,21 @@ #include "gbufferview.h" +#include + + /* Vue d'un tampon pour code désassemblé (instance) */ struct _GBufferView { GObject parent; /* A laisser en premier */ - GCodeBuffer *buffer; /* Tampon de code visualisé */ + GBufferCache *cache; /* Tampon du contenu visualisé */ + + segcnt_list *highlighted; /* Segments mis en évidence */ + bool external; /* Note l'origine de la liste */ + bool unrestricted; /* Validité des informations */ vmpa2t start; /* Première ligne intégrée */ vmpa2t end; /* Dernière ligne intégrée */ @@ -45,11 +52,6 @@ struct _GBufferView GWidthTracker *tracker; /* Suivi pour usage interne */ }; - bool unrestricted; /* Validité des informations */ - - segcnt_list *highlighted; /* Segments mis en évidence */ - bool external; /* Note l'origine de la liste */ - }; /* Vue d'un tampon pour code désassemblé (classe) */ @@ -57,10 +59,6 @@ struct _GBufferViewClass { GObjectClass parent; /* A laisser en premier */ - gint line_height; /* Hauteur maximale des lignes */ - gint left_margin; /* Marge gauche + espace */ - gint left_text; /* Début d'impression du code */ - /* Signaux */ void (* need_redraw) (GBufferView *); @@ -81,15 +79,23 @@ static void g_buffer_view_dispose(GBufferView *); static void g_buffer_view_finalize(GBufferView *); /* Accompagne une variation de la quantité de lignes du tampon. */ -static void on_buffer_size_changed(const GCodeBuffer *, bool, size_t, size_t, GBufferView *); +static void on_buffer_cache_size_changed(const GBufferCache *, bool, size_t, size_t, GBufferView *); -/* Réagit à un changement de contenu d'une ligne donnée. */ -static void on_buffer_line_changed(GCodeBuffer *, GBufferLine *, line_segment *, GBufferView *); +/* Calcule la position idéale de curseur pour un point donné. */ +bool _g_buffer_view_compute_caret_full(GBufferView *, gint, GBufferLine *, size_t, const bool *, GdkRectangle *, vmpa2t *); /* Déplace le curseur au sein d'une vue de tampon. */ static bool _g_buffer_view_move_caret(GBufferView *, const GBufferLine *, size_t, GdkRectangle *, bool, GdkScrollDirection, const bool *); +/* Fournit la ligne présente à une ordonnée donnée. */ +static GBufferLine *g_buffer_view_find_line_at(GBufferView *, gint, size_t *); + + + + + + /* Détermine le type de la vue d'un tampon pour code désassemblé. */ G_DEFINE_TYPE(GBufferView, g_buffer_view, G_TYPE_OBJECT); @@ -116,10 +122,7 @@ static void g_buffer_view_class_init(GBufferViewClass *class) object->dispose = (GObjectFinalizeFunc/* ! */)g_buffer_view_dispose; object->finalize = (GObjectFinalizeFunc)g_buffer_view_finalize; - class->line_height = 17; - class->left_margin = 2 * class->line_height; - class->left_text = 2.5 * class->line_height; - + /* Sigaux */ g_signal_new("need-redraw", G_TYPE_BUFFER_VIEW, @@ -146,7 +149,10 @@ static void g_buffer_view_class_init(GBufferViewClass *class) static void g_buffer_view_init(GBufferView *view) { - view->unrestricted = true; + /** + * Inversion du statut pour forcer l'actualisation lors de la création. + */ + view->unrestricted = false; } @@ -165,7 +171,10 @@ static void g_buffer_view_init(GBufferView *view) static void g_buffer_view_dispose(GBufferView *view) { - g_object_unref(G_OBJECT(view->buffer)); + g_object_unref(G_OBJECT(view->cache)); + + if (!view->unrestricted) + g_object_unref(G_OBJECT(view->int_tracker)); G_OBJECT_CLASS(g_buffer_view_parent_class)->dispose(G_OBJECT(view)); @@ -207,22 +216,17 @@ static void g_buffer_view_finalize(GBufferView *view) * * ******************************************************************************/ -GBufferView *g_buffer_view_new(GCodeBuffer *buffer, segcnt_list *highlighted) +GBufferView *g_buffer_view_new(GBufferCache *cache, segcnt_list *highlighted) { GBufferView *result; /* Composant à retourner */ result = g_object_new(G_TYPE_BUFFER_VIEW, NULL); - g_object_ref(G_OBJECT(buffer)); - result->buffer = buffer; + result->cache = cache; g_buffer_view_restrict(result, NULL, NULL); - g_code_buffer_register_view_callback(buffer, - (buffer_size_changed_cb)on_buffer_size_changed, - G_OBJECT(result)); - - g_signal_connect(buffer, "line-changed", G_CALLBACK(on_buffer_line_changed), result); + g_signal_connect(cache, "size-changed", G_CALLBACK(on_buffer_cache_size_changed), result); if (highlighted != NULL) result->highlighted = highlighted; @@ -238,11 +242,11 @@ GBufferView *g_buffer_view_new(GCodeBuffer *buffer, segcnt_list *highlighted) /****************************************************************************** * * -* Paramètres : buffer = tampon de lignes cohérentes à manipuler. * -* added = indication sur la variation de la taille du tampon. * -* index = indice de la première ligne à traiter. * -* count = nombre de lignes à traiter. * -* view = vue active du tampon de lignes concerné. * +* Paramètres : cache = tampon de lignes cohérentes à manipuler. * +* added = indication sur la variation de la taille du tampon. * +* index = indice de la première ligne à traiter. * +* count = nombre de lignes à traiter. * +* view = vue active du tampon de lignes concerné. * * * * Description : Accompagne une variation de la quantité de lignes du tampon. * * * @@ -252,11 +256,11 @@ GBufferView *g_buffer_view_new(GCodeBuffer *buffer, segcnt_list *highlighted) * * ******************************************************************************/ -static void on_buffer_size_changed(const GCodeBuffer *buffer, bool added, size_t index, size_t count, GBufferView *view) +static void on_buffer_cache_size_changed(const GBufferCache *cache, bool added, size_t index, size_t count, GBufferView *view) { - size_t i; /* Boucle de parcours */ - GBufferLine *line; /* Ligne à manipuler */ - const vmpa2t *addr; /* Localisation de ligne */ + //size_t i; /* Boucle de parcours */ + //GBufferLine *line; /* Ligne à manipuler */ + //const vmpa2t *addr; /* Localisation de ligne */ /** * Il n'y a pas besoin de verrou ici car la fonction est appelée directement par le tampon. @@ -270,6 +274,8 @@ static void on_buffer_size_changed(const GCodeBuffer *buffer, bool added, size_t else { +#if 0 + /* Avant la zone représentée ? */ if (index < view->first) { @@ -281,6 +287,8 @@ static void on_buffer_size_changed(const GCodeBuffer *buffer, bool added, size_t else if (view->first == index) for (i = 0; i < count; i++) { + g_buffer_cache_get_line_addr(const GBufferCache *, size_t, gint, vmpa2t *); + line = g_code_buffer_find_line_by_index(buffer, index + i); addr = get_mrange_addr(g_buffer_line_get_range(line)); @@ -302,6 +310,8 @@ static void on_buffer_size_changed(const GCodeBuffer *buffer, bool added, size_t else if ((view->last + 1) == index) for (i = 0; i < count; i++) { + g_buffer_cache_get_line_addr(const GBufferCache *, size_t, gint, vmpa2t *); + line = g_code_buffer_find_line_by_index(buffer, index + i); addr = get_mrange_addr(g_buffer_line_get_range(line)); @@ -312,7 +322,8 @@ static void on_buffer_size_changed(const GCodeBuffer *buffer, bool added, size_t } - g_width_tracker_update_added(view->int_tracker, index, count); + //g_width_tracker_update_added(view->int_tracker, index, count); +#endif } @@ -338,38 +349,36 @@ static void on_buffer_size_changed(const GCodeBuffer *buffer, bool added, size_t } - g_width_tracker_update_deleted(view->int_tracker, index, index + count - 1); + //g_width_tracker_update_deleted(view->int_tracker, index, index + count - 1); } - g_signal_emit_by_name(view, "need-redraw"); + //g_signal_emit_by_name(view, "need-redraw"); } /****************************************************************************** * * -* Paramètres : buffer = tampon de lignes cohérentes à manipuler. * -* line = ligne dont la définition vient d'évoluer. * -* segment = éventuel segment qui vient d'évoluer ou NULL. * -* view = vue active du tampon de lignes concerné. * +* Paramètres : view = visualisateur à consulter. * * * -* Description : Réagit à un changement de contenu d'une ligne donnée. * +* Description : Fournit le tampon de code lié à un visualisateur donné. * * * -* Retour : - * +* Retour : Tampon de code associé au gestionnaire d'affichage. * * * * Remarques : - * * * ******************************************************************************/ -static void on_buffer_line_changed(GCodeBuffer *buffer, GBufferLine *line, line_segment *segment, GBufferView *view) +GBufferCache *g_buffer_view_get_cache(const GBufferView *view) { - const vmpa2t *addr; /* Localisation de ligne */ + GBufferCache *result; /* Instance à retourner */ - addr = get_mrange_addr(g_buffer_line_get_range(line)); + result = view->cache; - if (cmp_vmpa(&view->start, addr) <= 0 && cmp_vmpa(addr, &view->end) <= 0) - g_signal_emit_by_name(view, "need-redraw"); + g_object_ref(G_OBJECT(result)); + + return result; } @@ -390,33 +399,41 @@ static void on_buffer_line_changed(GCodeBuffer *buffer, GBufferLine *line, line_ void g_buffer_view_restrict(GBufferView *view, const vmpa2t *start, const vmpa2t *end) { + bool state; /* Nouvel état à proclamer */ const GWidthTracker *template; /* Suivi déjà en place */ - if (!view->unrestricted) - g_object_unref(G_OBJECT(view->int_tracker)); + state = (start == NULL || end == NULL); - view->unrestricted = (start == NULL || end == NULL); + if (view->unrestricted != state) + { + view->unrestricted = state; - template = g_code_buffer_get_width_tracker(view->buffer); + template = g_buffer_cache_get_width_tracker(view->cache); - if (view->unrestricted) - { - view->first = 0; - view->last = g_code_buffer_count_lines(view->buffer) - 1; + if (view->unrestricted) + { + /* Vérification pour le cas particulier du démarrage */ + if (view->int_tracker != NULL) + g_object_unref(G_OBJECT(view->int_tracker)); - view->ext_tracker = template; + view->first = 0; + view->last = g_buffer_cache_count_lines(view->cache) - 1; - } + view->ext_tracker = template; - else - { - copy_vmpa(&view->start, start); - copy_vmpa(&view->end, end); + } + + else + { + copy_vmpa(&view->start, start); + copy_vmpa(&view->end, end); + + view->first = g_buffer_cache_find_index_by_addr(view->cache, start, true); + view->last = g_buffer_cache_find_index_by_addr(view->cache, end, false); - view->first = g_code_buffer_get_index_from_address(view->buffer, start, true); - view->last = g_code_buffer_get_index_from_address(view->buffer, end, false); + view->ext_tracker = g_width_tracker_new_restricted(template, view->first, view->last); - view->ext_tracker = g_width_tracker_new_restricted(template, view->first, view->last); + } } @@ -425,7 +442,7 @@ void g_buffer_view_restrict(GBufferView *view, const vmpa2t *start, const vmpa2t /****************************************************************************** * * -* Paramètres : view = visualisateur à mettre à jour. * +* Paramètres : view = visualisateur à consulter. * * first = première ligne à imprimer ou NULL. [OUT] * * last = première ligne hors cadre ou NULL. [OUT] * * * @@ -437,7 +454,7 @@ void g_buffer_view_restrict(GBufferView *view, const vmpa2t *start, const vmpa2t * * ******************************************************************************/ -bool g_buffer_view_get_restrictions(GBufferView *view, vmpa2t *start, vmpa2t *end) +bool g_buffer_view_get_restrictions(const GBufferView *view, vmpa2t *start, vmpa2t *end) { if (!view->unrestricted) { @@ -450,44 +467,11 @@ bool g_buffer_view_get_restrictions(GBufferView *view, vmpa2t *start, vmpa2t *en } -/****************************************************************************** -* * -* Paramètres : view = visualisateur à consulter. * -* * -* Description : Fournit le tampon de code lié à un visualisateur donné. * -* * -* Retour : Tampon de code associé au gestionnaire d'affichage. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GCodeBuffer *g_buffer_view_get_buffer(const GBufferView *view) -{ - g_object_ref(G_OBJECT(view->buffer)); - - return view->buffer; -} -/****************************************************************************** -* * -* Paramètres : view = visualisation à consulter. * -* * -* Description : Fournit la hauteur d'impression d'une ligne visualisée. * -* * -* Retour : Hauteur de ligne en pixel. * -* * -* Remarques : - * -* * -******************************************************************************/ -gint g_buffer_view_get_line_height(GBufferView *view) -{ - return G_BUFFER_VIEW_GET_CLASS(view)->line_height; -} /****************************************************************************** @@ -507,7 +491,7 @@ gint g_buffer_view_get_width(GBufferView *view, const bool *display) { gint result; /* Taille à retourner */ - result = G_BUFFER_VIEW_GET_CLASS(view)->left_text; + result = g_buffer_cache_get_text_position(view->cache); result += g_width_tracker_get_width(view->tracker, display); @@ -533,7 +517,7 @@ gint g_buffer_view_get_margin(GBufferView *view, const bool *display) { gint result; /* Taille à retourner */ - result = G_BUFFER_VIEW_GET_CLASS(view)->left_text; + result = g_buffer_cache_get_text_position(view->cache); result += g_width_tracker_get_margin(view->tracker, display); @@ -558,7 +542,7 @@ gint g_buffer_view_get_height(const GBufferView *view) { gint result; /* Taille à retourner */ - result = G_BUFFER_VIEW_GET_CLASS(view)->line_height; + result = g_buffer_cache_get_line_height(view->cache); result *= (view->last - view->first + 1); @@ -567,50 +551,66 @@ gint g_buffer_view_get_height(const GBufferView *view) } + + + + + + + + + + + /****************************************************************************** * * * Paramètres : view = vue de tampon à mettre à jour. * -* x = abscisse de la zone principale à traiter. * -* y = ordonnée de la zone principale à traiter. * +* x = abscisse proposée pour le nouvel emplacement. * +* y = ordonnée proposée pour le nouvel emplacement. * * display = règles d'affichage des colonnes modulables. * * caret = position du curseur à construire. [OUT] * +* addr = adresse correspondant à cette même position. [OUT] * * * * Description : Calcule la position idéale de curseur pour un point donné. * * * -* Retour : Adresse si une a pu être déterminée, NULL sinon. * +* Retour : true si les deux derniers arguments ont pu être constitués. * * * * Remarques : - * * * ******************************************************************************/ -const vmpa2t *g_buffer_view_compute_caret(GBufferView *view, gint x, gint y, const bool *display, GdkRectangle *caret) +bool g_buffer_view_compute_caret_full(GBufferView *view, gint x, gint y, const bool *display, GdkRectangle *caret, vmpa2t *addr) { - gint remaining; /* Copie de travail modifiable */ + bool result; /* Bilan à retourner */ + gint lheight; /* Hauteur d'une ligne */ size_t index; /* Indice de ligne de tampon */ GBufferLine *line; /* Ligne à la position courante*/ - const line_segment *segment; /* Segment présent sur la place*/ - GBufferViewClass *class; /* Classe pour les vues */ - remaining = x; + result = false; - line = g_buffer_view_find_line_and_segment_at(view, &remaining, y, &index, display, &segment); + /* Détermination de la ligne courante */ - /* FIXME : unref() ! */ - if (line == NULL) return NULL; - if (segment == NULL) printf(" -- no segment\n"); - if (segment == NULL) return NULL; + lheight = g_buffer_cache_get_line_height(view->cache); + index = y / lheight; + index += view->first; - class = G_BUFFER_VIEW_GET_CLASS(view); + if (index > view->last) + goto gbvccf_done; - caret->x = /*view->left_text +*/ (x - remaining) + get_caret_position_from_line_segment(segment, remaining); + line = g_buffer_cache_find_line_by_index(view->cache, index); - caret->y = (index - view->first) * class->line_height; + assert(line != NULL); - caret->width = 2; - caret->height = class->line_height; + /* Calcul d'une position */ + + result = _g_buffer_view_compute_caret_full(view, x, line, index, display, caret, addr); + + g_object_unref(G_OBJECT(line)); + + gbvccf_done: - return get_mrange_addr(g_buffer_line_get_range(line)); + return result; } @@ -618,50 +618,69 @@ const vmpa2t *g_buffer_view_compute_caret(GBufferView *view, gint x, gint y, con /****************************************************************************** * * * Paramètres : view = vue de tampon à mettre à jour. * +* x = abscisse proposée pour le nouvel emplacement. * * line = ligne correspondant à la position. * * index = indice de cette même ligne dans le tampon. * -* x = abscisse de la zone principale à traiter. * * display = règles d'affichage des colonnes modulables. * * caret = position du curseur à construire. [OUT] * +* addr = adresse correspondant à cette même position. [OUT] * * * * Description : Calcule la position idéale de curseur pour un point donné. * * * -* Retour : Adresse si une a pu être déterminée, NULL sinon. * +* Retour : true si les deux derniers arguments ont pu être constitués. * * * * Remarques : - * * * ******************************************************************************/ -const vmpa2t *g_buffer_view_compute_caret_full(GBufferView *view, GBufferLine *line, size_t index, gint x, const bool *display, GdkRectangle *caret) +bool _g_buffer_view_compute_caret_full(GBufferView *view, gint x, GBufferLine *line, size_t index, const bool *display, GdkRectangle *caret, vmpa2t *addr) { - GBufferViewClass *class; /* Classe pour les vues */ - gint offset; /* Point de travail modifiable */ + bool result; /* Bilan à retourner */ + gint text_pos; /* Abscisse de départ du texte */ line_width_summary summary; /* Résumé concis des largeurs */ gint base; /* Position absolue de segment */ bool status; /* Bilan de la localisation */ + gint lheight; /* Hauteur d'une ligne */ - class = G_BUFFER_VIEW_GET_CLASS(view); + result = false; - offset = x; + /* Zone d'intervention bornée ! */ - offset -= class->left_text; - if (offset < 0) return NULL; + text_pos = g_buffer_cache_get_text_position(view->cache); + + if (x < text_pos) + goto gbvccf_done; + + /* Calcul d'une position */ g_width_tracker_get_local_width_summary(view->tracker, index, &summary); - /* Traitement pour mise à jour de l'abscisse uniquement */ - status = g_buffer_line_get_coord_at(line, &summary, display, &base, &offset, + x -= text_pos; + + status = g_buffer_line_get_coord_at(line, &summary, display, &base, &x, GDK_SCROLL_LEFT, true, (col_coord_t []) { { 0 } }); - if (!status) return NULL; - caret->x = class->left_text + base + offset; + if (!status) + goto gbvccf_done; + + /* Transmission des informations */ + + lheight = g_buffer_cache_get_line_height(view->cache); - caret->y = (index - view->first) * class->line_height; + caret->x = text_pos + base + x; + + caret->y = (index - view->first) * lheight; caret->width = 2; - caret->height = class->line_height; + caret->height = lheight; + + g_buffer_cache_get_line_addr(view->cache, index, caret->x, addr); + + result = true; - return get_mrange_addr(g_buffer_line_get_range(line)); + gbvccf_done: + + return result; } @@ -687,16 +706,24 @@ const vmpa2t *g_buffer_view_compute_caret_full(GBufferView *view, GBufferLine *l static bool _g_buffer_view_move_caret(GBufferView *view, const GBufferLine *line, size_t index, GdkRectangle *caret, bool ctrl, GdkScrollDirection dir, const bool *display) { bool result; /* Bilan à retourner */ + gint text_pos; /* Abscisse de départ du texte */ gint offset; /* Point de travail modifiable */ line_width_summary summary; /* Résumé concis des largeurs */ gint base; /* Position absolue de segment */ col_coord_t coord; /* Coordonnées en interne */ const line_segment *segment; /* Bribe de texte trouvée */ - offset = caret->x; - offset -= G_BUFFER_VIEW_GET_CLASS(view)->left_text; - if (offset < 0) return false; + result = false; + + /* Zone d'intervention bornée ! */ + + text_pos = g_buffer_cache_get_text_position(view->cache); + + if (caret->x < text_pos) + goto gbvmc_done; + + offset = caret->x - text_pos; g_width_tracker_get_local_width_summary(view->tracker, index, &summary); @@ -725,7 +752,9 @@ static bool _g_buffer_view_move_caret(GBufferView *view, const GBufferLine *line /* Mise à jour éventuelle */ if (result) - caret->x = G_BUFFER_VIEW_GET_CLASS(view)->left_text + base + offset; + caret->x = text_pos + base + offset; + + gbvmc_done: return result; @@ -735,82 +764,35 @@ static bool _g_buffer_view_move_caret(GBufferView *view, const GBufferLine *line /****************************************************************************** * * * Paramètres : view = vue de tampon à mettre à jour. * -* caret = position du curseur à faire évoluer. * * ctrl = indique la demande d'un parcours rapide. * * dir = direction du parcours. * * display = règles d'affichage des colonnes modulables. * +* caret = position du curseur à faire évoluer. [OUT] * +* addr = adresse correspondant à cette même position. [OUT] * * * * Description : Déplace le curseur au sein d'une vue de tampon. * * * -* Retour : Adresse si une a pu être déterminée, VMPA_INVALID sinon. * +* Retour : true si les deux derniers arguments ont pu être constitués. * * * * Remarques : - * * * ******************************************************************************/ -const vmpa2t *g_buffer_view_move_caret(GBufferView *view, GdkRectangle *caret, bool ctrl, GdkScrollDirection dir, const bool *display) +bool g_buffer_view_move_caret(GBufferView *view, bool ctrl, GdkScrollDirection dir, const bool *display, GdkRectangle *caret, vmpa2t *addr) { - const vmpa2t *result; /* Actualisation à renvoyer */ + bool result; /* Bilan à retourner */ size_t index; /* Indice de ligne de tampon */ GBufferLine *line; /* Ligne sous le pointeur */ - - - line_width_summary summary; /* Résumé concis des largeurs */ - gint left_pos; /* Retour à la ligne */ - gint right_pos; /* Position d'extrème droite */ - BufferLineColumn i; /* Boucle de parcours */ size_t first; /* Première ligne intégrée */ size_t last; /* Dernière ligne intégrée */ - - - - + GBufferLine *other; /* Ligne voisine à visiter */ bool moved; /* Mémorisation d'une évolut° */ + gint text_pos; /* Abscisse de départ du texte */ - - - - - - - - - result = NULL; - - + result = false; line = g_buffer_view_find_line_at(view, caret->y, &index); - if (line == NULL) return NULL; - - g_width_tracker_get_local_width_summary(view->tracker, index, &summary); - - switch (dir) - { - case GDK_SCROLL_UP: - case GDK_SCROLL_DOWN: - break; - case GDK_SCROLL_LEFT: - case GDK_SCROLL_RIGHT: - left_pos = G_BUFFER_VIEW_GET_CLASS(view)->left_text; - if (display[BLC_PHYSICAL]) left_pos += summary.max_widths[BLC_PHYSICAL] + COL_MARGIN; - if (display[BLC_VIRTUAL]) left_pos += summary.max_widths[BLC_VIRTUAL] + COL_MARGIN; - if (display[BLC_BINARY]) left_pos += summary.max_widths[BLC_BINARY] + COL_MARGIN; - right_pos = left_pos; - for (i = BLC_ASSEMBLY_HEAD; i < BLC_COUNT; i++) - right_pos += summary.max_widths[i] + COL_MARGIN; - - /* -gint g_buffer_line_compute_max_width(const GBufferLine *line, BufferLineColumn index, const gint *max_widths) - -BufferLineColumn g_buffer_line_get_merge_start(const GBufferLine *line) - */ - - left_pos = G_BUFFER_VIEW_GET_CLASS(view)->left_text; - - break; - default: /* GDK_SCROLL_SMOOTH */ - break; - } + if (line == NULL) goto gbvmc_done; first = view->first; last = view->last; @@ -821,8 +803,12 @@ BufferLineColumn g_buffer_line_get_merge_start(const GBufferLine *line) if (index > first) { - line = g_code_buffer_find_line_by_index(view->buffer, index - 1); - result = g_buffer_view_compute_caret_full(view, line, index - 1, caret->x, display, caret); + index--; + + other = g_buffer_cache_find_line_by_index(view->cache, index); + result = _g_buffer_view_compute_caret_full(view, caret->x, other, index, display, caret, addr); + g_object_unref(G_OBJECT(other)); + } break; @@ -831,48 +817,58 @@ BufferLineColumn g_buffer_line_get_merge_start(const GBufferLine *line) if (index < last) { - line = g_code_buffer_find_line_by_index(view->buffer, index + 1); - result = g_buffer_view_compute_caret_full(view, line, index + 1, caret->x, display, caret); + index++; + + other = g_buffer_cache_find_line_by_index(view->cache, index); + result = _g_buffer_view_compute_caret_full(view, caret->x, other, index, display, caret, addr); + g_object_unref(G_OBJECT(other)); + } break; case GDK_SCROLL_LEFT: - /* - line = g_buffer_view_find_line_at(view, caret->y, &index); - if (line == NULL) break; - */ - moved = _g_buffer_view_move_caret(view, line, index, caret, ctrl, GDK_SCROLL_LEFT, display); if (moved) - result = get_mrange_addr(g_buffer_line_get_range(line)); + { + g_buffer_cache_get_line_addr(view->cache, index, caret->x, addr); + result = true; + } else if (index > first) { - line = g_code_buffer_find_line_by_index(view->buffer, index - 1); - result = g_buffer_view_compute_caret_full(view, line, index - 1, INT_MAX, display, caret); + index--; + + other = g_buffer_cache_find_line_by_index(view->cache, index); + result = _g_buffer_view_compute_caret_full(view, INT_MAX, other, index, display, caret, addr); + g_object_unref(G_OBJECT(other)); + } break; case GDK_SCROLL_RIGHT: - /* - line = g_buffer_view_find_line_at(view, caret->y, &index); - if (line == NULL) break; - */ - moved = _g_buffer_view_move_caret(view, line, index, caret, ctrl, GDK_SCROLL_RIGHT, display); if (moved) - result = get_mrange_addr(g_buffer_line_get_range(line)); + { + g_buffer_cache_get_line_addr(view->cache, index, caret->x, addr); + result = true; + } else if (index < last) { - line = g_code_buffer_find_line_by_index(view->buffer, index + 1); - result = g_buffer_view_compute_caret_full(view, line, index + 1, left_pos, display, caret); + index++; + + text_pos = g_buffer_cache_get_text_position(view->cache); + + other = g_buffer_cache_find_line_by_index(view->cache, index); + result = _g_buffer_view_compute_caret_full(view, text_pos, other, index, display, caret, addr); + g_object_unref(G_OBJECT(other)); + } break; @@ -882,11 +878,27 @@ BufferLineColumn g_buffer_line_get_merge_start(const GBufferLine *line) } + g_object_unref(G_OBJECT(line)); + + gbvmc_done: + return result; } + + + + + + + + + + + + /****************************************************************************** * * * Paramètres : view = vue de tampon à mettre à jour. * @@ -927,23 +939,64 @@ bool g_buffer_view_unhighlight_segments(GBufferView *view) bool g_buffer_view_highlight_segments(GBufferView *view, gint x, gint y, const bool *display) { - bool need_redraw; /* Besoin d'actualisation ? */ + bool result; /* Besoin à faire remonter */ + gint text_pos; /* Abscisse de départ du texte */ + gint lheight; /* Hauteur d'une ligne */ + size_t index; /* Indice de ligne de tampon */ + GBufferLine *line; /* Ligne à la position courante*/ + line_width_summary summary; /* Résumé concis des largeurs */ const line_segment *segment; /* Segment sélectionnable */ + /* Réinitialisation */ + if (view->highlighted != NULL) - need_redraw = g_buffer_view_unhighlight_segments(view); + result = g_buffer_view_unhighlight_segments(view); else - need_redraw = false; + result = false; + + /* Zone d'intervention bornée ! */ + + text_pos = g_buffer_cache_get_text_position(view->cache); + + if (x < text_pos) + goto gbvhs_done; + + /* Détermination de la ligne concernée */ - g_buffer_view_find_line_and_segment_at(view, &x, y, NULL, display, &segment); + lheight = g_buffer_cache_get_line_height(view->cache); + index = y / lheight; + + index += view->first; + + if (index > view->last) + goto gbvhs_done; + + line = g_buffer_cache_find_line_by_index(view->cache, index); + + assert(line != NULL); + + /* Recherche d'un segment et de son empreinte */ + + g_width_tracker_get_local_width_summary(view->tracker, index, &summary); + + x -= text_pos; + + segment = g_buffer_line_get_segment_at(line, &summary, display, + (gint []) { 0 }, &x, GDK_SCROLL_LEFT, true); - if (segment) - need_redraw |= add_segment_content_to_selection_list(view->highlighted, segment); + g_object_unref(G_OBJECT(line)); - if (need_redraw) + /* Conclusion */ + + if (segment != NULL) + result |= add_segment_content_to_selection_list(view->highlighted, segment); + + if (result) g_signal_emit_by_name(view, "need-redraw"); - return true; + gbvhs_done: + + return result; } @@ -952,13 +1005,12 @@ bool g_buffer_view_highlight_segments(GBufferView *view, gint x, gint y, const b * * * Paramètres : view = visualisation à représenter. * * cr = contexte graphique dédié à la procédure. * -* fake_x = abscisse réelle du point 0 à l'écran. * -* fake_y = ordonnée réelle du point 0 à l'écran. * +* virt_y = ordonnée réelle du point 0 à l'écran. * * area = position et surface à traiter. * * display = règles d'affichage des colonnes modulables. * * selected = ordonnée d'une ligne sélectionnée ou NULL. * * * -* Description : Imprime la visualisation du tampon de code désassemblé. * +* Description : Imprime la visualisation du tampon de lignes quelconques. * * * * Retour : - * * * @@ -966,148 +1018,57 @@ bool g_buffer_view_highlight_segments(GBufferView *view, gint x, gint y, const b * * ******************************************************************************/ -void g_buffer_view_draw(const GBufferView *view, cairo_t *cr, gint fake_x, gint fake_y, const cairo_rectangle_int_t *area, const bool *display, const gint *selected) +void g_buffer_view_draw(const GBufferView *view, cairo_t *cr, gint virt_y, const cairo_rectangle_int_t *area, const bool *display, gint *selected) { - GBufferViewClass *class; /* Classe pour les vues */ - gint real_x; /* Abscisse réelle pour tampon */ - gint real_y; /* Ordonnée réelle pour tampon */ + gint line_height; /* Hauteur d'une ligne */ + gint cr_y; /* Ordonnée pour le dessin */ size_t first; /* Première ligne visée */ - size_t last; /* Dernière ligne visée + 1 */ - gint y; /* Point de départ + décallage */ - bool wait_selection; /* Sélection déjà passée ? */ - gint rel_selected; /* Position relative de sélect°*/ - size_t i; /* Boucle de parcours */ - GBufferLine *line; /* Ligne à dessiner à l'écran */ - line_width_summary summary; /* Résumé concis des largeurs */ + size_t last; /* Dernière ligne visée */ - class = G_BUFFER_VIEW_GET_CLASS(view); + line_height = g_buffer_cache_get_line_height(view->cache); - real_x = fake_x + class->left_text; - real_y = fake_y + area->y; + /* Indice et point de départ */ first = view->first; - first += (real_y / class->line_height); - - last = first + (area->height / class->line_height); - if (area->height % class->line_height > 0) last++; - - last = MIN(last, view->last); - - y = area->y - (real_y % class->line_height); - - wait_selection = true; + first += (virt_y / line_height); - if (selected != NULL) - rel_selected = *selected - fake_y; - - if (g_code_buffer_count_lines(view->buffer) > 0) - for (i = first; i <= last; i++) - { - /* Si sélection, on sousligne la ligne concernée */ - if (wait_selection && selected != NULL && rel_selected == y) - { - cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.05); + cr_y = area->y - (virt_y % line_height); - cairo_rectangle(cr, area->x, y, area->width, class->line_height); - cairo_fill(cr); + /* Indice de d'arrivée */ - wait_selection = false; + last = first + (area->height / line_height); + if (area->height % line_height > 0) last++; - } + last = MIN(last, view->last); - line = g_code_buffer_find_line_by_index(view->buffer, i); + /* Phase de dessin ! */ - if (i == first || (g_buffer_line_get_flags(line) & BLF_WIDTH_MANAGER)) - g_width_tracker_get_local_width_summary(view->tracker, i, &summary); + /** + * Le contexte n'est pas sauvegardé avant modification ici car + * l'appelant l'a fait pour nous avant sa translation sur les abscisses. + */ - g_buffer_line_draw(line, cr, &summary, real_x, y, display, view->highlighted); + cairo_translate(cr, 0, cr_y); - y += class->line_height; + if (selected != NULL) + *selected -= cr_y; - } + g_buffer_cache_draw(view->cache, cr, first, last, area, display, selected, view->highlighted); } -/****************************************************************************** -* * -* Paramètres : view = visualisation à consulter. * -* addr = adresse où retrouver la ligne recherchée. * -* flags = propriétés à vérifier en tout ou partie. * -* idx = indice de la ligne trouvée ou NULL. [OUT] * -* * -* Description : Retrouve une ligne au sein d'un tampon avec une adresse. * -* * -* Retour : Line retrouvée ou NULL en cas d'échec. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GBufferLine *g_buffer_view_find_line_by_addr(const GBufferView *view, const vmpa2t *addr, BufferLineFlags flags, size_t *idx) -{ - GBufferLine *result; /* Ligne trouvée à retourner */ - phys_t length; /* Taille de la vue */ - mrange_t vrange; /* Couverture de la vue */ - bool allowed; /* Rechercher validée ? */ - - /* Vérification des bornes */ - - if (!view->unrestricted) - { - length = compute_vmpa_diff(&view->start, &view->end); - init_mrange(&vrange, &view->start, length); - allowed = mrange_contains_addr_inclusive(&vrange, addr); - } - else allowed = true; - /* Lancement des recherches ? */ - if (allowed) - result = g_code_buffer_find_line_by_addr(view->buffer, addr, flags, idx); - else - result = NULL; - return result; - -} -/****************************************************************************** -* * -* Paramètres : view = visualisation à consulter. * -* index = indice de la ligne recherchée. * -* * -* Description : Retrouve une ligne au sein d'un tampon avec un indice. * -* * -* Retour : Line retrouvée ou NULL en cas d'échec. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GBufferLine *g_buffer_view_find_line_by_index(const GBufferView *view, size_t index) -{ - GBufferLine *result; /* Ligne trouvée à retourner */ - bool allowed; /* Rechercher validée ? */ - /* Vérification des bornes */ - allowed = (view->first <= index && index <= view->last); - /* Lancement des recherches ? */ - - if (allowed) - result = g_code_buffer_find_line_by_index(view->buffer, index); - else - result = NULL; - - return result; - -} /****************************************************************************** @@ -1124,19 +1085,19 @@ GBufferLine *g_buffer_view_find_line_by_index(const GBufferView *view, size_t in * * ******************************************************************************/ -GBufferLine *g_buffer_view_find_line_at(GBufferView *view, gint y, size_t *idx) +static GBufferLine *g_buffer_view_find_line_at(GBufferView *view, gint y, size_t *idx) { GBufferLine *result; /* Ligne trouvée à retourner */ gint lheight; /* Hauteur d'une ligne */ size_t index; /* Indice attendu */ - lheight = g_buffer_view_get_line_height(view); + lheight = g_buffer_cache_get_line_height(view->cache); index = y / lheight; index += view->first; if (index <= view->last) - result = g_code_buffer_find_line_by_index(view->buffer, index); + result = g_buffer_cache_find_line_by_index(view->cache, index); else result = NULL; @@ -1148,125 +1109,26 @@ GBufferLine *g_buffer_view_find_line_at(GBufferView *view, gint y, size_t *idx) } -/****************************************************************************** -* * -* Paramètres : view = visualisation à consulter. * -* x = abscisse comprise dans le segment recherché. [OUT] * -* y = ordonnée comprise dans la ligne recherchée. * -* idx = indice de la ligne trouvée ou NULL. [OUT] * -* display = règles d'affichage des colonnes modulables. * -* segment = portion de texte recherchée ou NULL. [OUT] * -* * -* Description : Fournit la ligne et son segment présents à une position. * -* * -* Retour : Ligne retrouvée ou NULL si aucune. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GBufferLine *g_buffer_view_find_line_and_segment_at(GBufferView *view, gint *x, gint y, size_t *idx, const bool *display, const line_segment **segment) -{ - GBufferLine *result; /* Ligne trouvée à retourner */ - size_t index; /* Indice de la ligne trouvée */ - GBufferViewClass *class; /* Classe pour les vues */ - line_width_summary summary; /* Résumé concis des largeurs */ - - /* Recherche d'une ligne correspondante */ - result = g_buffer_view_find_line_at(view, y, &index); - if (idx != NULL) *idx = index; - /* Recherche du segment visé éventuel */ - if (result != NULL && segment != NULL) - { - class = G_BUFFER_VIEW_GET_CLASS(view); - if (*x < class->left_text) - *segment = NULL; - else - { - g_width_tracker_get_local_width_summary(view->tracker, index, &summary); - *x -= class->left_text; - *segment = g_buffer_line_get_segment_at(result, &summary, display, - (gint []) { 0 }, x, GDK_SCROLL_LEFT, true); - } - } - return result; -} /****************************************************************************** * * -* Paramètres : view = visualisation à consulter. * -* x = abscisse comprise dans le segment recherché. [OUT] * -* y = ordonnée comprise dans la ligne recherchée. * -* idx = indice de la ligne trouvée ou NULL. [OUT] * -* display = règles d'affichage des colonnes modulables. * -* creator = instance à l'origine de la représentation. [OUT] * -* * -* Description : Fournit la ligne et son segment présents à une position. * -* * -* Retour : Ligne retrouvée ou NULL si aucune. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GBufferLine *g_buffer_view_find_line_and_creator_at(GBufferView *view, gint *x, gint y, size_t *idx, const bool *display, GObject **creator) -{ - GBufferLine *result; /* Ligne trouvée à retourner */ - size_t index; /* Indice de la ligne trouvée */ - GBufferViewClass *class; /* Classe pour les vues */ - line_width_summary summary; /* Résumé concis des largeurs */ - - /* Recherche d'une ligne correspondante */ - - result = g_buffer_view_find_line_at(view, y, &index); - - if (idx != NULL) *idx = index; - - /* Recherche du segment visé éventuel */ - - if (result != NULL && creator != NULL) - { - class = G_BUFFER_VIEW_GET_CLASS(view); - - if (*x < class->left_text) - *creator = NULL; - - else - { - g_width_tracker_get_local_width_summary(view->tracker, index, &summary); - - *x -= class->left_text; - *creator = g_buffer_line_get_creator_at(result, &summary, display, - (gint []) { 0 }, x, GDK_SCROLL_LEFT, true); - - } - - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : view = composant GTK à consulter. * +* Paramètres : view = visualisation à consulter. * * addr = adresse à présenter à l'écran. * +* code = s'arrête si possible à une ligne avec code. * * x = position horizontale au sein du composant. [OUT] * * y = position verticale au sein du composant. [OUT] * -* code = s'arrête si possible à une ligne avec code. * * * * Description : Indique la position d'affichage d'une adresse donnée. * * * @@ -1276,61 +1138,11 @@ GBufferLine *g_buffer_view_find_line_and_creator_at(GBufferView *view, gint *x, * * ******************************************************************************/ -bool g_buffer_view_get_address_coordinates(GBufferView *view, const vmpa2t *addr, gint *x, gint *y, bool code) +bool g_buffer_view_get_address_coordinates(GBufferView *view, const vmpa2t *addr, bool code, gint *x, gint *y) { bool result; /* Bilan à retourner */ - gint lheight; /* Hauteur d'une ligne */ - size_t i; /* Boucle de parcours */ - GBufferLine *line; /* Ligne à consulter */ - const mrange_t *range; /* Emplacement parcouru */ - - result = false; - - *x = 0; - *y = 0; - - lheight = g_buffer_view_get_line_height(view); - - for (i = view->first; i <= view->last; i++) - { - /** - * Si l'adresse recherchée est plus petite que l'adresse de départ, - * on va effectuer un parcours complet pour rien. - * - * On considère cependant que le seul cas où celà peut arriver - * est lorsque que des découpages en blocs sont impliqués. - * - * Les découpages conduisent alors à la formation de petites zones, - * rapides à parcourir. - */ - - line = g_code_buffer_find_line_by_index(view->buffer, i); - range = g_buffer_line_get_range(line); - - result = mrange_contains_addr(range, addr); - if (result) break; - - *y += lheight; - } - - if (result && code) - for (; i <= view->last; i++) - { - line = g_code_buffer_find_line_by_index(view->buffer, i); - - if (g_buffer_line_get_flags(line) & BLF_HAS_CODE) break; - - if (i == view->last) break; - - line = g_code_buffer_find_line_by_index(view->buffer, i + 1); - - range = g_buffer_line_get_range(line); - if (!mrange_contains_addr(range, addr)) break; - - *y += lheight; - - } + result = g_buffer_cache_get_address_coordinates(view->cache, addr, view->first, view->last, code, x, y); return result; diff --git a/src/glibext/gbufferview.h b/src/glibext/gbufferview.h index 0aa26a6..dc1d704 100644 --- a/src/glibext/gbufferview.h +++ b/src/glibext/gbufferview.h @@ -28,7 +28,7 @@ #include -#include "gcodebuffer.h" +#include "gbuffercache.h" @@ -47,23 +47,22 @@ typedef struct _GBufferView GBufferView; typedef struct _GBufferViewClass GBufferViewClass; -/* Détermine le type de la vue d'un tampon pour code désassemblé. */ +/* Détermine le type de la vue d'un tampon pour lignes générées. */ GType g_buffer_view_get_type(void); -/* Crée une nouvelle vue d'un tampon pour code désassemblé. */ -GBufferView *g_buffer_view_new(GCodeBuffer *, segcnt_list *); +/* Crée une nouvelle vue d'un tampon pour lignes générées. */ +GBufferView *g_buffer_view_new(GBufferCache *, segcnt_list *); + +/* Fournit le tampon de code lié à un visualisateur donné. */ +GBufferCache *g_buffer_view_get_cache(const GBufferView *); /* Restreint le champ d'application de l'affichage. */ void g_buffer_view_restrict(GBufferView *, const vmpa2t *, const vmpa2t *); /* Indique le champ d'application de l'affichage. */ -bool g_buffer_view_get_restrictions(GBufferView *, vmpa2t *, vmpa2t *); +bool g_buffer_view_get_restrictions(const GBufferView *, vmpa2t *, vmpa2t *); -/* Fournit le tampon de code lié à un visualisateur donné. */ -GCodeBuffer *g_buffer_view_get_buffer(const GBufferView *); -/* Fournit la hauteur d'impression d'une ligne visualisée. */ -gint g_buffer_view_get_line_height(GBufferView *); /* Fournit la largeur requise par une visualisation. */ gint g_buffer_view_get_width(GBufferView *, const bool *); @@ -74,14 +73,18 @@ gint g_buffer_view_get_margin(GBufferView *, const bool *); /* Fournit la hauteur requise par une visualisation. */ gint g_buffer_view_get_height(const GBufferView *); -/* Calcule la position idéale de curseur pour un point donné. */ -const vmpa2t *g_buffer_view_compute_caret(GBufferView *, gint, gint, const bool *, GdkRectangle *); + + + /* Calcule la position idéale de curseur pour un point donné. */ -const vmpa2t *g_buffer_view_compute_caret_full(GBufferView *, GBufferLine *, size_t, gint, const bool *, GdkRectangle *); +bool g_buffer_view_compute_caret_full(GBufferView *, gint, gint, const bool *, GdkRectangle *, vmpa2t *); /* Déplace le curseur au sein d'une vue de tampon. */ -const vmpa2t *g_buffer_view_move_caret(GBufferView *, GdkRectangle *, bool, GdkScrollDirection, const bool *); +bool g_buffer_view_move_caret(GBufferView *, bool, GdkScrollDirection, const bool *, GdkRectangle *, vmpa2t *); + + + /* Supprime toute mise en évidence de segments. */ bool g_buffer_view_unhighlight_segments(GBufferView *); @@ -89,26 +92,18 @@ bool g_buffer_view_unhighlight_segments(GBufferView *); /* Surligne tous les segments similaires à celui sous la souris. */ bool g_buffer_view_highlight_segments(GBufferView *, gint, gint, const bool *); -/* Imprime la visualisation du tampon de code désassemblé. */ -void g_buffer_view_draw(const GBufferView *, cairo_t *, gint, gint, const cairo_rectangle_int_t *, const bool *, const gint *); +/* Imprime la visualisation du tampon de lignes quelconques. */ +void g_buffer_view_draw(const GBufferView *, cairo_t *, gint, const cairo_rectangle_int_t *, const bool *, gint *); -/* Retrouve une ligne au sein d'un tampon avec une adresse. */ -GBufferLine *g_buffer_view_find_line_by_addr(const GBufferView *, const vmpa2t *, BufferLineFlags, size_t *); -/* Retrouve une ligne au sein d'un tampon avec un indice. */ -GBufferLine *g_buffer_view_find_line_by_index(const GBufferView *, size_t ); -/* Fournit la ligne présente à une ordonnée donnée. */ -GBufferLine *g_buffer_view_find_line_at(GBufferView *, gint, size_t *); -/* Fournit la ligne et son segment présents à une position. */ -GBufferLine *g_buffer_view_find_line_and_segment_at(GBufferView *, gint *, gint, size_t *, const bool *, const line_segment **); -/* Fournit la ligne et son segment présents à une position. */ -GBufferLine *g_buffer_view_find_line_and_creator_at(GBufferView *, gint *, gint, size_t *, const bool *, GObject **); /* Indique la position d'affichage d'une adresse donnée. */ -bool g_buffer_view_get_address_coordinates(GBufferView *, const vmpa2t *, gint *, gint *, bool); +bool g_buffer_view_get_address_coordinates(GBufferView *, const vmpa2t *, bool, gint *, gint *); + + diff --git a/src/glibext/gcodebuffer.c b/src/glibext/gcodebuffer.c deleted file mode 100644 index e9f1762..0000000 --- a/src/glibext/gcodebuffer.c +++ /dev/null @@ -1,1778 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * gcodebuffer.c - affichage d'un fragment de code d'assemblage - * - * Copyright (C) 2010-2014 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 . - */ - - -#include "gcodebuffer.h" - - -#include -#include -#include -#include - - -#include "chrysamarshal.h" -#include "delayed-int.h" -#include "../common/extstr.h" - - - -/* -------------------------- PARCOURS DU CODE D'UN TAMPON -------------------------- */ - - -#define G_TYPE_BUFFER_SCAN g_buffer_scan_get_type() -#define G_BUFFER_SCAN(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_buffer_scan_get_type(), GDelayedExport)) -#define G_IS_BUFFER_SCAN(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_buffer_scan_get_type())) -#define G_BUFFER_SCAN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_BUFFER_SCAN, GDelayedExportClass)) -#define G_IS_BUFFER_SCAN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_BUFFER_SCAN)) -#define G_BUFFER_SCAN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_BUFFER_SCAN, GDelayedExportClass)) - - -/* Ensembles binaires à désassembler (instance) */ -typedef struct _GBufferScan -{ - GDelayedWork parent; /* A laisser en premier */ - - GCodeBuffer *buffer; /* Tampon à manipuler */ - - vmpa2t start; /* Début du parcours */ - bool has_start; /* Validité des données #1 */ - vmpa2t end; /* Fin du parcours */ - bool has_end; /* Validité des données #2 */ - - char *message; /* Message de progression */ - - process_line_fc process; /* Fonction de traitement réel */ - void *user_data; /* Données à faire suivre */ - -} GBufferScan; - -/* Ensembles binaires à désassembler (classe) */ -typedef struct _GBufferScanClass -{ - GDelayedWorkClass parent; /* A laisser en premier */ - -} GBufferScanClass; - - -/* Indique le type défini pour les tâches d'exportation différée. */ -static GType g_buffer_scan_get_type(void); - -/* Initialise la classe des tâches d'exportation différée. */ -static void g_buffer_scan_class_init(GBufferScanClass *); - -/* Initialise une tâche d'exportation différée. */ -static void g_buffer_scan_init(GBufferScan *); - -/* Supprime toutes les références externes. */ -static void g_buffer_scan_dispose(GBufferScan *); - -/* Procède à la libération totale de la mémoire. */ -static void g_buffer_scan_finalize(GBufferScan *); - -/* Crée une tâche d'exportation différée. */ -static GBufferScan *g_buffer_scan_new(GCodeBuffer *, const vmpa2t *, const vmpa2t *, const char *, process_line_fc, void *); - -/* Assure l'exportation en différé. */ -static void g_buffer_scan_process(GBufferScan *, GtkStatusStack *); - - - -/* -------------------------- TAMPON POUR CODE DESASSEMBLE -------------------------- */ - - -/* Suivi distant des évolutions */ -typedef struct _view_callback -{ - buffer_size_changed_cb size_changed; /* Evolution de taille */ - GObject *data; /* Données à associer */ - -} view_callback; - - -/* Tampon pour code désassemblé (instance) */ -struct _GCodeBuffer -{ - GObject parent; /* A laisser en premier */ - - BufferLineColumn main_column; /* Colonne principale */ - - GBufferLine **lines; /* Liste des lignes intégrées */ - size_t count; /* Quantité en cache */ - size_t used; /* Quantité utilisée */ - - GWidthTracker *tracker; /* Suivi des largeurs */ - - size_t indent; /* Indentation des lignes */ - - view_callback *vcallbacks; /* Vues à mettre à jour */ - size_t vcount; /* Quantité de ces vues */ - -}; - -/* Tampon pour code désassemblé (classe) */ -struct _GCodeBufferClass -{ - GObjectClass parent; /* A laisser en premier */ - - /* Signaux */ - - void (* line_changed) (GCodeBuffer *, GBufferLine *, line_segment *); - -}; - - -/* Taille des allocations de masse */ -#define LINE_ALLOC_BULK 20 - - -/* Procède à l'initialisation d'une classe de tampon de code. */ -static void g_code_buffer_class_init(GCodeBufferClass *); - -/* Procède à l'initialisation d'un tampon pour code désassemblé. */ -static void g_code_buffer_init(GCodeBuffer *); - -/* Réagit à un changement de contenu d'une ligne donnée. */ -static void on_line_content_change(GBufferLine *, line_segment *, GCodeBuffer *); - -/* Réagit à un changement de propriété rattachée à une ligne. */ -static void on_line_flag_flip(GBufferLine *, BufferLineFlags, BufferLineFlags, GCodeBuffer *); - -/* Ajoute de nouvelles lignes à une position donnée. */ -static void g_code_buffer_insert_lines_at(GCodeBuffer *, GBufferLine **, size_t, size_t); - - - -/* ------------------------- CONFORTS POUR LES COMMENTAIRES ------------------------- */ - - -/* Affiche un commentaire sur une ligne de tampon donnée. */ -static bool _g_code_buffer_write_inlined_comment(GCodeBuffer *, GBufferLine *, const char *, GObject *); - -/* Affiche un commentaire sur une ligne de tampon dédiée. */ -static bool _g_code_buffer_write_comment_area(GCodeBuffer *, GBufferLine *, const char *, bool, GObject *); - -/* Retrouve la première ligne d'une zone de commentaire. */ -static size_t g_code_buffer_find_first_line_comment(const GCodeBuffer *, size_t); - -/* Retrouve la dernière ligne d'une zone de commentaire. */ -static size_t g_code_buffer_find_last_line_comment(const GCodeBuffer *, size_t); - -/* Supprime un commentaire existant. */ -static bool _g_code_buffer_delete_lines_comment(GCodeBuffer *, GBufferLine *); - - - -/* ------------------------- SIGNAUX IMMEDIATS POUR UNE VUE ------------------------- */ - - -/* Fait suivre une variation de la quantité de lignes du tampon. */ -static void g_code_buffer_notify_size_changed(const GCodeBuffer *, bool, size_t, size_t); - - - -/* ---------------------------------------------------------------------------------- */ -/* PARCOURS DU CODE D'UN TAMPON */ -/* ---------------------------------------------------------------------------------- */ - - -/* Indique le type défini pour les tâches d'exportation différée. */ -G_DEFINE_TYPE(GBufferScan, g_buffer_scan, G_TYPE_DELAYED_WORK); - - -/****************************************************************************** -* * -* Paramètres : klass = classe à initialiser. * -* * -* Description : Initialise la classe des tâches d'exportation différée. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_buffer_scan_class_init(GBufferScanClass *klass) -{ - GObjectClass *object; /* Autre version de la classe */ - GDelayedWorkClass *work; /* Version en classe parente */ - - object = G_OBJECT_CLASS(klass); - - object->dispose = (GObjectFinalizeFunc/* ! */)g_buffer_scan_dispose; - object->finalize = (GObjectFinalizeFunc)g_buffer_scan_finalize; - - work = G_DELAYED_WORK_CLASS(klass); - - work->run = (run_task_fc)g_buffer_scan_process; - -} - - -/****************************************************************************** -* * -* Paramètres : scan = instance à initialiser. * -* * -* Description : Initialise une tâche d'exportation différée. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_buffer_scan_init(GBufferScan *scan) -{ - -} - - -/****************************************************************************** -* * -* Paramètres : scan = instance d'objet GLib à traiter. * -* * -* Description : Supprime toutes les références externes. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_buffer_scan_dispose(GBufferScan *scan) -{ - g_object_unref(G_OBJECT(scan->buffer)); - - G_OBJECT_CLASS(g_buffer_scan_parent_class)->dispose(G_OBJECT(scan)); - -} - - -/****************************************************************************** -* * -* Paramètres : scan = instance d'objet GLib à traiter. * -* * -* Description : Procède à la libération totale de la mémoire. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_buffer_scan_finalize(GBufferScan *scan) -{ - free(scan->message); - - G_OBJECT_CLASS(g_buffer_scan_parent_class)->finalize(G_OBJECT(scan)); - -} - - -/****************************************************************************** -* * -* Paramètres : buffer = tampon à manipuler. * -* start = première adresse visée ou NULL. * -* end = dernière adresse visée ou NULL. * -* message = message à afficher lors de la progression. * -* process = fonction assurant le traitement effectif. * -* data = données utilisateur à faire suivre. * -* * -* Description : Crée une tâche d'exportation différée. * -* * -* Retour : Tâche créée. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static GBufferScan *g_buffer_scan_new(GCodeBuffer *buffer, const vmpa2t *start, const vmpa2t *end, const char *message, process_line_fc process, void *data) -{ - GBufferScan *result; /* Tâche à retourner */ - - result = g_object_new(G_TYPE_BUFFER_SCAN, NULL); - - result->buffer = buffer; - g_object_ref(G_OBJECT(buffer)); - - result->has_start = (start != NULL); - - if (result->has_start) - copy_vmpa(&result->start, start); - - result->has_end = (end != NULL); - - if (result->has_end) - copy_vmpa(&result->end, end); - - result->message = strdup(message); - - result->process = process; - result->user_data = data; - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : scan = parcours à mener. * -* status = barre de statut à tenir informée. * -* * -* Description : Assure l'exportation en différé. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_buffer_scan_process(GBufferScan *scan, GtkStatusStack *status) -{ - size_t first; /* Première ligne visée */ - size_t last; /* Dernière ligne visée + 1 */ - GBufferLine **lines; /* Liste des lignes à traiter */ - //bstatus_id_t id; /* Identifiant de statut */ - size_t i; /* Boucle de parcours */ - - /* TODO : lock scan->buffer->lines */ - - if (scan->has_start) - first = g_code_buffer_get_index_from_address(scan->buffer, &scan->start, true); - else - first = 0; - - if (scan->has_end) - last = g_code_buffer_get_index_from_address(scan->buffer, &scan->end, false); - else - last = scan->buffer->used - 1; - - lines = scan->buffer->lines; - - //id = gtk_extended_status_bar_push(statusbar, scan->message, true); - - if (scan->buffer->used > 0) - for (i = first; i <= last; i++) - { - if (!scan->process(scan->buffer, lines[i], scan->user_data)) - break; - - /* - gtk_extended_status_bar_update_activity(statusbar, id, - (i - first) * 1.0 / (last - first)); - */ - - } - - /* TODO : unlock scan->buffer->lines */ - - //gtk_extended_status_bar_remove(statusbar, id); - -} - - - -/* ---------------------------------------------------------------------------------- */ -/* TAMPON POUR CODE DESASSEMBLE */ -/* ---------------------------------------------------------------------------------- */ - - -/* Détermine le type du composant de tampon pour code désassemblé. */ -G_DEFINE_TYPE(GCodeBuffer, g_code_buffer, G_TYPE_OBJECT); - - -/****************************************************************************** -* * -* Paramètres : class = classe de composant GTK à initialiser. * -* * -* Description : Procède à l'initialisation d'une classe de tampon de code. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_code_buffer_class_init(GCodeBufferClass *class) -{ - g_signal_new("line-changed", - G_TYPE_CODE_BUFFER, - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET(GCodeBufferClass, line_changed), - NULL, NULL, - g_cclosure_user_marshal_VOID__OBJECT_OBJECT, - G_TYPE_NONE, 2, G_TYPE_OBJECT, G_TYPE_OBJECT); - -} - - -/****************************************************************************** -* * -* Paramètres : buffer = composant GTK à initialiser. * -* * -* Description : Procède à l'initialisation d'un tampon pour code désassemblé.* -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_code_buffer_init(GCodeBuffer *buffer) -{ - buffer->tracker = g_width_tracker_new(buffer); - -} - - -/****************************************************************************** -* * -* Paramètres : main = colonne à référencer comme étant la principale. * -* * -* Description : Crée un nouveau composant de tampon pour code désassemblé. * -* * -* Retour : Composant GTK créé. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GCodeBuffer *g_code_buffer_new(BufferLineColumn main) -{ - GCodeBuffer *result; /* Composant à retourner */ - - result = g_object_new(G_TYPE_CODE_BUFFER, NULL); - - result->main_column = main; - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : buffer = composant GLib à consulter. * -* * -* Description : Compte le nombre de lignes rassemblées dans un tampon. * -* * -* Retour : Nombre de lignes constituant le tampon. * -* * -* Remarques : - * -* * -******************************************************************************/ - -size_t g_code_buffer_count_lines(const GCodeBuffer *buffer) -{ - return buffer->used; - -} - - -/****************************************************************************** -* * -* Paramètres : buffer = composant GLib à consulter. * -* * -* Description : Fournit un lien vers la structure de suivi de largeurs. * -* * -* Retour : Gestionnaire de largeurs de lignes. * -* * -* Remarques : - * -* * -******************************************************************************/ - -const GWidthTracker *g_code_buffer_get_width_tracker(const GCodeBuffer *buffer) -{ - return buffer->tracker; - -} - - -/****************************************************************************** -* * -* Paramètres : buffer = composant GLib à consulter. * -* range = emplacement où va se situer la ligne. * -* * -* Description : Initie une nouvelle ligne devant être insérée dans le tampon.* -* * -* Retour : Nouvelle ligne vierge à écrire. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GBufferLine *g_code_buffer_prepare_new_line(GCodeBuffer *buffer, const mrange_t *range) -{ - GBufferLine *result; /* Instance à retourner */ - size_t i; /* Boucle de parcours */ - - result = g_buffer_line_new(range, buffer->main_column); - - for (i = 0; i < buffer->indent; i++) - g_buffer_line_append_text(result, BLC_ASSEMBLY_HEAD, " ", 4, RTT_RAW, NULL); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : line = ligne dont la définition vient d'évoluer. * -* segment = éventuel segment qui vient d'évoluer ou NULL. * -* buffer = tampon de lignes cohérentes à manipuler. * -* * -* Description : Réagit à un changement de contenu d'une ligne donnée. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void on_line_content_change(GBufferLine *line, line_segment *segment, GCodeBuffer *buffer) -{ - g_signal_emit_by_name(buffer, "line-changed", line, segment); - -} - - -/****************************************************************************** -* * -* Paramètres : line = ligne dont la définition vient d'évoluer. * -* old = ancien groupe de propriétés associées. * -* old = nouveau groupe de propriétés associées. * -* buffer = tampon de lignes cohérentes à manipuler. * -* * -* Description : Réagit à un changement de propriété rattachée à une ligne. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void on_line_flag_flip(GBufferLine *line, BufferLineFlags old, BufferLineFlags new, GCodeBuffer *buffer) -{ - g_signal_emit_by_name(buffer, "line-changed", line, NULL); - -} - - -/****************************************************************************** -* * -* Paramètres : buffer = composant GLib à mettre à jour. * -* lines = liste de lignes à insérer. * -* count = taille de cette liste. * -* index = point d'insertion de la première ligne. * -* * -* Description : Ajoute de nouvelles lignes à une position donnée. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_code_buffer_insert_lines_at(GCodeBuffer *buffer, GBufferLine **lines, size_t count, size_t index) -{ - size_t i; /* Boucle de parcours */ - - /* Elaboration d'un espace suffisant */ - - if ((buffer->used + count) > buffer->count) - { - if (count > LINE_ALLOC_BULK) - buffer->count += count; - else - buffer->count += LINE_ALLOC_BULK; - - buffer->lines = (GBufferLine **)realloc(buffer->lines, - buffer->count * sizeof(GBufferLine *)); - - } - - /* Insertion des lignes */ - - if (index < buffer->used) - { - memmove(&buffer->lines[index + count], &buffer->lines[index], - (buffer->used - index) * sizeof(GBufferLine *)); - } - - buffer->used += count; - - for (i = 0; i < count; i++) - { - assert((index + i) < buffer->used); - - buffer->lines[index + i] = lines[i]; - - g_signal_connect(lines[i], "content-changed", G_CALLBACK(on_line_content_change), buffer); - g_signal_connect(lines[i], "flip-flag", G_CALLBACK(on_line_flag_flip), buffer); - - } - - /* Recueil initial des largeurs */ - - g_width_tracker_update_added(buffer->tracker, index, count); - - g_code_buffer_notify_size_changed(buffer, true, index, count); - -} - - -/****************************************************************************** -* * -* Paramètres : buffer = composant GLib à mettre à jour. * -* line = lign à insérer à la fin du tampon. * -* * -* Description : Ajoute une nouvelle ligne en fin de tampon. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_code_buffer_append_new_line(GCodeBuffer *buffer, GBufferLine *line) -{ - g_code_buffer_insert_lines_at(buffer, (GBufferLine *[]) { line }, 1, buffer->used); - -} - - -/****************************************************************************** -* * -* Paramètres : buffer = composant GLib à mettre à jour. * -* lines = liste de lignes à insérer. * -* count = taille de cette liste. * -* point = point d'insertion du bloc de ligne. * -* before = emplacement de l'insertion par rapport au point. * -* * -* Description : Ajoute de nouvelles lignes par rapport à une ligne donnée. * -* * -* Retour : Bilan : insertion réussie ou non ? * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool g_code_buffer_insert_lines(GCodeBuffer *buffer, GBufferLine **lines, size_t count, const GBufferLine *point, bool before) -{ - bool result; /* Bilan à retourner */ - size_t index; /* Indice d'insertion final */ - - result = false; - - index = g_code_buffer_find_index_by_line(buffer, point); - - if (index == buffer->used) - goto gcbil_exit; - - if (!before) - index++; - - g_code_buffer_insert_lines_at(buffer, lines, count, index); - - - - - result = true; - - gcbil_exit: - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : buffer = composant GLib à mettre à jour. * -* start = première ligne devant être supprimée. * -* end = dernière ligne devant être supprimée. * -* * -* Description : Supprime une ou plusieurs lignes du tampon indiqué. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_code_buffer_delete_lines(GCodeBuffer *buffer, size_t start, size_t end) -{ - size_t i; /* Boucle de parcours */ - GBufferLine *line; /* Ligne en cours de traitement*/ - - assert(start < buffer->used); - assert(end < buffer->used); - - for (i = start; i <= end; i++) - { - line = buffer->lines[i]; - - g_signal_handlers_disconnect_by_func(line, G_CALLBACK(on_line_content_change), buffer); - g_signal_handlers_disconnect_by_func(line, G_CALLBACK(on_line_flag_flip), buffer); - - g_object_unref(G_OBJECT(line)); - - } - - if ((end + 1) < buffer->used) - memmove(&buffer->lines[start], &buffer->lines[end + 1], - (buffer->used - end - 1) * sizeof(GBufferLine *)); - - buffer->used -= (end - start + 1); - - g_width_tracker_update_deleted(buffer->tracker, start, end); - - g_code_buffer_notify_size_changed(buffer, false, start, end - start + 1); - -} - - -/****************************************************************************** -* * -* Paramètres : buffer = composant GTK à mettre à jour. * -* addr = adresse où retrouver la ligne recherchée. * -* flags = propriétés à vérifier en tout ou partie. * -* idx = indice de la ligne trouvée ou NULL. [OUT] * -* * -* Description : Retrouve une ligne au sein d'un tampon avec une adresse. * -* * -* Retour : Line retrouvée ou NULL en cas d'échec. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GBufferLine *g_code_buffer_find_line_by_addr(const GCodeBuffer *buffer, const vmpa2t *addr, BufferLineFlags flags, size_t *idx) -{ - GBufferLine *result; /* Instance à retourner */ - size_t index; /* Indice de la ligne visée */ - - index = g_code_buffer_get_index_from_address(buffer, addr, true); - - if (index == buffer->used) - result = NULL; - - else - { - if (idx != NULL) - *idx = index; - - result = buffer->lines[index]; - - if (flags != BLF_NONE) - while ((g_buffer_line_get_flags(result) & flags) != flags) - { - if ((index + 1) == buffer->used) break; - - /* FIXME : vérifier que l'adresse est toujours celle recherchée ! */ - - if (idx != NULL) - (*idx)++; - - result = buffer->lines[++index]; - - } - - g_object_ref(G_OBJECT(result)); - - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : buffer = tampon de lignes à consulter. * -* index = indice de la ligne recherchée. * -* * -* Description : Retrouve une ligne au sein d'un tampon avec un indice. * -* * -* Retour : Line retrouvée ou NULL en cas d'échec. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GBufferLine *g_code_buffer_find_line_by_index(const GCodeBuffer *buffer, size_t index) -{ - GBufferLine *result; /* Ligne trouvée à retourner */ - - /* TODO : ref */ - - if (index < buffer->used) - result = buffer->lines[index]; - else - result = NULL; - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : buffer = composant GTK à mettre à jour. * -* addr = adresse où va se situer la ligne. * -* first = indique si on l'arrête à la première ou la dernière.* -* * -* Description : Convertit une adresse en indice de ligne. * -* * -* Retour : Indice de l'adresse trouvée, ou le nombre de lignes sinon. * -* * -* Remarques : - * -* * -******************************************************************************/ - -size_t g_code_buffer_get_index_from_address(const GCodeBuffer *buffer, const vmpa2t *addr, bool first) -{ - size_t result; /* Indice à retourner */ - GBufferLine **found; /* Renvoi vers une trouvaille */ - const mrange_t *range; /* Couverture d'une ligne */ - - /** - * Si aucune adresse (ie. aucune limite ?) n'est précisée, on se base sur - * la direction pour trouver le bon indice. - */ - - if (addr == NULL) - result = (first ? 0 : buffer->used - 1); - - /** - * Sinon on parcourt méthodiquement toutes les lignes ! - */ - - else - { - /* Recherche dichotomique grossière */ - - int cmp_addr_and_line(const vmpa2t *addr, const GBufferLine **line) - { - int status; /* Bilan d'une comparaison */ - const mrange_t *lrange; /* Couverture d'une ligne */ - - lrange = g_buffer_line_get_range(*line); - - status = cmp_mrange_with_vmpa(lrange, addr); - - return status; - - } - - found = bsearch(addr, buffer->lines, buffer->used, sizeof(GBufferLine *), - (__compar_fn_t)cmp_addr_and_line); - - /* Dernier raffinage pour approcher la cible réelle */ - - if (found == NULL) - result = buffer->used; - - else - { - result = found - buffer->lines; - - if (first) - for (; result > 0; result--) - { - range = g_buffer_line_get_range(buffer->lines[result - 1]); - if (!mrange_contains_addr(range, addr)) break; - } - - else - for (; (result + 1) < buffer->used; result++) - { - range = g_buffer_line_get_range(buffer->lines[result + 1]); - if (!mrange_contains_addr(range, addr)) break; - } - - } - - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : buffer = tampon de lignes à consulter. * -* line = ligne dont l'indice est à retrouver. * -* * -* Description : Retrouve l'indice associé à une ligne au sein d'un tampon. * -* * -* Retour : Indice de l'adresse trouvée, ou le nombre de lignes sinon. * -* * -* Remarques : - * -* * -******************************************************************************/ - -size_t g_code_buffer_find_index_by_line(const GCodeBuffer *buffer, const GBufferLine *line) -{ - size_t result; /* Indice trouvé à retourner */ - const mrange_t *range; /* Emplacement de la ligne */ - const mrange_t *next; /* Emplacement suivant */ - - range = g_buffer_line_get_range(line); - - result = g_code_buffer_get_index_from_address(buffer, get_mrange_addr(range), true); - - /** - * Comme plusieurs lignes consécutives peuvent avoir la même adresse, - * on parcourt les lignes suivantes pour retrouver la ligne recherchée. - */ - - if (result < buffer->used) - { - while (buffer->lines[result] != line) - { - if (++result == buffer->used) - break; - - next = g_buffer_line_get_range(buffer->lines[result]); - - if (cmp_vmpa(get_mrange_addr(range), get_mrange_addr(next)) != 0) - { - result = buffer->used; - break; - } - - } - - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : buffer = composant GTK à mettre à jour. * -* * -* Description : Augmente l'indentation des prochaines lignes. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_code_buffer_inc_indentation(GCodeBuffer *buffer) -{ - buffer->indent++; - -} - - -/****************************************************************************** -* * -* Paramètres : buffer = composant GTK à mettre à jour. * -* * -* Description : Diminue l'indentation des prochaines lignes. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_code_buffer_dec_indentation(GCodeBuffer *buffer) -{ - /* BUG_ON(buffer->indent == 0) */ - - buffer->indent--; - -} - - -/****************************************************************************** -* * -* Paramètres : buffer = tampon de données à utiliser. * -* start = première adresse visée ou 0. * -* end = dernière adresse visée ou VMPA_MAX. * -* message = message à afficher lors de la progression. * -* process = fonction assurant le traitement effectif. * -* data = données utilisateur à faire suivre. * -* * -* Description : Lance un parcours des différentes lignes du tampon de code. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -GDelayedWork *g_buffer_code_scan(GCodeBuffer *buffer, const vmpa2t *start, const vmpa2t *end, const char *message, process_line_fc process, void *data) -{ - GBufferScan *result; /* Procédure à créer / renvoyer*/ - GWorkQueue *queue; /* Gestionnaire de différés */ - - result = g_buffer_scan_new(buffer, start, end, message, process, data); - g_object_ref(G_OBJECT(result)); - - queue = get_work_queue(); - g_work_queue_schedule_work(queue, G_DELAYED_WORK(result), DEFAULT_WORK_GROUP); - - return G_DELAYED_WORK(result); - -} - - - -/* ---------------------------------------------------------------------------------- */ -/* CONFORTS POUR LES COMMENTAIRES */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* Paramètres : buffer = tampon de lignes à consulter. * -* line = ligne à l'intérieur d'un commentaire. * -* comment = nouveau commentaire à inscrire à la ligne donnée. * -* creator = créateur à l'origine de la construction. * -* * -* Description : Affiche un commentaire sur une ligne de tampon donnée. * -* * -* Retour : Bilan de l'opération : ajout ou non ? * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool _g_code_buffer_write_inlined_comment(GCodeBuffer *buffer, GBufferLine *line, const char *comment, GObject *creator) -{ - bool result; /* Bilan à retourner */ - const mrange_t *range; /* Emplace de ligne à utiliser */ - char *wcopy; /* Copie de travail */ - GBufferLine **extra; /* Lignes supplémentaires */ - size_t extra_count; /* Quantité de ces lignes */ - char *saveptr; /* Sauvegarde pour la sécurité */ - char *token; /* Fragment à insérer */ - size_t len; /* Taille dudit fragment */ - GBufferLine *new; /* Nouvelle ligne créée */ - size_t i; /* Boucle de parcours */ - - assert(!g_buffer_line_has_comment(line)); - - result = false; - - range = g_buffer_line_get_range(line); - - wcopy = strdup(comment); - - extra = NULL; - extra_count = 0; - - for (token = strtok_r(wcopy, COMMENT_LINE_SEP, &saveptr); - token != NULL; - token = strtok_r(NULL, COMMENT_LINE_SEP, &saveptr)) - { - len = strlen(token); - - if (!result) - g_buffer_line_append_text(line, BLC_COMMENTS, token, len, RTT_COMMENT, creator); - - else - { - new = g_code_buffer_prepare_new_line(buffer, range); - - g_buffer_line_append_text(new, BLC_COMMENTS, token, len, RTT_COMMENT, creator); - - extra = (GBufferLine **)realloc(extra, ++extra_count * sizeof(GBufferLine *)); - - extra[extra_count - 1] = new; - - } - - result = true; - - } - - free(wcopy); - - if (extra_count > 0) - { - result &= g_code_buffer_insert_lines(buffer, extra, extra_count, line, false); - - if (!result) - for (i = 0; i < extra_count; i++) - g_object_unref(G_OBJECT(extra[i])); - - free(extra); - - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : buffer = tampon de lignes à consulter. * -* line = ligne à l'intérieur d'un commentaire. * -* comment = nouveau commentaire à inscrire à la ligne donnée. * -* creator = créateur à l'origine de la construction. * -* * -* Description : Affiche un commentaire sur une ligne de tampon donnée. * -* * -* Retour : Bilan de l'opération : ajout ou non ? * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool g_code_buffer_update_inlined_comment(GCodeBuffer *buffer, GBufferLine *line, const char *comment, GObject *creator) -{ - bool result; /* Bilan à retourner */ - - if (g_buffer_line_has_comment(line)) - result = _g_code_buffer_delete_lines_comment(buffer, line); - else - result = true; - - if (result) - result = _g_code_buffer_write_inlined_comment(buffer, line, comment, creator); - - /* TODO : emit() */ - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : buffer = tampon de lignes à consulter. * -* line = ligne à l'intérieur d'un commentaire. * -* comment = nouveau commentaire à inscrire à la ligne donnée. * -* before = précise la position du commentaire. * -* creator = créateur à l'origine de la construction. * -* * -* Description : Affiche un commentaire sur une ligne de tampon dédiée. * -* * -* Retour : Bilan de l'opération : ajout ou non ? * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool _g_code_buffer_write_comment_area(GCodeBuffer *buffer, GBufferLine *line, const char *comment, bool before, GObject *creator) -{ - bool result; /* Bilan à retourner */ - const mrange_t *range; /* Emplace de ligne à utiliser */ - char *wcopy; /* Copie de travail */ - GBufferLine **extra; /* Lignes supplémentaires */ - size_t extra_count; /* Quantité de ces lignes */ - char *saveptr; /* Sauvegarde pour la sécurité */ - char *token; /* Fragment à insérer */ - size_t len; /* Taille dudit fragment */ - GBufferLine *new; /* Nouvelle ligne créée */ - size_t i; /* Boucle de parcours */ - - assert(!g_buffer_line_has_comment(line)); - - result = false; - - range = g_buffer_line_get_range(line); - - wcopy = strdup(comment); - - extra = NULL; - extra_count = 0; - - for (token = strtok_r(wcopy, COMMENT_LINE_SEP, &saveptr); - token != NULL; - token = strtok_r(NULL, COMMENT_LINE_SEP, &saveptr)) - { - len = strlen(token); - - new = g_code_buffer_prepare_new_line(buffer, range); - g_buffer_line_start_merge_at(new, BLC_DISPLAY); - - g_buffer_line_append_text(new, BLC_DISPLAY, token, len, RTT_COMMENT, creator); - - extra = (GBufferLine **)realloc(extra, ++extra_count * sizeof(GBufferLine *)); - - extra[extra_count - 1] = new; - - result = true; - - } - - free(wcopy); - - if (extra_count > 0) - { - result &= g_code_buffer_insert_lines(buffer, extra, extra_count, line, before); - - if (!result) - for (i = 0; i < extra_count; i++) - g_object_unref(G_OBJECT(extra[i])); - - free(extra); - - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : buffer = tampon de lignes à consulter. * -* line = ligne à l'intérieur d'un commentaire. * -* comment = nouveau commentaire à inscrire à la ligne donnée. * -* before = précise la position du commentaire. * -* creator = créateur à l'origine de la construction. * -* * -* Description : Affiche un commentaire sur une ligne de tampon dédiée. * -* * -* Retour : Bilan de l'opération : ajout ou non ? * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool g_code_buffer_update_comment_area(GCodeBuffer *buffer, GBufferLine *line, const char *comment, bool before, GObject *creator) -{ - bool result; /* Bilan à retourner */ - - if (g_buffer_line_has_comment(line)) - result = _g_code_buffer_delete_lines_comment(buffer, line); - else - result = true; - - if (result) - result = _g_code_buffer_write_comment_area(buffer, line, comment, before, creator); - - /* TODO : emit() */ - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : buffer = tampon de lignes à consulter. * -* index = indice de ligne à l'intérieur d'un commentaire. * -* * -* Description : Retrouve la première ligne d'une zone de commentaire. * -* * -* Retour : Indice de l'adresse trouvée, ou le nombre de lignes sinon. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static size_t g_code_buffer_find_first_line_comment(const GCodeBuffer *buffer, size_t index) -{ - size_t result; /* Indice trouvé à retourner */ - GBufferLine *prev; /* Ligne précédente */ - - assert(index < buffer->used); - - bool is_first_line_of_comment(const GBufferLine *ln, const GBufferLine *pv) - { - bool first; /* Statut à renvoyer */ - BufferLineColumn merge_col; /* Colonne de fusion #1 */ - BufferLineColumn prev_merge_col; /* Colonne de fusion #2 */ - - merge_col = g_buffer_line_get_merge_start(ln); - - /** - * La ligne consultée contient toujours un commentaire. - * - * Deux cas de figures sont possibles ici : - * - * - soit du texte est présent dans la colonne "commentaires". - * Si du texte est présent avant, alors il s'agit forcément de - * la première (et unique ?) ligne de commentaire. - * - * - soit la ligne effectue une fusion des colonnes depuis BLC_DISPLAY. - * Si la ligne qui précède fait de même, il s'agit alors d'une étiquette - * ou de l'amont du commentaire. - * - */ - - if (g_buffer_line_has_text(ln, BLC_COMMENTS, BLC_COUNT)) - { - first = g_buffer_line_has_text(ln, BLC_DISPLAY, BLC_COMMENTS); - - if (!first) - { - /* La ligne d'avant doit avoir un commentaire ! */ - first = !g_buffer_line_has_text(pv, BLC_COMMENTS, BLC_COUNT); - } - - } - - else - { - /** - * Le prologue "merge_col == BLC_FIRST" n'étant pas éditable, - * la seule fusion possible ici est la suivante. - */ - assert(merge_col == BLC_DISPLAY); - - /** - * La première ligne d'un tampon est toujours un prologue. - */ - assert(pv != NULL); - - prev_merge_col = g_buffer_line_get_merge_start(pv); - - first = (prev_merge_col != BLC_DISPLAY); - - if (!first) - first = (g_buffer_line_get_flags(pv) & BLF_IS_LABEL); - - } - - return first; - - } - - for (result = index; result > 0; result--) - { - prev = (result > 0 ? buffer->lines[result - 1] : NULL); - - if (is_first_line_of_comment(buffer->lines[result], prev)) - break; - - } - - if (result == 0) - { - if (!is_first_line_of_comment(buffer->lines[0], NULL)) - result = buffer->used; - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : buffer = tampon de lignes à consulter. * -* index = indice de ligne à l'intérieur d'un commentaire. * -* * -* Description : Retrouve la dernière ligne d'une zone de commentaire. * -* * -* Retour : Indice de l'adresse trouvée, ou le nombre de lignes sinon. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static size_t g_code_buffer_find_last_line_comment(const GCodeBuffer *buffer, size_t index) -{ - size_t result; /* Indice trouvé à retourner */ - GBufferLine *next; /* Ligne suivante */ - - assert(index < buffer->used); - - bool is_last_line_of_comment(const GBufferLine *ln, const GBufferLine *nx) - { - bool last; /* Statut à renvoyer */ - BufferLineColumn merge_col; /* Colonne de fusion #1 */ - BufferLineColumn next_merge_col; /* Colonne de fusion #2 */ - - merge_col = g_buffer_line_get_merge_start(ln); - - /** - * La ligne consultée contient toujours un commentaire. - * - * Deux cas de figures sont possibles ici : - * - * - soit du texte est présent dans la colonne "commentaires". - * Si la ligne suivante est similaire et si du texte est présent avant, - * alors il s'agit forcément de d'un nouveau commentaire. S'il n'y a - * aucun texte, il s'agit de la suite du commentaire. - * - * - soit la ligne effectue une fusion des colonnes depuis BLC_DISPLAY. - * Si la ligne qui suit fait de même, il s'agit alors d'une étiquette - * ou de l'aval du commentaire. - * - */ - - if (g_buffer_line_has_text(ln, BLC_COMMENTS, BLC_COUNT)) - { - last = !g_buffer_line_has_text(nx, BLC_COMMENTS, BLC_COUNT); - - if (!last) - last = g_buffer_line_has_text(nx, BLC_DISPLAY, BLC_COMMENTS); - - } - - else - { - /** - * Le prologue "merge_col == BLC_FIRST" n'étant pas éditable, - * la seule fusion possible ici est la suivante. - */ - assert(merge_col == BLC_DISPLAY); - - if (nx == NULL) - last = true; - - else - { - next_merge_col = g_buffer_line_get_merge_start(nx); - - last = (next_merge_col != BLC_DISPLAY); - - if (!last) - last = (g_buffer_line_get_flags(nx) & BLF_IS_LABEL); - - } - - } - - return last; - - } - - for (result = index; result < buffer->used; result++) - { - next = ((result + 1) < buffer->used ? buffer->lines[result + 1] : NULL); - - if (is_last_line_of_comment(buffer->lines[result], next)) - break; - - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : buffer = tampon de lignes à consulter. * -* line = ligne à l'intérieur d'un commentaire. * -* * -* Description : Retrouve le créateur d'un commentaire existant. * -* * -* Retour : Instance trouvée à déréférencer ensuite ou NULL si aucune. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GObject *g_code_buffer_get_comment_creator(const GCodeBuffer *buffer, const GBufferLine *line) -{ - GObject *result; /* Instance à retourner */ - BufferLineColumn merge_col; /* Colonne de fusion */ - - if (g_buffer_line_has_comment(line)) - { - merge_col = g_buffer_line_get_merge_start(line); - - if (merge_col == BLC_DISPLAY) - result = g_buffer_line_find_first_segment_creator(line, BLC_DISPLAY); - else - result = g_buffer_line_find_first_segment_creator(line, BLC_COMMENTS); - - } - - else - result = NULL; - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : buffer = tampon de lignes à consulter. * -* line = ligne à l'intérieur d'un commentaire. * -* * -* Description : Récupère le contenu d'un commentaire existant. * -* * -* Retour : Commentaire retrouver à libérer ou NULL en cas d'échec. * -* * -* Remarques : - * -* * -******************************************************************************/ - -char *g_code_buffer_get_lines_comment(const GCodeBuffer *buffer, const GBufferLine *line) -{ - char *result; /* Contenu à retourner */ - size_t index; /* Indice de la ligne fournie */ - size_t start; /* Ligne de départ */ - size_t end; /* Ligne d'arrivée */ - BufferLineColumn merge_col; /* Colonne de fusion */ - size_t i; /* Boucle de parcours */ - char *extra; /* Commentaire supplémentaire */ - - /* Pas de prologue ici ! */ - assert(g_buffer_line_has_comment(line)); - - result = NULL; - - index = g_code_buffer_find_index_by_line(buffer, line); - - if (index == buffer->used) - goto gcbglc_exit; - - start = g_code_buffer_find_first_line_comment(buffer, index); - - if (start == buffer->used) - goto gcbglc_exit; - - end = g_code_buffer_find_last_line_comment(buffer, index); - - if (end == buffer->used) - goto gcbglc_exit; - - merge_col = g_buffer_line_get_merge_start(line); - - for (i = start; i <= end; i++) - { - if (merge_col == BLC_DISPLAY) - extra = g_buffer_line_get_text(buffer->lines[i], BLC_DISPLAY, BLC_COUNT, false); - - else - extra = g_buffer_line_get_text(buffer->lines[i], BLC_COMMENTS, BLC_COUNT, false); - - assert(extra != NULL); - - if (result == NULL) - result = extra; - - else - { - result = stradd(result, extra); - free(extra); - } - - } - - gcbglc_exit: - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : buffer = tampon de lignes à modifier. * -* line = ligne à l'intérieur d'un commentaire. * -* * -* Description : Supprime un commentaire existant. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool _g_code_buffer_delete_lines_comment(GCodeBuffer *buffer, GBufferLine *line) -{ - bool result; /* Bilan à retourner */ - size_t index; /* Indice de la ligne fournie */ - size_t start; /* Ligne de départ */ - size_t end; /* Ligne d'arrivée */ - BufferLineColumn merge_col; /* Colonne de fusion */ - - /* Pas de prologue ici ! */ - assert(g_buffer_line_has_comment(line)); - - result = false; - - index = g_code_buffer_find_index_by_line(buffer, line); - - if (index == buffer->used) - goto gcbdlc_exit; - - start = g_code_buffer_find_first_line_comment(buffer, index); - - if (start == buffer->used) - goto gcbdlc_exit; - - end = g_code_buffer_find_last_line_comment(buffer, index); - - if (end == buffer->used) - goto gcbdlc_exit; - - result = true; - - merge_col = g_buffer_line_get_merge_start(line); - - if (merge_col == BLC_DISPLAY) - g_code_buffer_delete_lines(buffer, start, end); - - else - { - g_buffer_line_delete_text(buffer->lines[start], BLC_COMMENTS, BLC_COUNT); - - if (end > start) - g_code_buffer_delete_lines(buffer, start + 1, end); - - } - - gcbdlc_exit: - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : buffer = tampon de lignes à modifier. * -* line = ligne à l'intérieur d'un commentaire. * -* * -* Description : Supprime un commentaire existant. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool g_code_buffer_delete_lines_comment(GCodeBuffer *buffer, GBufferLine *line) -{ - bool result; /* Bilan à retourner */ - - result = _g_code_buffer_delete_lines_comment(buffer, line); - - /* TODO : emit() */ - - return result; - -} - - -/* ---------------------------------------------------------------------------------- */ -/* SIGNAUX IMMEDIATS POUR UNE VUE */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* Paramètres : buffer = tampon de lignes à modifier. * -* cb = fonction à appeler au moment opportun. * -* data = object GLib à associer à l'appel. * -* * -* Description : Enregistre l'adresse d'une fonction de mise à jour de vue. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_code_buffer_register_view_callback(GCodeBuffer *buffer, buffer_size_changed_cb cb, GObject *data) -{ - view_callback *new; /* Informations sur l'appel */ - - buffer->vcount++; - - buffer->vcallbacks = (view_callback *)realloc(buffer->vcallbacks, buffer->vcount * sizeof(view_callback)); - - new = &buffer->vcallbacks[buffer->vcount - 1]; - - new->size_changed = cb; - new->data = data; - -} - - -/****************************************************************************** -* * -* Paramètres : buffer = tampon de lignes à modifier. * -* data = object GLib à associer à l'appel. * -* * -* Description : Supprime un élément des vues à contacter pour mises à jour. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_code_buffer_unregister_view_callback(GCodeBuffer *buffer, GObject *data) -{ - size_t i; /* Boucle de parcours */ - - for (i = 0; i < buffer->vcount; i++) - if (buffer->vcallbacks[i].data == data) - { - if ((i + 1) < buffer->vcount) - memmove(&buffer->vcallbacks[i], &buffer->vcallbacks[i + 1], - (buffer->vcount - i - 1) * sizeof(view_callback)); - - buffer->vcount--; - - buffer->vcallbacks = (view_callback *)realloc(buffer->vcallbacks, - buffer->vcount * sizeof(view_callback)); - - } - -} - - -/****************************************************************************** -* * -* Paramètres : buffer = tampon de lignes à diffuser. * -* added = indication sur la variation de la taille du tampon. * -* index = indice de la première ligne à traiter. * -* count = nombre de lignes à traiter. * -* * -* Description : Fait suivre une variation de la quantité de lignes du tampon.* -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_code_buffer_notify_size_changed(const GCodeBuffer *buffer, bool added, size_t index, size_t count) -{ - size_t i; /* Boucle de parcours */ - view_callback *cb; /* Informations sur l'appel */ - - for (i = 0; i < buffer->vcount; i++) - { - cb = &buffer->vcallbacks[i]; - - cb->size_changed(buffer, added, index, count, cb->data); - - } - -} diff --git a/src/glibext/gcodebuffer.h b/src/glibext/gcodebuffer.h deleted file mode 100644 index f600aee..0000000 --- a/src/glibext/gcodebuffer.h +++ /dev/null @@ -1,155 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * gcodebuffer.h - prototypes pour l'affichage d'un fragment de code d'assemblage - * - * Copyright (C) 2010-2014 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 . - */ - - -#ifndef _GLIBEXT_GCODEBUFFER_H -#define _GLIBEXT_GCODEBUFFER_H - - -#include - - -#include "delayed.h" -#include "gbufferline.h" -#include "gwidthtracker.h" - - - -/* -------------------------- TAMPON POUR CODE DESASSEMBLE -------------------------- */ - - -#define G_TYPE_CODE_BUFFER (g_code_buffer_get_type()) -#define G_CODE_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_CODE_BUFFER, GCodeBuffer)) -#define G_CODE_BUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_CODE_BUFFER, GCodeBufferClass)) -#define G_IS_CODE_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_CODE_BUFFER)) -#define G_IS_CODE_BUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_CODE_BUFFER)) -#define G_CODE_BUFFER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_CODE_BUFFER, GCodeBufferClass)) - - -/* Tampon pour code désassemblé (instance) */ -typedef struct _GCodeBuffer GCodeBuffer; - -/* Tampon pour code désassemblé (classe) */ -typedef struct _GCodeBufferClass GCodeBufferClass; - - -/* Détermine le type du composant de tampon pour code désassemblé. */ -GType g_code_buffer_get_type(void); - -/* Crée un nouveau composant de tampon pour code désassemblé. */ -GCodeBuffer *g_code_buffer_new(BufferLineColumn); - -/* Compte le nombre de lignes rassemblées dans un tampon. */ -size_t g_code_buffer_count_lines(const GCodeBuffer *); - -/* Fournit un lien vers la structure de suivi de largeurs. */ -const GWidthTracker *g_code_buffer_get_width_tracker(const GCodeBuffer *); - -/* Initie une nouvelle ligne devant être insérée dans le tampon. */ -GBufferLine *g_code_buffer_prepare_new_line(GCodeBuffer *, const mrange_t *); - -/* Ajoute une nouvelle ligne en fin de tampon. */ -void g_code_buffer_append_new_line(GCodeBuffer *, GBufferLine *); - -/* Ajoute de nouvelles lignes par rapport à une ligne donnée. */ -bool g_code_buffer_insert_lines(GCodeBuffer *, GBufferLine **, size_t, const GBufferLine *, bool); - -/* Supprime une ou plusieurs lignes du tampon indiqué. */ -void g_code_buffer_delete_lines(GCodeBuffer *, size_t, size_t); - - - -/* FIXME */ -#define g_code_buffer_append_new_line_fixme(b) \ - g_code_buffer_prepare_new_line(b, (mrange_t []){ { 0, 0 }, 0 }) - -/* FIXME */ -#define g_code_buffer_insert_at(buf, a, b) NULL - - - -/* Retrouve une ligne au sein d'un tampon avec une adresse. */ -GBufferLine *g_code_buffer_find_line_by_addr(const GCodeBuffer *, const vmpa2t *, BufferLineFlags, size_t *); - -/* Retrouve une ligne au sein d'un tampon avec un indice. */ -GBufferLine *g_code_buffer_find_line_by_index(const GCodeBuffer *, size_t); - -/* Convertit une adresse en indice de ligne. */ -size_t g_code_buffer_get_index_from_address(const GCodeBuffer *, const vmpa2t *, bool); - -/* Retrouve l'indice associé à une ligne au sein d'un tampon. */ -size_t g_code_buffer_find_index_by_line(const GCodeBuffer *, const GBufferLine *); - -/* Augmente l'indentation des prochaines lignes. */ -void g_code_buffer_inc_indentation(GCodeBuffer *); - -/* Diminue l'indentation des prochaines lignes. */ -void g_code_buffer_dec_indentation(GCodeBuffer *); - -/* Traitement d'une ligne parcourue. */ -typedef bool (* process_line_fc) (GCodeBuffer *, GBufferLine *, void *); - -/* Lance un parcours des différentes lignes du tampon de code. */ -GDelayedWork *g_buffer_code_scan(GCodeBuffer *, const vmpa2t *, const vmpa2t *, const char *, process_line_fc, void *); - - - -/* ------------------------- CONFORTS POUR LES COMMENTAIRES ------------------------- */ - - -/* Séparateur commun à tous les plateformes */ -#define COMMENT_LINE_SEP "\n" - - -/* Affiche un commentaire sur une ligne de tampon donnée. */ -bool g_code_buffer_update_inlined_comment(GCodeBuffer *, GBufferLine *, const char *, GObject *); - -/* Affiche un commentaire sur une ligne de tampon dédiée. */ -bool g_code_buffer_update_comment_area(GCodeBuffer *, GBufferLine *, const char *, bool, GObject *); - -/* Retrouve le créateur d'un commentaire existant. */ -GObject *g_code_buffer_get_comment_creator(const GCodeBuffer *, const GBufferLine *); - -/* Récupère le contenu d'un commentaire existant. */ -char *g_code_buffer_get_lines_comment(const GCodeBuffer *, const GBufferLine *); - -/* Supprime un commentaire existant. */ -bool g_code_buffer_delete_lines_comment(GCodeBuffer *, GBufferLine *); - - - -/* ------------------------- SIGNAUX IMMEDIATS POUR UNE VUE ------------------------- */ - - -/* Accompagne une variation de la quantité de lignes du tampon. */ -typedef void (* buffer_size_changed_cb) (const GCodeBuffer *, bool, size_t, size_t, GObject *); - - -/* Enregistre l'adresse d'une fonction de mise à jour de vue. */ -void g_code_buffer_register_view_callback(GCodeBuffer *, buffer_size_changed_cb, GObject *); - -/* Supprime un élément des vues à contacter pour mises à jour. */ -void g_code_buffer_unregister_view_callback(GCodeBuffer *, GObject *); - - - -#endif /* _GLIBEXT_GCODEBUFFER_H */ diff --git a/src/glibext/generator-int.h b/src/glibext/generator-int.h new file mode 100644 index 0000000..d284d87 --- /dev/null +++ b/src/glibext/generator-int.h @@ -0,0 +1,52 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * generator-int.h - prototypes internes pour la génération de lignes à la volée + * + * Copyright (C) 2016 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 . + */ + + +#ifndef _GLIBEXT_GENERATOR_INT_H +#define _GLIBEXT_GENERATOR_INT_H + + +#include "generator.h" + + + + + +/* Accès à un contenu binaire quelconque (interface) */ +struct _GBinContentIface +{ + GTypeInterface base_iface; /* A laisser en premier */ + + + + + + +}; + + +/* Redéfinition */ +typedef GBinContentIface GBinContentInterface; + + + +#endif /* _GLIBEXT_GENERATOR_INT_H */ diff --git a/src/glibext/generators/Makefile.am b/src/glibext/generators/Makefile.am new file mode 100644 index 0000000..5dd7133 --- /dev/null +++ b/src/glibext/generators/Makefile.am @@ -0,0 +1,15 @@ + +noinst_LTLIBRARIES = libglibextgenerators.la + +libglibextgenerators_la_SOURCES = \ + prologue.h prologue.c \ + rborder.h rborder.c + +libglibextgenerators_la_LDFLAGS = + + +AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) + +AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) + +SUBDIRS = diff --git a/src/glibext/generators/prologue.c b/src/glibext/generators/prologue.c new file mode 100644 index 0000000..7a4fea5 --- /dev/null +++ b/src/glibext/generators/prologue.c @@ -0,0 +1,359 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * prologue.c - génération à la volée de lignes d'introduction + * + * Copyright (C) 2016 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 . + */ + + +#include "prologue.h" + + +#include +#include + + +#include "../gbufferline.h" +#include "../linegen-int.h" +#include "../linesegment.h" + + + +/* Tampon pour générateur de lignes en prologue (instance) */ +struct _GIntroGenerator +{ + GObject parent; /* A laisser en premier */ + + char **text; /* Lignes brutes à représenter */ + size_t count; /* Quantité de ces lignes */ + +}; + +/* Tampon pour générateur de lignes en prologue (classe) */ +struct _GIntroGeneratorClass +{ + GObjectClass parent; /* A laisser en premier */ + +}; + + +/* Procède à l'initialisation d'une classe de générateur. */ +static void g_intro_generator_class_init(GIntroGeneratorClass *); + +/* Procède à l'initialisation d'un générateur de lignes d'intro. */ +static void g_intro_generator_init(GIntroGenerator *); + +/* Procède à l'initialisation de l'interface de génération. */ +static void g_intro_generator_interface_init(GLineGeneratorInterface *); + +/* Supprime toutes les références externes. */ +static void g_intro_generator_dispose(GIntroGenerator *); + +/* Procède à la libération totale de la mémoire. */ +static void g_intro_generator_finalize(GIntroGenerator *); + +/* Indique le nombre de ligne prêtes à être générées. */ +static size_t g_intro_generator_count_lines(const GIntroGenerator *); + +/* Retrouve l'emplacement correspondant à une position donnée. */ +static void g_intro_generator_compute_addr(const GIntroGenerator *, gint, vmpa2t *, size_t, size_t); + +/* Détermine si le conteneur s'inscrit dans une plage donnée. */ +static int g_intro_generator_contains_addr(const GIntroGenerator *, const vmpa2t *, size_t, size_t); + +/* Renseigne sur les propriétés liées à un générateur. */ +static BufferLineFlags g_intro_generator_get_flags(const GIntroGenerator *, size_t, size_t); + +/* Imprime dans une ligne de rendu le contenu représenté. */ +static void g_intro_generator_print(GIntroGenerator *, GBufferLine *, size_t, size_t); + + + +/* Détermine le type du générateur de lignes d'introduction à la volée. */ +G_DEFINE_TYPE_WITH_CODE(GIntroGenerator, g_intro_generator, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE(G_TYPE_LINE_GENERATOR, g_intro_generator_interface_init)); + + +/****************************************************************************** +* * +* Paramètres : class = classe de composant GLib à initialiser. * +* * +* Description : Procède à l'initialisation d'une classe de générateur. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_intro_generator_class_init(GIntroGeneratorClass *class) +{ + GObjectClass *object; /* Autre version de la classe */ + + object = G_OBJECT_CLASS(class); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_intro_generator_dispose; + object->finalize = (GObjectFinalizeFunc)g_intro_generator_finalize; + +} + + +/****************************************************************************** +* * +* Paramètres : generator = composant GLib à initialiser. * +* * +* Description : Procède à l'initialisation d'un générateur de lignes d'intro.* +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_intro_generator_init(GIntroGenerator *generator) +{ + generator->text = NULL; + generator->count = 0; + +} + + +/****************************************************************************** +* * +* Paramètres : iface = interface GLib à initialiser. * +* * +* Description : Procède à l'initialisation de l'interface de génération. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_intro_generator_interface_init(GLineGeneratorInterface *iface) +{ + iface->count = (linegen_count_lines_fc)g_intro_generator_count_lines; + iface->compute = (linegen_compute_fc)g_intro_generator_compute_addr; + iface->contains = (linegen_contains_fc)g_intro_generator_contains_addr; + iface->get_flags = (linegen_get_flags_fc)g_intro_generator_get_flags; + iface->print = (linegen_print_fc)g_intro_generator_print; + +} + + +/****************************************************************************** +* * +* Paramètres : generator = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_intro_generator_dispose(GIntroGenerator *generator) +{ + G_OBJECT_CLASS(g_intro_generator_parent_class)->dispose(G_OBJECT(generator)); + +} + + +/****************************************************************************** +* * +* Paramètres : generator = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_intro_generator_finalize(GIntroGenerator *generator) +{ + size_t i; /* Boucle de parcours */ + + for (i = 0; i < generator->count; i++) + free(generator->text[i]); + + if (generator->text != NULL) + free(generator->text); + + G_OBJECT_CLASS(g_intro_generator_parent_class)->finalize(G_OBJECT(generator)); + +} + + +/****************************************************************************** +* * +* Paramètres : lang = trauducteur pour l'impression finale. * +* text = tableau de lignes à conserver. * +* count = taille du tableau fourni. * +* * +* Description : Crée un nouveau générateur de lignes d'introduction. * +* * +* Retour : Composant GLib créé. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GIntroGenerator *g_intro_generator_new(const GCodingLanguage *lang, char **text, size_t count) +{ + GIntroGenerator *result; /* Composant à retourner */ + + result = g_object_new(G_TYPE_INTRO_GENERATOR, NULL); + + result->text = text; + result->count = count; + + g_coding_language_encapsulate_comments(lang, &result->text, &result->count); + + result->text = (char **)realloc(result->text, ++result->count * sizeof(char *)); + + result->text[result->count - 1] = NULL; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : generator = générateur à consulter. * +* * +* Description : Indique le nombre de ligne prêtes à être générées. * +* * +* Retour : Nombre de lignes devant apparaître au final. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static size_t g_intro_generator_count_lines(const GIntroGenerator *generator) +{ + return generator->count; + +} + + +/****************************************************************************** +* * +* Paramètres : generator = générateur à consulter. * +* x = position géographique sur la ligne concernée. * +* addr = position en mémoire à analyser. * +* index = indice de cette même ligne dans le tampon global.* +* repeat = indice d'utilisations successives du générateur. * +* * +* Description : Retrouve l'emplacement correspondant à une position donnée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_intro_generator_compute_addr(const GIntroGenerator *generator, gint x, vmpa2t *addr, size_t index, size_t repeat) +{ + init_vmpa(addr, 0, 0); + +} + + +/****************************************************************************** +* * +* Paramètres : generator = générateur à consulter. * +* addr = position en mémoire à analyser. * +* index = indice de cette même ligne dans le tampon global.* +* repeat = indice d'utilisations successives du générateur. * +* * +* 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_intro_generator_contains_addr(const GIntroGenerator *generator, const vmpa2t *addr, size_t index, size_t repeat) +{ + /** + * Les lignes générées sont purement artificielles et sans attache. + * Elles n'existent donc pas. + */ + + return 1; + +} + + +/****************************************************************************** +* * +* 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_intro_generator_get_flags(const GIntroGenerator *generator, size_t index, size_t repeat) +{ + return BLF_NONE; + +} + + +/****************************************************************************** +* * +* Paramètres : generator = 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. * +* * +* Description : Imprime dans une ligne de rendu le contenu représenté. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_intro_generator_print(GIntroGenerator *generator, GBufferLine *line, size_t index, size_t repeat) +{ + assert(repeat < generator->count); + + if ((repeat + 1) != generator->count) + { + g_buffer_line_start_merge_at(line, BLC_PHYSICAL); + + g_buffer_line_append_text(line, BLC_PHYSICAL, SL(generator->text[repeat]), RTT_COMMENT, NULL); + + if (repeat == 0) + g_buffer_line_add_flag(line, BLF_WIDTH_MANAGER); + + } + +} diff --git a/src/glibext/generators/prologue.h b/src/glibext/generators/prologue.h new file mode 100644 index 0000000..40cdce3 --- /dev/null +++ b/src/glibext/generators/prologue.h @@ -0,0 +1,58 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * prologue.h - prototypes pour la génération à la volée de lignes d'introduction + * + * Copyright (C) 2016 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 . + */ + + +#ifndef _GLIBEXT_GENERATORS_PROLOGUE_H +#define _GLIBEXT_GENERATORS_PROLOGUE_H + + +#include + + +#include "../../analysis/human/lang.h" + + + +#define G_TYPE_INTRO_GENERATOR (g_intro_generator_get_type()) +#define G_INTRO_GENERATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_CODE_BUFFER, GIntroGenerator)) +#define G_INTRO_GENERATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_CODE_BUFFER, GIntroGeneratorClass)) +#define G_IS_INTRO_GENERATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_CODE_BUFFER)) +#define G_IS_INTRO_GENERATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_CODE_BUFFER)) +#define G_INTRO_GENERATOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_CODE_BUFFER, GIntroGeneratorClass)) + + +/* Tampon pour générateur de lignes en prologue (instance) */ +typedef struct _GIntroGenerator GIntroGenerator; + +/* Tampon pour générateur de lignes en prologue (classe) */ +typedef struct _GIntroGeneratorClass GIntroGeneratorClass; + + +/* Détermine le type du générateur de lignes d'introduction à la volée. */ +GType g_intro_generator_get_type(void); + +/* Crée un nouveau générateur de lignes d'introduction. */ +GIntroGenerator *g_intro_generator_new(const GCodingLanguage *, char **, size_t); + + + +#endif /* _GLIBEXT_GENERATORS_PROLOGUE_H */ diff --git a/src/glibext/generators/rborder.c b/src/glibext/generators/rborder.c new file mode 100644 index 0000000..ff34dfb --- /dev/null +++ b/src/glibext/generators/rborder.c @@ -0,0 +1,361 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * prologue.c - génération à la volée de délimitations de routines + * + * Copyright (C) 2016 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 . + */ + + +#include "rborder.h" + + +#include +#include +#include + + +#include "../gbufferline.h" +#include "../linegen-int.h" +#include "../linesegment.h" + + + +/* Tampon pour générateur de délimitations de routines (instance) */ +struct _GBorderGenerator +{ + GObject parent; /* A laisser en premier */ + + GCodingLanguage *lang; /* Traduction de la sortie */ + + vmpa2t addr; /* Position de la limite */ + bool start; /* Début ou fin de routine ? */ + + MemoryDataSize msize; /* Taille du bus d'adresses */ + +}; + +/* Tampon pour générateur de délimitations de routines (classe) */ +struct _GBorderGeneratorClass +{ + GObjectClass parent; /* A laisser en premier */ + +}; + + +#define ROUTINE_INTRO_MSG "--------------- BEGIN OF PROCEDURE ---------------" + +#define ROUTINE_OUTRO_MSG "---------------- END OF PROCEDURE ----------------" + + +/* Procède à l'initialisation d'une classe de générateur. */ +static void g_border_generator_class_init(GBorderGeneratorClass *); + +/* Procède à l'initialisation d'un générateur de délimitations. */ +static void g_border_generator_init(GBorderGenerator *); + +/* Procède à l'initialisation de l'interface de génération. */ +static void g_border_generator_interface_init(GLineGeneratorInterface *); + +/* Supprime toutes les références externes. */ +static void g_border_generator_dispose(GBorderGenerator *); + +/* Procède à la libération totale de la mémoire. */ +static void g_border_generator_finalize(GBorderGenerator *); + +/* Indique le nombre de ligne prêtes à être générées. */ +static size_t g_border_generator_count_lines(const GBorderGenerator *); + +/* Retrouve l'emplacement correspondant à une position donnée. */ +static void g_border_generator_compute_addr(const GBorderGenerator *, gint, vmpa2t *, size_t, size_t); + +/* Détermine si le conteneur s'inscrit dans une plage donnée. */ +static int g_border_generator_contains_addr(const GBorderGenerator *, const vmpa2t *, size_t, size_t); + +/* Renseigne sur les propriétés liées à un générateur. */ +static BufferLineFlags g_border_generator_get_flags(const GBorderGenerator *, size_t, size_t); + +/* Imprime dans une ligne de rendu le contenu représenté. */ +static void g_border_generator_print(GBorderGenerator *, GBufferLine *, size_t, size_t); + + + +/* Détermine le type du générateur de délimitations de routines à la volée. */ +G_DEFINE_TYPE_WITH_CODE(GBorderGenerator, g_border_generator, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE(G_TYPE_LINE_GENERATOR, g_border_generator_interface_init)); + + +/****************************************************************************** +* * +* Paramètres : class = classe de composant GLib à initialiser. * +* * +* Description : Procède à l'initialisation d'une classe de générateur. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_border_generator_class_init(GBorderGeneratorClass *class) +{ + GObjectClass *object; /* Autre version de la classe */ + + object = G_OBJECT_CLASS(class); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_border_generator_dispose; + object->finalize = (GObjectFinalizeFunc)g_border_generator_finalize; + +} + + +/****************************************************************************** +* * +* Paramètres : generator = composant GLib à initialiser. * +* * +* Description : Procède à l'initialisation d'un générateur de délimitations. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_border_generator_init(GBorderGenerator *generator) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : iface = interface GLib à initialiser. * +* * +* Description : Procède à l'initialisation de l'interface de génération. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_border_generator_interface_init(GLineGeneratorInterface *iface) +{ + iface->count = (linegen_count_lines_fc)g_border_generator_count_lines; + iface->compute = (linegen_compute_fc)g_border_generator_compute_addr; + iface->contains = (linegen_contains_fc)g_border_generator_contains_addr; + iface->get_flags = (linegen_get_flags_fc)g_border_generator_get_flags; + iface->print = (linegen_print_fc)g_border_generator_print; + +} + + +/****************************************************************************** +* * +* Paramètres : generator = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_border_generator_dispose(GBorderGenerator *generator) +{ + g_object_unref(G_OBJECT(generator->lang)); + + G_OBJECT_CLASS(g_border_generator_parent_class)->dispose(G_OBJECT(generator)); + +} + + +/****************************************************************************** +* * +* Paramètres : generator = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_border_generator_finalize(GBorderGenerator *generator) +{ + G_OBJECT_CLASS(g_border_generator_parent_class)->finalize(G_OBJECT(generator)); + +} + + +/****************************************************************************** +* * +* Paramètres : lang = trauducteur pour l'impression finale. * +* addr = position correspondant à la délimitation à marquer. * +* start = indique le type de délimitation observée. * +* msize = taille des adresses représentées. * +* * +* Description : Crée un nouveau générateur de délimitations de routines. * +* * +* Retour : Composant GLib créé. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBorderGenerator *g_border_generator_new(GCodingLanguage *lang, const vmpa2t *addr, bool start, MemoryDataSize msize) +{ + GBorderGenerator *result; /* Composant à retourner */ + + result = g_object_new(G_TYPE_BORDER_GENERATOR, NULL); + + result->lang = lang; + g_object_ref(G_OBJECT(lang)); + + copy_vmpa(&result->addr, addr); + result->start = start; + + result->msize = msize; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : generator = générateur à consulter. * +* * +* Description : Indique le nombre de ligne prêtes à être générées. * +* * +* Retour : Nombre de lignes devant apparaître au final. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static size_t g_border_generator_count_lines(const GBorderGenerator *generator) +{ + return 3; + +} + + +/****************************************************************************** +* * +* Paramètres : generator = générateur à consulter. * +* x = position géographique sur la ligne concernée. * +* addr = position en mémoire à analyser. * +* index = indice de cette même ligne dans le tampon global.* +* repeat = indice d'utilisations successives du générateur. * +* * +* Description : Retrouve l'emplacement correspondant à une position donnée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_border_generator_compute_addr(const GBorderGenerator *generator, gint x, vmpa2t *addr, size_t index, size_t repeat) +{ + copy_vmpa(addr, &generator->addr); + +} + + +/****************************************************************************** +* * +* Paramètres : generator = générateur à consulter. * +* addr = position en mémoire à analyser. * +* index = indice de cette même ligne dans le tampon global.* +* repeat = indice d'utilisations successives du générateur. * +* * +* 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_border_generator_contains_addr(const GBorderGenerator *generator, const vmpa2t *addr, size_t index, size_t repeat) +{ + return cmp_vmpa(addr, &generator->addr); + +} + + +/****************************************************************************** +* * +* 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_border_generator_get_flags(const GBorderGenerator *generator, size_t index, size_t repeat) +{ + return BLF_NONE; + +} + + +/****************************************************************************** +* * +* Paramètres : generator = 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. * +* * +* Description : Imprime dans une ligne de rendu le contenu représenté. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_border_generator_print(GBorderGenerator *generator, GBufferLine *line, size_t index, size_t repeat) +{ + char *text; /* Texte principal à insérer */ + + assert(repeat < 3); + + g_buffer_line_fill_vmpa(line, &generator->addr, generator->msize, generator->msize); + + if (repeat == 1) + { + text = strdup(generator->start ? ROUTINE_INTRO_MSG : ROUTINE_OUTRO_MSG); + g_coding_language_encapsulate_comment(generator->lang, &text); + + g_buffer_line_start_merge_at(line, BLC_ASSEMBLY_HEAD); + g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, SL(text), RTT_COMMENT, NULL); + + free(text); + + } + +} diff --git a/src/glibext/generators/rborder.h b/src/glibext/generators/rborder.h new file mode 100644 index 0000000..fa12734 --- /dev/null +++ b/src/glibext/generators/rborder.h @@ -0,0 +1,60 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * rborder.h - prototypes pour la génération à la volée de délimitations de routines + * + * Copyright (C) 2016 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 . + */ + + +#ifndef _GLIBEXT_GENERATORS_RBORDER_H +#define _GLIBEXT_GENERATORS_RBORDER_H + + +#include +#include + + +#include "../../analysis/human/lang.h" +#include "../../arch/vmpa.h" + + + +#define G_TYPE_BORDER_GENERATOR (g_border_generator_get_type()) +#define G_BORDER_GENERATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_CODE_BUFFER, GBorderGenerator)) +#define G_BORDER_GENERATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_CODE_BUFFER, GBorderGeneratorClass)) +#define G_IS_BORDER_GENERATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_CODE_BUFFER)) +#define G_IS_BORDER_GENERATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_CODE_BUFFER)) +#define G_BORDER_GENERATOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_CODE_BUFFER, GBorderGeneratorClass)) + + +/* Tampon pour générateur de délimitations de routines (instance) */ +typedef struct _GBorderGenerator GBorderGenerator; + +/* Tampon pour générateur de délimitations de routines (classe) */ +typedef struct _GBorderGeneratorClass GBorderGeneratorClass; + + +/* Détermine le type du générateur de délimitations de routines à la volée. */ +GType g_border_generator_get_type(void); + +/* Crée un nouveau générateur de délimitations de routines. */ +GBorderGenerator *g_border_generator_new(GCodingLanguage *, const vmpa2t *, bool, MemoryDataSize); + + + +#endif /* _GLIBEXT_GENERATORS_RBORDER_H */ diff --git a/src/glibext/gwidthtracker.c b/src/glibext/gwidthtracker.c index 3a1863e..cd452bc 100644 --- a/src/glibext/gwidthtracker.c +++ b/src/glibext/gwidthtracker.c @@ -30,7 +30,7 @@ #include -#include "gcodebuffer.h" +#include "gbuffercache.h" @@ -51,7 +51,7 @@ struct _GWidthTracker { GObject parent; /* A laisser en premier */ - GCodeBuffer *buffer; /* Ensemble complet de lignes */ + GBufferCache *cache; /* Ensemble complet de lignes */ common_metrics *portions; /* Portions représentées */ size_t count; /* Quantité de ces portions */ @@ -163,7 +163,7 @@ static void g_width_tracker_init(GWidthTracker *tracker) static void g_width_tracker_dispose(GWidthTracker *tracker) { - g_object_unref(G_OBJECT(tracker->buffer)); + g_object_unref(G_OBJECT(tracker->cache)); G_OBJECT_CLASS(g_width_tracker_parent_class)->dispose(G_OBJECT(tracker)); @@ -203,14 +203,14 @@ static void g_width_tracker_finalize(GWidthTracker *tracker) * * ******************************************************************************/ -GWidthTracker *g_width_tracker_new(GCodeBuffer *buffer) +GWidthTracker *g_width_tracker_new(GBufferCache *cache) { GWidthTracker *result; /* Composant à retourner */ result = g_object_new(G_TYPE_WIDTH_TRACKER, NULL); - g_object_ref(G_OBJECT(buffer)); - result->buffer = buffer; + g_object_ref(G_OBJECT(cache)); + result->cache = cache; return result; @@ -240,8 +240,8 @@ GWidthTracker *g_width_tracker_new_restricted(const GWidthTracker *template, siz result = g_object_new(G_TYPE_WIDTH_TRACKER, NULL); - g_object_ref(G_OBJECT(template->buffer)); - result->buffer = template->buffer; + g_object_ref(G_OBJECT(template->cache)); + result->cache = template->cache; start = g_width_tracker_find_metrics(template, first); assert(start < template->count); @@ -404,7 +404,6 @@ static const line_width_summary *g_width_tracker_get_up_to_date_widths(GWidthTra { common_metrics *portion; /* Portion à actualiser */ size_t i; /* Boucle de parcours */ - GBufferLine *line; /* Ligne à manipuler */ assert(index < tracker->count); @@ -419,12 +418,7 @@ static const line_width_summary *g_width_tracker_get_up_to_date_widths(GWidthTra /* Collecte */ for (i = portion->first; i <= portion->last; i++) - { - line = g_code_buffer_find_line_by_index(tracker->buffer, i); - - g_buffer_line_collect_widths(line, &portion->summary); - - } + g_buffer_cache_collect_widths(tracker->cache, i, &portion->summary); /* Marquage pour mémoire */ @@ -441,6 +435,30 @@ static const line_width_summary *g_width_tracker_get_up_to_date_widths(GWidthTra * * * Paramètres : tracker = gestionnaire de largeurs de lignes à mettre jour. * * index = position de la première des lignes à ajouter. * +* * +* Description : Prend acte d'un changement sur une ligne pour les largeurs. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_width_tracker_update(GWidthTracker *tracker, size_t index) +{ + size_t current; /* Indice de portion visée */ + + current = g_width_tracker_find_metrics(tracker, index); + + g_width_tracker_reset_widths(tracker, current); + +} + + +/****************************************************************************** +* * +* Paramètres : tracker = gestionnaire de largeurs de lignes à mettre jour. * +* index = position de la première des lignes à ajouter. * * count = quantité de lignes devant être ajoutées. * * * * Description : Prend acte de l'ajout de lignes pour les largeurs. * @@ -457,7 +475,6 @@ void g_width_tracker_update_added(GWidthTracker *tracker, size_t index, size_t c common_metrics *portion; /* Portion sélectionnée */ size_t next; /* Prochaine portion à décaller*/ size_t i; /* Boucle de parcours */ - GBufferLine *line; /* Ligne à manipuler */ size_t dest; /* Destination d'une recopie */ size_t src; /* Source d'une recopie */ @@ -502,9 +519,7 @@ void g_width_tracker_update_added(GWidthTracker *tracker, size_t index, size_t c for (i = index + count - 1; i >= index; i--) { - line = g_code_buffer_find_line_by_index(tracker->buffer, i); - - if (g_buffer_line_get_flags(line) & BLF_WIDTH_MANAGER) + if (g_buffer_cache_get_line_flags(tracker->cache, i) & BLF_WIDTH_MANAGER) { /* Insertion d'une nouvelle place */ @@ -602,11 +617,11 @@ void g_width_tracker_update_deleted(GWidthTracker *tracker, size_t start, size_t /* Suppression de portions inutiles ? */ - keep_first = (tracker->portions[first].first > start || end < tracker->portions[first].last); + keep_first = (tracker->portions[first].first < start || end < tracker->portions[first].last); dest = (keep_first ? first + 1 : first); - keep_last = (tracker->portions[last].first > start || end < tracker->portions[last].last); + keep_last = (tracker->portions[last].first < start || end < tracker->portions[last].last); src = (keep_last ? last : last + 1); @@ -647,7 +662,7 @@ void g_width_tracker_update_deleted(GWidthTracker *tracker, size_t start, size_t if (end < tracker->portions[first].last) tracker->portions[first].last -= diff; else - tracker->portions[first].last = start; + tracker->portions[first].last = start - 1; } if (keep_last && last != first) diff --git a/src/glibext/gwidthtracker.h b/src/glibext/gwidthtracker.h index fe22088..b9d22ed 100644 --- a/src/glibext/gwidthtracker.h +++ b/src/glibext/gwidthtracker.h @@ -33,9 +33,8 @@ -/* gcodebuffer.h : Tampon pour code désassemblé (instance) */ -typedef struct _GCodeBuffer GCodeBuffer; - +/* gbuffercache.h : Tampon pour gestion de lignes optimisée (instance) */ +typedef struct _GBufferCache GBufferCache; #define G_TYPE_WIDTH_TRACKER (g_width_tracker_get_type()) @@ -57,11 +56,14 @@ typedef struct _GWidthTrackerClass GWidthTrackerClass; GType g_width_tracker_get_type(void); /* Crée un nouveau suivi de largeurs au sein de lignes. */ -GWidthTracker *g_width_tracker_new(GCodeBuffer *); +GWidthTracker *g_width_tracker_new(GBufferCache *); /* Crée un nouveau suivi de largeurs au sein de lignes. */ GWidthTracker *g_width_tracker_new_restricted(const GWidthTracker *, size_t, size_t); +/* Prend acte d'un changement sur une ligne pour les largeurs. */ +void g_width_tracker_update(GWidthTracker *, size_t); + /* Prend acte de l'ajout de lignes pour les largeurs. */ void g_width_tracker_update_added(GWidthTracker *, size_t, size_t); diff --git a/src/glibext/linecolumn.c b/src/glibext/linecolumn.c index 83413cf..5cce969 100644 --- a/src/glibext/linecolumn.c +++ b/src/glibext/linecolumn.c @@ -389,7 +389,7 @@ line_segment *get_line_column_content_from_index(const line_column *column, size { line_segment *result; /* Trouvaille à retourner */ - assert(index < column->count); + assert(index != -1 && index < column->count); result = column->segments[index]; diff --git a/src/glibext/linegen-int.h b/src/glibext/linegen-int.h new file mode 100644 index 0000000..f43b2f3 --- /dev/null +++ b/src/glibext/linegen-int.h @@ -0,0 +1,67 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * linegen-int.h - définitions internes propres aux intermédiaires de génération de lignes + * + * Copyright (C) 2016 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 . + */ + + +#ifndef _GLIBEXT_LINEGEN_INT_H +#define _GLIBEXT_LINEGEN_INT_H + + +#include "linegen.h" + + + +/* Indique le nombre de ligne prêtes à être générées. */ +typedef size_t (* linegen_count_lines_fc) (const GLineGenerator *); + +/* Retrouve l'emplacement correspondant à une position donnée. */ +typedef void (* linegen_compute_fc) (const GLineGenerator *, gint, vmpa2t *, size_t, size_t); + +/* Détermine si le conteneur s'inscrit dans une plage donnée. */ +typedef int (* linegen_contains_fc) (const GLineGenerator *, const vmpa2t *, size_t, size_t); + +/* Renseigne sur les propriétés liées à un générateur. */ +typedef BufferLineFlags (* linegen_get_flags_fc) (const GLineGenerator *, size_t, size_t); + +/* Imprime dans une ligne de rendu le contenu représenté. */ +typedef void (* linegen_print_fc) (GLineGenerator *, GBufferLine *, size_t, size_t); + + +/* Intermédiaire pour la génération de lignes (interface) */ +struct _GLineGeneratorIface +{ + GTypeInterface base_iface; /* A laisser en premier */ + + linegen_count_lines_fc count; /* Décompte des lignes */ + linegen_compute_fc compute; /* Calcul d'emplacement */ + linegen_contains_fc contains; /* Inclusion de positions */ + linegen_get_flags_fc get_flags; /* Récupération des drapeaux */ + linegen_print_fc print; /* Impression d'une ligne */ + +}; + + +/* Redéfinition */ +typedef GLineGeneratorIface GLineGeneratorInterface; + + + +#endif /* _GLIBEXT_LINEGEN_INT_H */ diff --git a/src/glibext/linegen.c b/src/glibext/linegen.c new file mode 100644 index 0000000..fc0e01e --- /dev/null +++ b/src/glibext/linegen.c @@ -0,0 +1,208 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * linegen.c - intermédiaires de génération de lignes + * + * Copyright (C) 2016 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 . + */ + + +#include "linegen.h" + + +#include + + +#include "linegen-int.h" + + + +/* Procède à l'initialisation de l'interface de génération. */ +static void g_line_generator_default_init(GLineGeneratorInterface *); + + + +/* Détermine le type d'une interface pour la mise en place de lignes. */ +G_DEFINE_INTERFACE(GLineGenerator, g_line_generator, G_TYPE_OBJECT) + + +/****************************************************************************** +* * +* Paramètres : iface = interface GLib à initialiser. * +* * +* Description : Procède à l'initialisation de l'interface de génération. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_line_generator_default_init(GLineGeneratorInterface *iface) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : generator = générateur à consulter. * +* * +* Description : Indique le nombre de ligne prêtes à être générées. * +* * +* Retour : Nombre de lignes devant apparaître au final. * +* * +* Remarques : - * +* * +******************************************************************************/ + +size_t g_line_generator_count_lines(const GLineGenerator *generator) +{ + size_t result; /* Décompte à retourner */ + GLineGeneratorIface *iface; /* Interface utilisée */ + + iface = G_LINE_GENERATOR_GET_IFACE(generator); + + result = iface->count(generator); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : generator = générateur à consulter. * +* x = position géographique sur la ligne concernée. * +* addr = position en mémoire à analyser. * +* index = indice de cette même ligne dans le tampon global.* +* repeat = indice d'utilisations successives du générateur. * +* * +* Description : Retrouve l'emplacement correspondant à une position donnée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_line_generator_compute_addr(const GLineGenerator *generator, gint x, vmpa2t *addr, size_t index, size_t repeat) +{ + GLineGeneratorIface *iface; /* Interface utilisée */ + + iface = G_LINE_GENERATOR_GET_IFACE(generator); + +#ifndef NDEBUG + if (iface->count != NULL) + assert(repeat < g_line_generator_count_lines(generator)); +#endif + + iface->compute(generator, x, addr, index, repeat); + +} + + +/****************************************************************************** +* * +* Paramètres : generator = générateur à consulter. * +* addr = position en mémoire à analyser. * +* index = indice de cette même ligne dans le tampon global.* +* repeat = indice d'utilisations successives du générateur. * +* * +* Description : Détermine si le conteneur s'inscrit dans une plage donnée. * +* * +* Retour : Bilan de la détermination, utilisable en comparaisons. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int g_line_generator_contains_addr(const GLineGenerator *generator, const vmpa2t *addr, size_t index, size_t repeat) +{ + GLineGeneratorIface *iface; /* Interface utilisée */ + + iface = G_LINE_GENERATOR_GET_IFACE(generator); + +#ifndef NDEBUG + if (iface->count != NULL) + assert(repeat < g_line_generator_count_lines(generator)); +#endif + + return iface->contains(generator, addr, index, repeat); + +} + + +/****************************************************************************** +* * +* 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 : - * +* * +******************************************************************************/ + +BufferLineFlags g_line_generator_get_flags(const GLineGenerator *generator, size_t index, size_t repeat) +{ + GLineGeneratorIface *iface; /* Interface utilisée */ + + iface = G_LINE_GENERATOR_GET_IFACE(generator); + +#ifndef NDEBUG + if (iface->count != NULL) + assert(repeat < g_line_generator_count_lines(generator)); +#endif + + return iface->get_flags(generator, index, repeat); + +} + + +/****************************************************************************** +* * +* Paramètres : generator = 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. * +* * +* Description : Imprime dans une ligne de rendu le contenu représenté. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_line_generator_print(GLineGenerator *generator, GBufferLine *line, size_t index, size_t repeat) +{ + GLineGeneratorIface *iface; /* Interface utilisée */ + + iface = G_LINE_GENERATOR_GET_IFACE(generator); + +#ifndef NDEBUG + if (iface->count != NULL) + assert(repeat < g_line_generator_count_lines(generator)); +#endif + + return iface->print(generator, line, index, repeat); + +} diff --git a/src/glibext/linegen.h b/src/glibext/linegen.h new file mode 100644 index 0000000..c64baaa --- /dev/null +++ b/src/glibext/linegen.h @@ -0,0 +1,68 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * linegen.h - prototypes pour les intermédiaires de génération de lignes + * + * Copyright (C) 2016 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 . + */ + + +#ifndef _GLIBEXT_LINEGEN_H +#define _GLIBEXT_LINEGEN_H + + + +#include "gbufferline.h" + + + +#define G_TYPE_LINE_GENERATOR (g_line_generator_get_type()) +#define G_LINE_GENERATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_LINE_GENERATOR, GLineGenerator)) +#define G_LINE_GENERATOR_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST((vtable), G_TYPE_LINE_GENERATOR, GLineGeneratorIface)) +#define GTK_IS_LINE_GENERATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_LINE_GENERATOR)) +#define GTK_IS_LINE_GENERATOR_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE((vtable), G_TYPE_LINE_GENERATOR)) +#define G_LINE_GENERATOR_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), G_TYPE_LINE_GENERATOR, GLineGeneratorIface)) + + +/* Intermédiaire pour la génération de lignes (coquille vide) */ +typedef struct _GLineGenerator GLineGenerator; + +/* Intermédiaire pour la génération de lignes (interface) */ +typedef struct _GLineGeneratorIface GLineGeneratorIface; + + +/* Détermine le type d'une interface pour la mise en place de lignes. */ +GType g_line_generator_get_type(void) G_GNUC_CONST; + +/* Indique le nombre de ligne prêtes à être générées. */ +size_t g_line_generator_count_lines(const GLineGenerator *); + +/* Retrouve l'emplacement correspondant à une position donnée. */ +void g_line_generator_compute_addr(const GLineGenerator *, gint, vmpa2t *, size_t, size_t); + +/* Détermine si le conteneur s'inscrit dans une plage donnée. */ +int g_line_generator_contains_addr(const GLineGenerator *, const vmpa2t *, size_t, size_t); + +/* Renseigne sur les propriétés liées à un générateur. */ +BufferLineFlags g_line_generator_get_flags(const GLineGenerator *, size_t, size_t); + +/* Imprime dans une ligne de rendu le contenu représenté. */ +void g_line_generator_print(GLineGenerator *, GBufferLine *, size_t, size_t); + + + +#endif /* _GLIBEXT_LINEGEN_H */ diff --git a/src/glibext/linesegment.c b/src/glibext/linesegment.c index 8306320..5208db6 100644 --- a/src/glibext/linesegment.c +++ b/src/glibext/linesegment.c @@ -47,7 +47,11 @@ static const char *_segment_names[RTT_COUNT] = { + [RTT_NONE] = SEGMENT_NAME("none"), [RTT_RAW] = SEGMENT_NAME("raw"), + [RTT_RAW_NULL] = SEGMENT_NAME("raw-null"), + [RTT_PRINTABLE] = SEGMENT_NAME("printable"), + [RTT_NOT_PRINTABLE] = SEGMENT_NAME("not-printable"), [RTT_COMMENT] = SEGMENT_NAME("comment"), [RTT_INDICATION] = SEGMENT_NAME("indication"), [RTT_PHYS_ADDR_PAD] = SEGMENT_NAME("phys-addr-padding"), @@ -55,6 +59,7 @@ static const char *_segment_names[RTT_COUNT] = { [RTT_VIRT_ADDR_PAD] = SEGMENT_NAME("virt-addr-padding"), [RTT_VIRT_ADDR] = SEGMENT_NAME("virt-addr"), [RTT_RAW_CODE] = SEGMENT_NAME("raw-code"), + [RTT_RAW_CODE_NULL] = SEGMENT_NAME("raw-code-null"), [RTT_LABEL] = SEGMENT_NAME("label"), [RTT_INSTRUCTION] = SEGMENT_NAME("instruction"), [RTT_IMMEDIATE] = SEGMENT_NAME("immediate"), @@ -162,6 +167,10 @@ struct _segcnt_list }; +/* Indique si le contenu d'un segment est notable ou non. */ +bool selection_list_has_segment_content(const segcnt_list *, const line_segment *); + + /* ---------------------------------------------------------------------------------- */ /* NATURE POUR UN FRAGMENT DE TEXTE */ diff --git a/src/glibext/linesegment.h b/src/glibext/linesegment.h index da43e7e..892dce2 100644 --- a/src/glibext/linesegment.h +++ b/src/glibext/linesegment.h @@ -66,7 +66,12 @@ void exit_segment_content_hash_table(void); /* Types de partie de rendu */ typedef enum _RenderingTagType { + RTT_NONE, /* Espace ou tabulation */ + RTT_RAW, /* Contenu brut */ + RTT_RAW_NULL, /* Contenu brut et nul */ + RTT_PRINTABLE, /* Caractère imprimable */ + RTT_NOT_PRINTABLE, /* Caractère non imprimable */ RTT_COMMENT, /* Commentaire */ RTT_INDICATION, /* Aide à la lecture */ @@ -76,6 +81,7 @@ typedef enum _RenderingTagType RTT_VIRT_ADDR_PAD, /* Adresse virtuelle (début) */ RTT_VIRT_ADDR, /* Adresse virtuelle */ RTT_RAW_CODE, /* Code binaire brut */ + RTT_RAW_CODE_NULL, /* Code binaire brut et nul */ RTT_LABEL, /* Etiquette sur une adresse */ @@ -188,9 +194,6 @@ bool reset_segment_content_list(segcnt_list *); /* Marque le contenu d'un segment comme remarquable. */ bool add_segment_content_to_selection_list(segcnt_list *, const line_segment *); -/* Indique si le contenu d'un segment est notable ou non. */ -bool selection_list_has_segment_content(const segcnt_list *, const line_segment *); - #endif /* _GLIBEXT_LINESEGMENT_H */ diff --git a/src/gtkext/Makefile.am b/src/gtkext/Makefile.am index 45ce4ad..d874ac1 100644 --- a/src/gtkext/Makefile.am +++ b/src/gtkext/Makefile.am @@ -1,21 +1,20 @@ noinst_LTLIBRARIES = libgtkext.la -libgtkext_la_SOURCES = \ - easygtk.h easygtk.c \ - gtkbinarystrip.h gtkbinarystrip.c \ - gtkextstatusbar.h gtkextstatusbar.c \ - gtkblockview.h gtkblockview.c \ - gtkbufferview-int.h \ - gtkbufferview.h gtkbufferview.c \ - gtkdisplaypanel-int.h \ - gtkdisplaypanel.h gtkdisplaypanel.c \ - gtkdockable-int.h \ - gtkdockable.h gtkdockable.c \ - gtkdockstation.h gtkdockstation.c \ - gtkgraphview.h gtkgraphview.c \ - gtksourceview.h gtksourceview.c \ - gtkstatusstack.h gtkstatusstack.c \ +libgtkext_la_SOURCES = \ + easygtk.h easygtk.c \ + gtkbinarystrip.h gtkbinarystrip.c \ + gtkextstatusbar.h gtkextstatusbar.c \ + gtkblockdisplay.h gtkblockdisplay.c \ + gtkbufferdisplay-int.h \ + gtkbufferdisplay.h gtkbufferdisplay.c \ + gtkdisplaypanel-int.h \ + gtkdisplaypanel.h gtkdisplaypanel.c \ + gtkdockable-int.h \ + gtkdockable.h gtkdockable.c \ + gtkdockstation.h gtkdockstation.c \ + gtkgraphdisplay.h gtkgraphdisplay.c \ + gtkstatusstack.h gtkstatusstack.c \ support.h support.c libgtkext_la_LIBADD = \ diff --git a/src/gtkext/graph/cluster.c b/src/gtkext/graph/cluster.c index 06e06c2..558e3cd 100644 --- a/src/gtkext/graph/cluster.c +++ b/src/gtkext/graph/cluster.c @@ -30,8 +30,8 @@ #include -#include "../gtkblockview.h" -#include "../gtkbufferview.h" +#include "../gtkblockdisplay.h" +#include "../gtkbufferdisplay.h" #include "../gtkdisplaypanel.h" #include "../../common/sort.h" @@ -104,7 +104,7 @@ struct _GGraphCluster size_t ta_count; /* Quantité de ces accroches */ GBasicBlock *block; /* Bloc d'origine représenté */ - GtkWidget *view; /* Vue graphique associée */ + GtkWidget *display; /* Vue graphique associée */ GtkAllocation alloc; /* Emplacement final du bloc */ leaving_edge **bottom_anchors; /* Accroches inférieures */ @@ -255,7 +255,7 @@ static void g_graph_cluster_init(GGraphCluster *cluster) static void g_graph_cluster_dispose(GGraphCluster *cluster) { g_object_unref(G_OBJECT(cluster->block)); - g_object_unref(G_OBJECT(cluster->view)); + g_object_unref(G_OBJECT(cluster->display)); G_OBJECT_CLASS(g_graph_cluster_parent_class)->dispose(G_OBJECT(cluster)); @@ -301,7 +301,7 @@ GGraphCluster *g_graph_cluster_new(GLoadedBinary *binary, const GBlockList *list GGraphCluster *result; /* Structure à retourner */ vmpa2t first; /* Début d'un groupe de lignes */ vmpa2t last; /* Fin d'un groupe de lignes */ - GCodeBuffer *buffer; /* Tampon brut à découper */ + GBufferCache *cache; /* Tampon brut à découper */ GBufferView *view; /* Partie affichée du tampon */ GtkRequisition requisition; /* Taille à l'écran actuelle */ @@ -312,26 +312,26 @@ GGraphCluster *g_graph_cluster_new(GLoadedBinary *binary, const GBlockList *list result->block = g_block_list_get_block(list, index); g_object_ref(G_OBJECT(result->block)); - result->view = gtk_block_view_new(); + result->display = gtk_block_display_new(); - gtk_widget_show(result->view); - gtk_display_panel_attach_binary(GTK_DISPLAY_PANEL(result->view), binary, BVW_GRAPH); + gtk_widget_show(result->display); + gtk_display_panel_attach_binary(GTK_DISPLAY_PANEL(result->display), binary, BVW_GRAPH); - gtk_display_panel_show_border(GTK_DISPLAY_PANEL(result->view), true); + gtk_display_panel_show_border(GTK_DISPLAY_PANEL(result->display), true); /* Restriction au bloc basique */ g_basic_block_get_boundary_addresses(result->block, &first, &last); - buffer = g_loaded_binary_get_disassembled_buffer(binary); + cache = g_loaded_binary_get_disassembled_cache(binary); - view = g_buffer_view_new(buffer, highlighted); + view = g_buffer_view_new(cache, highlighted); g_buffer_view_restrict(view, &first, &last); - gtk_buffer_view_attach_buffer(GTK_BUFFER_VIEW(result->view), view); + gtk_buffer_display_set_view(GTK_BUFFER_DISPLAY(result->display), view); /* Détermination d'une position initiale centrée */ - gtk_widget_get_preferred_size(result->view, NULL, &requisition); + gtk_widget_get_preferred_size(result->display, NULL, &requisition); result->alloc.x = -requisition.width / 2; result->alloc.y = 0; @@ -741,7 +741,7 @@ void g_graph_cluster_compute_needed_alloc(const GGraphCluster *cluster, GtkAlloc if (needed.x < alloc->x) { - alloc->width += (alloc->x + needed.x); + alloc->width += (alloc->x - needed.x); alloc->x = needed.x; } @@ -765,7 +765,7 @@ void g_graph_cluster_compute_needed_alloc(const GGraphCluster *cluster, GtkAlloc if (needed.x < alloc->x) { - alloc->width += (alloc->x + needed.x); + alloc->width += (alloc->x - needed.x); alloc->x = needed.x; } @@ -800,7 +800,7 @@ void g_graph_cluster_compute_needed_alloc(const GGraphCluster *cluster, GtkAlloc /****************************************************************************** * * * Paramètres : cluster = encapsulation à traiter. * -* view = support de destination finale. * +* display = support de destination finale. * * * * Description : Dispose chaque noeud sur la surface de destination donnée. * * * @@ -810,23 +810,23 @@ void g_graph_cluster_compute_needed_alloc(const GGraphCluster *cluster, GtkAlloc * * ******************************************************************************/ -void g_graph_cluster_place(GGraphCluster *cluster, GtkGraphView *view) +void g_graph_cluster_place(GGraphCluster *cluster, GtkGraphDisplay *display) { size_t i; /* Boucle de parcours #1 */ size_t j; /* Boucle de parcours #2 */ - g_object_ref(G_OBJECT(cluster->view)); - gtk_graph_view_put(view, cluster->view, &cluster->alloc); + g_object_ref(G_OBJECT(cluster->display)); + gtk_graph_display_put(display, cluster->display, &cluster->alloc); for (i = 0; i < cluster->ta_count; i++) { g_object_ref(G_OBJECT(cluster->top_anchors[i]->edge)); - gtk_graph_view_add_edge(view, cluster->top_anchors[i]->edge); + gtk_graph_display_add_edge(display, cluster->top_anchors[i]->edge); } for (i = 0; i < cluster->ranks_count; i++) for (j = 0; j < cluster->ranks[i].count; j++) - g_graph_cluster_place(cluster->ranks[i].clusters[j], view); + g_graph_cluster_place(cluster->ranks[i].clusters[j], display); } @@ -1671,9 +1671,9 @@ static GGraphCluster *setup_graph_clusters(GLoadedBinary *binary, const GBlockLi /****************************************************************************** * * -* Paramètres : blocks = ensemble des blocs basiques déjà découpés. * -* views = morceaux de code à afficher de façon organisée. * -* count = quantité de ces morceaux de code. * +* Paramètres : blocXXXXXXXXXXXXXXXXXXXXks = ensemble des blocs basiques déjà découpés. * +* views = morceaux de codXXXXXXXXXXXXXXXXXxe à afficher de façon organisée. * +* count = quantité de ces morceaux de code.XXXXXXXXXXXXXXXXXX * * * * Description : Construit un graphique à partir de blocs basiques. * * * diff --git a/src/gtkext/graph/cluster.h b/src/gtkext/graph/cluster.h index d43622b..9c375d3 100644 --- a/src/gtkext/graph/cluster.h +++ b/src/gtkext/graph/cluster.h @@ -26,7 +26,7 @@ -#include "../gtkgraphview.h" +#include "../gtkgraphdisplay.h" #include "../../analysis/binary.h" #include "../../analysis/disass/block.h" @@ -57,7 +57,7 @@ GGraphCluster *g_graph_cluster_new(GLoadedBinary *, const GBlockList *, size_t, void g_graph_cluster_compute_needed_alloc(const GGraphCluster *, GtkAllocation *); /* Dispose chaque noeud sur la surface de destination donnée. */ -void g_graph_cluster_place(GGraphCluster *, GtkGraphView *); +void g_graph_cluster_place(GGraphCluster *, GtkGraphDisplay *); diff --git a/src/gtkext/graph/edge.c b/src/gtkext/graph/edge.c index 561b9f3..27400a6 100644 --- a/src/gtkext/graph/edge.c +++ b/src/gtkext/graph/edge.c @@ -267,6 +267,33 @@ void g_graph_edge_resolve(GGraphEdge *edge) /****************************************************************************** * * +* Paramètres : edge = ligne de rendu à modifier dans ses positions. * +* dx = déplacement à effectuer sur l'axe des abscisses. * +* dy = déplacement à effectuer sur l'axe des ordonnées. * +* * +* Description : Opère un décallage du lien dans une direction donnée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_graph_edge_offset(GGraphEdge *edge, gint dx, gint dy) +{ + size_t i; /* Boucle de parcours */ + + for (i = 0; i < edge->count; i++) + { + edge->points[i].x += dx; + edge->points[i].y += dy; + } + +} + + +/****************************************************************************** +* * * Paramètres : edge = ligne de rendu à manipuler. * * cairo = assistant pour le rendu graphique. * * arrow = indique le besoin en flèche à l'arrivée. * diff --git a/src/gtkext/graph/edge.h b/src/gtkext/graph/edge.h index f60954c..4c43edb 100644 --- a/src/gtkext/graph/edge.h +++ b/src/gtkext/graph/edge.h @@ -81,6 +81,9 @@ void g_graph_edge_get_x_borders(const GGraphEdge *, gint *, gint *); /* Détermine les positions finales d'un lien graphique. */ void g_graph_edge_resolve(GGraphEdge *); +/* Opère un décallage du lien dans une direction donnée. */ +void g_graph_edge_offset(GGraphEdge *, gint, gint); + /* Dessine les liens graphiques enregistrés dans le moteur. */ void g_graph_edge_draw(const GGraphEdge *, cairo_t *, bool); diff --git a/src/gtkext/gtkblockdisplay.c b/src/gtkext/gtkblockdisplay.c new file mode 100644 index 0000000..d53d766 --- /dev/null +++ b/src/gtkext/gtkblockdisplay.c @@ -0,0 +1,337 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * gtkblockdisplay.c - affichage d'un fragment de code d'assemblage + * + * Copyright (C) 2008-2012 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 . + */ + + +#include "gtkblockdisplay.h" + + +#include "gtkbufferdisplay-int.h" + + + +/* Composant d'affichage de bloc d'assembleur (instance) */ +struct _GtkBlockDisplay +{ + GtkBufferDisplay parent; /* A laisser en premier */ + +}; + +/* Composant d'affichage de code d'assembleur (classe) */ +struct _GtkBlockDisplayClass +{ + GtkBufferDisplayClass parent; /* A laisser en premier */ + + /* Signaux */ + + void (* highlight_changed) (GtkBlockDisplay *); + +}; + + +/* Procède à l'initialisation des afficheurs de bloc assembleur. */ +static void gtk_block_display_class_init(GtkBlockDisplayClass *); + +/* Procède à l'initialisation de l'afficheur de bloc assembleur. */ +static void gtk_block_display_init(GtkBlockDisplay *); + +/* Supprime toutes les références externes. */ +static void gtk_block_display_dispose(GtkBlockDisplay *); + +/* Procède à la libération totale de la mémoire. */ +static void gtk_block_display_finalize(GtkBlockDisplay *); + +/* Assure la gestion des clics de souris sur le composant. */ +static gboolean gtk_block_display_button_press(GtkWidget *, GdkEventButton *); + +/* Redessine l'affichage suite à un changement visuel. */ +static gboolean gtk_block_display_need_redraw(GtkBlockDisplay *, GBufferView *); + +/* Prend acte de l'association d'un binaire chargé. */ +static void gtk_block_display_attach_binary(GtkBlockDisplay *, GLoadedBinary *); + +/* Réagit à un déplacement de curseur. */ +static bool gtk_block_display_notify_caret_relocation(GtkBlockDisplay *, const GdkRectangle *, const vmpa2t *); + + + +/* Détermine le type du composant d'affichage de bloc en langage d'assemblage. */ +G_DEFINE_TYPE(GtkBlockDisplay, gtk_block_display, GTK_TYPE_BUFFER_DISPLAY) + + +/****************************************************************************** +* * +* Paramètres : class = classe GTK à initialiser. * +* * +* Description : Procède à l'initialisation des afficheurs de bloc assembleur.* +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_block_display_class_init(GtkBlockDisplayClass *class) +{ + GObjectClass *object; /* Autre version de la classe */ + GtkWidgetClass *widget_class; /* Classe version Widget */ + GtkDisplayPanelClass *panel_class; /* Classe parente */ + GtkBufferDisplayClass *buffer_class; /* Classe supérieure */ + + object = G_OBJECT_CLASS(class); + + object->dispose = (GObjectFinalizeFunc/* ! */)gtk_block_display_dispose; + object->finalize = (GObjectFinalizeFunc)gtk_block_display_finalize; + + widget_class = GTK_WIDGET_CLASS(class); + + widget_class->button_press_event = gtk_block_display_button_press; + + panel_class = GTK_DISPLAY_PANEL_CLASS(class); + + panel_class->attach = (attach_binary_fc)gtk_block_display_attach_binary; + + buffer_class = GTK_BUFFER_DISPLAY_CLASS(class); + + buffer_class->notify_caret = (notify_caret_relocation_fc)gtk_block_display_notify_caret_relocation; + + /* Signaux */ + + g_signal_new("highlight-changed", + GTK_TYPE_BLOCK_DISPLAY, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(GtkBlockDisplayClass, highlight_changed), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + +} + + +/****************************************************************************** +* * +* Paramètres : view = composant GTK à initialiser. * +* * +* Description : Procède à l'initialisation de l'afficheur de bloc assembleur.* +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_block_display_init(GtkBlockDisplay *view) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : display = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_block_display_dispose(GtkBlockDisplay *display) +{ + G_OBJECT_CLASS(gtk_block_display_parent_class)->dispose(G_OBJECT(display)); + +} + + +/****************************************************************************** +* * +* Paramètres : display = instance d'objet Gtk à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_block_display_finalize(GtkBlockDisplay *display) +{ + G_OBJECT_CLASS(gtk_block_display_parent_class)->finalize(G_OBJECT(display)); + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Crée un nouveau composant pour l'affichage de bloc en ASM. * +* * +* Retour : Composant GTK créé. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GtkWidget *gtk_block_display_new(void) +{ + GtkBlockDisplay *result; /* Composant à retourner */ + + result = g_object_new(GTK_TYPE_BLOCK_DISPLAY, NULL); + + return GTK_WIDGET(result); + +} + + +/****************************************************************************** +* * +* Paramètres : widget = composant GTK visé par l'opération. * +* event = informations liées à l'événement. * +* * +* Description : Assure la gestion des clics de souris sur le composant. * +* * +* Retour : FALSE pour poursuivre la propagation de l'événement. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static gboolean gtk_block_display_button_press(GtkWidget *widget, GdkEventButton *event) +{ + GtkBlockDisplay *display; /* Autre version du composant */ + gint real_x; /* Abscisse absolue réelle */ + gint real_y; /* Ordonnée absolue réelle */ + GBufferView *view; /* Vue du tampon représenté */ + bool changed; /* Suivi des changements */ + + GTK_WIDGET_CLASS(gtk_block_display_parent_class)->button_press_event(widget, event); + + display = GTK_BLOCK_DISPLAY(widget); + + if (event->type == GDK_2BUTTON_PRESS) + { + real_x = event->x; + real_y = event->y; + + gtk_display_panel_compute_real_coord(GTK_DISPLAY_PANEL(display), &real_x, &real_y); + + view = gtk_buffer_display_get_view(GTK_BUFFER_DISPLAY(display)); + + changed = g_buffer_view_highlight_segments(view, real_x, real_y, GTK_DISPLAY_PANEL(display)->display); + + g_object_unref(G_OBJECT(view)); + + if (changed) + g_signal_emit_by_name(display, "highlight-changed"); + + } + + return FALSE; + +} + + +/****************************************************************************** +* * +* Paramètres : display = composant GTK d'affichage. * +* view = composant GLib interne. * +* * +* Description : Redessine l'affichage suite à un changement visuel. * +* * +* Retour : FALSE pour poursuivre la propagation de l'événement. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static gboolean gtk_block_display_need_redraw(GtkBlockDisplay *display, GBufferView *view) +{ + gtk_widget_queue_draw(GTK_WIDGET(display)); + + return FALSE; + +} + + +/****************************************************************************** +* * +* Paramètres : display = composant GTK à mettre à jour. * +* binary = binaire associé à intégrer. * +* * +* Description : Prend acte de l'association d'un binaire chargé. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_block_display_attach_binary(GtkBlockDisplay *display, GLoadedBinary *binary) +{ + GBufferCache *cache; /* Tampon par défaut */ + GBufferView *view; /* Vue sur ce même tampon */ + + cache = g_loaded_binary_get_disassembled_cache(binary); + view = g_buffer_view_new(cache, NULL); + + gtk_buffer_display_set_view(GTK_BUFFER_DISPLAY(display), view); + + g_signal_connect_swapped(G_OBJECT(view), "need-redraw", + G_CALLBACK(gtk_block_display_need_redraw), display); + +} + + +/****************************************************************************** +* * +* Paramètres : display = composant GTK à manipuler. * +* area = emplacement pour le dessin d'un curseur. * +* addr = position dans la mémoire représentée du curseur. * +* * +* Description : Réagit à un déplacement de curseur. * +* * +* Retour : true si un changement a été opéré. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool gtk_block_display_notify_caret_relocation(GtkBlockDisplay *display, const GdkRectangle *area, const vmpa2t *addr) +{ + bool result; /* Bilan à retourner */ + GBufferView *view; /* Vue du tampon représenté */ + + view = gtk_buffer_display_get_view(GTK_BUFFER_DISPLAY(display)); + + result = g_buffer_view_highlight_segments(view, area->x, area->y, GTK_DISPLAY_PANEL(display)->display); + + g_object_unref(G_OBJECT(view)); + + if (result) + g_signal_emit_by_name(display, "highlight-changed"); + + return result; + +} diff --git a/src/gtkext/gtkblockdisplay.h b/src/gtkext/gtkblockdisplay.h new file mode 100644 index 0000000..caef762 --- /dev/null +++ b/src/gtkext/gtkblockdisplay.h @@ -0,0 +1,56 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * gtkblockdisplay.h - prototypes pour l'affichage d'un fragment de code d'assemblage + * + * Copyright (C) 2008-2014 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 . + */ + + +#ifndef _GTKEXT_GTKBLOCKDISPLAY_H +#define _GTKEXT_GTKBLOCKDISPLAY_H + + +#include +#include + + + +#define GTK_TYPE_BLOCK_DISPLAY (gtk_block_display_get_type()) +#define GTK_BLOCK_DISPLAY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_BLOCK_DISPLAY, GtkBlockDisplay)) +#define GTK_BLOCK_DISPLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GTK_TYPE_BLOCK_DISPLAY, GtkBlockDisplayClass)) +#define GTK_IS_BLOCK_DISPLAY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_BLOCK_DISPLAY)) +#define GTK_IS_BLOCK_DISPLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GTK_TYPE_BLOCK_DISPLAY)) +#define GTK_BLOCK_DISPLAY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_BLOCK_DISPLAY, GtkBlockDisplayClass)) + + +/* Composant d'affichage de code d'assembleur (instance) */ +typedef struct _GtkBlockDisplay GtkBlockDisplay; + +/* Composant d'affichage de code d'assembleur (classe) */ +typedef struct _GtkBlockDisplayClass GtkBlockDisplayClass; + + +/* Détermine le type du composant d'affichage de bloc en langage d'assemblage. */ +GType gtk_block_display_get_type(void); + +/* Crée un nouveau composant pour l'affichage de bloc en ASM. */ +GtkWidget *gtk_block_display_new(void); + + + +#endif /* _GTKEXT_GTKBLOCKDISPLAY_H */ diff --git a/src/gtkext/gtkblockview.c b/src/gtkext/gtkblockview.c deleted file mode 100644 index 82743b0..0000000 --- a/src/gtkext/gtkblockview.c +++ /dev/null @@ -1,289 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * gtkblockview.c - affichage d'un fragment de code d'assemblage - * - * Copyright (C) 2008-2012 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 . - */ - - -#include "gtkblockview.h" - - -#include "gtkbufferview-int.h" - - - -/* -------------------------- INTERACTION DIRECTE AVEC GTK -------------------------- */ - - -/* Composant d'affichage de bloc d'assembleur (instance) */ -struct _GtkBlockView -{ - GtkBufferView parent; /* A laisser en premier */ - -}; - -/* Composant d'affichage de code d'assembleur (classe) */ -struct _GtkBlockViewClass -{ - GtkBufferViewClass parent; /* A laisser en premier */ - - /* Signaux */ - - void (* highlight_changed) (GtkBlockView *); - -}; - - -/* Procède à l'initialisation des afficheurs de bloc assembleur. */ -static void gtk_block_view_class_init(GtkBlockViewClass *); - -/* Procède à l'initialisation de l'afficheur de bloc assembleur. */ -static void gtk_block_view_init(GtkBlockView *); - -/* Réagit à un déplacement de curseur. */ -static bool gtk_block_view_notify_caret_relocation(GtkBlockView *, const GdkRectangle *, const vmpa2t *); - -/* Assure la gestion des clics de souris sur le composant. */ -static gboolean gtk_block_view_button_press_event(GtkBlockView *, GdkEventButton *, gpointer); - -/* Redessine l'affichage suite à un changement visuel. */ -static gboolean gtk_block_view_need_redraw(GBufferView *, GtkBlockView *); - -/* Prend acte de l'association d'un binaire chargé. */ -static void gtk_block_view_attach_binary(GtkBlockView *, GLoadedBinary *); - - - -/* ---------------------------------------------------------------------------------- */ -/* INTERACTION DIRECTE AVEC GTK */ -/* ---------------------------------------------------------------------------------- */ - - -/* Détermine le type du composant d'affichage de bloc en langage d'assemblage. */ -G_DEFINE_TYPE(GtkBlockView, gtk_block_view, GTK_TYPE_BUFFER_VIEW) - - -/****************************************************************************** -* * -* Paramètres : class = classe GTK à initialiser. * -* * -* Description : Procède à l'initialisation des afficheurs de bloc assembleur.* -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void gtk_block_view_class_init(GtkBlockViewClass *class) -{ - GtkDisplayPanelClass *panel_class; /* Classe parente */ - GtkBufferViewClass *buffer_class; /* Classe supérieure */ - - panel_class = GTK_DISPLAY_PANEL_CLASS(class); - buffer_class = GTK_BUFFER_VIEW_CLASS(class); - - panel_class->attach = (attach_binary_fc)gtk_block_view_attach_binary; - - buffer_class->notify_caret = (notify_caret_relocation_fc)gtk_block_view_notify_caret_relocation; - - g_signal_new("highlight-changed", - GTK_TYPE_BLOCK_VIEW, - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET(GtkBlockViewClass, highlight_changed), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - -} - - -/****************************************************************************** -* * -* Paramètres : view = composant GTK à initialiser. * -* * -* Description : Procède à l'initialisation de l'afficheur de bloc assembleur.* -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void gtk_block_view_init(GtkBlockView *view) -{ - - - /* - g_signal_connect(G_OBJECT(view), "button_press_event", - G_CALLBACK(gtk_block_view_button_press_event), NULL); - */ - - -} - - -/****************************************************************************** -* * -* Paramètres : view = composant GTK à manipuler. * -* area = emplacement pour le dessin d'un curseur. * -* addr = position dans la mémoire représentée du curseur. * -* * -* Description : Réagit à un déplacement de curseur. * -* * -* Retour : true si un changement a été opéré. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool gtk_block_view_notify_caret_relocation(GtkBlockView *view, const GdkRectangle *area, const vmpa2t *addr) -{ - bool result; /* Bilan à retourner */ - - result = g_buffer_view_highlight_segments(GTK_BUFFER_VIEW(view)->buffer_view, area->x, area->y, - GTK_DISPLAY_PANEL(view)->display); - - if (result) - g_signal_emit_by_name(view, "highlight-changed"); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : - * -* * -* Description : Crée un nouveau composant pour l'affichage de bloc en ASM. * -* * -* Retour : Composant GTK créé. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GtkWidget *gtk_block_view_new(void) -{ - GtkBlockView *result; /* Composant à retourner */ - - result = g_object_new(GTK_TYPE_BLOCK_VIEW, NULL); - - return GTK_WIDGET(result); - -} - - -/****************************************************************************** -* * -* Paramètres : view = composant GTK visé par l'opération. * -* event = informations liées à l'événement. * -* data = donnée non utilisée ici. * -* * -* Description : Assure la gestion des clics de souris sur le composant. * -* * -* Retour : FALSE pour poursuivre la propagation de l'événement. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static gboolean gtk_block_view_button_press_event(GtkBlockView *view, GdkEventButton *event, gpointer data) -{ - GtkBufferView *bview; /* Autre vision du composant */ - gint real_x; /* Abscisse absolue réelle */ - gint real_y; /* Ordonnée absolue réelle */ - - if (event->type == GDK_2BUTTON_PRESS) - { - - - - printf("I feel %s clicked with button %d\n", - event->type == GDK_2BUTTON_PRESS ? "double" : "triple", - event->button); - - bview = GTK_BUFFER_VIEW(view); - - real_x = event->x; - real_y = event->y; - - gtk_display_panel_compute_real_coord(GTK_DISPLAY_PANEL(bview), &real_x, &real_y); - - g_buffer_view_highlight_segments(gtk_buffer_view_get_buffer(bview), real_x, real_y, NULL); - - - - } - - return FALSE; - -} - - -/****************************************************************************** -* * -* Paramètres : view = composant GLib interne. * -* block = composant GTK d'affichage. * -* * -* Description : Redessine l'affichage suite à un changement visuel. * -* * -* Retour : FALSE pour poursuivre la propagation de l'événement. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static gboolean gtk_block_view_need_redraw(GBufferView *view, GtkBlockView *block) -{ - gtk_widget_queue_draw(GTK_WIDGET(block)); - - return FALSE; - -} - - -/****************************************************************************** -* * -* Paramètres : view = composant GTK à mettre à jour. * -* binary = binaire associé à intégrer. * -* * -* Description : Prend acte de l'association d'un binaire chargé. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void gtk_block_view_attach_binary(GtkBlockView *view, GLoadedBinary *binary) -{ - GCodeBuffer *buffer; /* Tampon par défaut */ - GBufferView *bview; /* Vue sur ce même tampon */ - - buffer = g_loaded_binary_get_disassembled_buffer(binary); - bview = g_buffer_view_new(buffer, NULL); - - gtk_buffer_view_attach_buffer(GTK_BUFFER_VIEW(view), bview); - - g_signal_connect(G_OBJECT(bview), "need-redraw", - G_CALLBACK(gtk_block_view_need_redraw), view); - -} diff --git a/src/gtkext/gtkblockview.h b/src/gtkext/gtkblockview.h deleted file mode 100644 index 735d128..0000000 --- a/src/gtkext/gtkblockview.h +++ /dev/null @@ -1,56 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * gtkblockview.h - prototypes pour l'affichage d'un fragment de code d'assemblage - * - * Copyright (C) 2008-2014 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 . - */ - - -#ifndef _GTKEXT_GTKBLOCKVIEW_H -#define _GTKEXT_GTKBLOCKVIEW_H - - -#include -#include - - - -#define GTK_TYPE_BLOCK_VIEW (gtk_block_view_get_type()) -#define GTK_BLOCK_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_BLOCK_VIEW, GtkBlockView)) -#define GTK_BLOCK_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GTK_TYPE_BLOCK_VIEW, GtkBlockViewClass)) -#define GTK_IS_BLOCK_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_BLOCK_VIEW)) -#define GTK_IS_BLOCK_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GTK_TYPE_BLOCK_VIEW)) -#define GTK_BLOCK_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_BLOCK_VIEW, GtkBlockViewClass)) - - -/* Composant d'affichage de code d'assembleur (instance) */ -typedef struct _GtkBlockView GtkBlockView; - -/* Composant d'affichage de code d'assembleur (classe) */ -typedef struct _GtkBlockViewClass GtkBlockViewClass; - - -/* Détermine le type du composant d'affichage de bloc en langage d'assemblage. */ -GType gtk_block_view_get_type(void); - -/* Crée un nouveau composant pour l'affichage de bloc en ASM. */ -GtkWidget *gtk_block_view_new(void); - - - -#endif /* _GTKEXT_GTKBLOCKVIEW_H */ diff --git a/src/gtkext/gtkbufferdisplay-int.h b/src/gtkext/gtkbufferdisplay-int.h new file mode 100644 index 0000000..4406361 --- /dev/null +++ b/src/gtkext/gtkbufferdisplay-int.h @@ -0,0 +1,68 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * gtkbufferdisplay-int.h - prototypes internes pour l'affichage de tampons de lignes + * + * Copyright (C) 2016 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 . + */ + + +#ifndef _GTK_BUFFERDISPLAY_INT_H +#define _GTK_BUFFERDISPLAY_INT_H + + +#include "gtkbufferdisplay.h" + + +#include "gtkdisplaypanel-int.h" + + + +/* Réagit à un déplacement de curseur. */ +typedef bool (* notify_caret_relocation_fc) (GtkBufferDisplay *, const GdkRectangle *, const vmpa2t *); + + +/* Composant d'affichage de tampon de lignes (instance) */ +struct _GtkBufferDisplay +{ + GtkDisplayPanel parent; /* A laisser en premier */ + + GBufferView *view; /* Vue sur le contenu affiché */ + + GdkRectangle caret; /* Emplacement du curseur */ + vmpa2t caret_addr; /* Position mémoire du curseur */ + guint caret_timer; /* Identifiant du chronomètre */ + bool show_caret; /* Bascule entre les affichages*/ + +}; + +/* Composant d'affichage de tampon de lignes (classe) */ +struct _GtkBufferDisplayClass +{ + GtkDisplayPanelClass parent; /* A laisser en premier */ + + notify_caret_relocation_fc notify_caret;/* Accompagne un déplacement */ + + /* Signaux */ + + void (* reach_limit) (GtkBufferDisplay *, GdkScrollDirection); + +}; + + + +#endif /* _GTK_BUFFERDISPLAY_INT_H */ diff --git a/src/gtkext/gtkbufferdisplay.c b/src/gtkext/gtkbufferdisplay.c new file mode 100644 index 0000000..b510c8f --- /dev/null +++ b/src/gtkext/gtkbufferdisplay.c @@ -0,0 +1,1104 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * gtkbufferdisplay.c - affichage de tampons de lignes + * + * Copyright (C) 2016 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 . + */ + + +#include "gtkbufferdisplay.h" + + +#include "gtkbufferdisplay-int.h" + + +#include "../core/params.h" + + + +/* -------------------------- INTERACTION DIRECTE AVEC GTK -------------------------- */ + + +/* Procède à l'initialisation de l'afficheur de tampons. */ +static void gtk_buffer_display_class_init(GtkBufferDisplayClass *); + +/* Procède à l'initialisation de l'afficheur de tampons. */ +static void gtk_buffer_display_init(GtkBufferDisplay *); + +/* Supprime toutes les références externes. */ +static void gtk_buffer_display_dispose(GtkBufferDisplay *); + +/* Procède à la libération totale de la mémoire. */ +static void gtk_buffer_display_finalize(GtkBufferDisplay *); + +/* Intègre le focus dans le rendu du composant. */ +static gboolean gtk_buffer_display_focus(GtkWidget *, GdkEventFocus *); + +/* Assure la gestion des clics de souris sur le composant. */ +static gboolean gtk_buffer_display_button_press(GtkWidget *, GdkEventButton *); + +/* Met à jour l'affichage de la visualisation de code buffer. */ +static gboolean gtk_buffer_display_draw(GtkWidget *, cairo_t *); + +/* Prend en compte une frappe de touche sur le composant. */ +static gboolean gtk_buffer_display_key_press(GtkWidget *, GdkEventKey *); + +/* Indique les dimensions de travail du composant d'affichage. */ +static void gtk_buffer_display_compute_requested_size(GtkBufferDisplay *, gint *, gint *); + +/* Détermine la taille des bonds lors de défilements. */ +static void gtk_buffer_display_compute_scroll_inc(GtkBufferDisplay *, gint, GtkOrientation, gdouble *, gdouble *); + +/* Réagit à un défilement chez une barre associée au composant. */ +static void gtk_buffer_display_adjust_scroll_value(GtkBufferDisplay *, GtkAdjustment *, GtkOrientation); + +/* Indique la position courante du curseur. */ +static const vmpa2t *gtk_buffer_display_get_caret_location(const GtkBufferDisplay *); + +/* Indique la position d'affichage d'une adresse donnée. */ +static bool gtk_buffer_display_get_address_coordinates(const GtkBufferDisplay *, const vmpa2t *, gint *, gint *, ScrollPositionTweak); + +/* Place en cache un rendu destiné à l'aperçu graphique rapide. */ +static void gtk_buffer_display_cache_glance(GtkBufferDisplay *, cairo_t *, const GtkAllocation *, double); + + + +/* ------------------------------ ANIMATION DU CURSEUR ------------------------------ */ + + +/* Déplace le curseur à un emplacement défini. */ +static bool _gtk_buffer_display_move_caret_to(GtkBufferDisplay *, gint, gint); + +/* Déplace le curseur en effaçant son éventuelle position. */ +static void gtk_buffer_display_relocate_caret(GtkBufferDisplay *, const GdkRectangle *, const vmpa2t *); + +/* Redémarre l'affichage du curseur à l'emplacement courant. */ +static void gtk_buffer_display_restart_caret_blinking(GtkBufferDisplay *); + +/* Bascule et relance l'affichage du curseur. */ +static gboolean gtk_buffer_display_refresh_caret(GtkBufferDisplay *); + + + +/* ---------------------------------------------------------------------------------- */ +/* INTERACTION DIRECTE AVEC GTK */ +/* ---------------------------------------------------------------------------------- */ + + +/* Détermine le type du composant d'affichage de tampon de lignes. */ +G_DEFINE_TYPE(GtkBufferDisplay, gtk_buffer_display, GTK_TYPE_DISPLAY_PANEL) + + +/****************************************************************************** +* * +* Paramètres : class = classe GTK à initialiser. * +* * +* Description : Procède à l'initialisation de l'afficheur de tampons. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_buffer_display_class_init(GtkBufferDisplayClass *class) +{ + GObjectClass *object; /* Autre version de la classe */ + GtkWidgetClass *widget_class; /* Classe version Widget */ + GtkDisplayPanelClass *panel_class; /* Classe parente */ + + object = G_OBJECT_CLASS(class); + + object->dispose = (GObjectFinalizeFunc/* ! */)gtk_buffer_display_dispose; + object->finalize = (GObjectFinalizeFunc)gtk_buffer_display_finalize; + + widget_class = GTK_WIDGET_CLASS(class); + + widget_class->focus_in_event = gtk_buffer_display_focus; + widget_class->focus_out_event = gtk_buffer_display_focus; + widget_class->button_press_event = gtk_buffer_display_button_press; + widget_class->draw = gtk_buffer_display_draw; + widget_class->key_press_event = gtk_buffer_display_key_press; + + panel_class = GTK_DISPLAY_PANEL_CLASS(class); + + panel_class->compute_size = (compute_requested_size_fc)gtk_buffer_display_compute_requested_size; + panel_class->compute_inc = (compute_scroll_inc_fc)gtk_buffer_display_compute_scroll_inc; + panel_class->adjust = (adjust_scroll_value_fc)gtk_buffer_display_adjust_scroll_value; + panel_class->get_caret_loc = (get_caret_location_fc)gtk_buffer_display_get_caret_location; + panel_class->get_coordinates = (get_addr_coordinates_fc)gtk_buffer_display_get_address_coordinates; + panel_class->move_caret_to = (move_caret_to_fc)_gtk_buffer_display_move_caret_to; + panel_class->cache_glance = (cache_glance_fc)gtk_buffer_display_cache_glance; + + /* Signaux */ + + g_signal_new("reach-limit", + GTK_TYPE_BUFFER_DISPLAY, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(GtkBufferDisplayClass, reach_limit), + NULL, NULL, + g_cclosure_marshal_VOID__ENUM, + G_TYPE_NONE, 1, GTK_TYPE_SCROLL_TYPE); + +} + + +/****************************************************************************** +* * +* Paramètres : display = composant GTK à initialiser. * +* * +* Description : Procède à l'initialisation de l'afficheur de tampons. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_buffer_display_init(GtkBufferDisplay *display) +{ + init_vmpa(&display->caret_addr, VMPA_NO_PHYSICAL, VMPA_NO_VIRTUAL); + +} + + +/****************************************************************************** +* * +* Paramètres : display = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_buffer_display_dispose(GtkBufferDisplay *display) +{ + if (display->view != NULL) + g_object_unref(G_OBJECT(display->view)); + + G_OBJECT_CLASS(gtk_buffer_display_parent_class)->dispose(G_OBJECT(display)); + +} + + +/****************************************************************************** +* * +* Paramètres : display = instance d'objet Gtk à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_buffer_display_finalize(GtkBufferDisplay *display) +{ + G_OBJECT_CLASS(gtk_buffer_display_parent_class)->finalize(G_OBJECT(display)); + +} + + +/****************************************************************************** +* * +* Paramètres : widget = composant GTK visé par l'opération. * +* event = informations liées à l'événement. * +* * +* Description : Intègre le focus dans le rendu du composant. * +* * +* Retour : FALSE pour poursuivre la propagation de l'événement. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static gboolean gtk_buffer_display_focus(GtkWidget *widget, GdkEventFocus *event) +{ + GtkBufferDisplay *display; /* Autre version du composant */ + gboolean has_focus; /* Etat courant */ + + display = GTK_BUFFER_DISPLAY(widget); + has_focus = event->in; + + if (has_focus) + gtk_buffer_display_restart_caret_blinking(display); + + else if (display->caret_timer != 0) + { + g_source_remove(display->caret_timer); + display->caret_timer = 0; + + display->show_caret = true; + gtk_buffer_display_refresh_caret(display); + + } + + return TRUE; + +} + + +/****************************************************************************** +* * +* Paramètres : widget = composant GTK visé par l'opération. * +* event = informations liées à l'événement. * +* * +* Description : Assure la gestion des clics de souris sur le composant. * +* * +* Retour : FALSE pour poursuivre la propagation de l'événement. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static gboolean gtk_buffer_display_button_press(GtkWidget *widget, GdkEventButton *event) +{ + GtkBufferDisplay *display; /* Autre version du composant */ + GBufferCache *cache; /* Contenu représenté */ + gint left_margin; /* Limite entre zones réactives*/ + gint real_x; /* Abscisse absolue réelle */ + gint real_y; /* Ordonnée absolue réelle */ + + display = GTK_BUFFER_DISPLAY(widget); + + real_x = event->x; + real_y = event->y; + gtk_display_panel_compute_real_coord(GTK_DISPLAY_PANEL(display), &real_x, &real_y); + + cache = g_buffer_view_get_cache(display->view); + + left_margin = g_buffer_cache_get_left_margin(cache); + + g_object_unref(G_OBJECT(cache)); + + if (real_x < left_margin) + { + /* TODO */ + } + else + _gtk_buffer_display_move_caret_to(display, real_x, real_y); + + gtk_widget_grab_focus(widget); + + return FALSE; + +} + + +/****************************************************************************** +* * +* Paramètres : widget = composant GTK à redessiner. * +* cr = contexte graphique associé à l'événement. * +* * +* Description : Met à jour l'affichage de la visualisation de code buffer. * +* * +* Retour : FALSE pour poursuivre la propagation de l'événement. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static gboolean gtk_buffer_display_draw(GtkWidget *widget, cairo_t *cr) +{ + GtkBufferDisplay *display; /* Autre version du composant */ + GtkDisplayPanel *parent; /* Autre version du composant */ + GdkWindow *window; /* Fenêtre à redessiner */ + cairo_region_t *region; /* Région visible à redessiner */ + cairo_rectangle_int_t area; /* Surface correspondante */ + GtkStyleContext *context; /* Contexte du thème actuel */ + gint virt_x; /* Abscisse virtuelle */ + gint virt_y; /* Ordonnée virtuelle */ + GBufferCache *cache; /* Contenu représenté */ + gint left_margin; /* Marge gauche + espace */ + GdkRGBA color; /* Couleur de thème récupérée */ + bool sel_line; /* Souslignage de la sélection */ + gint *selected; /* Ordonnée d'une sélection */ + + + //gboolean status; + + + GtkStyleContext *other; + GtkWidgetPath *path; + + + other = gtk_style_context_new(); + + + path = gtk_widget_path_new (); + gtk_widget_path_append_type (path, GTK_TYPE_SCALE); + //gtk_widget_path_iter_add_class (path, 0, "slider"); + //gtk_widget_path_iter_add_class (path, 0, "scale"); + gtk_style_context_set_path (other, path); + gtk_widget_path_free (path); + + + + + //context = gtk_widget_get_style_context(widget); + + + //gtk_render_background(context, cr, 0, 0, 1000, 1000); + + + //status = GTK_WIDGET_CLASS(gtk_buffer_display_parent_class)->draw(widget, cr); + + //printf("status: %d\n", status); + + //return TRUE; + + + + + display = GTK_BUFFER_DISPLAY(widget); + parent = GTK_DISPLAY_PANEL(widget); + + window = gtk_widget_get_window(widget); + + cairo_save(cr); + gtk_cairo_transform_to_window(cr, widget, window); + + region = gdk_window_get_clip_region(window); + cairo_region_get_extents(region, &area); + cairo_region_destroy(region); + + context = gtk_widget_get_style_context(widget); + + if (parent->show_border) + { + gtk_display_panel_define_border_path(parent, cr, 0, 0); + cairo_clip(cr); + } + + + + gtk_render_background(context, cr, area.x, area.y, area.width, area.height); + + + + /* Décallage pour le défilement horizontal */ + + virt_x = 0; + virt_y = 0; + gtk_display_panel_compute_fake_coord(parent, &virt_x, &virt_y); + + cairo_save(cr); + + cairo_translate(cr, virt_x, 0); + + /* Récupération de la limite utile */ + + cache = g_buffer_view_get_cache(display->view); + + left_margin = g_buffer_cache_get_left_margin(cache); + + g_object_unref(G_OBJECT(cache)); + + + /* Dessin de la marge gauche */ + + gtk_style_context_save(context); + + gtk_style_context_add_class(other, GTK_STYLE_CLASS_TOOLBAR); + + gtk_style_context_get_background_color(other, GTK_STATE_FLAG_ACTIVE, &color); + + cairo_set_source_rgba(cr, color.red, color.green, color.blue, color.alpha); + //cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 1.0); + + cairo_rectangle(cr, 0, area.y, left_margin, area.height); + cairo_fill(cr); + + gtk_style_context_restore(context); + + /* Fond de la zone de texte */ + +#if 1 + gtk_style_context_save(context); + + gtk_style_context_add_class(context, GTK_STYLE_CLASS_VIEW); + + gtk_style_context_get_background_color(context, GTK_STATE_FLAG_ACTIVE, &color); + + cairo_set_source_rgba(cr, color.red, color.green, color.blue, color.alpha * 0.7); + + cairo_rectangle(cr, left_margin, area.y, area.width, area.height); + cairo_fill(cr); + + gtk_style_context_restore(context); +#endif + + /* Ligne de séparation */ + + gtk_style_context_save(context); + + gtk_style_context_add_class(context, GTK_STYLE_CLASS_FRAME); + + gtk_style_context_get_border_color(context, GTK_STATE_FLAG_ACTIVE, &color); + + cairo_set_source_rgba(cr, color.red, color.green, color.blue, color.alpha); + + cairo_set_line_width(cr, 1.0); + + cairo_move_to(cr, left_margin + 0.5, area.y - 0.5); + cairo_line_to(cr, left_margin + 0.5, area.y + area.height + 0.5); + cairo_stroke(cr); + + gtk_style_context_restore(context); + + /* Eventuelle bordure globale */ + + if (parent->show_border) + gtk_display_panel_draw_border(parent, cr); + + /* Impression du désassemblage */ + + if (display->view != NULL) + { + g_generic_config_get_value(get_main_configuration(), MPK_SELECTION_LINE, &sel_line); + sel_line &= gtk_widget_has_focus(widget); + + if (!sel_line || is_invalid_vmpa(&display->caret_addr)) + selected = NULL; + else + { + selected = (gint []) { display->caret.y }; + gtk_display_panel_compute_relative_coords(parent, NULL, selected); + } + + area.x -= virt_x; + virt_y += area.y; + + g_buffer_view_draw(display->view, cr, virt_y, &area, parent->display, selected); + + } + + cairo_restore(cr); + + /* Curseur clignotant ? */ + + /* + if (gtk_widget_is_focus(widget)) + { + view->show_caret = !view->show_caret; + gtk_buffer_view_refresh_caret(view); + } + */ + + cairo_restore(cr); + + return TRUE; + +} + + +/****************************************************************************** +* * +* Paramètres : widget = composant visé par l'opération. * +* event = informations liées à l'événement. * +* * +* Description : Prend en compte une frappe de touche sur le composant. * +* * +* Retour : FALSE pour poursuivre la propagation de l'événement. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static gboolean gtk_buffer_display_key_press(GtkWidget *widget, GdkEventKey *event) +{ + gboolean result; /* Suites à renvoyer */ + GdkScrollDirection dir; /* Direction du déplacement */ + GtkBufferDisplay *display; /* Autre version du composant */ + GtkDisplayPanel *panel; /* Autre version du composant */ + bool ctrl; /* Statut de la touche Contrôle*/ + GdkRectangle area; /* Emplacement de curseur */ + vmpa2t addr; /* Adresse du nouveau curseur */ + bool status; /* Validité d'un déplacement */ + + switch (event->keyval) + { + case GDK_KEY_Left: + dir = GDK_SCROLL_LEFT; + result = TRUE; + break; + + case GDK_KEY_Up: + dir = GDK_SCROLL_UP; + result = TRUE; + break; + + case GDK_KEY_Right: + dir = GDK_SCROLL_RIGHT; + result = TRUE; + break; + + case GDK_KEY_Down: + dir = GDK_SCROLL_DOWN; + result = TRUE; + break; + + default: + result = FALSE; + break; + + } + + if (result) + { + display = GTK_BUFFER_DISPLAY(widget); + panel = GTK_DISPLAY_PANEL(widget); + + ctrl = (event->state & GDK_CONTROL_MASK); + area = display->caret; + + status = g_buffer_view_move_caret(display->view, ctrl, dir, panel->display, &area, &addr); + + if (status) + { + gtk_buffer_display_relocate_caret(display, &area, &addr); + _gtk_display_panel_scroll_to_address(panel, &addr, SPT_RAW, false); + } + else + g_signal_emit_by_name(display, "reach-limit", dir); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : display = composant GTK à consulter. * +* width = largeur requise à renseigner ou NULL. [OUT] * +* height = hauteur requise à renseigner ou NULL. [OUT] * +* * +* Description : Indique les dimensions de travail du composant d'affichage. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_buffer_display_compute_requested_size(GtkBufferDisplay *display, gint *width, gint *height) +{ + if (width != NULL) + { + if (display->view != NULL) + *width = g_buffer_view_get_width(display->view, GTK_DISPLAY_PANEL(display)->display); + else + *width = 0; + } + + if (height != NULL) + { + if (display->view != NULL) + *height = g_buffer_view_get_height(display->view); + else + *height = 0; + } + +} + + +/****************************************************************************** +* * +* Paramètres : display = composant GTK d'affichage à consulter. * +* size = taille de l'espace dans la direction donnée. * +* orientation = indication sur le défilement à traiter. * +* step = valeur d'un petit pas de défilement. [OUT] * +* page = valeur d'un grand pas de défilement. [OUT] * +* * +* Description : Détermine la taille des bonds lors de défilements. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_buffer_display_compute_scroll_inc(GtkBufferDisplay *display, gint size, GtkOrientation orientation, gdouble *step, gdouble *page) +{ + GBufferCache *cache; /* Gestionnaire de lignes */ + + if (orientation == GTK_ORIENTATION_VERTICAL && display->view != NULL) + { + cache = g_buffer_view_get_cache(display->view); + + *step = g_buffer_cache_get_line_height(cache); + *page = *step * 10; + + g_object_unref(G_OBJECT(cache)); + + } + + else + GTK_DISPLAY_PANEL_CLASS(gtk_buffer_display_parent_class)->compute_inc(GTK_DISPLAY_PANEL(display), + size, orientation, step, page); + +} + + +/****************************************************************************** +* * +* Paramètres : display = panneau d'affichage concerné. * +* adj = défilement dont une valeur a changé. * +* orientation = indication sur le défilement à traiter. * +* * +* Description : Réagit à un défilement chez une barre associée au composant. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_buffer_display_adjust_scroll_value(GtkBufferDisplay *display, GtkAdjustment *adj, GtkOrientation orientation) +{ + GtkWidget *widget; /* Autre vision du composant */ + + widget = GTK_WIDGET(display); + + if (gtk_widget_get_realized(widget)) + gdk_window_invalidate_rect(gtk_widget_get_window(widget), NULL, FALSE); + +} + + +/****************************************************************************** +* * +* Paramètres : display = composant GTK à manipuler. * +* * +* Description : Indique la position courante du curseur. * +* * +* Retour : Emplacement courant du curseur ou NULL si aucun. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static const vmpa2t *gtk_buffer_display_get_caret_location(const GtkBufferDisplay *display) +{ + return &display->caret_addr; + +} + + +/****************************************************************************** +* * +* Paramètres : display = composant GTK à consulter. * +* addr = adresse à présenter à l'écran. * +* x = position horizontale au sein du composant. [OUT] * +* y = position verticale au sein du composant. [OUT] * +* tweak = adaptation finale à effectuer. * +* * +* Description : Indique la position d'affichage d'une adresse donnée. * +* * +* Retour : true si l'adresse fait partie du composant, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool gtk_buffer_display_get_address_coordinates(const GtkBufferDisplay *display, const vmpa2t *addr, gint *x, gint *y, ScrollPositionTweak tweak) +{ + bool result; /* Bilan à remonter */ + bool need_code; /* Recherche plus raffinée */ + GBufferCache *cache; /* Gestionnaire de lignes */ + int height; /* Hauteur allouée */ + + need_code = (tweak == SPT_BOTTOM); + + cache = g_buffer_view_get_cache(display->view); + + result = g_buffer_view_get_address_coordinates(display->view, addr, need_code, x, y); + + if (result) + { + *x += g_buffer_view_get_margin(display->view, GTK_DISPLAY_PANEL(display)->display); + + height = gtk_widget_get_allocated_height(GTK_WIDGET(display)); + + switch (tweak) + { + case SPT_RAW: + break; + + case SPT_TOP: + break; + + case SPT_CENTER: + *y -= (height / 2); + break; + + case SPT_BOTTOM: + *y -= height; + *y += g_buffer_cache_get_line_height(cache); + break; + + } + + } + + g_object_unref(G_OBJECT(cache)); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : display = composant GTK à manipuler. * +* cairo = assistant pour la création de rendus. * +* area = taille de la surface réduite à disposition. * +* scale = échelle vis à vis de la taille réelle. * +* * +* Description : Place en cache un rendu destiné à l'aperçu graphique rapide. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_buffer_display_cache_glance(GtkBufferDisplay *display, cairo_t *cairo, const GtkAllocation *area, double scale) +{ + cairo_set_line_width(cairo, 1); + cairo_set_source_rgb(cairo, 0.4, 0.4, 0.4); + + cairo_rectangle(cairo, area->x + 0.5, area->y + 0.5, area->width - 1, area->height - 1); + + cairo_stroke(cairo); + +} + + +/****************************************************************************** +* * +* Paramètres : display = instance d'objet Gtk à actualiser. * +* view = nouvelle vue à associer au composant. * +* * +* Description : Lie une vue au composant d'affichage de tampon. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void gtk_buffer_display_set_view(GtkBufferDisplay *display, GBufferView *view) +{ + if (display->view != NULL) + g_object_unref(G_OBJECT(display->view)); + + display->view = view; + +} + + +/****************************************************************************** +* * +* Paramètres : display = composant GTK à consulter. * +* * +* Description : Fournit la vue associée au tampon de lignes courant. * +* * +* Retour : Vue mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBufferView *gtk_buffer_display_get_view(const GtkBufferDisplay *display) +{ + GBufferView *result; /* Instance à retourner */ + + result = display->view; + + g_object_ref(G_OBJECT(result)); + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* ANIMATION DU CURSEUR */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : display = composant GTK à manipuler. * +* x = abscisse proposée pour le nouvel emplacement. * +* y = ordonnée proposée pour le nouvel emplacement. * +* * +* Description : Déplace le curseur à un emplacement défini. * +* * +* Retour : true si un traitement a été effectué, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool _gtk_buffer_display_move_caret_to(GtkBufferDisplay *display, gint x, gint y) +{ + bool result; /* Bilan à retourner */ + GtkDisplayPanel *panel; /* Autre version du composant */ + vmpa2t addr; /* Position mémoire associée */ + GdkRectangle new; /* Nouvel emplacement calculé */ + + panel = GTK_DISPLAY_PANEL(display); + + result = g_buffer_view_compute_caret_full(display->view, x, y, panel->display, &new, &addr); + + if (result) + gtk_buffer_display_relocate_caret(display, &new, &addr); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : display = composant GTK à manipuler. * +* beginning = précise le coin où se retrouvera le curseur. * +* same_x = tente de conserver une même abscisse ou NULL ? * +* * +* Description : Déplace le curseur à un emplacement en extrémité. * +* * +* Retour : true si un traitement a été effectué, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool gtk_buffer_display_move_caret_to(GtkBufferDisplay *display, bool beginning, gint *same_x) +{ + bool result; /* Bilan à remonter */ + GBufferCache *cache; /* Contenu représenté */ + gint left_margin; /* Limite entre zones réactives*/ + gint x; /* Abscisse d'emplacement */ + gint y; /* Ordonnée d'emplacement */ + + if (beginning) + { + cache = g_buffer_view_get_cache(display->view); + + left_margin = g_buffer_cache_get_left_margin(cache); + + g_object_unref(G_OBJECT(cache)); + + x = same_x != NULL ? *same_x : left_margin * 2; + y = 0; + + } + else + { + if (same_x != NULL) + x = *same_x; + else + gtk_widget_get_preferred_width(GTK_WIDGET(display), NULL, &x); + + gtk_widget_get_preferred_height(GTK_WIDGET(display), NULL, &y); + y--; + + } + + result = _gtk_buffer_display_move_caret_to(display, x, y); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : display = composant GTK à manipuler. * +* area = emplacement pour le dessin d'un curseur. * +* addr = position dans la mémoire représentée du curseur. * +* * +* Description : Déplace le curseur en effaçant son éventuelle position. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_buffer_display_relocate_caret(GtkBufferDisplay *display, const GdkRectangle *area, const vmpa2t *addr) +{ + bool clear_old; /* Effacement chirurgical */ + GdkRectangle old_area; /* Mémorisation de l'ancien */ + bool need_redraw; /* Besoin de rafraîchissement ?*/ + + if (!is_invalid_vmpa(&display->caret_addr)) + { + clear_old = true; + old_area = display->caret; + } + else + clear_old = false; + + display->caret = *area; + copy_vmpa(&display->caret_addr, addr); + + if (GTK_BUFFER_DISPLAY_GET_CLASS(display)->notify_caret != NULL) + need_redraw = GTK_BUFFER_DISPLAY_GET_CLASS(display)->notify_caret(display, area, addr); + else + need_redraw = false; + + if (need_redraw) + gtk_widget_queue_draw(GTK_WIDGET(display)); + + else if (clear_old) + { + gtk_display_panel_compute_relative_coords(GTK_DISPLAY_PANEL(display), &old_area.x, &old_area.y); + + gtk_widget_queue_draw_area(GTK_WIDGET(display), old_area.x, old_area.y, + old_area.width, old_area.height); + + } + + gtk_buffer_display_restart_caret_blinking(display); + +} + + +/****************************************************************************** +* * +* Paramètres : display = composant GTK à manipuler. * +* * +* Description : Redémarre l'affichage du curseur à l'emplacement courant. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_buffer_display_restart_caret_blinking(GtkBufferDisplay *display) +{ + + GtkSettings *settings; /* Propriétés du système */ + guint interval; /* Fréquence d'actualisation */ + + if (display->caret_timer != 0) + { + g_source_remove(display->caret_timer); + display->caret_timer = 0; + } + + if (!is_invalid_vmpa(&display->caret_addr)) + { + display->show_caret = false; + gtk_buffer_display_refresh_caret(display); + + settings = gtk_settings_get_default(); + + g_object_get(settings, "gtk-cursor-blink-time", &interval, NULL); + + g_object_ref(G_OBJECT(display)); + + display->caret_timer = g_timeout_add_full(G_PRIORITY_DEFAULT, interval, + (GSourceFunc)gtk_buffer_display_refresh_caret, + display, g_object_unref); + + } + + g_signal_emit_by_name(display, "caret-moved", &display->caret_addr); + +} + + +/****************************************************************************** +* * +* Paramètres : display = composant GTK à manipuler. * +* * +* Description : Bascule et relance l'affichage du curseur. * +* * +* Retour : TRUE pour poursuivre les basculements automatiques. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static gboolean gtk_buffer_display_refresh_caret(GtkBufferDisplay *display) +{ + GtkWidget *widget; /* Autre version du composant */ + GdkWindow *window; /* Fenêtre de support associée */ + GdkRectangle area; /* Région adaptée à traiter */ + cairo_t *cr; /* Contexte graphique */ + GdkRGBA *color; /* Couleur du curseur */ + + widget = GTK_WIDGET(display); + window = gtk_widget_get_window(widget); + + /** + * Si le composant n'est pas encore réalisé (ou caché, en cas de + * basculement entre les types de vues), gdk_cairo_create() ne va + * pas apprécier l'argument NULL. Donc on écourte l'opération. + */ + if (window == NULL) + { + display->show_caret = !display->show_caret; + return TRUE; + } + + area = display->caret; + gtk_display_panel_compute_relative_coords(GTK_DISPLAY_PANEL(display), &area.x, &area.y); + + /* Réinitialisation de la surface */ + if (display->show_caret) + { + display->show_caret = false; + gtk_widget_queue_draw_area(widget, area.x, area.y, area.width, area.height); + } + + /* Dessin */ + else + { + display->show_caret = true; + + cr = gdk_cairo_create(gtk_widget_get_window(widget)); + + gtk_style_context_get(gtk_widget_get_style_context(widget), + gtk_widget_get_state_flags(widget), + GTK_STYLE_PROPERTY_COLOR, &color, NULL); + + cairo_set_source_rgb(cr, color->red, color->green, color->blue); + + cairo_rectangle(cr, area.x, area.y, area.width, area.height); + cairo_fill(cr); + + cairo_destroy(cr); + + } + + return TRUE; + +} diff --git a/src/gtkext/gtkbufferdisplay.h b/src/gtkext/gtkbufferdisplay.h new file mode 100644 index 0000000..ea06b94 --- /dev/null +++ b/src/gtkext/gtkbufferdisplay.h @@ -0,0 +1,70 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * gtkbufferdisplay.h - prototypes pour l'affichage de tampons de lignes + * + * Copyright (C) 2016 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 . + */ + + +#ifndef _GTKEXT_GTKBUFFER_DISPLAY_H +#define _GTKEXT_GTKBUFFER_DISPLAY_H + + +#include +#include + + +#include "../glibext/gbufferview.h" + + + +#define GTK_TYPE_BUFFER_DISPLAY (gtk_buffer_display_get_type()) +#define GTK_BUFFER_DISPLAY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_BUFFER_DISPLAY, GtkBufferDisplay)) +#define GTK_BUFFER_DISPLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GTK_TYPE_BUFFER_DISPLAY, GtkBufferDisplayClass)) +#define GTK_IS_BUFFER_DISPLAY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_BUFFER_DISPLAY)) +#define GTK_IS_BUFFER_DISPLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GTK_TYPE_BUFFER_DISPLAY)) +#define GTK_BUFFER_DISPLAY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_BUFFER_VIEW, GtkBufferDisplayClass)) + + +/* Composant d'affichage de tampon de lignes (instance) */ +typedef struct _GtkBufferDisplay GtkBufferDisplay; + +/* Composant d'affichage de tampon de lignes (classe) */ +typedef struct _GtkBufferDisplayClass GtkBufferDisplayClass; + + +/* Détermine le type du composant d'affichage de tampon de lignes. */ +GType gtk_buffer_display_get_type(void); + +/* Lie une vue au composant d'affichage de tampon. */ +void gtk_buffer_display_set_view(GtkBufferDisplay *, GBufferView *); + +/* Fournit la vue associée au tampon de lignes courant. */ +GBufferView *gtk_buffer_display_get_view(const GtkBufferDisplay *); + + + +/* ------------------------------ ANIMATION DU CURSEUR ------------------------------ */ + + +/* Déplace le curseur à un emplacement en extrémité. */ +bool gtk_buffer_display_move_caret_to(GtkBufferDisplay *, bool, gint *); + + + +#endif /* _GTKEXT_GTKBUFFER_DISPLAY_H */ diff --git a/src/gtkext/gtkbufferview-int.h b/src/gtkext/gtkbufferview-int.h deleted file mode 100644 index a7da69d..0000000 --- a/src/gtkext/gtkbufferview-int.h +++ /dev/null @@ -1,73 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * gtkbufferview.h - prototypes pour l'affichage de tampons de lignes - * - * Copyright (C) 2010-2013 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 . - */ - - -#ifndef _GTK_BUFFERVIEW_INT_H -#define _GTK_BUFFERVIEW_INT_H - - -#include "gtkbufferview.h" - - -#include "gtkdisplaypanel-int.h" - - - -/* Réagit à un déplacement de curseur. */ -typedef bool (* notify_caret_relocation_fc) (GtkBufferView *, const GdkRectangle *, const vmpa2t *); - - -/* Composant d'affichage de tampon de lignes (instance) */ -struct _GtkBufferView -{ - GtkDisplayPanel parent; /* A laisser en premier */ - - //GCodeBuffer *buffer; /* Code sous forme de texte */ - GBufferView *buffer_view; /* Affichage de cette forme */ - - gint line_height; /* Hauteur maximale des lignes */ - gint left_margin; /* Marge gauche + espace */ - gint left_text; /* Début d'impression du code */ - - GdkRectangle caret; /* Emplacement du curseur */ - const vmpa2t *caret_addr; /* Position mémoire du curseur */ /* FIXME : REMME */ - guint caret_timer; /* Identifiant du chronomètre */ - bool show_caret; /* Bascule entre les affichages*/ - -}; - -/* Composant d'affichage de tampon de lignes (classe) */ -struct _GtkBufferViewClass -{ - GtkDisplayPanelClass parent; /* A laisser en premier */ - - notify_caret_relocation_fc notify_caret;/* Accompagne un déplacement */ - - /* Signaux */ - - void (* reach_limit) (GtkBufferView *, GdkScrollDirection); - -}; - - - -#endif /* _GTK_BUFFERVIEW_INT_H */ diff --git a/src/gtkext/gtkbufferview.c b/src/gtkext/gtkbufferview.c deleted file mode 100644 index bafb15d..0000000 --- a/src/gtkext/gtkbufferview.c +++ /dev/null @@ -1,1243 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * gtkbufferview.c - affichage de tampons de lignes - * - * Copyright (C) 2010-2014 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 . - */ - - -#include "gtkbufferview-int.h" - - -#include - - -#include "../arch/target.h" -#include "../common/extstr.h" -#include "../core/params.h" -#include "../glibext/chrysamarshal.h" - - - -/* -------------------------- INTERACTION DIRECTE AVEC GTK -------------------------- */ - - -/* Procède à l'initialisation de l'afficheur de tampons. */ -static void gtk_buffer_view_class_init(GtkBufferViewClass *); - -/* Procède à l'initialisation de l'afficheur de tampons. */ -static void gtk_buffer_view_init(GtkBufferView *); - -/* Supprime toutes les références externes. */ -static void gtk_buffer_view_dispose(GtkBufferView *); - -/* Procède à la libération totale de la mémoire. */ -static void gtk_buffer_view_finalize(GtkBufferView *); - -/* Intègre le focus dans le rendu du composant. */ -static gboolean gtk_buffer_view_focus(GtkWidget *, GdkEventFocus *); - -/* Assure la gestion des clics de souris sur le composant. */ -static gboolean gtk_buffer_view_button_press(GtkWidget *, GdkEventButton *); - -/* Met à jour l'affichage de la visualisation de code buffer. */ -static gboolean gtk_buffer_view_draw(GtkWidget *, cairo_t *); - -/* Prend en compte une frappe de touche sur le composant. */ -static gboolean gtk_buffer_view_key_press(GtkWidget *, GdkEventKey *); - -/* Prépare l'affichage d'une astuce. */ -static gboolean gtk_buffer_view_query_tooltip(GtkWidget *, gint, gint, gboolean, GtkTooltip *); - -/* Indique les dimensions de travail du composant d'affichage. */ -static void gtk_buffer_view_compute_requested_size(GtkBufferView *, gint *, gint *); - -/* Détermine la taille des bonds lors de défilements. */ -static void gtk_buffer_view_compute_scroll_inc(GtkBufferView *, gint, GtkOrientation, gdouble *, gdouble *); - -/* Réagit à un défilement chez une barre associée au composant. */ -static void gtk_buffer_view_adjust_scroll_value(GtkBufferView *, GtkAdjustment *, GtkOrientation); - -/* Indique la position courante du curseur. */ -static const vmpa2t *gtk_buffer_view_get_caret_location(const GtkBufferView *); - -/* Indique la position d'affichage d'une adresse donnée. */ -static bool gtk_buffer_view_get_address_coordinates(const GtkBufferView *, const vmpa2t *, gint *, gint *, ScrollPositionTweak); - -/* Fournit des éléments liés à la position courante dans la vue. */ -static bool gtk_buffer_view_get_position(const GtkBufferView *, GBufferLine **, GObject **); - -/* Place en cache un rendu destiné à l'aperçu graphique rapide. */ -static void gtk_buffer_view_cache_glance(GtkBufferView *, cairo_t *, const GtkAllocation *, double); - - - -/* ------------------------------ ANIMATION DU CURSEUR ------------------------------ */ - - -/* Déplace le curseur à un emplacement défini. */ -static bool _gtk_buffer_view_move_caret_to(GtkBufferView *, gint, gint); - -/* Déplace le curseur en effaçant son éventuelle position. */ -static void gtk_buffer_view_relocate_caret(GtkBufferView *, const GdkRectangle *, const vmpa2t *); - -/* Redémarre l'affichage du curseur à l'emplacement courant. */ -static void restart_caret_blinking(GtkBufferView *); - -/* Bascule et relance l'affichage du curseur. */ -static gboolean gtk_buffer_view_refresh_caret(GtkBufferView *); - - - -/* ---------------------------------------------------------------------------------- */ -/* INTERACTION DIRECTE AVEC GTK */ -/* ---------------------------------------------------------------------------------- */ - - -/* Détermine le type du composant d'affichage de tampon de lignes. */ -G_DEFINE_TYPE(GtkBufferView, gtk_buffer_view, GTK_TYPE_DISPLAY_PANEL) - - -/****************************************************************************** -* * -* Paramètres : class = classe GTK à initialiser. * -* * -* Description : Procède à l'initialisation de l'afficheur de tampons. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void gtk_buffer_view_class_init(GtkBufferViewClass *class) -{ - GObjectClass *object; /* Autre version de la classe */ - GtkWidgetClass *widget_class; /* Classe version Widget */ - GtkDisplayPanelClass *panel_class; /* Classe parente */ - - object = G_OBJECT_CLASS(class); - widget_class = GTK_WIDGET_CLASS(class); - panel_class = GTK_DISPLAY_PANEL_CLASS(class); - - object->dispose = (GObjectFinalizeFunc/* ! */)gtk_buffer_view_dispose; - object->finalize = (GObjectFinalizeFunc)gtk_buffer_view_finalize; - - widget_class->focus_in_event = gtk_buffer_view_focus; - widget_class->focus_out_event = gtk_buffer_view_focus; - widget_class->button_press_event = gtk_buffer_view_button_press; - widget_class->draw = gtk_buffer_view_draw; - widget_class->key_press_event = gtk_buffer_view_key_press; - widget_class->query_tooltip = gtk_buffer_view_query_tooltip; - - panel_class->compute_size = (compute_requested_size_fc)gtk_buffer_view_compute_requested_size; - panel_class->compute_inc = (compute_scroll_inc_fc)gtk_buffer_view_compute_scroll_inc; - panel_class->adjust = (adjust_scroll_value_fc)gtk_buffer_view_adjust_scroll_value; - - panel_class->get_caret_loc = (get_caret_location_fc)gtk_buffer_view_get_caret_location; - panel_class->get_coordinates = (get_addr_coordinates_fc)gtk_buffer_view_get_address_coordinates; - panel_class->get_position = (get_view_position_fc)gtk_buffer_view_get_position; - panel_class->move_caret_to = (move_caret_to_fc)_gtk_buffer_view_move_caret_to; - panel_class->cache_glance = (cache_glance_fc)gtk_buffer_view_cache_glance; - - g_signal_new("reach-limit", - GTK_TYPE_BUFFER_VIEW, - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET(GtkBufferViewClass, reach_limit), - NULL, NULL, - g_cclosure_marshal_VOID__ENUM, - G_TYPE_NONE, 1, GTK_TYPE_SCROLL_TYPE); - -} - - -/****************************************************************************** -* * -* Paramètres : view = composant GTK à initialiser. * -* * -* Description : Procède à l'initialisation de l'afficheur de tampons. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void gtk_buffer_view_init(GtkBufferView *view) -{ - GObject *object; /* Autre version de l'instance */ - - object = G_OBJECT(view); - - g_object_set(object, "has-tooltip", TRUE, NULL); - - view->caret.x = 10; - view->caret.y = 10; - view->caret.width = 100; - view->caret.height = 100; - -} - - -/****************************************************************************** -* * -* Paramètres : view = instance d'objet GLib à traiter. * -* * -* Description : Supprime toutes les références externes. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void gtk_buffer_view_dispose(GtkBufferView *view) -{ - G_OBJECT_CLASS(gtk_buffer_view_parent_class)->dispose(G_OBJECT(view)); - -} - - -/****************************************************************************** -* * -* Paramètres : view = instance d'objet GLib à traiter. * -* * -* Description : Procède à la libération totale de la mémoire. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void gtk_buffer_view_finalize(GtkBufferView *view) -{ - G_OBJECT_CLASS(gtk_buffer_view_parent_class)->finalize(G_OBJECT(view)); - -} - - -/****************************************************************************** -* * -* Paramètres : widget = composant GTK visé par l'opération. * -* event = informations liées à l'événement. * -* * -* Description : Intègre le focus dans le rendu du composant. * -* * -* Retour : FALSE pour poursuivre la propagation de l'événement. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static gboolean gtk_buffer_view_focus(GtkWidget *widget, GdkEventFocus *event) -{ - GtkBufferView *view; /* Autre version du composant */ - gboolean has_focus; /* Etat courant */ - - view = GTK_BUFFER_VIEW(widget); - has_focus = event->in; - - if (has_focus) - restart_caret_blinking(view); - - else if (view->caret_timer != 0) - { - g_source_remove(view->caret_timer); - view->caret_timer = 0; - - view->show_caret = true; - gtk_buffer_view_refresh_caret(view); - - } - - return TRUE; - -} - - -/****************************************************************************** -* * -* Paramètres : widget = composant GTK visé par l'opération. * -* event = informations liées à l'événement. * -* * -* Description : Assure la gestion des clics de souris sur le composant. * -* * -* Retour : FALSE pour poursuivre la propagation de l'événement. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static gboolean gtk_buffer_view_button_press(GtkWidget *widget, GdkEventButton *event) -{ - GtkBufferView *view; /* Autre version du composant */ - gint real_x; /* Abscisse absolue réelle */ - gint real_y; /* Ordonnée absolue réelle */ - GBufferLine *line; /* Ligne à la position courante*/ - - view = GTK_BUFFER_VIEW(widget); - - real_x = event->x; - real_y = event->y; - gtk_display_panel_compute_real_coord(GTK_DISPLAY_PANEL(view), &real_x, &real_y); - - printf(" !mouse! :: (%g ; %g) -> (%d ; %d)\n", - event->x, event->y, - real_x, real_y); - - - if (real_x < view->left_margin) - { - line = g_buffer_view_find_line_at(view->buffer_view, real_y, NULL); - if (line == NULL) return FALSE; - - /* TODO */ - printf("Border Line :: %p\n", line); - - } - else - _gtk_buffer_view_move_caret_to(view, real_x, real_y); - - gtk_widget_grab_focus(widget); - - return FALSE; - -} - - -/****************************************************************************** -* * -* Paramètres : widget = composant GTK à redessiner. * -* cr = contexte graphique associé à l'événement. * -* * -* Description : Met à jour l'affichage de la visualisation de code buffer. * -* * -* Retour : FALSE pour poursuivre la propagation de l'événement. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static gboolean gtk_buffer_view_draw(GtkWidget *widget, cairo_t *cr) -{ - GtkBufferView *view; /* Autre version du composant */ - GtkDisplayPanel *panel; /* Autre version du composant */ - GdkWindow *window; /* Fenêtre à redessiner */ - cairo_region_t *region; /* Région visible à redessiner */ - cairo_rectangle_int_t area; /* Surface correspondante */ - GtkStyleContext *context; /* Contexte du thème actuel */ - GdkRGBA color; /* Couleur de thème récupérée */ - gint fake_x; /* Abscisse virtuelle */ - gint fake_y; /* Ordonnée virtuelle */ - bool sel_line; /* Souslignage de la sélection */ - gint *selected; /* Ordonnée d'une sélection */ - - view = GTK_BUFFER_VIEW(widget); - panel = GTK_DISPLAY_PANEL(widget); - - window = gtk_widget_get_window(widget); - - cairo_save(cr); - gtk_cairo_transform_to_window(cr, widget, window); - - region = gdk_window_get_clip_region(window); - cairo_region_get_extents(region, &area); - cairo_region_destroy(region); - - context = gtk_widget_get_style_context(widget); - - if (panel->show_border) - { - gtk_display_panel_define_border_path(panel, cr, 0, 0); - cairo_clip(cr); - } - - /* Dessin de la marge gauche */ - - gtk_style_context_save(context); - - gtk_style_context_add_class(context, GTK_STYLE_CLASS_TOOLBAR); - - gtk_style_context_get_background_color(context, GTK_STATE_FLAG_ACTIVE, &color); - - cairo_set_source_rgba(cr, color.red, color.green, color.blue, color.alpha); - - cairo_rectangle(cr, 0, area.y, view->left_margin, area.height); - cairo_fill(cr); - - gtk_style_context_restore(context); - - /* Fond de la zone de texte */ - - gtk_style_context_save(context); - - gtk_style_context_add_class(context, GTK_STYLE_CLASS_VIEW); - - gtk_style_context_get_background_color(context, GTK_STATE_FLAG_ACTIVE, &color); - - cairo_set_source_rgba(cr, color.red, color.green, color.blue, color.alpha * 0.7); - - cairo_rectangle(cr, view->left_margin, area.y, area.width, area.height); - cairo_fill(cr); - - gtk_style_context_restore(context); - - /* Ligne de séparation */ - - gtk_style_context_save(context); - - gtk_style_context_add_class(context, GTK_STYLE_CLASS_FRAME); - - gtk_style_context_get_border_color(context, GTK_STATE_FLAG_ACTIVE, &color); - - cairo_set_source_rgba(cr, color.red, color.green, color.blue, color.alpha); - - cairo_set_line_width(cr, 1.0); - - cairo_move_to(cr, view->left_margin + 0.5, area.y - 0.5); - cairo_line_to(cr, view->left_margin + 0.5, area.y + area.height + 0.5); - cairo_stroke(cr); - - gtk_style_context_restore(context); - - /* Eventuelle bordure globale */ - - if (panel->show_border) - gtk_display_panel_draw_border(panel, cr); - - /* Impression du désassemblage */ - - if (view->buffer_view != NULL) - { - fake_x = 0; - fake_y = 0; - gtk_display_panel_compute_fake_coord(GTK_DISPLAY_PANEL(view), &fake_x, &fake_y); - - g_generic_config_get_value(get_main_configuration(), MPK_SELECTION_LINE, &sel_line); - sel_line &= gtk_widget_has_focus(widget); - - if (!sel_line || view->caret_addr == NULL) - selected = NULL; - else - selected = &view->caret.y; - - g_buffer_view_draw(view->buffer_view, cr, fake_x, fake_y, &area, panel->display, selected); - - } - - /* Curseur clignotant ? */ - - if (gtk_widget_is_focus(widget)) - { - view->show_caret = !view->show_caret; - gtk_buffer_view_refresh_caret(view); - } - - cairo_restore(cr); - - return TRUE; - -} - - -/****************************************************************************** -* * -* Paramètres : widget = composant visé par l'opération. * -* event = informations liées à l'événement. * -* * -* Description : Prend en compte une frappe de touche sur le composant. * -* * -* Retour : FALSE pour poursuivre la propagation de l'événement. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static gboolean gtk_buffer_view_key_press(GtkWidget *widget, GdkEventKey *event) -{ - gboolean result; /* Suites à renvoyer */ - GtkBufferView *view; /* Autre version du composant */ - GtkDisplayPanel *panel; /* Autre version du composant */ - bool ctrl; /* Statut de la touche Contrôle*/ - GdkScrollDirection dir; /* Direction du déplacement */ - GdkRectangle area; /* Emplacement de curseur */ - const vmpa2t *addr; /* Adresse du nouveau curseur */ - - result = FALSE; - - view = GTK_BUFFER_VIEW(widget); - panel = GTK_DISPLAY_PANEL(widget); - - switch (event->keyval) - { - case GDK_KEY_Left: - dir = GDK_SCROLL_LEFT; - result = TRUE; - break; - - case GDK_KEY_Up: - dir = GDK_SCROLL_UP; - result = TRUE; - break; - - case GDK_KEY_Right: - dir = GDK_SCROLL_RIGHT; - result = TRUE; - break; - - case GDK_KEY_Down: - dir = GDK_SCROLL_DOWN; - result = TRUE; - break; - - default: - break; - - } - - if (result) - { - area = view->caret; - ctrl = (event->state & GDK_CONTROL_MASK); - - addr = g_buffer_view_move_caret(view->buffer_view, &area, ctrl, dir, panel->display); - - if (addr != NULL) - { - gtk_buffer_view_relocate_caret(view, &area, addr); - _gtk_display_panel_scroll_to_address(panel, addr, SPT_RAW, false); - } - else - g_signal_emit_by_name(view, "reach-limit", dir); - - - - //if (addr == NULL) return FALSE; - - - - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : widget = composant GTK visé par l'opération. * -* x = abscisse de la position du message. * -* y = ordonnée de la position du message. * -* keyboard = indique une demande suite à obtiention du focus. * -* tooltip = astuce à compléter. [OUT] * -* * -* Description : Prépare l'affichage d'une astuce. * -* * -* Retour : TRUE pour un affichage validé, FALSE sinon. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static gboolean gtk_buffer_view_query_tooltip(GtkWidget *widget, gint x, gint y, gboolean keyboard, GtkTooltip *tooltip) -{ - gboolean result; /* Bilan à retourner */ - GBinFormat *format; /* Format du fichier binaire */ - GtkBufferView *view; /* Autre version du composant */ - gint real_x; /* Abscisse absolue réelle */ - gint real_y; /* Ordonnée absolue réelle */ - GBufferLine *line; /* Ligne en cours de survol */ - GObject *creator; /* Créateur à l'orgine du seg. */ - virt_t virt; /* Adresse virtuelle */ - vmpa2t addr; /* Adresse de destination */ - GBinSymbol *target_sym; /* Symbole présent à l'adresse */ - GBinSymbol *next_sym; /* Symbole suivant l'adresse */ - GCodeBuffer *buffer; /* Tampon où lire les lignes */ - const vmpa2t *stop_addr; /* Adresse associée, pour fin */ - const mrange_t *lrange; /* Couverture d'une ligne */ - size_t count; /* Nbre de lignes max à traiter*/ - char *markup; /* Description à construire */ - size_t i; /* Boucle de parcours */ - size_t index; /* Indice d'une ligne imprimée */ - char *text; /* Contenu à ajouter */ - - if (keyboard) return FALSE; - - result = FALSE; - - format = NULL; - - view = GTK_BUFFER_VIEW(widget); - - /* Récupération de la destination pointée */ - - real_x = x; - real_y = y; - gtk_display_panel_compute_real_coord(GTK_DISPLAY_PANEL(view), &real_x, &real_y); - - line = g_buffer_view_find_line_and_creator_at(view->buffer_view, - &real_x, real_y, NULL, - GTK_DISPLAY_PANEL(view)->display, &creator); - - if (line == NULL || creator == NULL) goto no_tooltip; - - /** - * On fait le pari de reposer uniquement sur des adresses virtuelles ! - * A changer dans un futur ? - */ - - virt = VMPA_NO_VIRTUAL; - - if (G_IS_TARGET_OPERAND(creator)) - virt = g_target_operand_get_addr(G_TARGET_OPERAND(creator)); - - else if (G_IS_IMM_OPERAND(creator)) - { - if (!g_imm_operand_to_virt_t(G_IMM_OPERAND(creator), &virt)) - virt = VMPA_NO_VIRTUAL; - } - - if (virt == VMPA_NO_VIRTUAL) goto no_tooltip; - - init_vmpa(&addr, VMPA_NO_PHYSICAL, virt); - - /* Construction du contenu textuel */ - - format = G_BIN_FORMAT(g_loaded_binary_get_format(GTK_DISPLAY_PANEL(view)->binary)); - - if (!g_binary_format_find_symbol_at(format, &addr, &target_sym)) - goto no_tooltip; - - g_object_unref(G_OBJECT(target_sym)); - - /* Construction du contenu textuel */ - - /** - * Dans le cas des vues de blocs basiques, il est impératif - * de chercher les lignes dans le tampon global, et non uniquement dans - * celui propre au bloc basique courant. - */ - - buffer = g_loaded_binary_get_disassembled_buffer(GTK_DISPLAY_PANEL(view)->binary); - - if (g_binary_format_find_next_symbol_at(format, &addr, &next_sym)) - stop_addr = get_mrange_addr(g_binary_symbol_get_range(next_sym)); - else - stop_addr = NULL; /* Pour GCC */ - - g_generic_config_get_value(get_main_configuration(), MPK_TOOLTIP_SIZE, &count); - - markup = NULL; - - for (i = 0, line = g_code_buffer_find_line_by_addr(buffer, &addr, BLF_NONE, &index); - i < count && line != NULL; - i++, line = g_code_buffer_find_line_by_index(buffer, index + i)) - { - /* Si on commence à marcher sur les plates-bandes du symbole suivant... */ - if (next_sym != NULL) - { - lrange = g_buffer_line_get_range(line); - - if (mrange_contains_addr(lrange, stop_addr)) - break; - - } - - text = g_buffer_line_get_text(line, BLC_ASSEMBLY_HEAD, BLC_COUNT, true); - - if (markup != NULL) - markup = stradd(markup, "\n"); - - if (text != NULL) - markup = stradd(markup, text); - - free(text); - - } - - if (next_sym != NULL) - g_object_unref(G_OBJECT(next_sym)); - - if (markup == NULL) goto no_tooltip; - - /* Impression finale */ - - result = TRUE; - - gtk_tooltip_set_markup(tooltip, markup); - free(markup); - - no_tooltip: - - if (creator != NULL) - g_object_unref(creator); - - /* - FIXME : ref() ! - if (line != NULL) - g_object_unref(G_OBJECT(line)); - */ - - if (format != NULL) - g_object_unref(G_OBJECT(format)); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : view = composant GTK à consulter. * -* width = largeur requise à renseigner ou NULL. [OUT] * -* height = hauteur requise à renseigner ou NULL. [OUT] * -* * -* Description : Indique les dimensions de travail du composant d'affichage. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void gtk_buffer_view_compute_requested_size(GtkBufferView *view, gint *width, gint *height) -{ - if (width != NULL) - { - if (view->buffer_view != NULL) - *width = g_buffer_view_get_width(view->buffer_view, GTK_DISPLAY_PANEL(view)->display); - else - *width = 0; - } - - if (height != NULL) - { - if (view->buffer_view != NULL) - *height = g_buffer_view_get_height(view->buffer_view); - else - *height = 0; - } - -} - - -/****************************************************************************** -* * -* Paramètres : panel = composant GTK d'affichage à mettre à jour. * -* size = taille de l'espace dans la direction donnée. * -* orientation = indication sur le défilement à traiter. * -* step = valeur d'un petit pas de défilement. [OUT] * -* page = valeur d'un grand pas de défilement. [OUT] * -* * -* Description : Détermine la taille des bonds lors de défilements. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void gtk_buffer_view_compute_scroll_inc(GtkBufferView *view, gint size, GtkOrientation orientation, gdouble *step, gdouble *page) -{ - if (orientation == GTK_ORIENTATION_VERTICAL) - { - *step = 17; // FIXME g_buffer_view_get_line_height(view->buffer_view); - *page = *step * 10; - } - - else - GTK_DISPLAY_PANEL_CLASS(gtk_buffer_view_parent_class)->compute_inc(GTK_DISPLAY_PANEL(view), - size, orientation, step, page); - -} - - -/****************************************************************************** -* * -* Paramètres : view = panneau d'affichage concerné. * -* adj = défilement dont une valeur a changé. * -* orientation = indication sur le défilement à traiter. * -* * -* Description : Réagit à un défilement chez une barre associée au composant. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void gtk_buffer_view_adjust_scroll_value(GtkBufferView *view, GtkAdjustment *adj, GtkOrientation orientation) -{ - GtkWidget *widget; /* Autre vision du composant */ - - widget = GTK_WIDGET(view); - - if (gtk_widget_get_realized(widget)) - gdk_window_invalidate_rect(gtk_widget_get_window(widget), NULL, false); - -} - - -/****************************************************************************** -* * -* Paramètres : view = composant GTK à manipuler. * -* * -* Description : Indique la position courante du curseur. * -* * -* Retour : Emplacement courant du curseur ou NULL si aucun. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static const vmpa2t *gtk_buffer_view_get_caret_location(const GtkBufferView *view) -{ - return view->caret_addr; - -} - - -/****************************************************************************** -* * -* Paramètres : view = composant GTK à consulter. * -* addr = adresse à présenter à l'écran. * -* x = position horizontale au sein du composant. [OUT] * -* y = position verticale au sein du composant. [OUT] * -* tweak = adaptation finale à effectuer. * -* * -* Description : Indique la position d'affichage d'une adresse donnée. * -* * -* Retour : true si l'adresse fait partie du composant, false sinon. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool gtk_buffer_view_get_address_coordinates(const GtkBufferView *view, const vmpa2t *addr, gint *x, gint *y, ScrollPositionTweak tweak) -{ - bool result; /* Bilan à remonter */ - bool need_code; /* Recherche plus raffinée */ - int height; /* Hauteur allouée */ - - need_code = (tweak == SPT_BOTTOM); - - result = g_buffer_view_get_address_coordinates(view->buffer_view, addr, x, y, need_code); - - if (result) - { - *x += g_buffer_view_get_margin(view->buffer_view, GTK_DISPLAY_PANEL(view)->display); - - height = gtk_widget_get_allocated_height(GTK_WIDGET(view)); - - switch (tweak) - { - case SPT_RAW: - break; - - case SPT_TOP: - break; - - case SPT_CENTER: - *y -= (height / 2); - break; - - case SPT_BOTTOM: - *y -= height; - *y += g_buffer_view_get_line_height(view->buffer_view); - break; - - } - - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : view = composant GTK à consulter. * -* line = ligne de tampon où se trouve le curseur. [OUT] * -* creator = instance à l'origine de la représentation. [OUT] * -* * -* Description : Fournit des éléments liés à la position courante dans la vue.* -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool gtk_buffer_view_get_position(const GtkBufferView *view, GBufferLine **line, GObject **creator) -{ - GObject *obj; /* Elément à récupérer */ - - /* Si aucune position n'est définie... */ - if (view->caret_addr == NULL) - return false; - - *line = g_buffer_view_find_line_and_creator_at(view->buffer_view, - (gint []){ view->caret.x }, view->caret.y, NULL, - GTK_DISPLAY_PANEL(view)->display, &obj); - - if (creator != NULL) - *creator = obj; - - return (line != NULL); - -} - - -/****************************************************************************** -* * -* Paramètres : view = composant GTK à manipuler. * -* cairo = assistant pour la création de rendus. * -* area = taille de la surface réduite à disposition. * -* scale = échelle vis à vis de la taille réelle. * -* * -* Description : Place en cache un rendu destiné à l'aperçu graphique rapide. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void gtk_buffer_view_cache_glance(GtkBufferView *view, cairo_t *cairo, const GtkAllocation *area, double scale) -{ - cairo_set_line_width(cairo, 1); - cairo_set_source_rgb(cairo, 0.4, 0.4, 0.4); - - cairo_rectangle(cairo, area->x + 0.5, area->y + 0.5, area->width - 1, area->height - 1); - - cairo_stroke(cairo); - -} - - -/****************************************************************************** -* * -* Paramètres : view = composant GTK à mettre à jour. * -* buffer = tampon de lignes à encadrer. * -* * -* Description : Prend acte de l'association d'un tampon de lignes. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void gtk_buffer_view_attach_buffer(GtkBufferView *view, GBufferView *buffer) -{ - gint width; /* Largeur de l'objet actuelle */ - gint height; /* Hauteur de l'objet actuelle */ - - if (view->buffer_view != NULL) - { - //g_object_unref(G_OBJECT(view->buffer)); - g_object_unref(G_OBJECT(view->buffer_view)); - } - - //view->buffer = g_buffer_view_get_buffer(buffer); - //g_object_ref(G_OBJECT(view->buffer)); - - view->buffer_view = buffer; - - /* Taille des marges */ - - view->line_height = g_buffer_view_get_line_height(view->buffer_view); - view->left_margin = 2 * view->line_height; - view->left_text = -2.5 * view->line_height; - - /* Validation finale */ - - width = g_buffer_view_get_width(view->buffer_view, GTK_DISPLAY_PANEL(view)->display); - height = g_buffer_view_get_height(view->buffer_view); - - width += -view->left_text + 1; - height += 1; - - //gtk_widget_set_size_request(GTK_WIDGET(view), width, height); - - gtk_widget_queue_draw(GTK_WIDGET(view)); - -} - - -/****************************************************************************** -* * -* Paramètres : view = composant GTK à consulter. * -* * -* Description : Fournit la vue associée au tampon de lignes courant. * -* * -* Retour : Vue mise en place. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GBufferView *gtk_buffer_view_get_buffer(const GtkBufferView *view) -{ - /* TODO : ref... */ - - return view->buffer_view; - -} - - - -/* ---------------------------------------------------------------------------------- */ -/* ANIMATION DU CURSEUR */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* Paramètres : view = composant GTK à manipuler. * -* x = abscisse proposée pour le nouvel emplacement. * -* y = ordonnée proposée pour le nouvel emplacement. * -* * -* Description : Déplace le curseur à un emplacement défini. * -* * -* Retour : true si un traitement a été effectué, false sinon. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool _gtk_buffer_view_move_caret_to(GtkBufferView *view, gint x, gint y) -{ - size_t index; /* Indice de ligne de tampon */ - GBufferLine *line; /* Ligne à la position courante*/ - GtkDisplayPanel *panel; /* Autre version du composant */ - const vmpa2t *addr; /* Position mémoire associée */ - GdkRectangle new; /* Nouvel emplacement calculé */ - - if (x < view->left_margin) return false; - - line = g_buffer_view_find_line_at(view->buffer_view, y, &index); - if (line == NULL) return false; - - panel = GTK_DISPLAY_PANEL(view); - - addr = g_buffer_view_compute_caret_full(view->buffer_view, line, index, x, panel->display, &new); - - if (addr != NULL) - gtk_buffer_view_relocate_caret(view, &new, addr); - - return (addr != NULL); - -} - - -/****************************************************************************** -* * -* Paramètres : view = composant GTK à manipuler. * -* beginning = précise le coin où se retrouvera le curseur. * -* same_x = tente de conserver une même abscisse ou NULL ? * -* * -* Description : Déplace le curseur à un emplacement en extrémité. * -* * -* Retour : true si un traitement a été effectué, false sinon. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool gtk_buffer_view_move_caret_to(GtkBufferView *view, bool beginning, gint *same_x) -{ - bool result; /* Bilan à remonter */ - gint x; /* Abscisse d'emplacement */ - gint y; /* Ordonnée d'emplacement */ - - if (beginning) - { - x = same_x != NULL ? *same_x : view->left_margin * 2; - y = 0; - } - else - { - if (same_x != NULL) x = *same_x; - gtk_buffer_view_compute_requested_size(view, same_x != NULL ? NULL : &x, &y); - y--; - } - - result = _gtk_buffer_view_move_caret_to(view, x, y); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : view = composant GTK à manipuler. * -* area = emplacement pour le dessin d'un curseur. * -* addr = position dans la mémoire représentée du curseur. * -* * -* Description : Déplace le curseur en effaçant son éventuelle position. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void gtk_buffer_view_relocate_caret(GtkBufferView *view, const GdkRectangle *area, const vmpa2t *addr) -{ - bool clear_old; /* Effacement chirurgical */ - GdkRectangle old_area; /* Mémorisation de l'ancien */ - bool need_redraw; /* Besoin de rafraîchissement ?*/ - - if (view->caret_addr != NULL) - { - clear_old = true; - old_area = view->caret; - } - else - clear_old = false; - - view->caret = *area; - view->caret_addr = addr; - - if (GTK_BUFFER_VIEW_GET_CLASS(view)->notify_caret != NULL) - need_redraw = GTK_BUFFER_VIEW_GET_CLASS(view)->notify_caret(view, area, addr); - else - need_redraw = false; - - if (need_redraw) - gtk_widget_queue_draw(GTK_WIDGET(view)); - - else if (clear_old) - { - gtk_display_panel_compute_relative_coords(GTK_DISPLAY_PANEL(view), &old_area.x, &old_area.y); - - gtk_widget_queue_draw_area(GTK_WIDGET(view), old_area.x, old_area.y, - old_area.width, old_area.height); - - } - - restart_caret_blinking(view); - -} - - -/****************************************************************************** -* * -* Paramètres : view = composant GTK à manipuler. * -* * -* Description : Redémarre l'affichage du curseur à l'emplacement courant. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void restart_caret_blinking(GtkBufferView *view) -{ - if (view->caret_timer != 0) - { - g_source_remove(view->caret_timer); - view->caret_timer = 0; - } - - if (view->caret_addr != NULL) - { - view->show_caret = false; - gtk_buffer_view_refresh_caret(view); - - view->caret_timer = g_timeout_add_seconds(1, (GSourceFunc)gtk_buffer_view_refresh_caret, view); - - } - - g_signal_emit_by_name(view, "caret-moved", view->caret_addr); - -} - - -/****************************************************************************** -* * -* Paramètres : view = composant GTK à manipuler. * -* * -* Description : Bascule et relance l'affichage du curseur. * -* * -* Retour : TRUE pour poursuivre les basculements automatiques. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static gboolean gtk_buffer_view_refresh_caret(GtkBufferView *view) -{ - GtkWidget *widget; /* Autre version du composant */ - GdkWindow *window; /* Fenêtre de support associée */ - GdkRectangle area; /* Région adaptée à traiter */ - cairo_t *cr; /* Contexte graphique */ - GdkRGBA *color; /* Couleur du curseur */ - - widget = GTK_WIDGET(view); - window = gtk_widget_get_window(widget); - - /** - * Si le composant n'est pas encore réalisé (ou caché, en cas de - * basculement entre les types de vues), gdk_cairo_create() ne va - * pas apprécier l'argument NULL. Donc on écourte l'opération. - */ - if (window == NULL) - { - view->show_caret = !view->show_caret; - return TRUE; - } - - area = view->caret; - gtk_display_panel_compute_relative_coords(GTK_DISPLAY_PANEL(view), &area.x, &area.y); - - /* Réinitialisation de la surface */ - if (view->show_caret) - { - view->show_caret = false; - gtk_widget_queue_draw_area(widget, area.x, area.y, area.width, area.height); - } - - /* Dessin */ - else - { - view->show_caret = true; - - cr = gdk_cairo_create(gtk_widget_get_window(widget)); - - gtk_style_context_get(gtk_widget_get_style_context(widget), - gtk_widget_get_state_flags(widget), - GTK_STYLE_PROPERTY_COLOR, &color, NULL); - - cairo_set_source_rgb(cr, color->red, color->green, color->blue); - - cairo_rectangle(cr, area.x, area.y, area.width, area.height); - cairo_fill(cr); - - cairo_destroy(cr); - - } - - return TRUE; - -} diff --git a/src/gtkext/gtkbufferview.h b/src/gtkext/gtkbufferview.h deleted file mode 100644 index 1b13ab0..0000000 --- a/src/gtkext/gtkbufferview.h +++ /dev/null @@ -1,70 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * gtkbufferview.h - prototypes pour l'affichage de tampons de lignes - * - * Copyright (C) 2010-2014 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 . - */ - - -#ifndef _GTK_BUFFERVIEW_H -#define _GTK_BUFFERVIEW_H - - -#include -#include - - -#include "../glibext/gbufferview.h" - - - -#define GTK_TYPE_BUFFER_VIEW (gtk_buffer_view_get_type()) -#define GTK_BUFFER_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_BUFFER_VIEW, GtkBufferView)) -#define GTK_BUFFER_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GTK_TYPE_BUFFER_VIEW, GtkBufferViewClass)) -#define GTK_IS_BUFFER_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_BUFFER_VIEW)) -#define GTK_IS_BUFFER_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GTK_TYPE_BUFFER_VIEW)) -#define GTK_BUFFER_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_BUFFER_VIEW, GtkBufferViewClass)) - - -/* Composant d'affichage de tampon de lignes (instance) */ -typedef struct _GtkBufferView GtkBufferView; - -/* Composant d'affichage de tampon de lignes (classe) */ -typedef struct _GtkBufferViewClass GtkBufferViewClass; - - -/* Détermine le type du composant d'affichage de tampon de lignes. */ -GType gtk_buffer_view_get_type(void); - -/* Prend acte de l'association d'un tampon de lignes. */ -void gtk_buffer_view_attach_buffer(GtkBufferView *, GBufferView *); - -/* Fournit la vue associée au tampon de lignes courant. */ -GBufferView *gtk_buffer_view_get_buffer(const GtkBufferView *); - - - -/* ------------------------------ ANIMATION DU CURSEUR ------------------------------ */ - - -/* Déplace le curseur à un emplacement en extrémité. */ -bool gtk_buffer_view_move_caret_to(GtkBufferView *, bool, gint *); - - - -#endif /* _GTK_BUFFERVIEW_H */ diff --git a/src/gtkext/gtkdisplaypanel-int.h b/src/gtkext/gtkdisplaypanel-int.h index bc0e229..f6221d5 100644 --- a/src/gtkext/gtkdisplaypanel-int.h +++ b/src/gtkext/gtkdisplaypanel-int.h @@ -48,9 +48,6 @@ typedef void (* adjust_scroll_value_fc) (GtkDisplayPanel *, GtkAdjustment *, Gtk /* Réagit à la sélection externe d'une adresse. */ typedef void (* define_address_fc) (GtkDisplayPanel *, const vmpa2t *); -/* Actualise les besoins internes avant un redimensionnement. */ -typedef void (* prepare_resize_fc) (GtkDisplayPanel *); - /* Indique la position courante du curseur. */ typedef const vmpa2t * (* get_caret_location_fc) (const GtkDisplayPanel *); @@ -84,9 +81,6 @@ struct _GtkDisplayPanel GLoadedBinary *binary; /* Binaire à visualiser */ - //define_address_fc define; /* Centrage sur une partie */ - prepare_resize_fc resize; /* Prépare une nouvelle taille */ - }; /* Composant d'affichage générique (classe) */ diff --git a/src/gtkext/gtkdisplaypanel.c b/src/gtkext/gtkdisplaypanel.c index 6793d4e..66ec909 100644 --- a/src/gtkext/gtkdisplaypanel.c +++ b/src/gtkext/gtkdisplaypanel.c @@ -641,7 +641,8 @@ static void gtk_display_panel_adjustment_value_changed(GtkAdjustment *adj, GtkDi orientation = (adj == panel->hadjustment ? GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL); - GTK_DISPLAY_PANEL_GET_CLASS(panel)->adjust(panel, adj, orientation); + if (GTK_DISPLAY_PANEL_GET_CLASS(panel)->adjust != NULL) + GTK_DISPLAY_PANEL_GET_CLASS(panel)->adjust(panel, adj, orientation); } @@ -832,9 +833,6 @@ static void on_view_panel_binary_display_change(GLoadedBinary *binary, BinaryVie { if (panel->content == view) { - if (panel->resize != NULL) - panel->resize(panel); - gtk_widget_queue_resize(gtk_widget_get_parent(GTK_WIDGET(panel))); gtk_widget_queue_resize(GTK_WIDGET(panel)); gtk_widget_queue_draw(GTK_WIDGET(panel)); @@ -924,23 +922,15 @@ void _gtk_display_panel_scroll_to_address(GtkDisplayPanel *panel, const vmpa2t * double value; /* Valeur courante */ /** - * Si une vue partielle se déplacer via cette fonction, il faut potentiellement + * Si une vue partielle se déplace via cette fonction, il faut potentiellement * rediriger l'appel vers la vue en graphiques parente. */ parent = gtk_widget_get_parent(GTK_WIDGET(panel)); parent = gtk_widget_get_parent(GTK_WIDGET(parent)); - printf(" Widgets : %s -> %s\n", - G_OBJECT_TYPE_NAME(parent), G_OBJECT_TYPE_NAME(panel)); - if (GTK_IS_DISPLAY_PANEL(parent)) - { - printf("reparent !\n"); panel = GTK_DISPLAY_PANEL(parent); - } - else - printf("no need reparent !\n"); if (GTK_DISPLAY_PANEL_GET_CLASS(panel)->define != NULL) GTK_DISPLAY_PANEL_GET_CLASS(panel)->define(panel, addr); diff --git a/src/gtkext/gtkgraphdisplay.c b/src/gtkext/gtkgraphdisplay.c new file mode 100644 index 0000000..1d4f831 --- /dev/null +++ b/src/gtkext/gtkgraphdisplay.c @@ -0,0 +1,1226 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * gtkgraphdisplay.c - affichage de morceaux de code sous forme graphique + * + * Copyright (C) 2009-2016 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 . + */ + + +#include "gtkgraphdisplay.h" + + +#include + + +#include "gtkblockdisplay.h" +#include "gtkbufferdisplay.h" +#include "gtkdisplaypanel-int.h" +#include "graph/cluster.h" +#include "../analysis/blocks/flow.h" +#include "../format/format.h" +#include "../gui/editem.h" + + + +/* Composant d'affichage sous forme graphique (instance) */ +struct _GtkGraphDisplay +{ + GtkDisplayPanel parent; /* A laisser en premier */ + GtkWidget *support; /* Support des vues en bloc */ + GtkWidget *extender; /* Force la taille du support */ + + GBinRoutine *routine; /* Routine en cours d'affichage*/ + + segcnt_list *highlighted; /* Segments mis en évidence */ + + GGraphCluster *cluster; /* Disposition en graphique */ + + GGraphEdge **edges; /* Liens entre les noeuds */ + size_t edges_count; /* Quantité de ces liens */ + + gdouble start_x; /* Abscisse du point de souris */ + gdouble start_y; /* Ordonnée du point de souris */ + bool big_enough; /* Capacités de déplacement ? */ + gdouble ref_h; /* Position horizontale de ref.*/ + gdouble ref_v; /* Position verticale de ref. */ + +}; + +/* Composant d'affichage sous forme graphique (classe) */ +struct _GtkGraphDisplayClass +{ + GtkDisplayPanelClass parent; /* A laisser en premier */ + +}; + + +/* Profondeur de l'ombre */ +#define SHADOW_SIZE 4 + +/* Marges en bordure de graphique */ +#define GRAPH_MARGIN 23 + + +/* Initialise la classe générique des graphiques de code. */ +static void gtk_graph_display_class_init(GtkGraphDisplayClass *); + +/* Initialise une instance d'afficheur de code en graphique. */ +static void gtk_graph_display_init(GtkGraphDisplay *); + +/* Supprime toutes les références externes. */ +static void gtk_graph_display_dispose(GtkGraphDisplay *); + +/* Procède à la libération totale de la mémoire. */ +static void gtk_graph_display_finalize(GtkGraphDisplay *); + +/* S'adapte à la surface concédée par le composant parent. */ +static void gtk_graph_display_size_allocate(GtkWidget *, GtkAllocation *); + +/* Centre si possible le contenu du panneau d'affichage. */ +static void gtk_graph_display_update_support_margins(GtkGraphDisplay *, const GtkAllocation *); + +/* Indique les dimensions de travail du composant d'affichage. */ +static void gtk_graph_display_compute_requested_size(GtkGraphDisplay *, gint *, gint *); + +/* Réagit à un défilement chez une barre associée au composant. */ +static void gtk_graph_display_adjust_scroll_value(GtkGraphDisplay *, GtkAdjustment *, GtkOrientation); + +/* Met à jour l'affichage de la vue sous forme graphique. */ +static gboolean gtk_graph_display_draw(GtkWidget *, cairo_t *, GtkGraphDisplay *); + +/* Assure la gestion des clics de souris sur le composant. */ +static gboolean gtk_graph_display_button_press(GtkWidget *, GdkEventButton *, GtkGraphDisplay *); + +/* Assure la gestion des clics de souris sur le composant. */ +static gboolean gtk_graph_display_button_release(GtkWidget *, GdkEventButton *, GtkGraphDisplay *); + +/* Assure la suivi des déplacements de souris sur le composant. */ +static gboolean gtk_graph_display_motion_notify(GtkWidget *, GdkEventMotion *, GtkGraphDisplay *); + +/* Réagit à la sélection externe d'une adresse. */ +static void gtk_graph_display_define_main_address(GtkGraphDisplay *, const vmpa2t *); + +/* Indique la position courante du curseur. */ +static const vmpa2t *gtk_graph_display_get_caret_location(const GtkGraphDisplay *); + +/* Indique la position d'affichage d'une adresse donnée. */ +static bool gtk_graph_display_get_address_coordinates(const GtkGraphDisplay *, const vmpa2t *addr, gint *x, gint *y, ScrollPositionTweak tweak); + +/* Déplace le curseur à un emplacement défini. */ +static bool gtk_graph_display_move_caret_to(GtkGraphDisplay *, gint, gint); + +/* Place en cache un rendu destiné à l'aperçu graphique rapide. */ +static void gtk_graph_display_cache_glance(GtkGraphDisplay *, cairo_t *, const GtkAllocation *, double); + +/* Supprime tout contenu de l'afficheur de code en graphique. */ +static void gtk_graph_display_reset(GtkGraphDisplay *); + +/* Notifie un changement de surbrillance au sein d'un noeud. */ +static void gtk_graph_display_changed_highlights(GtkBlockDisplay *, GtkGraphDisplay *); + +/* Notifie une incapacité de déplacement au sein d'un noeud. */ +static void gtk_graph_display_reach_caret_limit(GtkBufferDisplay *, GdkScrollDirection, GtkGraphDisplay *); + + + +/* Détermine le type du composant d'affichage en graphique. */ +G_DEFINE_TYPE(GtkGraphDisplay, gtk_graph_display, GTK_TYPE_DISPLAY_PANEL) + + +/****************************************************************************** +* * +* Paramètres : class = classe GTK à initialiser. * +* * +* Description : Initialise la classe générique des graphiques de code. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_graph_display_class_init(GtkGraphDisplayClass *class) +{ + GObjectClass *object; /* Autre version de la classe */ + GtkWidgetClass *widget_class; /* Classe de haut niveau */ + GtkDisplayPanelClass *panel_class; /* Classe parente */ + + object = G_OBJECT_CLASS(class); + + object->dispose = (GObjectFinalizeFunc/* ! */)gtk_graph_display_dispose; + object->finalize = (GObjectFinalizeFunc)gtk_graph_display_finalize; + + widget_class = GTK_WIDGET_CLASS(class); + + widget_class->size_allocate = gtk_graph_display_size_allocate; + + panel_class = GTK_DISPLAY_PANEL_CLASS(class); + + panel_class->compute_size = (compute_requested_size_fc)gtk_graph_display_compute_requested_size; + panel_class->adjust = (adjust_scroll_value_fc)gtk_graph_display_adjust_scroll_value; + panel_class->define = (define_address_fc)gtk_graph_display_define_main_address; + + panel_class->get_caret_loc = (get_caret_location_fc)gtk_graph_display_get_caret_location; + panel_class->get_coordinates = (get_addr_coordinates_fc)gtk_graph_display_get_address_coordinates; + panel_class->move_caret_to = (move_caret_to_fc)gtk_graph_display_move_caret_to; + panel_class->cache_glance = (cache_glance_fc)gtk_graph_display_cache_glance; + +} + + +/****************************************************************************** +* * +* Paramètres : display = instance GTK à initialiser. * +* * +* Description : Initialise une instance d'afficheur de code en graphique. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_graph_display_init(GtkGraphDisplay *display) +{ + display->support = gtk_fixed_new(); + gtk_widget_set_has_window(display->support, TRUE); + gtk_widget_set_can_focus(display->support, TRUE); + + g_signal_connect(G_OBJECT(display->support), "draw", + G_CALLBACK(gtk_graph_display_draw), display); + + g_signal_connect(G_OBJECT(display->support), "button-press-event", + G_CALLBACK(gtk_graph_display_button_press), display); + g_signal_connect(G_OBJECT(display->support), "button-release-event", + G_CALLBACK(gtk_graph_display_button_release), display); + g_signal_connect(G_OBJECT(display->support), "motion-notify-event", + G_CALLBACK(gtk_graph_display_motion_notify), display); + + gtk_widget_add_events(display->support, + GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK); + + gtk_widget_show(display->support); + + gtk_fixed_put(GTK_FIXED(display), display->support, 0, 0); + + display->extender = gtk_fixed_new(); + + gtk_widget_set_margin_end(display->extender, 1); + gtk_widget_set_margin_top(display->extender, 1); + + gtk_widget_show(display->extender); + +} + + +/****************************************************************************** +* * +* Paramètres : display = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_graph_display_dispose(GtkGraphDisplay *display) +{ + g_object_unref(G_OBJECT(display->extender)); + + gtk_graph_display_reset(display); + + G_OBJECT_CLASS(gtk_graph_display_parent_class)->dispose(G_OBJECT(display)); + +} + + +/****************************************************************************** +* * +* Paramètres : display = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_graph_display_finalize(GtkGraphDisplay *display) +{ + G_OBJECT_CLASS(gtk_graph_display_parent_class)->finalize(G_OBJECT(display)); + +} + + +/****************************************************************************** +* * +* Paramètres : widget = composant GTK à mettre à jour. * +* allocation = étendue accordée à la vue. * +* * +* Description : S'adapte à la surface concédée par le composant parent. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_graph_display_size_allocate(GtkWidget *widget, GtkAllocation *allocation) +{ + GtkGraphDisplay *display; /* Autre version du composant */ + + GTK_WIDGET_CLASS(gtk_graph_display_parent_class)->size_allocate(widget, allocation); + + display = GTK_GRAPH_DISPLAY(widget); + + gtk_graph_display_update_support_margins(display, allocation); + +} + + +/****************************************************************************** +* * +* Paramètres : display = panneau dont le contenu est à déplacer. * +* allocation = étendue accordée à la vue. * +* * +* Description : Centre si possible le contenu du panneau d'affichage. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_graph_display_update_support_margins(GtkGraphDisplay *display, const GtkAllocation *allocation) +{ + gint width; /* Largeur totale du support */ + gint height; /* Hauteur totale du support */ + gint start; /* Bordure horizontale */ + gint top; /* Bordure verticale */ + + gtk_graph_display_compute_requested_size(display, &width, &height); + + if (width > allocation->width) + start = 0; + else + start = (allocation->width - width) / 2; + + if (height > allocation->height) + top = 0; + else + top = (allocation->height - height) / 2; + + gtk_widget_set_margin_start(display->support, start); + gtk_widget_set_margin_top(display->support, top); + +} + + +/****************************************************************************** +* * +* Paramètres : display = composant GTK à consulter. * +* width = largeur requise à renseigner ou NULL. [OUT] * +* height = hauteur requise à renseigner ou NULL. [OUT] * +* * +* Description : Indique les dimensions de travail du composant d'affichage. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_graph_display_compute_requested_size(GtkGraphDisplay *display, gint *width, gint *height) +{ + GtkAllocation needed; /* Taille requise */ + + if (display->cluster != NULL) + { + g_graph_cluster_compute_needed_alloc(display->cluster, &needed); + assert(needed.x == 0 && needed.y == 0); + + needed.width += 2 * GRAPH_MARGIN; + needed.height += 2 * GRAPH_MARGIN; + + } + else + { + needed.width = 0; + needed.height = 0; + } + + if (width != NULL) *width = needed.width; + if (height != NULL) *height = needed.height; + +} + + +/****************************************************************************** +* * +* Paramètres : display = panneau d'affichage concerné. * +* adj = défilement dont une valeur a changé. * +* orientation = indication sur le défilement à traiter. * +* * +* Description : Réagit à un défilement chez une barre associée au composant. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_graph_display_adjust_scroll_value(GtkGraphDisplay *display, GtkAdjustment *adj, GtkOrientation orientation) +{ + gint fake_x; /* Abscisse virtuelle */ + gint fake_y; /* Ordonnée virtuelle */ + + fake_x = 0; + fake_y = 0; + gtk_display_panel_compute_fake_coord(GTK_DISPLAY_PANEL(display), &fake_x, &fake_y); + + gtk_fixed_move(GTK_FIXED(display), display->support, fake_x, -fake_y); + +} + + +/****************************************************************************** +* * +* Paramètres : widget = composant GTK à redessiner. * +* cr = contexte graphique associé à l'événement. * +* display = support maître à consulter. * +* * +* Description : Met à jour l'affichage de la vue sous forme graphique. * +* * +* Retour : FALSE pour poursuivre la propagation de l'événement. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static gboolean gtk_graph_display_draw(GtkWidget *widget, cairo_t *cr, GtkGraphDisplay *display) +{ + size_t i; /* Boucle de parcours */ + + void draw_shadow(GtkWidget *child, gpointer unused) + { + GtkAllocation alloc; /* Emplacement de l'enfant */ + gint j; /* Boucle de parcours */ + cairo_pattern_t *pattern; /* Zones d'application */ + + /* On évite l'extenseur de support... */ + if (!GTK_IS_DISPLAY_PANEL(child)) + return; + + gtk_widget_get_allocation(child, &alloc); + + for (j = 1; j < SHADOW_SIZE; j++) + { + cairo_push_group(cr); + + gtk_display_panel_define_border_path(GTK_DISPLAY_PANEL(child), cr, alloc.x + j, alloc.y + j); + cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0); + cairo_fill(cr); + + cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); + + gtk_display_panel_define_border_path(GTK_DISPLAY_PANEL(child), cr, alloc.x, alloc.y); + cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 0.0); + cairo_fill(cr); + + pattern = cairo_pop_group(cr); + + cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 0.3); + cairo_mask(cr, pattern); + cairo_fill(cr); + + cairo_pattern_destroy(pattern); + + } + + } + + gtk_container_foreach(GTK_CONTAINER(display->support), (GtkCallback)draw_shadow, NULL); + + for (i = 0; i < display->edges_count; i++) + g_graph_edge_draw(display->edges[i], cr, true); + + return FALSE; + +} + + +/****************************************************************************** +* * +* Paramètres : widget = composant GTK visé par l'opération. * +* event = informations liées à l'événement. * +* display = support maître à consulter. * +* * +* Description : Assure la gestion des clics de souris sur le composant. * +* * +* Retour : FALSE pour poursuivre la propagation de l'événement. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static gboolean gtk_graph_display_button_press(GtkWidget *widget, GdkEventButton *event, GtkGraphDisplay *display) +{ + gboolean result; /* Poursuite à faire suivre */ + GtkScrolledWindow *support; /* Support défilant associé */ + GtkAdjustment *hadj; /* Gestionnaire du défilement */ + GtkAdjustment *vadj; /* Gestionnaire du défilement */ + GdkCursor *cursor; /* Pointeur pour la surface */ + + result = FALSE; + + if (event->button == 1) + { + support = GTK_SCROLLED_WINDOW(gtk_widget_get_parent(GTK_WIDGET(display))); + + hadj = gtk_scrolled_window_get_hadjustment(support); + vadj = gtk_scrolled_window_get_vadjustment(support); + + display->big_enough = (gtk_adjustment_get_upper(hadj) > gtk_adjustment_get_page_size(hadj) + || gtk_adjustment_get_upper(vadj) > gtk_adjustment_get_page_size(vadj)); + + if (display->big_enough) + { + display->start_x = event->x_root; + display->start_y = event->y_root; + + display->ref_h = gtk_adjustment_get_value(hadj); + display->ref_v = gtk_adjustment_get_value(vadj); + + cursor = gdk_cursor_new(GDK_FLEUR); + gdk_window_set_cursor(gtk_widget_get_window(widget), cursor); + g_object_unref(G_OBJECT(cursor)); + + result = TRUE; + + } + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : widget = composant GTK visé par l'opération. * +* event = informations liées à l'événement. * +* display = support maître à consulter. * +* * +* Description : Assure la gestion des clics de souris sur le composant. * +* * +* Retour : FALSE pour poursuivre la propagation de l'événement. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static gboolean gtk_graph_display_button_release(GtkWidget *widget, GdkEventButton *event, GtkGraphDisplay *display) +{ + if (event->button == 1 && display->big_enough) + gdk_window_set_cursor(gtk_widget_get_window(widget), NULL); + + return FALSE; + +} + + +/****************************************************************************** +* * +* Paramètres : widget = composant GTK visé par l'opération. * +* event = informations liées à l'événement. * +* display = support maître à consulter. * +* * +* Description : Assure la suivi des déplacements de souris sur le composant. * +* * +* Retour : FALSE pour poursuivre la propagation de l'événement. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static gboolean gtk_graph_display_motion_notify(GtkWidget *widget, GdkEventMotion *event, GtkGraphDisplay *display) +{ + gdouble diff_x; /* Evolution sur les abscisses */ + gdouble diff_y; /* Evolution sur les ordonnées */ + GtkScrolledWindow *support; /* Support défilant associé */ + GtkAdjustment *hadj; /* Gestionnaire du défilement */ + GtkAdjustment *vadj; /* Gestionnaire du défilement */ + gdouble value; /* Nouvelle valeur bornée */ + + if (event->state & GDK_BUTTON1_MASK && display->big_enough) + { + diff_x = display->start_x - event->x_root; + diff_y = display->start_y - event->y_root; + + support = GTK_SCROLLED_WINDOW(gtk_widget_get_parent(GTK_WIDGET(display))); + + hadj = gtk_scrolled_window_get_hadjustment(support); + vadj = gtk_scrolled_window_get_vadjustment(support); + + value = CLAMP(display->ref_h + diff_x, gtk_adjustment_get_lower(hadj), + gtk_adjustment_get_upper(hadj) - gtk_adjustment_get_page_size(hadj)); + gtk_adjustment_set_value(hadj, value); + + value = CLAMP(display->ref_v + diff_y, gtk_adjustment_get_lower(vadj), + gtk_adjustment_get_upper(vadj) - gtk_adjustment_get_page_size(vadj)); + gtk_adjustment_set_value(vadj, value); + + } + + return FALSE; + +} + + +/****************************************************************************** +* * +* Paramètres : display = composant GTK à mettre à jour. * +* addr = adresse sélectionnée de manière externe. * +* * +* Description : Réagit à la sélection externe d'une adresse. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_graph_display_define_main_address(GtkGraphDisplay *display, const vmpa2t *addr) +{ + bool need_update; /* Mise à jour du contenu ? */ + const mrange_t *range; /* Couverture courante */ + GExeFormat *format; /* Type de fichier chargé */ + GBinRoutine **routines; /* Liste des routines trouvées */ + size_t routines_count; /* Nombre de ces routines */ + size_t i; /* Boucle de parcours */ + gint right; /* Abscisse du coin droit */ + gint bottom; /* Ordonnée du coin inférieur */ + GtkAllocation allocation; /* Espace alloué au panneau */ + + if (display->routine == NULL) + need_update = true; + else + { + range = g_binary_routine_get_range(display->routine); + need_update = !mrange_contains_addr(range, addr); + } + + if (need_update) + { + gtk_graph_display_reset(display); + + format = g_loaded_binary_get_format(GTK_DISPLAY_PANEL(display)->binary); + routines = g_binary_format_get_routines(G_BIN_FORMAT(format), &routines_count); + + for (i = 0; i < routines_count; i++) + { + range = g_binary_routine_get_range(routines[i]); + + if (mrange_contains_addr(range, addr)) + { + display->routine = routines[i]; + g_object_ref(G_OBJECT(display->routine)); + + display->highlighted = init_segment_content_list(); + + /* + display->children = gtk_graph_display_load_nodes(display, GTK_DISPLAY_PANEL(display)->binary, + routines[i]); + + display->allocs = (GtkAllocation *)calloc(display->children_count, + sizeof(GtkAllocation)); + + display->layout = g_graph_layout_new(g_binary_routine_get_basic_blocks(display->routine), + display->children, display->children_count); + + g_graph_layout_place(display->layout, display); + */ + + do + { + + GBlockList *list; + + list = g_binary_routine_get_basic_blocks(routines[i]); + +#if 0 + display->cluster = g_graph_cluster_new(GTK_DISPLAY_PANEL(display)->binary, + list, 0/* FIXME */, display->highlighted); +#endif + + + display->cluster = bootstrap_graph_cluster(GTK_DISPLAY_PANEL(display)->binary, + list, display->highlighted); + + + + g_graph_cluster_place(display->cluster, display); + + /** + * Comme la taille du support ne peut pas être forcée et + * étendue pour comprendre les ombres, on place un composant + * minuscule à l'extrémité de ce support. + */ + + gtk_graph_display_compute_requested_size(display, &right, &bottom); + + g_object_ref(G_OBJECT(display->extender)); + gtk_fixed_put(GTK_FIXED(display->support), display->extender, right - 1, bottom - 1); + + /** + * Si possible, on centre le contenu obtenu. + */ + + gtk_widget_get_allocation(GTK_WIDGET(display), &allocation); + + gtk_graph_display_update_support_margins(display, &allocation); + + + + } + while (0); + + + + break; + + } + + } + + change_editor_items_current_view_content(GTK_DISPLAY_PANEL(display)); + + g_object_unref(G_OBJECT(format)); + + } + +} + + +/****************************************************************************** +* * +* Paramètres : display = composant GTK à manipuler. * +* * +* Description : Indique la position courante du curseur. * +* * +* Retour : Emplacement courant du curseur ou NULL si aucun. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static const vmpa2t *gtk_graph_display_get_caret_location(const GtkGraphDisplay *display) +{ + return NULL; /* FIXME */ + +} + + +/****************************************************************************** +* * +* Paramètres : display = composant GTK à consulter. * +* addr = adresse à présenter à l'écran. * +* x = position horizontale au sein du composant. [OUT] * +* y = position verticale au sein du composant. [OUT] * +* tweak = adaptation finale à effectuer. * +* * +* Description : Indique la position d'affichage d'une adresse donnée. * +* * +* Retour : true si l'adresse fait partie du composant, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool gtk_graph_display_get_address_coordinates(const GtkGraphDisplay *display, const vmpa2t *addr, gint *x, gint *y, ScrollPositionTweak tweak) +{ + /* TODO */ + + return false; + +} + + +/****************************************************************************** +* * +* Paramètres : display = composant GTK à manipuler. * +* x = abscisse proposée pour le nouvel emplacement. * +* y = ordonnée proposée pour le nouvel emplacement. * +* * +* Description : Déplace le curseur à un emplacement défini. * +* * +* Retour : true si un traitement a été effectué, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool gtk_graph_display_move_caret_to(GtkGraphDisplay *display, gint x, gint y) +{ + bool result; /* Bilan à retourner */ + + result = false; + + void move_caret_to_sub_block(GtkWidget *child, gpointer unused) + { + GtkAllocation alloc; /* Emplacement réservé */ + GtkDisplayPanel *panel; /* Autre vision d'enfance */ + gint sub_x; /* Abscisse relative à l'enfant*/ + gint sub_y; /* Ordonnée relative à l'enfant*/ + + if (result) + return; + + if (!GTK_IS_BUFFER_DISPLAY(child)) + return; + + gtk_widget_get_allocation(child, &alloc); + + if (x < alloc.x || x >= (alloc.x + alloc.width)) return; + if (y < alloc.y || y >= (alloc.y + alloc.height)) return; + + panel = GTK_DISPLAY_PANEL(child); + + sub_x = x - alloc.x; + sub_y = y - alloc.y; + + result = GTK_DISPLAY_PANEL_GET_CLASS(panel)->move_caret_to(panel, sub_x, sub_y); + + } + + gtk_container_foreach(GTK_CONTAINER(display->support), (GtkCallback)move_caret_to_sub_block, NULL); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : display = composant GTK à manipuler. * +* cr = assistant pour la création de rendus. * +* area = taille de la surface réduite à disposition. * +* scale = échelle vis à vis de la taille réelle. * +* * +* Description : Place en cache un rendu destiné à l'aperçu graphique rapide. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_graph_display_cache_glance(GtkGraphDisplay *display, cairo_t *cr, const GtkAllocation *area, double scale) +{ + size_t i; /* Boucle de parcours */ + + void draw_child_glance(GtkWidget *child, gpointer unused) + { + GtkAllocation sub_area; /* Emplacement réservé */ + + if (!GTK_IS_BUFFER_DISPLAY(child)) + return; + + gtk_widget_get_allocation(child, &sub_area); + + sub_area.x *= scale; + sub_area.y *= scale; + sub_area.width = sub_area.width * scale + 1; + sub_area.height = sub_area.height * scale + 1; + + gtk_display_panel_cache_glance(GTK_DISPLAY_PANEL(child), cr, &sub_area, scale); + + } + + gtk_container_foreach(GTK_CONTAINER(display->support), (GtkCallback)draw_child_glance, NULL); + + cairo_scale(cr, scale, scale); + + for (i = 0; i < display->edges_count; i++) + g_graph_edge_draw(display->edges[i], cr, false); + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Crée un nouveau composant pour l'affichage en graphique. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +GtkWidget *gtk_graph_display_new(void) +{ + return g_object_new(GTK_TYPE_GRAPH_DISPLAY, NULL); + +} + + +/****************************************************************************** +* * +* Paramètres : display = composant GTK à mettre à jour. * +* widget = composant GTK à insérer. * +* x = abscisse du point d'insertion. * +* y = ordonnée du point d'insertion. * +* * +* Description : Place une vue sous forme de bloc dans le graphique. * +* * +* Retour : Plutôt que de redéfinir *toutes* les méthodes de * +* GtkContainer, on étend ! * +* * +* Remarques : - * +* * +******************************************************************************/ + +void gtk_graph_display_put(GtkGraphDisplay *display, GtkWidget *widget, const GtkAllocation *alloc) +{ + g_signal_connect(widget, "reach-limit", G_CALLBACK(gtk_graph_display_reach_caret_limit), display); + g_signal_connect(widget, "highlight-changed", G_CALLBACK(gtk_graph_display_changed_highlights), display); + + gtk_fixed_put(GTK_FIXED(display->support), widget, GRAPH_MARGIN + alloc->x, GRAPH_MARGIN + alloc->y); + +} + + + +/****************************************************************************** +* * +* Paramètres : display = composant GTK à mettre à jour. * +* edge = lien entre noeuds à conserver. * +* * +* Description : Intègre un lien entre blocs graphiques dans l'afficheur. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void gtk_graph_display_add_edge(GtkGraphDisplay *display, GGraphEdge *edge) +{ + g_graph_edge_offset(edge, GRAPH_MARGIN, GRAPH_MARGIN); + + display->edges = (GGraphEdge **)realloc(display->edges, + ++display->edges_count * sizeof(GGraphEdge *)); + + display->edges[display->edges_count - 1] = edge; + +} + + +/****************************************************************************** +* * +* Paramètres : display = instance GTK à réinitialiser. * +* * +* Description : Supprime tout contenu de l'afficheur de code en graphique. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_graph_display_reset(GtkGraphDisplay *display) +{ + size_t i; /* Boucle de parcours */ + + + void detach_all_blocks(GtkWidget *widget, GtkContainer *container) + { + + + + gtk_container_remove(container, widget); + + + } + + + gtk_container_foreach(GTK_CONTAINER(display->support), (GtkCallback)detach_all_blocks, display->support); + + + + if (display->routine != NULL) + { + g_object_unref(G_OBJECT(display->routine)); + display->routine = NULL; + } + + if (display->highlighted != NULL) + exit_segment_content_list(display->highlighted); + + if (display->cluster != NULL) + { + g_object_unref(G_OBJECT(display->cluster)); + display->cluster = NULL; + } + + for (i = 0; i < display->edges_count; i++) + g_object_unref(G_OBJECT(display->edges[i])); + + if (display->edges_count > 0) + { + free(display->edges); + display->edges = NULL; + + display->edges_count = 0; + + } + +} + + +/****************************************************************************** +* * +* Paramètres : node = composant d'affichage impliqué dans la procédure. * +* display = support graphique de tous les noeuds. * +* * +* Description : Notifie un changement de surbrillance au sein d'un noeud. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_graph_display_changed_highlights(GtkBlockDisplay *node, GtkGraphDisplay *display) +{ + void refresh_highlights(GtkWidget *child, gpointer unused) + { + if (!GTK_IS_BUFFER_DISPLAY(child)) + return; + + if (child != GTK_WIDGET(node)) + gtk_widget_queue_draw(child); + + } + + gtk_container_foreach(GTK_CONTAINER(display->support), (GtkCallback)refresh_highlights, NULL); + +} + + +/****************************************************************************** +* * +* Paramètres : node = composant d'affichage impliqué dans la procédure. * +* dir = direction du déplacement souhaité et impossible. * +* display = support graphique de tous les noeuds. * +* * +* Description : Notifie une incapacité de déplacement au sein d'un noeud. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_graph_display_reach_caret_limit(GtkBufferDisplay *node, GdkScrollDirection dir, GtkGraphDisplay *display) +{ + GBufferView *view; /* Vue d'un tampon global */ + vmpa2t first; /* Début d'un groupe de lignes */ + vmpa2t last; /* Fin d'un groupe de lignes */ + const mrange_t *range; /* Couverture courante */ + GArchProcessor *proc; /* Processeur pour instructions*/ + vmpa2t iaddr; /* Position de l'instructin */ + instr_iter_t *iter; /* Boucle de parcours */ + GArchInstruction *instr; /* Instruction à venir visiter */ +#ifndef NDEBUG + bool is_return; /* Est-ce une instruc. finale ?*/ +#endif + GtkBufferDisplay *target; /* Bloc suivant pour le focus */ + + /* Détermination de l'instruction à cibler */ + + view = gtk_buffer_display_get_view(node); + g_buffer_view_get_restrictions(view, &first, &last); + g_object_unref(G_OBJECT(view)); + + range = g_binary_routine_get_range(display->routine); + + proc = g_loaded_binary_get_processor(GTK_DISPLAY_PANEL(display)->binary); + + init_vmpa(&iaddr, VMPA_NO_PHYSICAL, VMPA_NO_VIRTUAL); + +#ifndef NDEBUG + is_return = false; +#endif + + switch (dir) + { + case GDK_SCROLL_LEFT: + case GDK_SCROLL_UP: + + if (cmp_vmpa(get_mrange_addr(range), &first) != 0) + { + iter = g_arch_processor_get_iter_from_address(proc, &first); + + if (iter != NULL) + { + instr = get_instruction_iterator_prev(iter); + + if (instr != NULL) + { + /* TODO : boucler si !HAS_CODE */ + + if (mrange_contains_addr(range, &iaddr)) + copy_vmpa(&iaddr, get_mrange_addr(g_arch_instruction_get_range(instr))); + + g_object_unref(G_OBJECT(instr)); + + } + + delete_instruction_iterator(iter); + + } + + } + + break; + + case GDK_SCROLL_RIGHT: + case GDK_SCROLL_DOWN: + + iter = g_arch_processor_get_iter_from_address(proc, &last); + + if (iter != NULL) + { +#ifndef NDEBUG + instr = get_instruction_iterator_current(iter); + if (instr != NULL) + { + is_return = (g_arch_instruction_get_flags(instr) & AIF_RETURN_POINT); + g_object_unref(G_OBJECT(instr)); + } +#endif + + instr = get_instruction_iterator_next(iter); + + if (instr != NULL) + { + /* TODO : boucler si !HAS_CODE */ + + copy_vmpa(&iaddr, get_mrange_addr(g_arch_instruction_get_range(instr))); + + if (!mrange_contains_addr(range, &iaddr)) + init_vmpa(&iaddr, VMPA_NO_PHYSICAL, VMPA_NO_VIRTUAL); + + g_object_unref(G_OBJECT(instr)); + + } + + delete_instruction_iterator(iter); + + } + + break; + + case GDK_SCROLL_SMOOTH: + assert(false); /* Argument jamais généré */ + break; + + } + + g_object_unref(G_OBJECT(proc)); + + /* Recherche du bloc parent */ + + if (is_invalid_vmpa(&iaddr)) + return; + + target = NULL; + + void find_target_block(GtkWidget *child, gpointer unused) + { + GtkBufferDisplay *test; /* Candidat potentiel à tester */ + + if (!GTK_IS_BUFFER_DISPLAY(child)) + return; + + test = GTK_BUFFER_DISPLAY(child); + + view = gtk_buffer_display_get_view(test); + g_buffer_view_get_restrictions(view, &first, &last); + g_object_unref(G_OBJECT(view)); + + if (cmp_vmpa(&first, &iaddr) <= 0 && cmp_vmpa(&iaddr, &last) <= 0) + { + assert(target == NULL); + assert(node != test); + target = test; + return; + } + + } + + gtk_container_foreach(GTK_CONTAINER(display->support), (GtkCallback)find_target_block, NULL); + + assert(target != NULL || is_return); + + /* Affichage du nouveau curseur */ + + /** + * Il se peut qu'aucune adresse suivante ne soit disponible : c'est typiquement + * le cas sous ARM, avec les valeurs brutes référencées dans le code. Ces valeurs + * sont incluses dans la surface couverte par la routine concernée, mais ne sont + * pas intégrées dans les blocs basiques associés. + */ + + if (target == NULL) + return; + + gtk_widget_grab_focus(GTK_WIDGET(target)); + + switch (dir) + { + case GDK_SCROLL_UP: + case GDK_SCROLL_LEFT: + gtk_buffer_display_move_caret_to(target, false, NULL); + break; + + break; + + case GDK_SCROLL_RIGHT: + case GDK_SCROLL_DOWN: + gtk_buffer_display_move_caret_to(target, true, NULL); + break; + + break; + + case GDK_SCROLL_SMOOTH: + assert(false); /* Argument jamais généré */ + break; + + } + + /* TODO : scrolling... */ + +} diff --git a/src/gtkext/gtkgraphdisplay.h b/src/gtkext/gtkgraphdisplay.h new file mode 100644 index 0000000..8d553b7 --- /dev/null +++ b/src/gtkext/gtkgraphdisplay.h @@ -0,0 +1,64 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * gtkgraphdisplay.h - prototypes pour l'affichage de morceaux de code sous forme graphique + * + * Copyright (C) 2009-2016 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 . + */ + + +#ifndef _GTKEXT_GTKGRAPHDISPLAY_H +#define _GTKEXT_GTKGRAPHDISPLAY_H + + +#include + + +#include "graph/edge.h" + + + +#define GTK_TYPE_GRAPH_DISPLAY (gtk_graph_display_get_type()) +#define GTK_GRAPH_DISPLAY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_GRAPH_DISPLAY, GtkGraphDisplay)) +#define GTK_GRAPH_DISPLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GTK_TYPE_GRAPH_DISPLAY, GtkGraphDisplayClass)) +#define GTK_IS_GRAPH_DISPLAY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_GRAPH_DISPLAY)) +#define GTK_IS_GRAPH_DISPLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GTK_TYPE_GRAPH_DISPLAY)) +#define GTK_GRAPH_DISPLAY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_GRAPH_DISPLAY, GtkGraphDisplayClass)) + + +/* Composant d'affichage sous forme graphique (instance) */ +typedef struct _GtkGraphDisplay GtkGraphDisplay; + +/* Composant d'affichage sous forme graphique (classe) */ +typedef struct _GtkGraphDisplayClass GtkGraphDisplayClass; + + +/* Détermine le type du composant d'affichage en graphique. */ +GType gtk_graph_display_get_type(void); + +/* Crée un nouveau composant pour l'affichage en graphique. */ +GtkWidget *gtk_graph_display_new(void); + +/* Place une vue sous forme de bloc dans le graphique. */ +void gtk_graph_display_put(GtkGraphDisplay *, GtkWidget *, const GtkAllocation *); + +/* Intègre un lien entre blocs graphiques dans l'afficheur. */ +void gtk_graph_display_add_edge(GtkGraphDisplay *, GGraphEdge *); + + + +#endif /* _GTKEXT_GTKGRAPHDISPLAY_H */ diff --git a/src/gtkext/gtkgraphview.c b/src/gtkext/gtkgraphview.c deleted file mode 100644 index 57bbec0..0000000 --- a/src/gtkext/gtkgraphview.c +++ /dev/null @@ -1,1371 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * gtkgraphview.c - affichage de morceaux de code sous forme graphique - * - * Copyright (C) 2009-2014 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 . - */ - - -#include "gtkgraphview.h" - - -#include - - -#include "gtkblockview.h" -#include "gtkbufferview.h" -#include "gtkdisplaypanel-int.h" -#include "graph/cluster.h" -#include "../analysis/blocks/flow.h" -#include "../format/format.h" -#include "../gui/editem.h" - - - -/* Composant d'affichage sous forme graphique (instance) */ -struct _GtkGraphView -{ - GtkDisplayPanel parent; /* A laisser en premier */ - GtkWidget *support; /* Support des vues en bloc */ - GtkWidget *extender; /* Force la taille du support */ - - GBinRoutine *routine; /* Routine en cours d'affichage*/ - - segcnt_list *highlighted; /* Segments mis en évidence */ - GtkBufferView **children; /* Liste des sous-blocs */ - GtkAllocation *allocs; /* Emplacements prévisibles */ - size_t children_count; /* Taille de cette liste */ - - //GGraphLayout *layout; /* Disposition en graphique */ - GGraphCluster *cluster; /* Disposition en graphique */ - - GGraphEdge **edges; /* Liens entre les noeuds */ - size_t edges_count; /* Quantité de ces liens */ - - gdouble start_x; /* Abscisse du point de souris */ - gdouble start_y; /* Ordonnée du point de souris */ - bool big_enough; /* Capacités de déplacement ? */ - gdouble ref_h; /* Position horizontale de ref.*/ - gdouble ref_v; /* Position verticale de ref. */ - -}; - -/* Composant d'affichage sous forme graphique (classe) */ -struct _GtkGraphViewClass -{ - GtkDisplayPanelClass parent; /* A laisser en premier */ - -}; - - -/* Profondeur de l'ombre */ -#define SHADOW_SIZE 4 - - -/* Initialise la classe générique des graphiques de code. */ -static void gtk_graph_view_class_init(GtkGraphViewClass *); - -/* Initialise une instance d'afficheur de code en graphique. */ -static void gtk_graph_view_init(GtkGraphView *); - -/* Supprime toutes les références externes. */ -static void gtk_graph_view_dispose(GtkGraphView *); - -/* Procède à la libération totale de la mémoire. */ -static void gtk_graph_view_finalize(GtkGraphView *); - -/* S'adapte à la surface concédée par le composant parent. */ -static void gtk_graph_view_size_allocate(GtkWidget *, GtkAllocation *); - -/* Centre si possible le contenu du panneau d'affichage. */ -static void gtk_graph_view_update_support_margins(GtkGraphView *, const GtkAllocation *); - -/* Indique les dimensions de travail du composant d'affichage. */ -static void gtk_graph_view_compute_requested_size(GtkGraphView *, gint *, gint *); - -/* Réagit à un défilement chez une barre associée au composant. */ -static void gtk_graph_view_adjust_scroll_value(GtkGraphView *, GtkAdjustment *, GtkOrientation); - -/* Met à jour l'affichage de la vue sous forme graphique. */ -static gboolean gtk_graph_view_draw(GtkWidget *, cairo_t *, GtkGraphView *); - -/* Assure la gestion des clics de souris sur le composant. */ -static gboolean gtk_graph_view_button_press(GtkWidget *, GdkEventButton *, GtkGraphView *); - -/* Assure la gestion des clics de souris sur le composant. */ -static gboolean gtk_graph_view_button_release(GtkWidget *, GdkEventButton *, GtkGraphView *); - -/* Assure la suivi des déplacements de souris sur le composant. */ -static gboolean gtk_graph_view_motion_notify(GtkWidget *, GdkEventMotion *, GtkGraphView *); - -/* Actualise les besoins internes avant un redimensionnement. */ -static void gtk_graph_view_prepare_resize(GtkGraphView *); - -/* Réagit à la sélection externe d'une adresse. */ -static void gtk_graph_view_define_main_address(GtkGraphView *, const vmpa2t *); - -/* Indique la position courante du curseur. */ -static const vmpa2t *gtk_graph_view_get_caret_location(const GtkGraphView *); - -/* Indique la position d'affichage d'une adresse donnée. */ -static bool gtk_graph_view_get_address_coordinates(const GtkGraphView *, const vmpa2t *addr, gint *x, gint *y, ScrollPositionTweak tweak); - -/* Déplace le curseur à un emplacement défini. */ -static bool gtk_graph_view_move_caret_to(GtkGraphView *, gint, gint); - -/* Place en cache un rendu destiné à l'aperçu graphique rapide. */ -static void gtk_graph_view_cache_glance(GtkGraphView *, cairo_t *, const GtkAllocation *, double); - -/* Supprime tout contenu de l'afficheur de code en graphique. */ -static void gtk_graph_view_reset(GtkGraphView *); - -/* Définit la liste complète des éléments du futur graphique. */ -static GtkBufferView **gtk_graph_view_load_nodes(GtkGraphView *, GLoadedBinary *, const GBinRoutine *); - -/* Notifie un changement de surbrillance au sein d'un noeud. */ -static void gtk_graph_view_changed_highlights(GtkBlockView *, GtkGraphView *); - -/* Notifie une incapacité de déplacement au sein d'un noeud. */ -static void gtk_graph_view_reach_caret_limit(GtkBufferView *, GdkScrollDirection, GtkGraphView *); - - - -/* Détermine le type du composant d'affichage en graphique. */ -G_DEFINE_TYPE(GtkGraphView, gtk_graph_view, GTK_TYPE_DISPLAY_PANEL) - - -/****************************************************************************** -* * -* Paramètres : class = classe GTK à initialiser. * -* * -* Description : Initialise la classe générique des graphiques de code. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void gtk_graph_view_class_init(GtkGraphViewClass *class) -{ - GObjectClass *object; /* Autre version de la classe */ - GtkWidgetClass *widget_class; /* Classe de haut niveau */ - GtkDisplayPanelClass *panel_class; /* Classe parente */ - - object = G_OBJECT_CLASS(class); - - object->dispose = (GObjectFinalizeFunc/* ! */)gtk_graph_view_dispose; - object->finalize = (GObjectFinalizeFunc)gtk_graph_view_finalize; - - widget_class = GTK_WIDGET_CLASS(class); - - widget_class->size_allocate = gtk_graph_view_size_allocate; - - panel_class = GTK_DISPLAY_PANEL_CLASS(class); - - panel_class->compute_size = (compute_requested_size_fc)gtk_graph_view_compute_requested_size; - panel_class->adjust = (adjust_scroll_value_fc)gtk_graph_view_adjust_scroll_value; - panel_class->define = (define_address_fc)gtk_graph_view_define_main_address; - - panel_class->get_caret_loc = (get_caret_location_fc)gtk_graph_view_get_caret_location; - panel_class->get_coordinates = (get_addr_coordinates_fc)gtk_graph_view_get_address_coordinates; - panel_class->move_caret_to = (move_caret_to_fc)gtk_graph_view_move_caret_to; - panel_class->cache_glance = (cache_glance_fc)gtk_graph_view_cache_glance; - -} - - -/****************************************************************************** -* * -* Paramètres : view = instance GTK à initialiser. * -* * -* Description : Initialise une instance d'afficheur de code en graphique. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void gtk_graph_view_init(GtkGraphView *view) -{ - GtkDisplayPanel *panel; /* Instance parente #1 */ - //GtkBinView *binview; /* Instance parente #2 */ - - panel = GTK_DISPLAY_PANEL(view); - - panel->resize = (prepare_resize_fc)gtk_graph_view_prepare_resize; - ////////viewpanel->get_coordinates = (get_addr_coordinates_fc)gtk_graph_view_get_address_coordinates; - - //binview = GTK_BIN_VIEW(view); - - //binview->set_lines = (set_rendering_lines_fc)gtk_graph_view_set_rendering_lines; - //binview->define_address = (define_main_address_fc)gtk_graph_view_define_main_address; - //binview->get_coordinates = (get_addr_coordinates_fc)gtk_graph_view_get_address_coordinates; - - view->support = gtk_fixed_new(); - gtk_widget_set_has_window(view->support, TRUE); - gtk_widget_set_can_focus(view->support, TRUE); - - g_signal_connect(G_OBJECT(view->support), "draw", - G_CALLBACK(gtk_graph_view_draw), view); - - g_signal_connect(G_OBJECT(view->support), "button-press-event", - G_CALLBACK(gtk_graph_view_button_press), view); - g_signal_connect(G_OBJECT(view->support), "button-release-event", - G_CALLBACK(gtk_graph_view_button_release), view); - g_signal_connect(G_OBJECT(view->support), "motion-notify-event", - G_CALLBACK(gtk_graph_view_motion_notify), view); - - gtk_widget_add_events(view->support, - GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK); - - gtk_widget_show(view->support); - - gtk_fixed_put(GTK_FIXED(view), view->support, 0, 0); - - //view->mutex = g_mutex_new(); - //view->cond = g_cond_new(); - - - view->extender = gtk_fixed_new(); - - gtk_widget_set_margin_end(view->extender, 1); - gtk_widget_set_margin_top(view->extender, 1); - - gtk_widget_show(view->extender); - - - view->cluster = NULL; - - -} - - -/****************************************************************************** -* * -* Paramètres : view = instance d'objet GLib à traiter. * -* * -* Description : Supprime toutes les références externes. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void gtk_graph_view_dispose(GtkGraphView *view) -{ - g_object_unref(G_OBJECT(view->extender)); - - if (view->cluster != NULL) - { - g_object_unref(G_OBJECT(view->cluster)); - view->cluster = NULL; - } - - G_OBJECT_CLASS(gtk_graph_view_parent_class)->dispose(G_OBJECT(view)); - -} - - -/****************************************************************************** -* * -* Paramètres : view = instance d'objet GLib à traiter. * -* * -* Description : Procède à la libération totale de la mémoire. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void gtk_graph_view_finalize(GtkGraphView *view) -{ - G_OBJECT_CLASS(gtk_graph_view_parent_class)->finalize(G_OBJECT(view)); - -} - - -/****************************************************************************** -* * -* Paramètres : widget = composant GTK à mettre à jour. * -* allocation = étendue accordée à la vue. * -* * -* Description : S'adapte à la surface concédée par le composant parent. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void gtk_graph_view_size_allocate(GtkWidget *widget, GtkAllocation *allocation) -{ - GtkGraphView *view; /* Autre version du composant */ - - GTK_WIDGET_CLASS(gtk_graph_view_parent_class)->size_allocate(widget, allocation); - - view = GTK_GRAPH_VIEW(widget); - - gtk_graph_view_update_support_margins(view, allocation); - -} - -/****************************************************************************** -* * -* Paramètres : view = panneau dont le contenu est à déplacer. * -* allocation = étendue accordée à la vue. * -* * -* Description : Centre si possible le contenu du panneau d'affichage. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void gtk_graph_view_update_support_margins(GtkGraphView *view, const GtkAllocation *allocation) -{ - gint width; /* Largeur totale du support */ - gint height; /* Hauteur totale du support */ - gint start; /* Bordure horizontale */ - gint top; /* Bordure verticale */ - - gtk_graph_view_compute_requested_size(view, &width, &height); - - if (width > allocation->width) - start = 0; - else - start = (allocation->width - width) / 2; - - if (height > allocation->height) - top = 0; - else - top = (allocation->height - height) / 2; - - gtk_widget_set_margin_start(view->support, start); - gtk_widget_set_margin_top(view->support, top); - -} - - -/****************************************************************************** -* * -* Paramètres : view = composant GTK à consulter. * -* width = largeur requise à renseigner ou NULL. [OUT] * -* height = hauteur requise à renseigner ou NULL. [OUT] * -* * -* Description : Indique les dimensions de travail du composant d'affichage. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void gtk_graph_view_compute_requested_size(GtkGraphView *view, gint *width, gint *height) -{ - GtkAllocation needed; /* Taille requise */ - gint rwidth; /* Largeur demandée */ - gint rheight; /* Hauteur demandée */ - - if (view->cluster != NULL) - { - g_graph_cluster_compute_needed_alloc(view->cluster, &needed); - assert(needed.x == 0 && needed.y == 0); - - /* TODO : marges ou centrage */ - - } - else - { - needed.width = 0; - needed.height = 0; - } - - if (width != NULL) *width = needed.width + SHADOW_SIZE; - if (height != NULL) *height = needed.height + SHADOW_SIZE; - -} - - -/****************************************************************************** -* * -* Paramètres : view = panneau d'affichage concerné. * -* adj = défilement dont une valeur a changé. * -* orientation = indication sur le défilement à traiter. * -* * -* Description : Réagit à un défilement chez une barre associée au composant. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void gtk_graph_view_adjust_scroll_value(GtkGraphView *view, GtkAdjustment *adj, GtkOrientation orientation) -{ - gint fake_x; /* Abscisse virtuelle */ - gint fake_y; /* Ordonnée virtuelle */ - - fake_x = 0; - fake_y = 0; - gtk_display_panel_compute_fake_coord(GTK_DISPLAY_PANEL(view), &fake_x, &fake_y); - - gtk_fixed_move(GTK_FIXED(view), view->support, fake_x, -fake_y); - -} - - -/****************************************************************************** -* * -* Paramètres : widget = composant GTK à redessiner. * -* cr = contexte graphique associé à l'événement. * -* view = support maître à consulter. * -* * -* Description : Met à jour l'affichage de la vue sous forme graphique. * -* * -* Retour : FALSE pour poursuivre la propagation de l'événement. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static gboolean gtk_graph_view_draw(GtkWidget *widget, cairo_t *cr, GtkGraphView *view) -{ - size_t i; /* Boucle de parcours */ - - void draw_shadow(GtkWidget *child, gpointer unused) - { - GtkAllocation alloc; /* Emplacement de l'enfant */ - gint j; /* Boucle de parcours */ - cairo_pattern_t *pattern; /* Zones d'application */ - - gtk_widget_get_allocation(child, &alloc); - - for (j = 1; j < SHADOW_SIZE; j++) - { - cairo_push_group(cr); - - gtk_display_panel_define_border_path(GTK_DISPLAY_PANEL(child), cr, alloc.x + j, alloc.y + j); - cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0); - cairo_fill(cr); - - cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); - - gtk_display_panel_define_border_path(GTK_DISPLAY_PANEL(child), cr, alloc.x, alloc.y); - cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 0.0); - cairo_fill(cr); - - pattern = cairo_pop_group(cr); - - cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 0.3); - cairo_mask(cr, pattern); - cairo_fill(cr); - - cairo_pattern_destroy(pattern); - - } - - } - - gtk_container_foreach(GTK_CONTAINER(view->support), (GtkCallback)draw_shadow, NULL); - - - for (i = 0; i < view->edges_count; i++) - g_graph_edge_draw(view->edges[i], cr, true); - - - /* - if (view->layout != NULL) - g_graph_layout_draw(view->layout, cr, true); - */ - - return FALSE; - -} - - -/****************************************************************************** -* * -* Paramètres : widget = composant GTK visé par l'opération. * -* event = informations liées à l'événement. * -* view = support maître à consulter. * -* * -* Description : Assure la gestion des clics de souris sur le composant. * -* * -* Retour : FALSE pour poursuivre la propagation de l'événement. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static gboolean gtk_graph_view_button_press(GtkWidget *widget, GdkEventButton *event, GtkGraphView *view) -{ - gboolean result; /* Poursuite à faire suivre */ - GtkScrolledWindow *support; /* Support défilant associé */ - GtkAdjustment *hadj; /* Gestionnaire du défilement */ - GtkAdjustment *vadj; /* Gestionnaire du défilement */ - GdkCursor *cursor; /* Pointeur pour la surface */ - - result = FALSE; - - if (event->button == 1) - { - support = GTK_SCROLLED_WINDOW(gtk_widget_get_parent(GTK_WIDGET(view))); - - hadj = gtk_scrolled_window_get_hadjustment(support); - vadj = gtk_scrolled_window_get_vadjustment(support); - - view->big_enough = (gtk_adjustment_get_upper(hadj) > gtk_adjustment_get_page_size(hadj) - || gtk_adjustment_get_upper(vadj) > gtk_adjustment_get_page_size(vadj)); - - if (view->big_enough) - { - view->start_x = event->x_root; - view->start_y = event->y_root; - - view->ref_h = gtk_adjustment_get_value(hadj); - view->ref_v = gtk_adjustment_get_value(vadj); - - cursor = gdk_cursor_new(GDK_FLEUR); - gdk_window_set_cursor(gtk_widget_get_window(widget), cursor); - g_object_unref(G_OBJECT(cursor)); - - result = TRUE; - - } - - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : widget = composant GTK visé par l'opération. * -* event = informations liées à l'événement. * -* view = support maître à consulter. * -* * -* Description : Assure la gestion des clics de souris sur le composant. * -* * -* Retour : FALSE pour poursuivre la propagation de l'événement. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static gboolean gtk_graph_view_button_release(GtkWidget *widget, GdkEventButton *event, GtkGraphView *view) -{ - if (event->button == 1 && view->big_enough) - gdk_window_set_cursor(gtk_widget_get_window(widget), NULL); - - return FALSE; - -} - - -/****************************************************************************** -* * -* Paramètres : widget = composant GTK visé par l'opération. * -* event = informations liées à l'événement. * -* view = support maître à consulter. * -* * -* Description : Assure la suivi des déplacements de souris sur le composant. * -* * -* Retour : FALSE pour poursuivre la propagation de l'événement. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static gboolean gtk_graph_view_motion_notify(GtkWidget *widget, GdkEventMotion *event, GtkGraphView *view) -{ - gdouble diff_x; /* Evolution sur les abscisses */ - gdouble diff_y; /* Evolution sur les ordonnées */ - GtkScrolledWindow *support; /* Support défilant associé */ - GtkAdjustment *hadj; /* Gestionnaire du défilement */ - GtkAdjustment *vadj; /* Gestionnaire du défilement */ - gdouble value; /* Nouvelle valeur bornée */ - - if (event->state & GDK_BUTTON1_MASK && view->big_enough) - { - diff_x = view->start_x - event->x_root; - diff_y = view->start_y - event->y_root; - - support = GTK_SCROLLED_WINDOW(gtk_widget_get_parent(GTK_WIDGET(view))); - - hadj = gtk_scrolled_window_get_hadjustment(support); - vadj = gtk_scrolled_window_get_vadjustment(support); - - value = CLAMP(view->ref_h + diff_x, gtk_adjustment_get_lower(hadj), - gtk_adjustment_get_upper(hadj) - gtk_adjustment_get_page_size(hadj)); - gtk_adjustment_set_value(hadj, value); - - value = CLAMP(view->ref_v + diff_y, gtk_adjustment_get_lower(vadj), - gtk_adjustment_get_upper(vadj) - gtk_adjustment_get_page_size(vadj)); - gtk_adjustment_set_value(vadj, value); - - } - - return FALSE; - -} - - -/****************************************************************************** -* * -* Paramètres : view = composant GTK à mettre à jour. * -* * -* Description : Actualise les besoins internes avant un redimensionnement. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void gtk_graph_view_prepare_resize(GtkGraphView *view) -{ - size_t i; /* Boucle de parcours */ - - if (view->children_count > 0) - { - for (i = 0; i < view->children_count; i++) - gtk_widget_queue_resize(GTK_WIDGET(view->children[i])); - - /* - g_graph_layout_refresh(view->layout); - g_graph_layout_place(view->layout, view); - */ - - change_editor_items_current_view_content(GTK_DISPLAY_PANEL(view)); - - } - -} - - -/****************************************************************************** -* * -* Paramètres : view = composant GTK à mettre à jour. * -* addr = adresse sélectionnée de manière externe. * -* * -* Description : Réagit à la sélection externe d'une adresse. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void gtk_graph_view_define_main_address(GtkGraphView *view, const vmpa2t *addr) -{ - bool need_update; /* Mise à jour du contenu ? */ - const mrange_t *range; /* Couverture courante */ - GExeFormat *format; /* Type de fichier chargé */ - GBinRoutine **routines; /* Liste des routines trouvées */ - size_t routines_count; /* Nombre de ces routines */ - size_t i; /* Boucle de parcours */ - gint right; /* Abscisse du coin droit */ - gint bottom; /* Ordonnée du coin inférieur */ - GtkAllocation allocation; /* Espace alloué au panneau */ - - if (view->routine == NULL) - need_update = true; - else - { - range = g_binary_routine_get_range(view->routine); - need_update = !mrange_contains_addr(range, addr); - } - - if (need_update) - { - gtk_graph_view_reset(view); - - format = g_loaded_binary_get_format(GTK_DISPLAY_PANEL(view)->binary); - routines = g_binary_format_get_routines(G_BIN_FORMAT(format), &routines_count); - - for (i = 0; i < routines_count; i++) - { - range = g_binary_routine_get_range(routines[i]); - - if (mrange_contains_addr(range, addr)) - { - view->routine = routines[i]; - g_object_ref(G_OBJECT(view->routine)); - - view->highlighted = init_segment_content_list(); - - /* - view->children = gtk_graph_view_load_nodes(view, GTK_DISPLAY_PANEL(view)->binary, - routines[i]); - - view->allocs = (GtkAllocation *)calloc(view->children_count, - sizeof(GtkAllocation)); - - view->layout = g_graph_layout_new(g_binary_routine_get_basic_blocks(view->routine), - view->children, view->children_count); - - g_graph_layout_place(view->layout, view); - */ - - do - { - - GBlockList *list; - - list = g_binary_routine_get_basic_blocks(routines[i]); - -#if 0 - view->cluster = g_graph_cluster_new(GTK_DISPLAY_PANEL(view)->binary, - list, 0/* FIXME */, view->highlighted); -#endif - - - view->cluster = bootstrap_graph_cluster(GTK_DISPLAY_PANEL(view)->binary, - list, view->highlighted); - - - - g_graph_cluster_place(view->cluster, view); - - /** - * Comme la taille du support ne peut pas être forcée et - * étendue pour comprendre les ombres, on place un composant - * minuscule à l'extrémité de ce support. - */ - - gtk_graph_view_compute_requested_size(view, &right, &bottom); - - g_object_ref(G_OBJECT(view->extender)); - gtk_fixed_put(GTK_FIXED(view->support), view->extender, right, bottom); - - /** - * Si possible, on centre le contenu obtenu. - */ - - gtk_widget_get_allocation(GTK_WIDGET(view), &allocation); - - gtk_graph_view_update_support_margins(view, &allocation); - - - - } - while (0); - - - - break; - - } - - } - - change_editor_items_current_view_content(GTK_DISPLAY_PANEL(view)); - - g_object_unref(G_OBJECT(format)); - - } - -} - - -/****************************************************************************** -* * -* Paramètres : view = composant GTK à manipuler. * -* * -* Description : Indique la position courante du curseur. * -* * -* Retour : Emplacement courant du curseur ou NULL si aucun. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static const vmpa2t *gtk_graph_view_get_caret_location(const GtkGraphView *view) -{ - return NULL; /* FIXME */ - -} - - -/****************************************************************************** -* * -* Paramètres : view = composant GTK à consulter. * -* addr = adresse à présenter à l'écran. * -* x = position horizontale au sein du composant. [OUT] * -* y = position verticale au sein du composant. [OUT] * -* tweak = adaptation finale à effectuer. * -* * -* Description : Indique la position d'affichage d'une adresse donnée. * -* * -* Retour : true si l'adresse fait partie du composant, false sinon. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool gtk_graph_view_get_address_coordinates(const GtkGraphView *view, const vmpa2t *addr, gint *x, gint *y, ScrollPositionTweak tweak) -{ - /* TODO */ - - return false; - -} - - -/****************************************************************************** -* * -* Paramètres : view = composant GTK à manipuler. * -* x = abscisse proposée pour le nouvel emplacement. * -* y = ordonnée proposée pour le nouvel emplacement. * -* * -* Description : Déplace le curseur à un emplacement défini. * -* * -* Retour : true si un traitement a été effectué, false sinon. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool gtk_graph_view_move_caret_to(GtkGraphView *view, gint x, gint y) -{ - bool result; /* Bilan à retourner */ - size_t i; /* Boucle de parcours */ - GtkDisplayPanel *panel; /* Autre vision d'enfance */ - gint sub_x; /* Abscisse relative à l'enfant*/ - gint sub_y; /* Ordonnée relative à l'enfant*/ - - result = false; - - for (i = 0; i < view->children_count; i++) - { - if (x < view->allocs[i].x || x >= (view->allocs[i].x + view->allocs[i].width)) continue; - if (y < view->allocs[i].y || y >= (view->allocs[i].y + view->allocs[i].height)) continue; - - panel = GTK_DISPLAY_PANEL(view->children[i]); - - sub_x = x - view->allocs[i].x; - sub_y = y - view->allocs[i].y; - - result = GTK_DISPLAY_PANEL_GET_CLASS(panel)->move_caret_to(panel, sub_x, sub_y); - break; - - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : view = composant GTK à manipuler. * -* cairo = assistant pour la création de rendus. * -* area = taille de la surface réduite à disposition. * -* scale = échelle vis à vis de la taille réelle. * -* * -* Description : Place en cache un rendu destiné à l'aperçu graphique rapide. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void gtk_graph_view_cache_glance(GtkGraphView *view, cairo_t *cairo, const GtkAllocation *area, double scale) -{ - size_t i; /* Boucle de parcours */ - GtkAllocation sub_area; /* Emplacement réservé */ - - for (i = 0; i < view->children_count; i++) - { - sub_area.x = view->allocs[i].x * scale; - sub_area.y = view->allocs[i].y * scale; - sub_area.width = view->allocs[i].width * scale + 1; - sub_area.height = view->allocs[i].height * scale + 1; - - gtk_display_panel_cache_glance(GTK_DISPLAY_PANEL(view->children[i]), cairo, &sub_area, scale); - - } - - cairo_scale(cairo, scale, scale); - - /* - if (view->layout != NULL) - g_graph_layout_draw(view->layout, cairo, false); - */ - -} - - -/****************************************************************************** -* * -* Paramètres : - * -* * -* Description : Crée un nouveau composant pour l'affichage en graphique. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -GtkWidget *gtk_graph_view_new(void) -{ - return g_object_new(GTK_TYPE_GRAPH_VIEW, NULL); - -} - - -/****************************************************************************** -* * -* Paramètres : view = composant GTK à mettre à jour. * -* widget = composant GTK à insérer. * -* x = abscisse du point d'insertion. * -* y = ordonnée du point d'insertion. * -* * -* Description : Place une vue sous forme de bloc dans le graphique. * -* * -* Retour : Plutôt que de redéfinir *toutes* les méthodes de * -* GtkContainer, on étend ! * -* * -* Remarques : - * -* * -******************************************************************************/ - -void gtk_graph_view_put(GtkGraphView *view, GtkWidget *widget, const GtkAllocation *alloc) -{ - size_t i; /* Boucle de parcours */ - GtkWidget *parent; /* Parent en cas de réajustemt.*/ - - /* - for (i = 0; i < view->children_count; i++) - if (GTK_WIDGET(view->children[i]) == widget) - { - view->allocs[i] = *alloc; - break; - } - - parent = gtk_widget_get_parent(widget); - - if (parent != NULL) - { - g_object_ref(G_OBJECT(widget)); - gtk_container_remove(GTK_CONTAINER(parent), widget); - } - */ - - gtk_fixed_put(GTK_FIXED(view->support), widget, alloc->x, alloc->y); - - /* - if (parent != NULL) - g_object_unref(G_OBJECT(widget)); - */ - -} - - - -/****************************************************************************** -* * -* Paramètres : view = composant GTK à mettre à jour. * -* edge = lien entre noeuds à conserver. * -* * -* Description : Intègre un lien entre blocs graphiques dans l'afficheur. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void gtk_graph_view_add_edge(GtkGraphView *view, GGraphEdge *edge) -{ - view->edges = (GGraphEdge **)realloc(view->edges, - ++view->edges_count * sizeof(GGraphEdge *)); - - view->edges[view->edges_count - 1] = edge; - -} - - -/****************************************************************************** -* * -* Paramètres : view = instance GTK à réinitialiser. * -* * -* Description : Supprime tout contenu de l'afficheur de code en graphique. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void gtk_graph_view_reset(GtkGraphView *view) -{ - size_t i; /* Boucle de parcours */ - - - void detach_all_blocks(GtkWidget *widget, GtkContainer *container) - { - - - - gtk_container_remove(container, widget); - - - } - - - gtk_container_foreach(GTK_CONTAINER(view->support), (GtkCallback)detach_all_blocks, view->support); - - - if (view->cluster != NULL) - { - g_object_unref(G_OBJECT(view->cluster)); - view->cluster = NULL; - } - - for (i = 0; i < view->edges_count; i++) - g_object_unref(G_OBJECT(view->edges[i])); - - if (view->edges_count > 0) - { - free(view->edges); - view->edges = NULL; - - view->edges_count = 0; - - } - - - /* - for (i = 0; i < view->links_count; i++) - gtk_object_destroy(GTK_OBJECT(view->links[i])); - - if (view->links_count > 0) - { - free(view->links); - view->links = NULL; - - view->links_count = 0; - - } - */ - - if (view->highlighted) - exit_segment_content_list(view->highlighted); - - for (i = 0; i < view->children_count; i++) - { - g_signal_handlers_disconnect_by_func(view->children[i], gtk_graph_view_reach_caret_limit, view); - gtk_widget_destroy(GTK_WIDGET(view->children[i])); - } - - if (view->children_count > 0) - { - free(view->children); - view->children = NULL; - free(view->allocs); - view->allocs = NULL; - - view->children_count = 0; - - } - -} - - -/****************************************************************************** -* * -* Paramètres : view = composant d'affichage GTK à mettre à jour. * -* routine = routine à présenter via ledit composant. * -* * -* Description : Définit la liste complète des éléments du futur graphique. * -* * -* Retour : Liste d'éléments du graphique à placer. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static GtkBufferView **gtk_graph_view_load_nodes(GtkGraphView *view, GLoadedBinary *binary, const GBinRoutine *routine) -{ - GtkBufferView **result; /* Liste à retourner */ - GCodeBuffer *buffer; /* Tampon brut à découper */ - size_t *count; /* Nombre d'éléments créés. */ - GInstrBlock *main_block; /* Premier bloc rattaché */ - GInstrBlock **blocks; /* Liste des blocs basiques */ - size_t i; /* Boucle de parcours */ - vmpa2t first; /* Début d'un groupe de lignes */ - vmpa2t last; /* Fin d'un groupe de lignes */ - GBufferView *subview; /* Partie affichée du tampon */ - - buffer = g_loaded_binary_get_disassembled_buffer(binary); - - count = &view->children_count; - - main_block = g_binary_routine_get_basic_blocks(routine); - - blocks = NULL; - *count = 0; - g_instr_block_list_all_blocks(main_block, &blocks, count); - - result = (GtkBufferView **)calloc(*count, sizeof(GtkBufferView *)); - - for (i = 0; i < *count; i++) - { - result[i] = GTK_BUFFER_VIEW(gtk_block_view_new()); - g_signal_connect(result[i], "reach-limit", G_CALLBACK(gtk_graph_view_reach_caret_limit), view); - g_signal_connect(result[i], "highlight-changed", G_CALLBACK(gtk_graph_view_changed_highlights), view); - - gtk_widget_show(GTK_WIDGET(result[i])); - gtk_display_panel_attach_binary(GTK_DISPLAY_PANEL(result[i]), binary, BVW_GRAPH); - - gtk_display_panel_show_border(GTK_DISPLAY_PANEL(result[i]), true); - - g_flow_block_get_boundary_addresses(G_FLOW_BLOCK(blocks[i]), &first, &last); - - subview = g_buffer_view_new(buffer, view->highlighted); - g_buffer_view_restrict(subview, &first, &last); - gtk_buffer_view_attach_buffer(result[i], subview); - - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : node = composant d'affichage GTK impliqué dans la procédure. * -* view = support graphique de tous les noeuds. * -* * -* Description : Notifie un changement de surbrillance au sein d'un noeud. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void gtk_graph_view_changed_highlights(GtkBlockView *node, GtkGraphView *view) -{ - size_t i; /* Boucle de parcours */ - - for (i = 0; i < view->children_count; i++) - { - if (view->children[i] == GTK_BUFFER_VIEW(node)) - continue; - - gtk_widget_queue_draw(GTK_WIDGET(view->children[i])); - - } - -} - - -/****************************************************************************** -* * -* Paramètres : node = composant d'affichage GTK impliqué dans la procédure. * -* dir = direction du déplacement souhaité et impossible. * -* view = support graphique de tous les noeuds. * -* * -* Description : Notifie une incapacité de déplacement au sein d'un noeud. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void gtk_graph_view_reach_caret_limit(GtkBufferView *node, GdkScrollDirection dir, GtkGraphView *view) -{ - GBufferView *bview; /* Vue d'un tampon global */ - vmpa2t first; /* Début d'un groupe de lignes */ - vmpa2t last; /* Fin d'un groupe de lignes */ - const mrange_t *range; /* Couverture courante */ - GArchProcessor *proc; /* Processeur pour instructions*/ - vmpa2t iaddr; /* Adresse du prochain saut */ - instr_iter_t *iter; /* Boucle de parcours */ - GArchInstruction *instr; /* Instruction à venir visiter */ -#ifndef NDEBUG - bool is_return; /* Est-ce une instruc. finale ?*/ -#endif - size_t i; /* Boucle de parcours */ - bool updated; /* Besoin d'une mise à jour ? */ - - /* Détermination de l'instruction à cibler */ - - bview = gtk_buffer_view_get_buffer(node); - g_buffer_view_get_restrictions(bview, &first, &last); - - range = g_binary_routine_get_range(view->routine); - - proc = g_loaded_binary_get_processor(GTK_DISPLAY_PANEL(view)->binary); - - init_vmpa(&iaddr, VMPA_NO_PHYSICAL, VMPA_NO_VIRTUAL); - -#ifndef NDEBUG - is_return = false; -#endif - - switch (dir) - { - case GDK_SCROLL_LEFT: - case GDK_SCROLL_UP: - - if (cmp_vmpa(get_mrange_addr(range), &first) != 0) - { - iter = g_arch_processor_get_iter_from_address(proc, &first); - - if (iter != NULL) - { - instr = get_instruction_iterator_prev(iter); - - if (instr != NULL) - { - /* TODO : boucler si !HAS_CODE */ - - if (mrange_contains_addr(range, &iaddr)) - copy_vmpa(&iaddr, get_mrange_addr(g_arch_instruction_get_range(instr))); - - g_object_unref(G_OBJECT(instr)); - - } - - delete_instruction_iterator(iter); - - } - - } - - break; - - case GDK_SCROLL_RIGHT: - case GDK_SCROLL_DOWN: - - iter = g_arch_processor_get_iter_from_address(proc, &last); - - if (iter != NULL) - { -#ifndef NDEBUG - instr = get_instruction_iterator_current(iter); - if (instr != NULL) - { - is_return = (g_arch_instruction_get_flags(instr) & AIF_RETURN_POINT); - g_object_unref(G_OBJECT(instr)); - } -#endif - - instr = get_instruction_iterator_next(iter); - - if (instr != NULL) - { - /* TODO : boucler si !HAS_CODE */ - - copy_vmpa(&iaddr, get_mrange_addr(g_arch_instruction_get_range(instr))); - - if (!mrange_contains_addr(range, &iaddr)) - init_vmpa(&iaddr, VMPA_NO_PHYSICAL, VMPA_NO_VIRTUAL); - - g_object_unref(G_OBJECT(instr)); - - } - - delete_instruction_iterator(iter); - - } - - break; - - case GDK_SCROLL_SMOOTH: - assert(0); /* Argument jamais généré */ - break; - - } - - g_object_unref(G_OBJECT(proc)); - - /* Recherche du bloc parent */ - - /* FIXME : valid ! */ - if (iaddr.physical == VMPA_NO_PHYSICAL && iaddr.virtual == VMPA_NO_VIRTUAL) - return; - - for (i = 0; i < view->children_count; i++) - { - bview = gtk_buffer_view_get_buffer(view->children[i]); - g_buffer_view_get_restrictions(bview, &first, &last); - - if (cmp_vmpa(&first, &iaddr) <= 0 && cmp_vmpa(&iaddr, &last) <= 0) - { - assert(node != view->children[i]); - break; - } - - } - - assert(i < view->children_count || is_return); - - /* Affichage du nouveau curseur */ - - /** - * Il se peut qu'aucune adresse suivante ne soit disponible : c'est typiquement - * le cas sous ARM, avec les valeurs brutes référencées dans le code. Ces valeurs - * sont incluses dans la surface couverte par la routine concernée, mais ne sont - * pas intégrées dans les blocs basiques associés. - */ - - if (i == view->children_count) - return; - - gtk_widget_grab_focus(GTK_WIDGET(view->children[i])); - - switch (dir) - { - case GDK_SCROLL_LEFT: - updated = gtk_buffer_view_move_caret_to(view->children[i], false, NULL); - break; - - case GDK_SCROLL_UP: - break; - - case GDK_SCROLL_RIGHT: - updated = gtk_buffer_view_move_caret_to(view->children[i], true, NULL); - break; - - case GDK_SCROLL_DOWN: - break; - - case GDK_SCROLL_SMOOTH: - assert(0); /* Argument jamais généré */ - break; - - } - - /* TODO : scrolling... */ - -} diff --git a/src/gtkext/gtkgraphview.h b/src/gtkext/gtkgraphview.h deleted file mode 100644 index eb3e6ad..0000000 --- a/src/gtkext/gtkgraphview.h +++ /dev/null @@ -1,64 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * gtkgraphview.h - prototypes pour l'affichage de morceaux de code sous forme graphique - * - * Copyright (C) 2009-2014 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 . - */ - - -#ifndef _GTKEXT_GTKGRAPHVIEW_H -#define _GTKEXT_GTKGRAPHVIEW_H - - -#include - - -#include "graph/edge.h" - - - -#define GTK_TYPE_GRAPH_VIEW (gtk_graph_view_get_type()) -#define GTK_GRAPH_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_GRAPH_VIEW, GtkGraphView)) -#define GTK_GRAPH_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GTK_TYPE_GRAPH_VIEW, GtkGraphViewClass)) -#define GTK_IS_GRAPH_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_GRAPH_VIEW)) -#define GTK_IS_GRAPH_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GTK_TYPE_GRAPH_VIEW)) -#define GTK_GRAPH_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_GRAPH_VIEW, GtkGraphViewClass)) - - -/* Composant d'affichage sous forme graphique (instance) */ -typedef struct _GtkGraphView GtkGraphView; - -/* Composant d'affichage sous forme graphique (classe) */ -typedef struct _GtkGraphViewClass GtkGraphViewClass; - - -/* Détermine le type du composant d'affichage en graphique. */ -GType gtk_graph_view_get_type(void); - -/* Crée un nouveau composant pour l'affichage en graphique. */ -GtkWidget *gtk_graph_view_new(void); - -/* Place une vue sous forme de bloc dans le graphique. */ -void gtk_graph_view_put(GtkGraphView *, GtkWidget *, const GtkAllocation *); - -/* Intègre un lien entre blocs graphiques dans l'afficheur. */ -void gtk_graph_view_add_edge(GtkGraphView *, GGraphEdge *); - - - -#endif /* _GTKEXT_GTKGRAPHVIEW_H */ diff --git a/src/gtkext/gtksourceview.c b/src/gtkext/gtksourceview.c deleted file mode 100644 index 0d2670b..0000000 --- a/src/gtkext/gtksourceview.c +++ /dev/null @@ -1,156 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * gtksourceview.c - affichage de code source - * - * Copyright (C) 2010-2012 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 . - */ - - -#include "gtksourceview.h" - - -#include "gtkbufferview-int.h" - - - -/* -------------------------- INTERACTION DIRECTE AVEC GTK -------------------------- */ - - -/* Composant d'affichage de code source (instance) */ -struct _GtkSourceView -{ - GtkBufferView parent; /* A laisser en premier */ - -}; - -/* Composant d'affichage de code source (classe) */ -struct _GtkSourceViewClass -{ - GtkBufferViewClass parent; /* A laisser en premier */ - -}; - - -/* Procède à l'initialisation de l'afficheur de code source. */ -static void gtk_source_view_class_init(GtkSourceViewClass *); - -/* Procède à l'initialisation de l'afficheur de code source. */ -static void gtk_source_view_init(GtkSourceView *); - -/* Prend acte de l'association d'un binaire chargé. */ -static void gtk_source_view_attach_binary(GtkSourceView *, GLoadedBinary *); - - - -/* ---------------------------------------------------------------------------------- */ -/* INTERACTION DIRECTE AVEC GTK */ -/* ---------------------------------------------------------------------------------- */ - - -/* Détermine le type du composant d'affichage de code source. */ -G_DEFINE_TYPE(GtkSourceView, gtk_source_view, GTK_TYPE_BUFFER_VIEW) - - -/****************************************************************************** -* * -* Paramètres : class = classe GTK à initialiser. * -* * -* Description : Procède à l'initialisation de l'afficheur de code source. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void gtk_source_view_class_init(GtkSourceViewClass *class) -{ - GtkDisplayPanelClass *panel_class; /* Classe parente */ - - panel_class = GTK_DISPLAY_PANEL_CLASS(class); - - panel_class->attach = (attach_binary_fc)gtk_source_view_attach_binary; - -} - - -/****************************************************************************** -* * -* Paramètres : view = composant GTK à initialiser. * -* * -* Description : Procède à l'initialisation de l'afficheur de code source. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void gtk_source_view_init(GtkSourceView *view) -{ - -} - - -/****************************************************************************** -* * -* Paramètres : - * -* * -* Description : Crée un nouveau composant pour l'affichage de code source. * -* * -* Retour : Composant GTK créé. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GtkWidget *gtk_source_view_new(void) -{ - GtkSourceView *result; /* Composant à retourner */ - - result = g_object_new(GTK_TYPE_SOURCE_VIEW, NULL); - - return GTK_WIDGET(result); - -} - - -/****************************************************************************** -* * -* Paramètres : view = composant GTK à mettre à jour. * -* binary = binaire associé à intégrer. * -* * -* Description : Prend acte de l'association d'un binaire chargé. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void gtk_source_view_attach_binary(GtkSourceView *view, GLoadedBinary *binary) -{ - GCodeBuffer *buffer; /* Tampon par défaut */ - - buffer = g_loaded_binary_get_decompiled_buffer(binary, -1); - - /* Si une source existe... */ - if (buffer != NULL) - gtk_buffer_view_attach_buffer(GTK_BUFFER_VIEW(view), g_buffer_view_new(buffer, NULL)); - -} diff --git a/src/gtkext/gtksourceview.h b/src/gtkext/gtksourceview.h deleted file mode 100644 index 3e4c7c6..0000000 --- a/src/gtkext/gtksourceview.h +++ /dev/null @@ -1,56 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * gtksourceview.h - prototypes pour l'affichage de code source - * - * Copyright (C) 2010-2014 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 . - */ - - -#ifndef _GTK_SOURCEVIEW_H -#define _GTK_SOURCEVIEW_H - - -#include -#include - - - -#define GTK_TYPE_SOURCE_VIEW (gtk_source_view_get_type()) -#define GTK_SOURCE_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_SOURCE_VIEW, GtkSourceView)) -#define GTK_SOURCE_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GTK_TYPE_SOURCE_VIEW, GtkSourceViewClass)) -#define GTK_IS_SOURCE_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_SOURCE_VIEW)) -#define GTK_IS_SOURCE_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GTK_TYPE_SOURCE_VIEW)) -#define GTK_SOURCE_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_SOURCE_VIEW, GtkSourceViewClass)) - - -/* Composant d'affichage de code source (instance) */ -typedef struct _GtkSourceView GtkSourceView; - -/* Composant d'affichage de code source (classe) */ -typedef struct _GtkSourceViewClass GtkSourceViewClass; - - -/* Détermine le type du composant d'affichage de code source. */ -GType gtk_source_view_get_type(void); - -/* Crée un nouveau composant pour l'affichage de code source. */ -GtkWidget *gtk_source_view_new(void); - - - -#endif /* _GTK_SOURCEVIEW_H */ diff --git a/src/gui/dialogs/export.c b/src/gui/dialogs/export.c index c16e7d8..b39a5c1 100644 --- a/src/gui/dialogs/export.c +++ b/src/gui/dialogs/export.c @@ -49,7 +49,7 @@ static void export_assistant_cancel(GtkAssistant *, gpointer); static void export_assistant_close(GtkAssistant *, GObject *); /* Réalise l'exportation d'un contenu binaire comme demandé. */ -static void do_binary_export(GCodeBuffer *, const vmpa2t *, const vmpa2t *, buffer_export_context *, BufferExportType, const bool *); +static void do_binary_export(void/*GCodeBuffer*/ *, const vmpa2t *, const vmpa2t *, buffer_export_context *, BufferExportType, const bool *); @@ -181,6 +181,8 @@ static void export_assistant_cancel(GtkAssistant *assistant, gpointer data) static void export_assistant_close(GtkAssistant *assistant, GObject *ref) { +#if 0 + GtkComboBox *combo; /* Selection du format */ BufferExportType type; /* Type d'exportation requise */ buffer_export_context ctx; /* Contexte à constituer */ @@ -283,7 +285,7 @@ static void export_assistant_close(GtkAssistant *assistant, GObject *ref) support = G_OBJECT(g_object_get_data(G_OBJECT(assistant), "html_options")); if (support != NULL) g_object_unref(support); - +#endif gtk_widget_destroy(GTK_WIDGET(assistant)); } @@ -306,8 +308,9 @@ static void export_assistant_close(GtkAssistant *assistant, GObject *ref) * * ******************************************************************************/ -static void do_binary_export(GCodeBuffer *buffer, const vmpa2t *start, const vmpa2t *end, buffer_export_context *ctx, BufferExportType type, const bool *display) +static void do_binary_export(void/*GCodeBuffer*/ *buffer, const vmpa2t *start, const vmpa2t *end, buffer_export_context *ctx, BufferExportType type, const bool *display) { +#if 0 typedef struct _export_data { buffer_export_context *ctx; /* Contexte d'exportation */ @@ -373,7 +376,7 @@ static void do_binary_export(GCodeBuffer *buffer, const vmpa2t *start, const vmp default: break; } - +#endif } diff --git a/src/gui/dialogs/gotox.c b/src/gui/dialogs/gotox.c index 872cd4f..abd9377 100644 --- a/src/gui/dialogs/gotox.c +++ b/src/gui/dialogs/gotox.c @@ -342,6 +342,7 @@ GtkWidget *create_gotox_dialog_for_cross_references(GtkWindow *parent, GLoadedBi static void add_new_location_to_list(GtkTreeStore *store, GLoadedBinary *binary, const vmpa2t *addr, GBinSymbol *hint) { +#if 0 GCodeBuffer *buffer; /* Tampon de désassemblage */ GBufferLine *line; /* Ligne présente à l'adresse */ char *virtual; /* Transcription d'adresse */ @@ -465,7 +466,7 @@ static void add_new_location_to_list(GtkTreeStore *store, GLoadedBinary *binary, if (line != NULL) g_object_unref(G_OBJECT(line)); - +#endif } diff --git a/src/gui/editem-int.h b/src/gui/editem-int.h index 919e8ae..f77cf99 100644 --- a/src/gui/editem-int.h +++ b/src/gui/editem-int.h @@ -33,7 +33,6 @@ #include "../common/dllist.h" -#include "../gtkext/gtkbufferview.h" #include "../gtkext/gtkdisplaypanel.h" diff --git a/src/gui/editem.c b/src/gui/editem.c index fc502a0..0ec2d72 100644 --- a/src/gui/editem.c +++ b/src/gui/editem.c @@ -27,7 +27,6 @@ #include "editem-int.h" #include "../analysis/db/items/move.h" -#include "../gtkext/gtkblockview.h" @@ -250,10 +249,14 @@ void change_editor_items_current_binary(GObject *ref, GLoadedBinary *binary) GEditorItem *iter; /* Boucle de parcours */ GEditorItemClass *klass; /* Classe correspondante */ - if (binary != NULL) - g_object_ref(G_OBJECT(binary)); + if (binary == NULL) + g_object_set_data(ref, "current_binary", NULL); - g_object_set_data_full(ref, "current_binary", binary, g_object_unref); + else + { + g_object_ref(G_OBJECT(binary)); + g_object_set_data_full(ref, "current_binary", binary, g_object_unref); + } editem_list_for_each(iter, _editem_list) { diff --git a/src/gui/editor.c b/src/gui/editor.c index f8922a1..7322ed7 100644 --- a/src/gui/editor.c +++ b/src/gui/editor.c @@ -41,7 +41,6 @@ #include "panels/panel.h" #include "panels/welcome.h" #include "tb/portions.h" -#include "tb/source.h" #include "../analysis/project.h" #include "../common/extstr.h" #include "../core/params.h" @@ -481,9 +480,6 @@ static GtkWidget *build_editor_toolbar(GObject *ref) g_object_set_data(ref, "toolbar", result); - item = create_source_tb_item(ref); - register_editor_item(item); - item = create_portions_tb_item(ref); register_editor_item(item); @@ -1097,7 +1093,7 @@ void on_panel_item_dock_request(GPanelItem *panel, void *unused) if (!g_welcome_panel_get_user_origin(G_WELCOME_PANEL(welcome))) { /* Equivalent d'un appel "g_panel_item_undock(welcome)", avec effet immédiat */ - on_panel_item_undock_request(welcome, NULL); + /////on_panel_item_undock_request(welcome, NULL); } } diff --git a/src/gui/menus/edition.c b/src/gui/menus/edition.c index 89b5fe9..d5ef541 100644 --- a/src/gui/menus/edition.c +++ b/src/gui/menus/edition.c @@ -37,7 +37,6 @@ #include "../../analysis/db/items/switcher.h" #include "../../arch/target.h" #include "../../gtkext/easygtk.h" -#include "../../gtkext/gtkbufferview.h" diff --git a/src/gui/menus/view.c b/src/gui/menus/view.c index 9447724..2b3f37e 100644 --- a/src/gui/menus/view.c +++ b/src/gui/menus/view.c @@ -25,6 +25,9 @@ #include "view.h" +#include + + #include @@ -32,6 +35,8 @@ #include "../core/panels.h" #include "../../analysis/project.h" #include "../../gtkext/easygtk.h" +#include "../../gtkext/gtkblockdisplay.h" +#include "../../gtkext/gtkgraphdisplay.h" @@ -100,6 +105,7 @@ GtkWidget *build_menu_view(GObject *ref, GtkAccelGroup *accgroup, GMenuBar *bar) G_CALLBACK(mcb_view_change_support), bar); add_accelerator_to_menu_item(submenuitem, "F3", accgroup); g_object_set_data(G_OBJECT(submenuitem), "kind_of_view", GUINT_TO_POINTER(BVW_BLOCK)); + g_object_set_data(G_OBJECT(submenuitem), "kind_of_display", GSIZE_TO_POINTER(GTK_TYPE_BLOCK_DISPLAY)); gtk_container_add(GTK_CONTAINER(menubar), submenuitem); rgroup = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(submenuitem)); @@ -108,14 +114,7 @@ GtkWidget *build_menu_view(GObject *ref, GtkAccelGroup *accgroup, GMenuBar *bar) G_CALLBACK(mcb_view_change_support), bar); add_accelerator_to_menu_item(submenuitem, "F4", accgroup); g_object_set_data(G_OBJECT(submenuitem), "kind_of_view", GUINT_TO_POINTER(BVW_GRAPH)); - gtk_container_add(GTK_CONTAINER(menubar), submenuitem); - - rgroup = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(submenuitem)); - - submenuitem = qck_create_radio_menu_item(ref, "mnu_view_switch_sourceview", rgroup, _("Source code"), - G_CALLBACK(mcb_view_change_support), bar); - add_accelerator_to_menu_item(submenuitem, "F5", accgroup); - g_object_set_data(G_OBJECT(submenuitem), "kind_of_view", GUINT_TO_POINTER(BVW_SOURCE)); + g_object_set_data(G_OBJECT(submenuitem), "kind_of_display", GSIZE_TO_POINTER(GTK_TYPE_GRAPH_DISPLAY)); gtk_container_add(GTK_CONTAINER(menubar), submenuitem); /* - */ @@ -174,6 +173,9 @@ GtkWidget *build_menu_view(GObject *ref, GtkAccelGroup *accgroup, GMenuBar *bar) void update_menu_view_for_view(GtkWidget *widget, GtkDisplayPanel *panel, GMenuBar *bar) { GObject *ref; /* Espace de référencements */ + GtkRadioMenuItem *item; /* Elément de menu arbitraire */ + GSList *radios; /* Liste des menus d'affichage */ + GSList *found; /* Elément de menu à activer */ GLoadedBinary *binary; /* Binaire courant */ BinaryView content; /* Type de vue active */ const bool *display; /* Règles d'affichage courantes*/ @@ -182,6 +184,49 @@ void update_menu_view_for_view(GtkWidget *widget, GtkDisplayPanel *panel, GMenuB ref = g_editor_item_get_global_ref(G_EDITOR_ITEM(bar)); + /* Types de panneau de code */ + + item = GTK_RADIO_MENU_ITEM(g_object_get_data(ref, "mnu_view_switch_graphview")); + + radios = gtk_radio_menu_item_get_group(item); + + void disconnect_display_radio(GtkWidget *wgt, gpointer unused) + { + g_signal_handlers_disconnect_by_func(wgt, G_CALLBACK(mcb_view_change_support), bar); + + } + + g_slist_foreach(radios, (GFunc)disconnect_display_radio, NULL); + + gint find_suitable_display_radio(GObject *rdo, GObject *pnl) + { + GType rdo_type; /* Type d'affichage supporté */ + GType pnl_type; /* Type du panneau affiché */ + + rdo_type = GPOINTER_TO_SIZE(g_object_get_data(rdo, "kind_of_display")); + + pnl_type = G_OBJECT_TYPE(pnl); + + return (rdo_type == pnl_type ? 0 : -1); + + } + + found = g_slist_find_custom(radios, G_OBJECT(panel), (GCompareFunc)find_suitable_display_radio); + + assert(found != NULL); + + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(found->data), TRUE); + + void reconnect_display_radio(GtkWidget *wgt, gpointer unused) + { + g_signal_connect(wgt, "toggled", G_CALLBACK(mcb_view_change_support), bar); + + } + + g_slist_foreach(radios, (GFunc)reconnect_display_radio, NULL); + + /* - */ + binary = g_editor_item_get_current_binary(G_EDITOR_ITEM(bar)); content = gtk_display_panel_describe_content(panel); @@ -246,17 +291,6 @@ void update_access_in_menu_view(GObject *ref, GtkDisplayPanel *panel) access = (panel != NULL); - /* Types de panneau de code */ - - item = GTK_WIDGET(g_object_get_data(ref, "mnu_view_switch_textview")); - gtk_widget_set_sensitive(item, access); - - item = GTK_WIDGET(g_object_get_data(ref, "mnu_view_switch_graphview")); - gtk_widget_set_sensitive(item, access); - - item = GTK_WIDGET(g_object_get_data(ref, "mnu_view_switch_sourceview")); - gtk_widget_set_sensitive(item, access); - /* Affichage des données */ item = GTK_WIDGET(g_object_get_data(ref, "mnu_view_display_off")); @@ -450,7 +484,8 @@ static void mcb_view_change_support(GtkRadioMenuItem *menuitem, GMenuBar *bar) station = get_dock_station_for_view_panel(panel); /* En vue du retrait de la station d'accueil... */ - g_object_ref(G_OBJECT(panel)); + scroll = get_scroll_window_for_view_panel(panel); + g_object_ref(G_OBJECT(scroll)); panel = get_alt_view_for_view_panel(panel, wanted); scroll = get_scroll_window_for_view_panel(panel); diff --git a/src/gui/status.c b/src/gui/status.c index fc8eafd..daa5f91 100644 --- a/src/gui/status.c +++ b/src/gui/status.c @@ -36,8 +36,7 @@ #include "editem-int.h" #include "core/global.h" #include "../common/extstr.h" -#include "../gtkext/gtkbufferview.h" -#include "../gtkext/gtkblockview.h" +#include "../gtkext/gtkbufferdisplay.h" #include "../gtkext/gtkstatusstack.h" @@ -71,7 +70,7 @@ static void g_status_info_dispose(GStatusInfo *); static void g_status_info_finalize(GStatusInfo *); /* Imprime la position du parcours courant dans le statut. */ -static void track_caret_address_for_status_info(GStatusInfo *, GtkBufferView *, const vmpa2t *); +static void track_caret_address_for_status_info(GStatusInfo *, GtkBufferDisplay *, const vmpa2t *); /* Concentre l'attention de l'ensemble sur une adresse donnée. */ static void focus_address_in_status_info(GStatusInfo *, GLoadedBinary *, const vmpa2t *); @@ -209,9 +208,9 @@ GEditorItem *g_status_info_new(GObject *ref) /****************************************************************************** * * -* Paramètres : info = barre de statut présentant les informations. * -* view = composant d'affichage parcouru. * -* addr = nouvelle adresse du curseur courant. * +* Paramètres : info = barre de statut présentant les informations. * +* display = composant d'affichage parcouru. * +* addr = nouvelle adresse du curseur courant. * * * * Description : Imprime la position du parcours courant dans le statut. * * * @@ -221,7 +220,7 @@ GEditorItem *g_status_info_new(GObject *ref) * * ******************************************************************************/ -static void track_caret_address_for_status_info(GStatusInfo *info, GtkBufferView *view, const vmpa2t *addr) +static void track_caret_address_for_status_info(GStatusInfo *info, GtkBufferDisplay *display, const vmpa2t *addr) { GEditorItem *item; /* Autre version de l'élément */ GLoadedBinary *binary; /* Binaire courant */ @@ -257,7 +256,7 @@ static void focus_address_in_status_info(GStatusInfo *info, GLoadedBinary *binar item = G_EDITOR_ITEM(info); - if (addr == NULL) + if (is_invalid_vmpa(addr)) gtk_status_stack_reset_current_instruction(GTK_STATUS_STACK(item->widget)); else diff --git a/src/gui/tb/Makefile.am b/src/gui/tb/Makefile.am index 60aa031..b8559f7 100644 --- a/src/gui/tb/Makefile.am +++ b/src/gui/tb/Makefile.am @@ -3,7 +3,6 @@ noinst_LTLIBRARIES = libguitb.la libguitb_la_SOURCES = \ portions.h portions.c \ - source.h source.c \ tbitem-int.h \ tbitem.h tbitem.c diff --git a/src/gui/tb/source.c b/src/gui/tb/source.c deleted file mode 100644 index 504c532..0000000 --- a/src/gui/tb/source.c +++ /dev/null @@ -1,321 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * source.c - sélection du fichier ciblé lors d'une décompilation - * - * Copyright (C) 2010-2013 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 "source.h" - - -#include - - -#include "tbitem-int.h" -#include "../../format/format.h" -#include "../../gtkext/easygtk.h" -#include "../../gtkext/gtkbufferview.h" -#include "../../gtkext/gtksourceview.h" - - - -/* Elément réactif listant les fichiers décompilés (instance) */ -struct _GSourceTbItem -{ - GToolbarItem parent; /* A laisser en premier */ - -}; - - -/* Elément réactif listant les fichiers décompilés (classe) */ -struct _GSourceTbItemClass -{ - GToolbarItemClass parent; /* A laisser en premier */ - -}; - - - -/* Initialise la classe des éléments réactifs de l'éditeur. */ -static void g_source_tbitem_class_init(GSourceTbItemClass *); - -/* Initialise une instance d'élément réactif pour l'éditeur. */ -static void g_source_tbitem_init(GSourceTbItem *); - -/* Supprime toutes les références externes. */ -static void g_source_tbitem_dispose(GSourceTbItem *); - -/* Procède à la libération totale de la mémoire. */ -static void g_source_tbitem_finalize(GSourceTbItem *); - -/* Réagit à un changement du binaire courant. */ -static void update_source_item_binary(GEditorItem *, GLoadedBinary *); - -/* Réagit à un changement de panneau d'affichage courant. */ -static void update_source_item_view(GEditorItem *, GtkDisplayPanel *); - -/* Réagit à un changement de sélection de la source courante. */ -static void change_selected_source(GtkComboBox *, GSourceTbItem *); - - - -/* Indique le type défini pour une liste de fichiers destinée à une barre d'outils. */ -G_DEFINE_TYPE(GSourceTbItem, g_source_tbitem, G_TYPE_TOOLBAR_ITEM); - - -/****************************************************************************** -* * -* Paramètres : klass = classe à initialiser. * -* * -* Description : Initialise la classe des éléments réactifs de l'éditeur. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_source_tbitem_class_init(GSourceTbItemClass *klass) -{ - GObjectClass *object; /* Autre version de la classe */ - GEditorItemClass *item; /* Encore une autre vision */ - - object = G_OBJECT_CLASS(klass); - item = G_EDITOR_ITEM_CLASS(klass); - - object->dispose = (GObjectFinalizeFunc/* ! */)g_source_tbitem_dispose; - object->finalize = (GObjectFinalizeFunc)g_source_tbitem_finalize; - - item->update_binary = update_source_item_binary; - item->update_view = update_source_item_view; - -} - - -/****************************************************************************** -* * -* Paramètres : item = instance à initialiser. * -* * -* Description : Initialise une instance d'élément réactif pour l'éditeur. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_source_tbitem_init(GSourceTbItem *item) -{ - GtkWidget *widget; /* Composant principal */ - GtkWidget *hbox; /* Support interne */ - GtkWidget *label; /* Etiquette d'introduction */ - GtkWidget *comboboxentry; /* Liste de fichiers */ - - widget = GTK_WIDGET(gtk_tool_item_new()); - gtk_widget_show(widget); - - G_EDITOR_ITEM(item)->widget = widget; - - hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8); - gtk_widget_show(hbox); - gtk_container_add(GTK_CONTAINER(widget), hbox); - - label = qck_create_label(G_OBJECT(widget), "label", _(" Source: ")); - gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); - - comboboxentry = qck_create_combobox2(G_OBJECT(widget), "combo", - G_CALLBACK(change_selected_source), item); - gtk_box_pack_start(GTK_BOX(hbox), comboboxentry, TRUE, TRUE, 0); - -} - - -/****************************************************************************** -* * -* Paramètres : item = instance d'objet GLib à traiter. * -* * -* Description : Supprime toutes les références externes. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_source_tbitem_dispose(GSourceTbItem *item) -{ - G_OBJECT_CLASS(g_source_tbitem_parent_class)->dispose(G_OBJECT(item)); - -} - - -/****************************************************************************** -* * -* Paramètres : item = instance d'objet GLib à traiter. * -* * -* Description : Procède à la libération totale de la mémoire. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_source_tbitem_finalize(GSourceTbItem *item) -{ - G_OBJECT_CLASS(g_source_tbitem_parent_class)->finalize(G_OBJECT(item)); - -} - - -/****************************************************************************** -* * -* Paramètres : ref = espace de référencement global. * -* * -* Description : Crée un élément réactif présentant des source de binaire. * -* * -* Retour : Adresse de la structure d'encadrement mise en place. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GEditorItem *create_source_tb_item(GObject *ref) -{ - GSourceTbItem *result; /* Structure à retourner */ - - result = g_object_new(G_TYPE_SOURCE_TBITEM, NULL); - - return g_toolbar_item_setup(G_TOOLBAR_ITEM(result), ref, "source", _("Source files")); - -} - - -/****************************************************************************** -* * -* Paramètres : item = élément réactif sollicité. * -* binary = binaire chargé nouvellement affiché. * -* * -* Description : Réagit à un changement du binaire courant. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void update_source_item_binary(GEditorItem *item, GLoadedBinary *binary) -{ -#if 0 - GtkComboBoxText *combo; /* Liste de sélection */ - GtkTreeModel *model; /* Gestionnaire d'éléments */ - GtkTreeIter iter; /* Boucle de parcours #2 */ - GExeFormat *format; /* Format d'exécutable associé */ - size_t count; /* Quantité de fichiers */ - size_t defsrc; /* Fichier source principal */ - const char * const *files; /* Liste de fichiers source */ - size_t i; /* Boucle de parcours #2 */ - - combo = GTK_COMBO_BOX_TEXT(g_object_get_data(G_OBJECT(item->widget), "combo")); - - /* Réinitialisation */ - - g_signal_handlers_block_by_func(combo, G_CALLBACK(change_selected_source), item); - - /* FIXME : 3.0 */ - //gtk_combo_box_text_remove_all(combo); - - model = gtk_combo_box_get_model(GTK_COMBO_BOX(combo)); - - while (gtk_tree_model_get_iter_first(model, &iter)) - gtk_combo_box_text_remove(combo, 0); - - /* Inscriptions */ - - format = g_loaded_binary_get_format(binary); - files = g_binary_format_get_source_files(G_BIN_FORMAT(format), &count, &defsrc); - - for (i = 0; i < count; i++) - gtk_combo_box_text_append_text(combo, files[i]); - - /* Réactivation */ - - g_signal_handlers_unblock_by_func(combo, G_CALLBACK(change_selected_source), item); - - //gtk_combo_box_set_active(combo, defsrc); - - g_object_unref(G_OBJECT(format)); - -#endif -} - - -/****************************************************************************** -* * -* Paramètres : item = élément réactif sollicité. * -* panel = nouveau panneau d'affichage actif. * -* * -* Description : Réagit à un changement de panneau d'affichage courant. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void update_source_item_view(GEditorItem *item, GtkDisplayPanel *panel) -{ - gtk_widget_set_sensitive(item->widget, GTK_IS_SOURCE_VIEW(panel)); - -} - - -/****************************************************************************** -* * -* Paramètres : widget = composant GTK en cause. * -* item = élément réactif associé. * -* * -* Description : Réagit à un changement de sélection de la source courante. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void change_selected_source(GtkComboBox *widget, GSourceTbItem *item) -{ -#if 0 - gint index; /* Nouvelle source ciblée */ - GLoadedBinary *binary; /* Binaire chargé courant */ - GCodeBuffer *buffer; /* Nouveau tampon à présenter */ - GtkBufferView *view; /* Afficheur de tampons */ - - index = gtk_combo_box_get_active(widget); - - binary = G_LOADED_BINARY(g_object_get_data(ref, "current_binary")); - buffer = g_loaded_binary_get_decompiled_buffer(binary, index); - - view = GTK_BUFFER_VIEW(g_object_get_data(ref, /*"current_view"*/)); /* TODO : utiliser g_editor_item_get_current_view() */ - if (GTK_IS_BUFFER_VIEW(view)) - gtk_buffer_view_attach_buffer(view, buffer, - g_loaded_binary_display_decomp_lines(binary), NULL); -#endif -} diff --git a/src/gui/tb/source.h b/src/gui/tb/source.h deleted file mode 100644 index 760238d..0000000 --- a/src/gui/tb/source.h +++ /dev/null @@ -1,56 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * source.h - prototypes pour la sélection du fichier ciblé lors d'une décompilation - * - * Copyright (C) 2010-2014 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_TB_SOURCE_H -#define _GUI_TB_SOURCE_H - - -#include "tbitem.h" - - - -#define G_TYPE_SOURCE_TBITEM g_source_tbitem_get_type() -#define G_SOURCE_TBITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_source_tbitem_get_type(), GToolbarItem)) -#define G_IS_SOURCE_TBITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_source_tbitem_get_type())) -#define G_SOURCE_TBITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SOURCE_TBITEM, GToolbarItemClass)) -#define G_IS_SOURCE_TBITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SOURCE_TBITEM)) -#define G_SOURCE_TBITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SOURCE_TBITEM, GToolbarItemClass)) - - -/* Elément réactif listant les fichiers décompilés (instance) */ -typedef struct _GSourceTbItem GSourceTbItem; - -/* Elément réactif listant les fichiers décompilés (classe) */ -typedef struct _GSourceTbItemClass GSourceTbItemClass; - - -/* Indique le type défini pour une liste de fichiers destinée à une barre d'outils. */ -GType g_source_tbitem_get_type(void); - -/* Crée une sélection de fichier réactive pour barre d'outils. */ -GEditorItem *create_source_tb_item(GObject *ref); - - - -#endif /* _GUI_TB_SOURCE_H */ diff --git a/src/plugins/plugin.h b/src/plugins/plugin.h index fda42e4..4c6ffa6 100644 --- a/src/plugins/plugin.h +++ b/src/plugins/plugin.h @@ -32,6 +32,7 @@ #include "plugin-def.h" #include "../analysis/binary.h" #include "../format/format.h" +#include "../gtkext/gtkstatusstack.h" -- cgit v0.11.2-87-g4458