From 77f88a59bfb9296df7e995e99218d27862136588 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Thu, 27 Jul 2017 19:13:19 +0200
Subject: Fixed several mistakes in the Python bindings.

---
 ChangeLog                               |  41 ++++
 plugins/pychrysa/arch/instruction.c     | 215 +----------------
 plugins/pychrysa/glibext/Makefile.am    |   1 +
 plugins/pychrysa/glibext/linegen.c      | 404 ++++++++++++++++++++++++++++++++
 plugins/pychrysa/glibext/linegen.h      |  42 ++++
 plugins/pychrysa/glibext/module.c       |   2 +
 plugins/pychrysa/gtkext/Makefile.am     |   1 +
 plugins/pychrysa/gtkext/blockdisplay.c  |  15 +-
 plugins/pychrysa/gtkext/bufferdisplay.c |  15 +-
 plugins/pychrysa/gtkext/displaypanel.c  |  35 ++-
 plugins/pychrysa/gtkext/dockable.c      | 102 ++++++++
 plugins/pychrysa/gtkext/dockable.h      |  42 ++++
 plugins/pychrysa/gtkext/module.c        |   2 +
 plugins/pychrysa/gui/panels/panel.c     |   4 +-
 plugins/pychrysa/helpers.c              |  35 ++-
 plugins/pychrysa/helpers.h              |   5 +-
 plugins/pychrysa/pychrysa.c             |  86 ++++++-
 src/glibext/generator-int.h             |  52 ----
 18 files changed, 816 insertions(+), 283 deletions(-)
 create mode 100644 plugins/pychrysa/glibext/linegen.c
 create mode 100644 plugins/pychrysa/glibext/linegen.h
 create mode 100644 plugins/pychrysa/gtkext/dockable.c
 create mode 100644 plugins/pychrysa/gtkext/dockable.h
 delete mode 100644 src/glibext/generator-int.h

diff --git a/ChangeLog b/ChangeLog
index 840d83b..d11ea68 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,44 @@
+17-07-27  Cyrille Bagard <nocbos@gmail.com>
+
+	* plugins/pychrysa/arch/instruction.c:
+	Add LineGenerator as base for architecture instructions.
+
+	* plugins/pychrysa/glibext/Makefile.am:
+	Add the 'linegen.[ch]' files to libpychrysaglibext_la_SOURCES.
+
+	* plugins/pychrysa/glibext/linegen.c:
+	* plugins/pychrysa/glibext/linegen.h:
+	New entries: register the LineGenerator interface for Python.
+
+	* plugins/pychrysa/glibext/module.c:
+	Update code.
+
+	* plugins/pychrysa/gtkext/Makefile.am:
+	Add the 'dockable.[ch]' files to libpychrysagtkext_la_SOURCES.
+
+	* plugins/pychrysa/gtkext/blockdisplay.c:
+	* plugins/pychrysa/gtkext/bufferdisplay.c:
+	* plugins/pychrysa/gtkext/displaypanel.c:
+	Mark all panels with the Py_TPFLAGS_HEAPTYPE flag.
+
+	* plugins/pychrysa/gtkext/dockable.c:
+	* plugins/pychrysa/gtkext/dockable.h:
+	New entries: register the GtkDockable interface for Python.
+
+	* plugins/pychrysa/gtkext/module.c:
+	Update code.
+
+	* plugins/pychrysa/gui/panels/panel.c:
+	Mark the panel with the Py_TPFLAGS_HEAPTYPE flag.
+
+	* plugins/pychrysa/helpers.c:
+	* plugins/pychrysa/helpers.h:
+	Allow to register a type with several bases.
+
+	* plugins/pychrysa/pychrysa.c:
+	Improve the code. Define the required version of GTK to load. Use colons
+	as separators in PYTHONPATH.
+
 17-07-26  Cyrille Bagard <nocbos@gmail.com>
 
 	* src/gtkext/easygtk.c:
diff --git a/plugins/pychrysa/arch/instruction.c b/plugins/pychrysa/arch/instruction.c
index 0efca5a..61d1987 100644
--- a/plugins/pychrysa/arch/instruction.c
+++ b/plugins/pychrysa/arch/instruction.c
@@ -34,6 +34,7 @@
 
 #include "vmpa.h"
 #include "../helpers.h"
+#include "../glibext/linegen.h"
 
 
 
@@ -440,6 +441,7 @@ bool register_python_arch_instruction(PyObject *module)
 {
     PyTypeObject *py_arch_instruction_type; /* Type Python 'ArchInstruc...'*/
     PyObject *dict;                         /* Dictionnaire du module      */
+    PyTypeObject *py_line_generator_type;   /* Type Python 'LineGenerator' */
 
     py_arch_instruction_type = get_python_arch_instruction_type();
 
@@ -447,217 +449,12 @@ bool register_python_arch_instruction(PyObject *module)
 
     dict = PyModule_GetDict(module);
 
-    if (!register_class_for_pygobject(dict, G_TYPE_ARCH_INSTRUCTION, py_arch_instruction_type, &PyGObject_Type))
-        return false;
-
-    return true;
-
-}
-
-
-
-
-
-
-
-#if 0
-
-
-#include <pygobject.h>
-#include <stdbool.h>
-#include <string.h>
-
-
-#include <arch/instruction.h>
-
-
-#include "../quirks.h"
-
-
-
-/* --------------------- INSTRUCTIONS D'ARCHITECTURES EN PYTHON --------------------- */
-
-
-/* Crée un nouvel objet Python de type 'ArchInstruction'. */
-static PyObject *py_arch_instruction_new(PyTypeObject *, PyObject *, PyObject *);
-
-/* Prépare un parcours d'instructions. */
-static PyObject *py_arch_instruction_get_iter(PyObject *);
-
-/* Fournit la valeur associée à une propriété donnée. */
-static PyObject *py_arch_instruction_get_location(PyObject *, char *);
-
-/* Fournit le nom humain de l'instruction manipulée. */
-static PyObject *py_arch_instruction_get_keyword(PyObject *, void *);
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/*                       INSTRUCTIONS D'ARCHITECTURES EN PYTHON                       */
-/* ---------------------------------------------------------------------------------- */
-
+    py_line_generator_type = get_python_line_generator_type();
 
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : type = type de l'objet à instancier.                         *
-*                args = arguments fournis à l'appel.                          *
-*                kwds = arguments de type key=val fournis.                    *
-*                                                                             *
-*  Description : Crée un nouvel objet Python de type 'ArchInstruction'.       *
-*                                                                             *
-*  Retour      : Instance Python mise en place.                               *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static PyObject *py_arch_instruction_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
-    Py_RETURN_NONE;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : self = instance manipulée à traiter.                         *
-*                                                                             *
-*  Description : Prépare un parcours d'instructions.                          *
-*                                                                             *
-*  Retour      : Point de départ d'un parcours.                               *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static PyObject *py_arch_instruction_get_iter(PyObject *self)
-{
-    return py_arch_instruction_iterator_create(self);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : self = classe représentant une instruction.                  *
-*                name = nom de la propriété à lire.                           *
-*                                                                             *
-*  Description : Fournit la valeur associée à une propriété donnée.           *
-*                                                                             *
-*  Retour      : Valeur associée à la propriété consultée.                    *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static PyObject *py_arch_instruction_get_location(PyObject *self, char *name)
-{
-    PyObject *result;                       /* Trouvailles à retourner     */
-    GArchInstruction *instr;                /* Version native              */
-    off_t offset;                           /* Position dans le fichier    */
-    off_t length;                           /* Taille de l'instruction     */
-    vmpa_t address;                         /* Position en mémoire         */
-
-    instr = G_ARCH_INSTRUCTION(pygobject_get(self));
-    g_arch_instruction_get_location(instr, &offset, &length, &address);
-
-    if (strcmp(name, "offset") == 0)
-        result = PyLong_FromLong(offset);
-
-    else if (strcmp(name, "length") == 0)
-        result = PyLong_FromLong(length);
-
-    else if (strcmp(name, "address") == 0)
-        result = PyLong_FromLongLong(address);
-
-    else
-        result = NULL;
-
-    return result;
-
-}
-
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : module = module dont la définition est à compléter.          *
-*                                                                             *
-*  Description : Prend en charge l'objet 'pychrysalide.arch.ArchInstruction'. *
-*                                                                             *
-*  Retour      : Bilan de l'opération.                                        *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-bool register_python_arch_instruction(PyObject *module)
-{
-    PyObject *pygobj_mod;                   /* Module Python-GObject       */
-    int ret;                                /* Bilan d'un appel            */
-
-    static PyMethodDef py_arch_instruction_methods[] = {
-        { NULL }
-    };
-
-    static PyGetSetDef py_arch_instruction_getseters[] = {
-        {
-            "offset", (getter)py_arch_instruction_get_location, (setter)NULL,
-            "Provide the location of the instruction in the binary file.", "offset"
-        },
-        {
-            "length", (getter)py_arch_instruction_get_location, (setter)NULL,
-            "Provide the length of the instruction.", "length"
-        },
-        {
-            "address", (getter)py_arch_instruction_get_location, (setter)NULL,
-            "Provide the location of the instruction in memory.", "address"
-        },
-        {
-            "keyword", (getter)py_arch_instruction_get_keyword, (setter)NULL,
-            "Give le name of the assembly instruction.", NULL
-        },
-        { NULL }
-    };
-
-    static PyTypeObject py_arch_instruction_type = {
-
-        PyObject_HEAD_INIT(NULL)
-
-        .tp_name        = "pychrysalide.arch.ArchInstruction",
-        .tp_basicsize   = sizeof(PyGObject),
-
-        .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
-
-        .tp_doc         = "PyChrysalide architecture instruction",
-
-        .tp_methods     = py_arch_instruction_methods,
-        .tp_getset      = py_arch_instruction_getseters,
-        .tp_new         = (newfunc)py_arch_instruction_new,
-
-        .tp_iter        = (getiterfunc)py_arch_instruction_get_iter
-
-    };
-
-    pygobj_mod = PyImport_ImportModule("gobject");
-    if (pygobj_mod == NULL) return false;
-
-    py_arch_instruction_type.tp_base = (PyTypeObject *)PyObject_GetAttrString(pygobj_mod, "GObject");
-    Py_DECREF(pygobj_mod);
-
-    if (PyType_Ready(&py_arch_instruction_type) < 0)
+    if (!_register_class_for_pygobject(dict, G_TYPE_ARCH_INSTRUCTION, py_arch_instruction_type,
+                                       &PyGObject_Type, py_line_generator_type, NULL))
         return false;
 
-    Py_INCREF(&py_arch_instruction_type);
-    ret = PyModule_AddObject(module, "ArchInstruction", (PyObject *)&py_arch_instruction_type);
-
-    register_class_for_pygobject(module, "GArchInstruction", G_TYPE_ARCH_INSTRUCTION,
-                             &py_arch_instruction_type,
-                             Py_BuildValue("(O)", py_arch_instruction_type.tp_base));
-
-    return (ret == 0);
+    return true;
 
 }
-
-
-#endif
diff --git a/plugins/pychrysa/glibext/Makefile.am b/plugins/pychrysa/glibext/Makefile.am
index b53f4b0..d1b2569 100644
--- a/plugins/pychrysa/glibext/Makefile.am
+++ b/plugins/pychrysa/glibext/Makefile.am
@@ -5,6 +5,7 @@ libpychrysaglibext_la_SOURCES =			\
 	buffercache.h buffercache.c			\
 	bufferline.h bufferline.c			\
 	configuration.h configuration.c		\
+	linegen.h linegen.c					\
 	module.h module.c
 
 
diff --git a/plugins/pychrysa/glibext/linegen.c b/plugins/pychrysa/glibext/linegen.c
new file mode 100644
index 0000000..b6aad6b
--- /dev/null
+++ b/plugins/pychrysa/glibext/linegen.c
@@ -0,0 +1,404 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * linegen.c - équivalent Python du fichier "glibext/linegen.h"
+ *
+ * Copyright (C) 2017 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 "linegen.h"
+
+
+#include <pygobject.h>
+
+
+#include <common/cpp.h>
+#include <glibext/linegen.h>
+
+
+#include "../helpers.h"
+#include "../analysis/content.h"
+#include "../arch/vmpa.h"
+#include "../glibext/bufferline.h"
+
+
+
+/* Indique le nombre de ligne prêtes à être générées. */
+static PyObject *py_line_generator_count_lines(PyObject *, PyObject *);
+
+/* Retrouve l'emplacement correspondant à une position donnée. */
+static PyObject *py_line_generator_compute_addr(PyObject *, PyObject *);
+
+/* Détermine si le conteneur s'inscrit dans une plage donnée. */
+static PyObject *py_line_generator_contains_addr(PyObject *, PyObject *);
+
+/* Renseigne sur les propriétés liées à un générateur. */
+static PyObject *py_line_generator_get_flags(PyObject *, PyObject *);
+
+/* Imprime dans une ligne de rendu le contenu représenté. */
+static PyObject *py_line_generator_print(PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = classe représentant un générateur à manipuler.        *
+*                args = arguments fournis à l'appel.                          *
+*                                                                             *
+*  Description : Indique le nombre de ligne prêtes à être générées.           *
+*                                                                             *
+*  Retour      : Nombre de lignes devant apparaître au final.                 *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_line_generator_count_lines(PyObject *self, PyObject *args)
+{
+    PyObject *result;                       /* Décompte à retourner        */
+    GLineGenerator *generator;              /* Version native              */
+    size_t count;                           /* Nombre de lignes présentes  */
+
+    generator = G_LINE_GENERATOR(pygobject_get(self));
+
+    count = g_line_generator_count_lines(generator);
+
+    result = Py_BuildValue("k", count);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = classe représentant un générateur à manipuler.        *
+*                args = arguments fournis à l'appel.                          *
+*                                                                             *
+*  Description : Retrouve l'emplacement correspondant à une position donnée.  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_line_generator_compute_addr(PyObject *self, PyObject *args)
+{
+    PyObject *result;                       /* Localisation à retourner    */
+    GLineGenerator *generator;              /* Version native              */
+    gint x;                                 /* Position géographique       */
+    size_t index;                           /* Indice dans le tampon       */
+    size_t repeat;                          /* Utilisations successives    */
+    int ret;                                /* Bilan de lecture des args.  */
+    vmpa2t addr;                            /* Adresse visée par l'opérat° */
+
+    generator = G_LINE_GENERATOR(pygobject_get(self));
+
+    ret = PyArg_ParseTuple(args, "ikk", &x, &index, &repeat);
+    if (!ret) return NULL;
+
+    g_line_generator_compute_addr(generator, x, &addr, index, repeat);
+
+    result = build_from_internal_vmpa(&addr);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = classe représentant un générateur à manipuler.        *
+*                args = arguments fournis à l'appel.                          *
+*                                                                             *
+*  Description : Détermine si le conteneur s'inscrit dans une plage donnée.   *
+*                                                                             *
+*  Retour      : Bilan de la détermination, utilisable en comparaisons.       *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_line_generator_contains_addr(PyObject *self, PyObject *args)
+{
+    GLineGenerator *generator;              /* Version native              */
+    PyObject *py_vmpa;                      /* Localisation version Python */
+    size_t index;                           /* Indice dans le tampon       */
+    size_t repeat;                          /* Utilisations successives    */
+    int ret;                                /* Bilan de lecture des args.  */
+    vmpa2t *addr;                           /* Adresse visée par l'opérat° */
+
+    generator = G_LINE_GENERATOR(pygobject_get(self));
+
+    ret = PyArg_ParseTuple(args, "O!kk", get_python_vmpa_type(), &py_vmpa, &index, &repeat);
+    if (!ret) return NULL;
+
+    addr = get_internal_vmpa(py_vmpa);
+    if (addr == NULL) return NULL;
+
+    g_line_generator_contains_addr(generator, addr, index, repeat);
+
+    Py_RETURN_NONE;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = classe représentant un générateur à manipuler.        *
+*                args = arguments fournis à l'appel.                          *
+*                                                                             *
+*  Description : Renseigne sur les propriétés liées à un générateur.          *
+*                                                                             *
+*  Retour      : Propriétés particulières associées.                          *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_line_generator_get_flags(PyObject *self, PyObject *args)
+{
+    PyObject *result;                       /* Propriétés à retourner      */
+    GLineGenerator *generator;              /* Version native              */
+    size_t index;                           /* Indice dans le tampon       */
+    size_t repeat;                          /* Utilisations successives    */
+    int ret;                                /* Bilan de lecture des args.  */
+    BufferLineFlags flags;                  /* Propriétés courantes        */
+
+    generator = G_LINE_GENERATOR(pygobject_get(self));
+
+    ret = PyArg_ParseTuple(args, "kk", &index, &repeat);
+    if (!ret) return NULL;
+
+    flags = g_line_generator_get_flags(generator, index, repeat);
+
+    result = Py_BuildValue("I", flags);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = classe représentant un générateur à manipuler.        *
+*                args = arguments fournis à l'appel.                          *
+*                                                                             *
+*  Description : Imprime dans une ligne de rendu le contenu représenté.       *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_line_generator_print(PyObject *self, PyObject *args)
+{
+    GLineGenerator *generator;              /* Version native              */
+    PyObject *py_line;                      /* Ligne version Python        */
+    size_t index;                           /* Indice dans le tampon       */
+    size_t repeat;                          /* Utilisations successives    */
+    PyObject *py_content;                   /* Contenu version Python      */
+    int ret;                                /* Bilan de lecture des args.  */
+    GBufferLine *line;                      /* Ligne de rendu à compléter  */
+    GBinContent *content;                   /* Contenu binaire associé     */
+
+    generator = G_LINE_GENERATOR(pygobject_get(self));
+
+    ret = PyArg_ParseTuple(args, "O!kkO!", get_python_buffer_line_type(), &py_line, &index,
+                           &repeat, get_python_binary_content_type(), &py_content);
+    if (!ret) return NULL;
+
+    line = G_BUFFER_LINE(pygobject_get(py_line));
+
+    content = G_BIN_CONTENT(pygobject_get(py_content));
+
+    g_line_generator_print(generator, line, index, repeat, content);
+
+    Py_RETURN_NONE;
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+#if 0
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Fournit un accès à une définition de type à diffuser.        *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void python_line_generator_interface_init(GLineGeneratorIface *iface, PyTypeObject *type)
+{
+    GLineGeneratorIface *parent;            /* Défintion parente           */
+    size_t i;                               /* Boucle de parcours          */
+    PyObject *method;                       /* Méthode à associer          */
+
+    static const char *meth_names[] = {
+        "count_lines",
+        "compute_addr",
+        "contains_addr",
+        "get_flags",
+        "print"
+    };
+
+    parent = g_type_interface_peek_parent(iface);
+
+    for (i = 0; i < ARRAY_SIZE(meth_names); i++)
+    {
+        method = NULL;
+
+        if (type != NULL)
+            method = PyObject_GetAttrString((PyObject *)type, meth_names[i]);
+
+        if (method != NULL && PyObject_TypeCheck(method, &PyCFunction_Type) == 0)
+            /*iface->iface_method = _wrap_TestInterface__proxy_do_iface_method*/;
+
+        else
+        {
+            PyErr_Clear();
+
+            if (parent != NULL)
+                /*iface->iface_method = parent->iface_method*/;
+
+        }
+
+        Py_XDECREF(method);
+
+    }
+
+}
+
+
+#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_line_generator_type(void)
+{
+    static PyMethodDef py_line_generator_methods[] = {
+        {
+            "count_lines", py_line_generator_count_lines,
+            METH_NOARGS,
+            "count_lines($self, /)\n--\n\nCount the number of lines which can be displayed."
+        },
+        {
+            "compute_addr", py_line_generator_compute_addr,
+            METH_VARARGS,
+            "compute_addr($self, x, index, repeat, /)\n--\n\nReturn the position at a given location."
+        },
+        {
+            "contains_addr", py_line_generator_contains_addr,
+            METH_VARARGS,
+            "contains_addr($self, addr, index, repeat, /)\n--\n\nTell if the generator contains an address."
+        },
+        {
+            "get_flags", py_line_generator_get_flags,
+            METH_VARARGS,
+            "get_flags($self, index, repeat, /)\n--\n\nGet the flags of a position from the generator."
+        },
+        {
+            "print", py_line_generator_print,
+            METH_VARARGS,
+            "print($self, line, index, repeat, content, /)\n--\n\nProduce output into a line from content."
+        },
+        { NULL }
+    };
+
+    static PyGetSetDef py_line_generator_getseters[] = {
+        { NULL }
+    };
+
+    static PyTypeObject py_line_generator_type = {
+
+        PyVarObject_HEAD_INIT(NULL, 0)
+
+        .tp_name        = "pychrysalide.glibext.LineGenerator",
+        //.tp_basicsize   = sizeof(PyGObject),
+
+        .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+        .tp_doc         = "PyChrysalide line content generator",
+
+        .tp_methods     = py_line_generator_methods,
+        .tp_getset      = py_line_generator_getseters,
+
+    };
+
+    return &py_line_generator_type;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : module = module dont la définition est à compléter.          *
+*                                                                             *
+*  Description : Prend en charge l'objet 'pychrysalide.glibext.LineGenerator'.*
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool register_python_line_generator(PyObject *module)
+{
+    PyTypeObject *py_line_generator_type;   /* Type Python 'LineGenerator' */
+    PyObject *dict;                         /* Dictionnaire du module      */
+
+    py_line_generator_type = get_python_line_generator_type();
+
+    dict = PyModule_GetDict(module);
+    pyg_register_interface(dict, "LineGenerator", G_TYPE_LINE_GENERATOR, py_line_generator_type);
+
+    return true;
+
+}
diff --git a/plugins/pychrysa/glibext/linegen.h b/plugins/pychrysa/glibext/linegen.h
new file mode 100644
index 0000000..8669bb7
--- /dev/null
+++ b/plugins/pychrysa/glibext/linegen.h
@@ -0,0 +1,42 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * linegen.h - prototypes pour l'équivalent Python du fichier "glibext/linegen.h"
+ *
+ * Copyright (C) 2017 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_LINEGEN_H
+#define _PLUGINS_PYCHRYSA_GLIBEXT_LINEGEN_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_line_generator_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.glibext.LineGenerator'. */
+bool register_python_line_generator(PyObject *);
+
+
+
+#endif  /* _PLUGINS_PYCHRYSA_GLIBEXT_LINEGEN_H */
diff --git a/plugins/pychrysa/glibext/module.c b/plugins/pychrysa/glibext/module.c
index eb5c892..f62b17b 100644
--- a/plugins/pychrysa/glibext/module.c
+++ b/plugins/pychrysa/glibext/module.c
@@ -31,6 +31,7 @@
 #include "buffercache.h"
 #include "bufferline.h"
 #include "configuration.h"
+#include "linegen.h"
 
 
 
@@ -85,6 +86,7 @@ bool add_glibext_module_to_python_module(PyObject *super)
     result &= register_python_config_param(module);
     result &= register_python_config_param_iterator(module);
     result &= register_python_generic_config(module);
+    result &= register_python_line_generator(module);
 
  agmtpm_exit:
 
diff --git a/plugins/pychrysa/gtkext/Makefile.am b/plugins/pychrysa/gtkext/Makefile.am
index fee2032..4a36e63 100644
--- a/plugins/pychrysa/gtkext/Makefile.am
+++ b/plugins/pychrysa/gtkext/Makefile.am
@@ -5,6 +5,7 @@ libpychrysagtkext_la_SOURCES =			\
 	blockdisplay.h blockdisplay.c		\
 	bufferdisplay.h bufferdisplay.c		\
 	displaypanel.h displaypanel.c		\
+	dockable.h dockable.c				\
 	module.h module.c
 
 
diff --git a/plugins/pychrysa/gtkext/blockdisplay.c b/plugins/pychrysa/gtkext/blockdisplay.c
index 06f14d8..a329daf 100644
--- a/plugins/pychrysa/gtkext/blockdisplay.c
+++ b/plugins/pychrysa/gtkext/blockdisplay.c
@@ -25,6 +25,7 @@
 #include "blockdisplay.h"
 
 
+#include <string.h>
 #include <pygobject.h>
 
 
@@ -65,7 +66,7 @@ PyTypeObject *get_python_block_display_type(void)
         .tp_name        = "pychrysalide.gtkext.BlockDisplay",
         .tp_basicsize   = sizeof(PyGObject),
 
-        .tp_flags       = Py_TPFLAGS_DEFAULT,
+        .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HEAPTYPE,
 
         .tp_doc         = "PyChrysalide block display.",
 
@@ -74,7 +75,17 @@ PyTypeObject *get_python_block_display_type(void)
 
     };
 
-    return &py_block_display_type;
+    static PyTypeObject *result = NULL;
+
+    if (result == NULL)
+    {
+        result = calloc(1, sizeof(PyTypeObject));
+
+        memcpy(result, &py_block_display_type, sizeof(PyTypeObject));
+
+    }
+
+    return result;
 
 }
 
diff --git a/plugins/pychrysa/gtkext/bufferdisplay.c b/plugins/pychrysa/gtkext/bufferdisplay.c
index 7cc82ff..a6e5327 100644
--- a/plugins/pychrysa/gtkext/bufferdisplay.c
+++ b/plugins/pychrysa/gtkext/bufferdisplay.c
@@ -25,6 +25,7 @@
 #include "bufferdisplay.h"
 
 
+#include <string.h>
 #include <pygobject.h>
 
 
@@ -65,7 +66,7 @@ PyTypeObject *get_python_buffer_display_type(void)
         .tp_name        = "pychrysalide.gtkext.BufferDisplay",
         .tp_basicsize   = sizeof(PyGObject),
 
-        .tp_flags       = Py_TPFLAGS_DEFAULT,
+        .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HEAPTYPE,
 
         .tp_doc         = "PyChrysalide buffer display.",
 
@@ -74,7 +75,17 @@ PyTypeObject *get_python_buffer_display_type(void)
 
     };
 
-    return &py_buffer_display_type;
+    static PyTypeObject *result = NULL;
+
+    if (result == NULL)
+    {
+        result = calloc(1, sizeof(PyTypeObject));
+
+        memcpy(result, &py_buffer_display_type, sizeof(PyTypeObject));
+
+    }
+
+    return result;
 
 }
 
diff --git a/plugins/pychrysa/gtkext/displaypanel.c b/plugins/pychrysa/gtkext/displaypanel.c
index d085f4f..e857475 100644
--- a/plugins/pychrysa/gtkext/displaypanel.c
+++ b/plugins/pychrysa/gtkext/displaypanel.c
@@ -25,6 +25,7 @@
 #include "displaypanel.h"
 
 
+#include <string.h>
 #include <pygobject.h>
 
 
@@ -196,7 +197,7 @@ PyTypeObject *get_python_display_panel_type(void)
         .tp_name        = "pychrysalide.gtkext.DisplayPanel",
         .tp_basicsize   = sizeof(PyGObject),
 
-        .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+        .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HEAPTYPE,
 
         .tp_doc         = "PyChrysalide view panel.",
 
@@ -207,7 +208,17 @@ PyTypeObject *get_python_display_panel_type(void)
 
     };
 
-    return &py_display_panel_type;
+    static PyTypeObject *result = NULL;
+
+    if (result == NULL)
+    {
+        result = calloc(1, sizeof(PyTypeObject));
+
+        memcpy(result, &py_display_panel_type, sizeof(PyTypeObject));
+
+    }
+
+    return result;
 
 }
 
@@ -226,27 +237,37 @@ PyTypeObject *get_python_display_panel_type(void)
 
 bool register_python_display_panel(PyObject *module)
 {
+    bool result;                            /* Bilan à retourner           */
     PyTypeObject *py_display_panel_type;    /* Type Python 'DisplayPanel'  */
     PyObject *parent_mod;                   /* Module Python Fixed         */
     PyObject *fixed;                        /* Module "GtkFixed"           */
     PyObject *dict;                         /* Dictionnaire du module      */
 
+    result = false;
+
     py_display_panel_type = get_python_display_panel_type();
 
     parent_mod = PyImport_ImportModule("gi.repository.Gtk");
     if (parent_mod == NULL) return false;
 
     fixed = PyObject_GetAttrString(parent_mod, "Fixed");
+
     Py_DECREF(parent_mod);
 
     dict = PyModule_GetDict(module);
 
-    if (!register_class_for_pygobject(dict, GTK_TYPE_DISPLAY_PANEL, py_display_panel_type, (PyTypeObject *)fixed))
-        return false;
+    result = register_class_for_pygobject(dict, GTK_TYPE_DISPLAY_PANEL,
+                                          py_display_panel_type, (PyTypeObject *)fixed);
+
+    Py_DECREF(fixed);
 
-    if (!py_display_panel_define_constants(py_display_panel_type))
-        return false;
+    if (!result)
+        goto rpdp_exit;
 
-    return true;
+    result = py_display_panel_define_constants(py_display_panel_type);
+
+ rpdp_exit:
+
+    return result;
 
 }
diff --git a/plugins/pychrysa/gtkext/dockable.c b/plugins/pychrysa/gtkext/dockable.c
new file mode 100644
index 0000000..9c66159
--- /dev/null
+++ b/plugins/pychrysa/gtkext/dockable.c
@@ -0,0 +1,102 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * dockable.c - équivalent Python du fichier "gtkext/gtkdockable.c"
+ *
+ * Copyright (C) 2017 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 "dockable.h"
+
+
+#include <pygobject.h>
+
+
+#include <gtkext/gtkdockable.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_gtk_dockable_type(void)
+{
+    static PyMethodDef py_gtk_dockable_methods[] = {
+        { NULL }
+    };
+
+    static PyGetSetDef py_gtk_dockable_getseters[] = {
+        { NULL }
+    };
+
+    static PyTypeObject py_gtk_dockable_type = {
+
+        PyVarObject_HEAD_INIT(NULL, 0)
+
+        .tp_name        = "pychrysalide.gtkext.GtkDockable",
+        //.tp_basicsize   = sizeof(PyGObject),
+
+        .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+        .tp_doc         = "PyChrysalide interface for Gtk dockable widgets",
+
+        .tp_methods     = py_gtk_dockable_methods,
+        .tp_getset      = py_gtk_dockable_getseters,
+
+    };
+
+    return &py_gtk_dockable_type;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : module = module dont la définition est à compléter.          *
+*                                                                             *
+*  Description : Prend en charge l'objet 'pychrysalide.gtkext.GtkDockable'.   *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool register_python_gtk_dockable(PyObject *module)
+{
+    PyTypeObject *py_gtk_dockable_type;     /* Type Python 'LineGenerator' */
+    PyObject *dict;                         /* Dictionnaire du module      */
+
+    py_gtk_dockable_type = get_python_gtk_dockable_type();
+
+    dict = PyModule_GetDict(module);
+    pyg_register_interface(dict, "LineGenerator", GTK_TYPE_DOCKABLE, py_gtk_dockable_type);
+
+    return true;
+
+}
diff --git a/plugins/pychrysa/gtkext/dockable.h b/plugins/pychrysa/gtkext/dockable.h
new file mode 100644
index 0000000..1709966
--- /dev/null
+++ b/plugins/pychrysa/gtkext/dockable.h
@@ -0,0 +1,42 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * dockable.h - prototypes pour l'équivalent Python du fichier "gtkext/gtkdockable.h"
+ *
+ * Copyright (C) 2017 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_DOCKABLE_H
+#define _PLUGINS_PYCHRYSA_GTKEXT_DOCKABLE_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_gtk_dockable_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.gtkext.GtkDockable'. */
+bool register_python_gtk_dockable(PyObject *);
+
+
+
+#endif  /* _PLUGINS_PYCHRYSA_GTKEXT_DOCKABLE_H */
diff --git a/plugins/pychrysa/gtkext/module.c b/plugins/pychrysa/gtkext/module.c
index 00720bb..8b2cc5e 100644
--- a/plugins/pychrysa/gtkext/module.c
+++ b/plugins/pychrysa/gtkext/module.c
@@ -31,6 +31,7 @@
 #include "blockdisplay.h"
 #include "bufferdisplay.h"
 #include "displaypanel.h"
+#include "dockable.h"
 
 
 
@@ -83,6 +84,7 @@ bool add_gtkext_module_to_python_module(PyObject *super)
     result &= register_python_display_panel(module);
     result &= register_python_buffer_display(module);
     result &= register_python_block_display(module);
+    result &= register_python_gtk_dockable(module);
 
  agmtpm_exit:
 
diff --git a/plugins/pychrysa/gui/panels/panel.c b/plugins/pychrysa/gui/panels/panel.c
index 26637e0..9ca271f 100644
--- a/plugins/pychrysa/gui/panels/panel.c
+++ b/plugins/pychrysa/gui/panels/panel.c
@@ -36,6 +36,7 @@
 #include "../editem.h"
 #include "../../helpers.h"
 #include "../../quirks.h"
+#include "../../gtkext/dockable.h"
 
 
 
@@ -232,7 +233,8 @@ bool register_python_panel_item(PyObject *module)
 
     dict = PyModule_GetDict(module);
 
-    if (!register_class_for_pygobject(dict, G_TYPE_PANEL_ITEM, py_panel_item_type, get_python_editor_item_type()))
+    if (!_register_class_for_pygobject(dict, G_TYPE_PANEL_ITEM, py_panel_item_type,
+                                       get_python_editor_item_type(), get_python_gtk_dockable_type(), NULL))
         return false;
 
     if (!py_panel_item_define_constants(py_panel_item_type))
diff --git a/plugins/pychrysa/helpers.c b/plugins/pychrysa/helpers.c
index df1df05..a0a828f 100644
--- a/plugins/pychrysa/helpers.c
+++ b/plugins/pychrysa/helpers.c
@@ -26,6 +26,7 @@
 
 #include <assert.h>
 #include <pygobject.h>
+#include <stdarg.h>
 
 
 
@@ -256,8 +257,13 @@ bool PyDict_AddStringConstant(PyTypeObject *obj_type, const char *key, const cha
 *                                                                             *
 ******************************************************************************/
 
-bool register_class_for_pygobject(PyObject *dict, GType gtype, PyTypeObject *type, PyTypeObject *base)
+bool _register_class_for_pygobject(PyObject *dict, GType gtype, PyTypeObject *type, PyTypeObject *base, ...)
 {
+    Py_ssize_t size;                        /* Taille de liste actuelle    */
+    PyObject *static_bases;                 /* Base(s) de l'objet          */
+    va_list ap;                             /* Parcours des arguments      */
+    PyTypeObject *static_base;              /* Base à rajouter à la liste  */
+
     /**
      * pygobject_register_class() définit type->tp_base à partir des arguments fournis,
      * puis fait appel à PyType_Ready().
@@ -285,7 +291,32 @@ bool register_class_for_pygobject(PyObject *dict, GType gtype, PyTypeObject *typ
         type->tp_basicsize = base->tp_basicsize;
     }
 
-    pygobject_register_class(dict, NULL, gtype, type, Py_BuildValue("(O)", base));
+    size = 1;
+    static_bases = PyTuple_New(size);
+
+    Py_INCREF(base);
+    PyTuple_SetItem(static_bases, 0, (PyObject *)base);
+
+    va_start(ap, base);
+
+    while (1)
+    {
+        static_base = va_arg(ap, PyTypeObject *);
+
+        if (static_base == NULL) break;
+
+        _PyTuple_Resize(&static_bases, ++size);
+
+        Py_INCREF(static_base);
+        PyTuple_SetItem(static_bases, size - 1, (PyObject *)static_base);
+
+    }
+
+    va_end(ap);
+
+    pygobject_register_class(dict, NULL, gtype, type, static_bases);
+
+    assert(PyErr_Occurred() == NULL);
 
     return true;
 
diff --git a/plugins/pychrysa/helpers.h b/plugins/pychrysa/helpers.h
index 950c85b..9fb83d0 100644
--- a/plugins/pychrysa/helpers.h
+++ b/plugins/pychrysa/helpers.h
@@ -65,7 +65,10 @@ bool PyDict_AddStringConstant(PyTypeObject *, const char *, const char *);
 
 
 /* Enregistre correctement une surcouche de conversion GObject. */
-bool register_class_for_pygobject(PyObject *, GType, PyTypeObject *, PyTypeObject *);
+bool _register_class_for_pygobject(PyObject *, GType, PyTypeObject *, PyTypeObject *, ...);
+
+#define register_class_for_pygobject(dict, gtype, type, base) \
+    _register_class_for_pygobject(dict, gtype, type, base, NULL)
 
 
 /**
diff --git a/plugins/pychrysa/pychrysa.c b/plugins/pychrysa/pychrysa.c
index 45e32b4..f09c234 100644
--- a/plugins/pychrysa/pychrysa.c
+++ b/plugins/pychrysa/pychrysa.c
@@ -40,6 +40,7 @@
 #include <plugins/plugin-int.h>
 
 
+#include "helpers.h"
 #include "plugin.h"
 #include "quirks.h"
 #include "analysis/module.h"
@@ -72,6 +73,9 @@ static PyObject *py_chrysalide_get_global_gobject(PyObject *, PyObject *);
 /* Détermine si l'interpréteur lancé est celui pris en compte. */
 static bool is_current_abi_suitable(void);
 
+/* Définit la version attendue de GTK à charger dans Python. */
+static bool set_version_for_gtk_namespace(const char *);
+
 /* Charge autant de greffons composés en Python que possible. */
 static bool load_python_plugins(GPluginModule *plugin, GObject *);
 
@@ -251,6 +255,55 @@ static bool is_current_abi_suitable(void)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : version = idenfiant de la version de GTK à stipuler.         *
+*                                                                             *
+*  Description : Définit la version attendue de GTK à charger dans Python.    *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool set_version_for_gtk_namespace(const char *version)
+{
+    bool result;                            /* Bilan à retourner           */
+    PyObject *gi_mod;                       /* Module Python-GObject       */
+    PyObject *args;                         /* Arguments à fournir         */
+
+    result = false;
+
+    /**
+     * On cherche ici à éviter le message suivant si on charge 'gi.repository.Gtk' directement :
+     *
+     *
+     *   PyGIWarning: Gtk was imported without specifying a version first. \
+     *   Use gi.require_version('Gtk', '3.0') before import to ensure that the right version gets loaded.
+     *
+     */
+
+    gi_mod = PyImport_ImportModule("gi");
+
+    if (gi_mod != NULL)
+    {
+        args = Py_BuildValue("ss", "Gtk", "3.0");
+
+        run_python_method(gi_mod, "require_version", args);
+
+        result = (PyErr_Occurred() == NULL);
+
+        Py_DECREF(args);
+        Py_DECREF(gi_mod);
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : -                                                            *
 *                                                                             *
 *  Description : Point d'entrée pour l'initialisation de Python.              *
@@ -362,6 +415,9 @@ PyMODINIT_FUNC PyInit_pychrysalide(void)
         return NULL;
     }
 
+    if (!set_version_for_gtk_namespace("3.0"))
+        return NULL;
+
     if (!load_all_basic_components())
     {
         PyErr_SetString(PyExc_SystemError, "unable to load all basic components.");
@@ -386,15 +442,16 @@ PyMODINIT_FUNC PyInit_pychrysalide(void)
 
     result = PyModule_Create(&py_chrysalide_module);
 
-    status = register_python_plugin_module(result);
+    /* Interface 'LineGenerator' en premier... */
+    status = add_glibext_module_to_python_module(result);
 
+    status &= register_python_plugin_module(result);
     status &= add_analysis_module_to_python_module(result);
     status &= add_arch_module_to_python_module(result);
     status &= add_common_module_to_python_module(result);
     status &= add_core_module_to_python_module(result);
     status &= add_debug_module_to_python_module(result);
     status &= add_format_module_to_python_module(result);
-    status &= add_glibext_module_to_python_module(result);
     status &= add_gtkext_module_to_python_module(result);
     status &= add_gui_module_to_python_module(result);
 
@@ -439,9 +496,9 @@ static bool load_python_plugins(GPluginModule *plugin, GObject *ref)
 
     save = NULL;   /* gcc... */
 
-    for (path = strtok_r(paths, ";", &save);
+    for (path = strtok_r(paths, ":", &save);
          path != NULL; 
-         path = strtok_r(NULL, ";", &save))
+         path = strtok_r(NULL, ":", &save))
     {
         dir = opendir(path);
         if (dir == NULL)
@@ -514,6 +571,7 @@ G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin, GObject *ref)
 {
     bool result;                            /* Bilan à retourner           */
     DIR *dir;                               /* Répertoire à parcourir      */
+    int ret;                                /* Bilan de préparatifs        */
 
     define_internal_ref(ref);
 
@@ -524,15 +582,27 @@ G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin, GObject *ref)
     if (dir != NULL)
     {
          closedir(dir);
-         add_to_env_var("PYTHONPATH", PLUGINS_DIR G_DIR_SEPARATOR_S "python", ";");
+         add_to_env_var("PYTHONPATH", PLUGINS_DIR G_DIR_SEPARATOR_S "python", ":");
     }
     else
         add_to_env_var("PYTHONPATH", PACKAGE_SOURCE_DIR G_DIR_SEPARATOR_S "plugins" \
-                       G_DIR_SEPARATOR_S "python", ";");
+                       G_DIR_SEPARATOR_S "python", ":");
+
+    g_plugin_module_log_variadic_message(plugin, LMT_INFO,
+                                         _("PYTHONPATH environment variable set to '%s'"),
+                                         getenv("PYTHONPATH"));
 
     /* Chargement du module pour Python */
 
-    PyImport_AppendInittab("pychrysalide", &PyInit_pychrysalide);
+    ret = PyImport_AppendInittab("pychrysalide", &PyInit_pychrysalide);
+
+    if (ret == -1)
+    {
+        g_plugin_module_log_variadic_message(plugin, LMT_ERROR,
+                                             _("Can not extend the existing table of Python built-in modules."));
+        result = false;
+        goto cpi_done;
+    }
 
     Py_Initialize();
 
@@ -540,6 +610,8 @@ G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin, GObject *ref)
 
     result = load_python_plugins(plugin, ref);
 
+ cpi_done:
+
     return result;
 
 }
diff --git a/src/glibext/generator-int.h b/src/glibext/generator-int.h
deleted file mode 100644
index dbf08a2..0000000
--- a/src/glibext/generator-int.h
+++ /dev/null
@@ -1,52 +0,0 @@
-
-/* 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-2017 Cyrille Bagard
- *
- *  This file is part of Chrysalide.
- *
- *  Chrysalide is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 3 of the License, or
- *  (at your option) any later version.
- *
- *  Chrysalide is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#ifndef _GLIBEXT_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 */
-- 
cgit v0.11.2-87-g4458