summaryrefslogtreecommitdiff
path: root/plugins/pychrysalide/glibext
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2020-05-11 21:33:36 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2020-05-11 21:33:36 (GMT)
commitd2861533cc53fbcc217048bafebf34b1f70ba3aa (patch)
tree28c847a8093761fcaa0916be54445328d843096d /plugins/pychrysalide/glibext
parent6c9e1b5f7ee0915036d47b83f1e34b87b44b1723 (diff)
Updated the API for buffer caches.
Diffstat (limited to 'plugins/pychrysalide/glibext')
-rw-r--r--plugins/pychrysalide/glibext/buffercache.c947
-rw-r--r--plugins/pychrysalide/glibext/buffercache.h3
-rw-r--r--plugins/pychrysalide/glibext/bufferline.c24
-rw-r--r--plugins/pychrysalide/glibext/constants.c100
-rw-r--r--plugins/pychrysalide/glibext/constants.h6
-rw-r--r--plugins/pychrysalide/glibext/linegen.c734
-rw-r--r--plugins/pychrysalide/glibext/linegen.h3
7 files changed, 1645 insertions, 172 deletions
diff --git a/plugins/pychrysalide/glibext/buffercache.c b/plugins/pychrysalide/glibext/buffercache.c
index 9ce06c1..fec5844 100644
--- a/plugins/pychrysalide/glibext/buffercache.c
+++ b/plugins/pychrysalide/glibext/buffercache.c
@@ -28,63 +28,897 @@
#include <pygobject.h>
-#include <glibext/gbuffercache.h>
+#include <glibext/gbuffercache-int.h>
+#include <plugins/dt.h>
+#include "constants.h"
+#include "bufferline.h"
+#include "linegen.h"
#include "../access.h"
#include "../helpers.h"
-#include "../arch/vmpa.h"
+#include "../analysis/content.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 *);
+/* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */
+/* Accompagne la création d'une instance dérivée en Python. */
+static PyObject *py_buffer_cache_new(PyTypeObject *, PyObject *, PyObject *);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_buffer_cache_init(PyObject *, PyObject *, PyObject *);
+
+
+
+/* -------------------------- TAMPON POUR CODE DESASSEMBLE -------------------------- */
+
+
+/* Insère un générateur dans des lignes à une position donnée. */
+static PyObject *py_buffer_cache_insert_at(PyObject *, PyObject *);
+
+/* Retire une ligne du tampon. */
+static PyObject *py_buffer_cache_delete_at(PyObject *, PyObject *);
+
+/* Retire un type de générateur de lignes. */
+static PyObject *py_buffer_cache_delete_type_at(PyObject *, PyObject *);
+
+/* Ajoute en fin de tampon un générateur de lignes. */
+static PyObject *py_buffer_cache_append(PyObject *, PyObject *);
+
+/* Etend un tampon avec un générateur de lignes unique. */
+static PyObject *py_buffer_cache_extend_with(PyObject *, PyObject *);
+
+/* Réduit le tampon à une quantité de lignes précise. */
+static PyObject *py_buffer_cache_truncate(PyObject *, PyObject *);
+
+/* Détermine l'ensemble des propriétés attachées à une ligne. */
+static PyObject *py_buffer_cache_get_line_flags(PyObject *, PyObject *);
+
+/* Retrouve une ligne au sein d'un tampon avec un indice. */
+static PyObject *py_buffer_cache_find_line_by_index(PyObject *, PyObject *);
+
+/* Avance autant que possible vers une ligne idéale. */
+static PyObject *py_buffer_cache_look_for_flag(PyObject *, PyObject *);
+
+/* Indique l'éventuel contenu binaire associé au cache. */
+static PyObject *py_buffer_cache_get_content(PyObject *, void *);
+
+/* Fournit la hauteur d'impression d'une ligne visualisée. */
+static PyObject *py_buffer_cache_get_line_height(PyObject *, void *);
+
+/* Fournit la taille réservée pour la marge gauche. */
+static PyObject *py_buffer_cache_get_left_margin(PyObject *, void *);
+
+/* Fournit la position de départ pour l'impression de texte. */
+static PyObject *py_buffer_cache_get_text_position(PyObject *, void *);
+
+/* Compte le nombre de lignes rassemblées dans un tampon. */
+static PyObject *py_buffer_cache_get_lines_count(PyObject *, void *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* GLUE POUR CREATION DEPUIS PYTHON */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : type = type du nouvel objet à mettre en place. *
+* args = éventuelle liste d'arguments. *
+* kwds = éventuel dictionnaire de valeurs mises à disposition. *
+* *
+* Description : Accompagne la création d'une instance dérivée en Python. *
+* *
+* Retour : Nouvel objet Python mis en place ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_buffer_cache_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+ PyObject *result; /* Objet à retourner */
+ PyTypeObject *base; /* Type de base à dériver */
+ bool first_time; /* Evite les multiples passages*/
+ GType gtype; /* Nouveau type de processeur */
+ bool status; /* Bilan d'un enregistrement */
+
+ /* Validations diverses */
+
+ base = get_python_buffer_cache_type();
+
+ if (type == base)
+ goto simple_way;
+
+ /* Mise en place d'un type dédié */
+
+ first_time = (g_type_from_name(type->tp_name) == 0);
+
+ gtype = build_dynamic_type(G_TYPE_BUFFER_CACHE, type->tp_name, NULL, NULL, NULL);
+
+ if (first_time)
+ {
+ status = register_class_for_dynamic_pygobject(gtype, type, base);
+
+ if (!status)
+ {
+ result = NULL;
+ goto exit;
+ }
+
+ }
+
+ /* On crée, et on laisse ensuite la main à PyGObject_Type.tp_init() */
+
+ simple_way:
+
+ result = PyType_GenericNew(type, args, kwds);
+
+ exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet à initialiser (théoriquement). *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
+* *
+* Retour : 0. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_buffer_cache_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ GBinContent *content; /* Instance GLib du contenu */
+ int ret; /* Bilan de lecture des args. */
+ GBufferCache *cache; /* Version GLib du tampon */
+
+#define BUFFER_CACHE_DOC \
+ "The BufferCache object manages a group of lines intended to get" \
+ " printed onto the screen or into a file.\n" \
+ "\n" \
+ "These lines are cached and rebuilt when needed.\n" \
+ "\n" \
+ "Instances can be created using the following constructor:\n" \
+ "\n" \
+ " BufferCache(content=None)" \
+ "\n" \
+ "Where content is a pychrysalide.analysis.BinContent instance, if" \
+ " defined. This content is provided to lines as argument when the" \
+ " lines get printed, so it may not be always useful and thus can be" \
+ " discarded when creating a new buffer cache." \
+
+ /* Récupération des paramètres */
+
+ content = NULL;
+
+ ret = PyArg_ParseTuple(args, "|O&", convert_to_binary_content_or_none, &content);
+ if (!ret) return -1;
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ /* Eléments de base */
+
+ cache = G_BUFFER_CACHE(pygobject_get(self));
+
+ if (content != NULL)
+ {
+ cache->content = content;
+ g_object_ref(G_OBJECT(content));
+ }
+
+ return 0;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* TAMPON POUR CODE DESASSEMBLE */
+/* ---------------------------------------------------------------------------------- */
+
/******************************************************************************
* *
* 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. *
+* Description : Insère un générateur dans des lignes à une position donnée. *
* *
-* Retour : Instance de la ligne trouvée. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-static PyObject *py_code_buffer_find_line_by_addr(PyObject *self, PyObject *args)
+static PyObject *py_buffer_cache_insert_at(PyObject *self, PyObject *args)
{
PyObject *result; /* Trouvailles à retourner */
- PyObject *py_vmpa; /* Localisation version Python */
+ size_t index; /* Indice de ligne à supprimer */
+ GLineGenerator *generator; /* Générateur à associer */
+ BufferLineFlags flags; /* Particularités nominales */
+ int before; /* Insertion avant ? */
+ int after; /* Insertion après ? */
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 */
+ GBufferCache *cache; /* Tampon natif à consulter */
+
+#define BUFFER_CACHE_INSERT_AT_METHOD PYTHON_METHOD_DEF \
+( \
+ insert_at, "$self, index, generator, /, flags=" \
+ "pychrysalide.glibext.BufferLine.BufferLineFlags.NONE," \
+ " before=False, after=False", \
+ METH_VARARGS, py_buffer_cache, \
+ "Add an extra content generator to a given line.\n" \
+ "\n" \
+ "The new content generator for the line at, before or after" \
+ " the provided index is a pychrysalide.glibext.LineGenerator" \
+ " instance. Nominal properties can be set for this line as" \
+ " extra pychrysalide.glibext.BufferLine.BufferLineFlags" \
+ " values.\n" \
+ "\n" \
+ "An access lock has to be held for the cache; see the" \
+ " pychrysalide.glibext.BufferCache.lock() function." \
+)
- ret = PyArg_ParseTuple(args, "O", &py_vmpa);
+ flags = BLF_NONE;
+ before = 0;
+ after = 0;
+
+ ret = PyArg_ParseTuple(args, "nO&|O&pp", &index, convert_to_line_generator, &generator,
+ convert_to_buffer_line_flags, &flags, &before, &after);
if (!ret) return NULL;
- ret = PyObject_IsInstance(py_vmpa, (PyObject *)get_python_vmpa_type());
+ cache = G_BUFFER_CACHE(pygobject_get(self));
+
+ g_buffer_cache_insert_at(cache, index, generator, flags, before, after);
+
+ result = Py_None;
+ Py_INCREF(result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = classe représentant un tampon de code. *
+* args = arguments fournis à l'appel. *
+* *
+* Description : Retire une ligne du tampon. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_buffer_cache_delete_at(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Trouvailles à retourner */
+ size_t index; /* Indice de ligne à supprimer */
+ int ret; /* Bilan de lecture des args. */
+ GBufferCache *cache; /* Tampon natif à consulter */
+
+#define BUFFER_CACHE_DELETE_AT_METHOD PYTHON_METHOD_DEF \
+( \
+ delete_at, "$self, index, /", \
+ METH_VARARGS, py_buffer_cache, \
+ "Delete the line at the *index* position from a buffer cache.\n" \
+ "\n" \
+ "An access lock has to be held for the cache; see the" \
+ " pychrysalide.glibext.BufferCache.lock() function." \
+)
+
+ ret = PyArg_ParseTuple(args, "n", &index);
if (!ret) return NULL;
- addr = get_internal_vmpa(py_vmpa);
- if (addr == NULL) return NULL;
+ cache = G_BUFFER_CACHE(pygobject_get(self));
+
+ g_buffer_cache_delete_at(cache, index);
+
+ result = Py_None;
+ Py_INCREF(result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = classe représentant un tampon de code. *
+* args = arguments fournis à l'appel. *
+* *
+* Description : Retire un type de générateur de lignes. *
+* *
+* Retour : Générateur éventuellement trouvé ou NULL si aucun. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_buffer_cache_delete_type_at(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Trouvailles à retourner */
+ size_t index; /* Indice de ligne à supprimer */
+ PyObject *py_gtype; /* Version Python d'un GType */
+ int before; /* Insertion avant ? */
+ int after; /* Insertion après ? */
+ int ret; /* Bilan de lecture des args. */
+ GType gtype; /* Type de générateur visé */
+ GBufferCache *cache; /* Tampon natif à consulter */
+ GLineGenerator *generator; /* Générateur retiré ou NULL */
+
+#define BUFFER_CACHE_DELETE_TYPE_AT_METHOD PYTHON_METHOD_DEF \
+( \
+ delete_type_at, "$self, index, gtype, /, before=False, after=False", \
+ METH_VARARGS, py_buffer_cache, \
+ "Delete the first generator of a given type found inside a line of a" \
+ " buffer cache.\n" \
+ "\n" \
+ "The target type has to be a gobject.GType, usually provided by the" \
+ " *__gtype__* attribute of a generator interface. The generator is" \
+ " deleted from the line at, before or after the provided index.\n" \
+ "\n" \
+ "The function returns the deleted generator as a" \
+ " pychrysalide.glibext.LineGenerator instance, or None if none found.\n"\
+ "\n" \
+ "An access lock has to be held for the cache; see the" \
+ " pychrysalide.glibext.BufferCache.lock() function." \
+)
+
+ before = 0;
+ after = 0;
+
+ ret = PyArg_ParseTuple(args, "nO|pp", &index, &py_gtype, &before, &after);
+ if (!ret) return NULL;
- buffer = G_CODE_BUFFER(pygobject_get(self));
+ gtype = pyg_type_from_object(py_gtype);
+ if (gtype == 0) return NULL;
- line = g_code_buffer_find_line_by_addr(buffer, addr, 0, NULL);
- if (line == NULL) Py_RETURN_NONE;
+ cache = G_BUFFER_CACHE(pygobject_get(self));
- result = pygobject_new(G_OBJECT(line));
+ generator = g_buffer_cache_delete_type_at(cache, index, gtype, before, after);
+
+ if (generator != NULL)
+ {
+ result = pygobject_new(G_OBJECT(generator));
+ g_object_unref(G_OBJECT(generator));
+ }
+
+ else
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = classe représentant un tampon de code. *
+* args = arguments fournis à l'appel. *
+* *
+* Description : Ajoute en fin de tampon un générateur de lignes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_buffer_cache_append(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Trouvailles à retourner */
+ GLineGenerator *generator; /* Générateur à associer */
+ BufferLineFlags flags; /* Particularités nominales */
+ int ret; /* Bilan de lecture des args. */
+ GBufferCache *cache; /* Tampon natif à consulter */
+
+#define BUFFER_CACHE_APPEND_METHOD PYTHON_METHOD_DEF \
+( \
+ append, "$self, generator, /, flags=" \
+ "pychrysalide.glibext.BufferLine.BufferLineFlags.NONE", \
+ METH_VARARGS, py_buffer_cache, \
+ "Append a new line at the end of a buffer cache.\n" \
+ "\n" \
+ "The content generator for this new line is a" \
+ " pychrysalide.glibext.LineGenerator instance. Nominal" \
+ " properties can be set for the line as extra" \
+ " pychrysalide.glibext.BufferLine.BufferLineFlags values.\n" \
+ "\n" \
+ "An access lock has to be held for the cache; see the" \
+ " pychrysalide.glibext.BufferCache.lock() function." \
+)
+
+ flags = BLF_NONE;
+
+ ret = PyArg_ParseTuple(args, "O&|O&", convert_to_line_generator, &generator,
+ convert_to_buffer_line_flags, &flags);
+ if (!ret) return NULL;
+
+ cache = G_BUFFER_CACHE(pygobject_get(self));
+
+ g_buffer_cache_append(cache, generator, flags);
+
+ result = Py_None;
+ Py_INCREF(result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = classe représentant un tampon de code. *
+* args = arguments fournis à l'appel. *
+* *
+* Description : Etend un tampon avec un générateur de lignes unique. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_buffer_cache_extend_with(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Trouvailles à retourner */
+ size_t count; /* Quantité de lignes à créer */
+ GLineGenerator *generator; /* Générateur à associer */
+ int ret; /* Bilan de lecture des args. */
+ GBufferCache *cache; /* Tampon natif à consulter */
+
+#define BUFFER_CACHE_EXTEND_WITH_METHOD PYTHON_METHOD_DEF \
+( \
+ extend_with, "$self, count, generator, /", \
+ METH_VARARGS, py_buffer_cache, \
+ "Extend the buffer cache so it will contain *count* lines.\n" \
+ "\n" \
+ "The *count* number should be greater than the current line" \
+ " quantity, otherwise the call makes no sense. The generator" \
+ " is a pychrysalide.glibext.LineGenerator instance used to" \
+ " produce the extra new lines on demand." \
+ "\n" \
+ "An access lock has to be held for the cache; see the" \
+ " pychrysalide.glibext.BufferCache.lock() function." \
+)
+
+ ret = PyArg_ParseTuple(args, "nO&", &count, convert_to_line_generator, &generator);
+ if (!ret) return NULL;
+
+ cache = G_BUFFER_CACHE(pygobject_get(self));
+
+ g_buffer_cache_extend_with(cache, count, generator);
+
+ result = Py_None;
+ Py_INCREF(result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = classe représentant un tampon de code. *
+* args = arguments fournis à l'appel. *
+* *
+* Description : Réduit le tampon à une quantité de lignes précise. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_buffer_cache_truncate(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Trouvailles à retourner */
+ size_t max; /* Nombre de lignes au maximum */
+ int ret; /* Bilan de lecture des args. */
+ GBufferCache *cache; /* Tampon natif à consulter */
+
+#define BUFFER_CACHE_TRUNCATE_METHOD PYTHON_METHOD_DEF \
+( \
+ truncate, "$self, max, /", \
+ METH_VARARGS, py_buffer_cache, \
+ "Shrink the buffer cache so it will contain at most *max* lines.\n" \
+ "\n" \
+ "The *max* number should be lesser than the current line quantity," \
+ " otherwise no effect will happen." \
+ "\n" \
+ "An access lock has to be held for the cache; see the" \
+ " pychrysalide.glibext.BufferCache.lock() function." \
+)
+
+ ret = PyArg_ParseTuple(args, "n", &max);
+ if (!ret) return NULL;
+
+ cache = G_BUFFER_CACHE(pygobject_get(self));
+
+ g_buffer_cache_truncate(cache, max);
+
+ result = Py_None;
+ Py_INCREF(result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = classe représentant un tampon de code. *
+* args = arguments fournis à l'appel. *
+* *
+* Description : Détermine l'ensemble des propriétés attachées à une ligne. *
+* *
+* Retour : Somme de toutes les propriétés enregistrées. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_buffer_cache_get_line_flags(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Trouvailles à retourner */
+ size_t index; /* Indice de la ligne visée */
+ int ret; /* Bilan de lecture des args. */
+ GBufferCache *cache; /* Tampon natif à consulter */
+ BufferLineFlags flags; /* Fanions conservés */
+
+#define BUFFER_CACHE_GET_LINE_FLAGS_METHOD PYTHON_METHOD_DEF \
+( \
+ get_line_flags, "$self, index, /", \
+ METH_VARARGS, py_buffer_cache, \
+ "Provide the optional flags assigned to a given buffer line. The" \
+ " line is located using the *index* argument.\n" \
+ "\n" \
+ "The result is a pychrysalide.glibext.BufferLine.BufferLineFlags" \
+ " value.\n" \
+ "\n" \
+ "An access lock has to be held for the cache; see the" \
+ " pychrysalide.glibext.BufferCache.lock() function." \
+)
+
+ ret = PyArg_ParseTuple(args, "n", &index);
+ if (!ret) return NULL;
+
+ cache = G_BUFFER_CACHE(pygobject_get(self));
+
+ flags = g_buffer_cache_get_line_flags(cache, index);
+
+ result = cast_with_constants_group_from_type(get_python_buffer_line_type(), "BufferLineFlags", flags);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* 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 un indice. *
+* *
+* Retour : Line retrouvée ou None en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_buffer_cache_find_line_by_index(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Trouvailles à retourner */
+ size_t index; /* Indice de la ligne visée */
+ int ret; /* Bilan de lecture des args. */
+ GBufferCache *cache; /* Tampon natif à consulter */
+ GBufferLine *line; /* Ligne trouvée ? */
+
+#define BUFFER_CACHE_FIND_LINE_BY_INDEX_METHOD PYTHON_METHOD_DEF \
+( \
+ find_line_by_index, "$self, index, /", \
+ METH_VARARGS, py_buffer_cache, \
+ "Retrieve the line contained in a buffer cache at a given index.\n" \
+ "\n" \
+ "The result is a pychrysalide.glibext.BufferLine instance or" \
+ " None.\n" \
+ "\n" \
+ "An access lock has to be held for the cache; see the" \
+ " pychrysalide.glibext.BufferCache.lock() function." \
+)
+
+ ret = PyArg_ParseTuple(args, "n", &index);
+ if (!ret) return NULL;
+
+ cache = G_BUFFER_CACHE(pygobject_get(self));
+
+ line = g_buffer_cache_find_line_by_index(cache, index);
+
+ if (line != NULL)
+ {
+ result = pygobject_new(G_OBJECT(line));
+ g_object_unref(G_OBJECT(line));
+ }
+
+ else
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = classe représentant un tampon de code. *
+* args = arguments fournis à l'appel. *
+* *
+* Description : Avance autant que possible vers une ligne idéale. *
+* *
+* Retour : Indice de la ligne recherchée, si elle existe. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_buffer_cache_look_for_flag(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Trouvailles à retourner */
+ size_t index; /* Indice de la ligne visée */
+ BufferLineFlags flag; /* Particularité à retrouver */
+ int ret; /* Bilan de lecture des args. */
+ GBufferCache *cache; /* Tampon natif à consulter */
+ size_t found; /* Indice de la ligne trouvée */
+
+#define BUFFER_CACHE_LOOK_FOR_FLAG_METHOD PYTHON_METHOD_DEF \
+( \
+ look_for_flag, "$self, index, flag, /", \
+ METH_VARARGS, py_buffer_cache, \
+ "Iterate the buffer cache lines from a starting index until a" \
+ " line with flags matching the provided flag is met.\n" \
+ "\n" \
+ "The *flag* argument has to be a" \
+ " pychrysalide.glibext.BufferLine.BufferLineFlags value.\n" \
+ "\n" \
+ "The result is an index equal or greater than the starting index" \
+ " or, if no match is found, the number of lines in the buffer" \
+ " cache.\n" \
+ "\n" \
+ "An access lock has to be held for the cache; see the" \
+ " pychrysalide.glibext.BufferCache.lock() function." \
+)
+
+ ret = PyArg_ParseTuple(args, "nO&", &index, convert_to_buffer_line_flags, &flag);
+ if (!ret) return NULL;
+
+ cache = G_BUFFER_CACHE(pygobject_get(self));
+
+ found = g_buffer_cache_look_for_flag(cache, index, flag);
+
+ result = PyLong_FromSize_t(found);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* closure = non utilisé ici. *
+* *
+* Description : Indique l'éventuel contenu binaire associé au cache. *
+* *
+* Retour : Eventuel contenu renseigné ou None. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_buffer_cache_get_content(PyObject *self, void *closure)
+{
+ PyObject *result; /* Contenu binaire à retourner */
+ GBufferCache *cache; /* Tampon natif à consulter */
+ GBinContent *content; /* Contenu éventuel à renvoyer */
+
+#define BUFFER_CACHE_CONTENT_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ content, py_buffer_cache, \
+ "Binary content linked to the buffer cache, as a" \
+ " pychrysalide.analysis.BinContent instance, or None." \
+)
+
+ cache = G_BUFFER_CACHE(pygobject_get(self));
+
+ content = g_buffer_cache_get_content(cache);
+
+ if (content != NULL)
+ {
+ result = pygobject_new(G_OBJECT(content));
+ g_object_unref(G_OBJECT(content));
+ }
+
+ else
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* closure = non utilisé ici. *
+* *
+* Description : Fournit la hauteur d'impression d'une ligne visualisée. *
+* *
+* Retour : Hauteur de ligne en pixels. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_buffer_cache_get_line_height(PyObject *self, void *closure)
+{
+ PyObject *result; /* Valeur à retourner */
+ GBufferCache *cache; /* Tampon natif à consulter */
+ gint height; /* Valeur obtenue du cache */
+
+#define BUFFER_CACHE_LINE_HEIGHT_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ line_height, py_buffer_cache, \
+ "Height of a line printed from the buffer cache." \
+)
+
+ cache = G_BUFFER_CACHE(pygobject_get(self));
+
+ height = g_buffer_cache_get_line_height(cache);
+
+ result = PyLong_FromLong(height);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* closure = non utilisé ici. *
+* *
+* Description : Fournit la taille réservée pour la marge gauche. *
+* *
+* Retour : Largeur en pixels. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_buffer_cache_get_left_margin(PyObject *self, void *closure)
+{
+ PyObject *result; /* Valeur à retourner */
+ GBufferCache *cache; /* Tampon natif à consulter */
+ gint width; /* Valeur obtenue du cache */
+
+#define BUFFER_CACHE_LEFT_MARGIN_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ left_margin, py_buffer_cache, \
+ "Width of the left margin inside of a buffer cache output." \
+)
+
+ cache = G_BUFFER_CACHE(pygobject_get(self));
+
+ width = g_buffer_cache_get_left_margin(cache);
+
+ result = PyLong_FromLong(width);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* closure = non utilisé ici. *
+* *
+* Description : Fournit la position de départ pour l'impression de texte. *
+* *
+* Retour : Position en pixels. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_buffer_cache_get_text_position(PyObject *self, void *closure)
+{
+ PyObject *result; /* Valeur à retourner */
+ GBufferCache *cache; /* Tampon natif à consulter */
+ gint pos; /* Valeur obtenue du cache */
+
+#define BUFFER_CACHE_TEXT_POSITION_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ text_position, py_buffer_cache, \
+ "Starting position of the text on the left of a buffer cache output." \
+)
+
+ cache = G_BUFFER_CACHE(pygobject_get(self));
+
+ pos = g_buffer_cache_get_text_position(cache);
+
+ result = PyLong_FromLong(pos);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* closure = non utilisé ici. *
+* *
+* Description : Compte le nombre de lignes rassemblées dans un tampon. *
+* *
+* Retour : Nombre de lignes constituant le tampon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_buffer_cache_get_lines_count(PyObject *self, void *closure)
+{
+ PyObject *result; /* Valeur à retourner */
+ GBufferCache *cache; /* Tampon natif à consulter */
+ size_t count; /* Décompte de première main */
+
+#define BUFFER_CACHE_LINES_COUNT_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ lines_count, py_buffer_cache, \
+ "Count the number of lines contained in a buffer cache.\n" \
+ "\n" \
+ "An access lock has to be held for the cache; see the" \
+ " pychrysalide.glibext.BufferCache.lock() function." \
+)
+
+ cache = G_BUFFER_CACHE(pygobject_get(self));
+
+ count = g_buffer_cache_count_lines(cache);
+
+ result = PyLong_FromSize_t(count);
return result;
}
-#endif
/******************************************************************************
@@ -102,17 +936,24 @@ static PyObject *py_code_buffer_find_line_by_addr(PyObject *self, PyObject *args
PyTypeObject *get_python_buffer_cache_type(void)
{
static PyMethodDef py_buffer_cache_methods[] = {
-#if 0
- {
- "find_line_by_addr", 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
+ BUFFER_CACHE_INSERT_AT_METHOD,
+ BUFFER_CACHE_DELETE_AT_METHOD,
+ BUFFER_CACHE_DELETE_TYPE_AT_METHOD,
+ BUFFER_CACHE_APPEND_METHOD,
+ BUFFER_CACHE_EXTEND_WITH_METHOD,
+ BUFFER_CACHE_TRUNCATE_METHOD,
+ BUFFER_CACHE_GET_LINE_FLAGS_METHOD,
+ BUFFER_CACHE_FIND_LINE_BY_INDEX_METHOD,
+ BUFFER_CACHE_LOOK_FOR_FLAG_METHOD,
{ NULL }
};
static PyGetSetDef py_buffer_cache_getseters[] = {
+ BUFFER_CACHE_CONTENT_ATTRIB,
+ BUFFER_CACHE_LINE_HEIGHT_ATTRIB,
+ BUFFER_CACHE_LEFT_MARGIN_ATTRIB,
+ BUFFER_CACHE_TEXT_POSITION_ATTRIB,
+ BUFFER_CACHE_LINES_COUNT_ATTRIB,
{ NULL }
};
@@ -125,11 +966,14 @@ PyTypeObject *get_python_buffer_cache_type(void)
.tp_flags = Py_TPFLAGS_DEFAULT,
- .tp_doc = "PyChrysalide code buffer",
+ .tp_doc = BUFFER_CACHE_DOC,
.tp_methods = py_buffer_cache_methods,
.tp_getset = py_buffer_cache_getseters,
+ .tp_init = py_buffer_cache_init,
+ .tp_new = py_buffer_cache_new
+
};
return &py_buffer_cache_type;
@@ -171,3 +1015,48 @@ bool ensure_python_buffer_cache_is_registered(void)
return true;
}
+
+
+/******************************************************************************
+* *
+* Paramètres : arg = argument quelconque à tenter de convertir. *
+* dst = destination des valeurs récupérées en cas de succès. *
+* *
+* Description : Tente de convertir en tampon de lignes. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_buffer_cache(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_buffer_cache_type());
+
+ switch (result)
+ {
+ case -1:
+ /* L'exception est déjà fixée par Python */
+ result = 0;
+ break;
+
+ case 0:
+ PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to buffer cache");
+ break;
+
+ case 1:
+ *((GBufferCache **)dst) = G_BUFFER_CACHE(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/glibext/buffercache.h b/plugins/pychrysalide/glibext/buffercache.h
index 3135e22..1908434 100644
--- a/plugins/pychrysalide/glibext/buffercache.h
+++ b/plugins/pychrysalide/glibext/buffercache.h
@@ -37,6 +37,9 @@ PyTypeObject *get_python_buffer_cache_type(void);
/* Prend en charge l'objet 'pychrysalide.glibext.BufferCache'. */
bool ensure_python_buffer_cache_is_registered(void);
+/* Tente de convertir en tampon de lignes. */
+int convert_to_buffer_cache(PyObject *, void *);
+
#endif /* _PLUGINS_PYCHRYSALIDE_GLIBEXT_BUFFERCACHE_H */
diff --git a/plugins/pychrysalide/glibext/bufferline.c b/plugins/pychrysalide/glibext/bufferline.c
index 47b2bc4..af3cf1d 100644
--- a/plugins/pychrysalide/glibext/bufferline.c
+++ b/plugins/pychrysalide/glibext/bufferline.c
@@ -155,7 +155,7 @@ static PyObject *py_buffer_line_new(PyTypeObject *type, PyObject *args, PyObject
static PyObject *py_buffer_line_append_text(PyObject *self, PyObject *args)
{
PyObject *result; /* Trouvailles à retourner */
- unsigned long column; /* Indice de colonne */
+ size_t column; /* Indice de colonne */
const char *text; /* Texte à ajouter */
RenderingTagType type; /* Type de rendu attendu */
GObject *creator; /* Eventuel créateur à associer*/
@@ -177,7 +177,7 @@ static PyObject *py_buffer_line_append_text(PyObject *self, PyObject *args)
creator = NULL;
- ret = PyArg_ParseTuple(args, "ksO&|O&", &column, &text,
+ ret = PyArg_ParseTuple(args, "nsO&|O&", &column, &text,
convert_to_rendering_tag_type, &type, convert_to_gobject, &creator);
if (!ret) return NULL;
@@ -228,9 +228,17 @@ static PyObject *py_buffer_line_get_text(PyObject *self, PyObject *args)
line = G_BUFFER_LINE(pygobject_get(self));
text = g_buffer_line_get_text(line, first, end, markup);
- result = PyUnicode_FromString(text);
+ if (text != NULL)
+ {
+ result = PyUnicode_FromString(text);
+ free(text);
+ }
- free(text);
+ else
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
return result;
@@ -398,11 +406,6 @@ static bool py_buffer_line_define_constants(PyTypeObject *obj_type)
result &= PyDict_AddULongMacro(obj_type, BLC_FIRST);
result &= PyDict_AddULongMacro(obj_type, BLC_DISPLAY);
- result &= PyDict_AddULongMacro(obj_type, BLF_NONE);
- result &= PyDict_AddULongMacro(obj_type, BLF_HAS_CODE);
- result &= PyDict_AddULongMacro(obj_type, BLF_ENTRYPOINT);
- result &= PyDict_AddULongMacro(obj_type, BLF_BOOKMARK);
-
return result;
}
@@ -509,6 +512,9 @@ bool ensure_python_buffer_line_is_registered(void)
if (!define_line_segment_constants(type))
return false;
+ if (!define_buffer_line_constants(type))
+ return false;
+
if (!py_buffer_line_define_constants(type))
return false;
diff --git a/plugins/pychrysalide/glibext/constants.c b/plugins/pychrysalide/glibext/constants.c
index d18e051..823465a 100644
--- a/plugins/pychrysalide/glibext/constants.c
+++ b/plugins/pychrysalide/glibext/constants.c
@@ -26,6 +26,7 @@
#include <glibext/linesegment.h>
+#include <glibext/gbufferline.h>
#include "../helpers.h"
@@ -140,3 +141,102 @@ int convert_to_rendering_tag_type(PyObject *arg, void *dst)
return result;
}
+
+
+/******************************************************************************
+* *
+* Paramètres : type = type dont le dictionnaire est à compléter. *
+* *
+* Description : Définit les constantes relatives aux lignes de tampon. *
+* *
+* Retour : true en cas de succès de l'opération, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool define_buffer_line_constants(PyTypeObject *type)
+{
+ bool result; /* Bilan à retourner */
+ PyObject *values; /* Groupe de valeurs à établir */
+
+ values = PyDict_New();
+
+ result = add_const_to_group(values, "NONE", BLF_NONE);
+ if (result) result = add_const_to_group(values, "HAS_CODE", BLF_HAS_CODE);
+ if (result) result = add_const_to_group(values, "IS_LABEL", BLF_IS_LABEL);
+ if (result) result = add_const_to_group(values, "ENTRYPOINT", BLF_ENTRYPOINT);
+ if (result) result = add_const_to_group(values, "BOOKMARK", BLF_BOOKMARK);
+ if (result) result = add_const_to_group(values, "WIDTH_MANAGER", BLF_WIDTH_MANAGER);
+ if (result) result = add_const_to_group(values, "ALL", BLF_ALL);
+
+ if (!result)
+ {
+ Py_DECREF(values);
+ goto exit;
+ }
+
+ result = attach_constants_group_to_type(type, true, "BufferLineFlags", values,
+ "Optional flags linked to a rendering line.");
+
+ exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : arg = argument quelconque à tenter de convertir. *
+* dst = destination des valeurs récupérées en cas de succès. *
+* *
+* Description : Tente de convertir en constante BufferLineFlags. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_buffer_line_flags(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+ unsigned long value; /* Valeur transcrite */
+
+ result = PyObject_IsInstance(arg, (PyObject *)&PyLong_Type);
+
+ switch (result)
+ {
+ case -1:
+ /* L'exception est déjà fixée par Python */
+ result = 0;
+ break;
+
+ case 0:
+ PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to BufferLineFlags");
+ break;
+
+ case 1:
+ value = PyLong_AsUnsignedLong(arg);
+
+ if ((value & BLF_ALL) != value)
+ {
+ PyErr_SetString(PyExc_TypeError, "invalid value for BufferLineFlags");
+ result = 0;
+ }
+
+ else
+ *((BufferLineFlags *)dst) = value;
+
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/glibext/constants.h b/plugins/pychrysalide/glibext/constants.h
index 472507b..a1c56af 100644
--- a/plugins/pychrysalide/glibext/constants.h
+++ b/plugins/pychrysalide/glibext/constants.h
@@ -37,6 +37,12 @@ bool define_line_segment_constants(PyTypeObject *);
/* Tente de convertir en constante RenderingTagType. */
int convert_to_rendering_tag_type(PyObject *, void *);
+/* Définit les constantes relatives aux lignes de tampon. */
+bool define_buffer_line_constants(PyTypeObject *);
+
+/* Tente de convertir en constante BufferLineFlags. */
+int convert_to_buffer_line_flags(PyObject *, void *);
+
#endif /* _PLUGINS_PYCHRYSALIDE_GLIBEXT_CONSTANTS_H */
diff --git a/plugins/pychrysalide/glibext/linegen.c b/plugins/pychrysalide/glibext/linegen.c
index 3ca7fcc..4d6d60d 100644
--- a/plugins/pychrysalide/glibext/linegen.c
+++ b/plugins/pychrysalide/glibext/linegen.c
@@ -28,26 +28,49 @@
#include <pygobject.h>
-#include <common/cpp.h>
-#include <glibext/linegen.h>
+#include <glibext/linegen-int.h>
+#include "bufferline.h"
+#include "constants.h"
+#include "linecursor.h"
#include "../access.h"
#include "../helpers.h"
#include "../analysis/content.h"
-#include "../arch/vmpa.h"
-#include "../glibext/bufferline.h"
+/* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */
+
+
+/* Procède à l'initialisation de l'interface de génération. */
+static void py_line_generator_interface_init(GLineGeneratorIface *, gpointer *);
+
/* Indique le nombre de ligne prêtes à être générées. */
-static PyObject *py_line_generator_count_lines(PyObject *, PyObject *);
+static size_t py_line_generator_count_lines_wrapper(const GLineGenerator *);
/* Retrouve l'emplacement correspondant à une position donnée. */
-//static PyObject *py_line_generator_compute_addr(PyObject *, PyObject *);
+static void py_line_generator_compute_cursor_wrapper(const GLineGenerator *, gint, size_t, size_t, GLineCursor **);
/* Détermine si le conteneur s'inscrit dans une plage donnée. */
-//static PyObject *py_line_generator_contains_addr(PyObject *, PyObject *);
+static int py_line_generator_contain_cursor_wrapper(const GLineGenerator *, size_t, size_t, const GLineCursor *);
+
+/* Renseigne sur les propriétés liées à un générateur. */
+static BufferLineFlags py_line_generator_get_flags_wrapper(const GLineGenerator *, size_t, size_t);
+
+/* Imprime dans une ligne de rendu le contenu représenté. */
+static void py_line_generator_print_wrapper(GLineGenerator *, GBufferLine *, size_t, size_t, const GBinContent *);
+
+
+
+/* ------------------------- CONNEXION AVEC L'API DE PYTHON ------------------------- */
+
+
+/* Retrouve l'emplacement correspondant à une position donnée. */
+static PyObject *py_line_generator_compute_cursor(PyObject *, PyObject *);
+
+/* Détermine si le conteneur s'inscrit dans une plage donnée. */
+static PyObject *py_line_generator_contain_cursor(PyObject *, PyObject *);
/* Renseigne sur les propriétés liées à un générateur. */
static PyObject *py_line_generator_get_flags(PyObject *, PyObject *);
@@ -55,12 +78,61 @@ 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 *);
+/* Indique le nombre de ligne prêtes à être générées. */
+static PyObject *py_line_generator_get_lines_count(PyObject *, void *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* GLUE POUR CREATION DEPUIS PYTHON */
+/* ---------------------------------------------------------------------------------- */
/******************************************************************************
* *
-* Paramètres : self = classe représentant un générateur à manipuler. *
-* args = arguments fournis à l'appel. *
+* Paramètres : iface = interface GLib à initialiser. *
+* unused = adresse non utilisée ici. *
+* *
+* Description : Procède à l'initialisation de l'interface de génération. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void py_line_generator_interface_init(GLineGeneratorIface *iface, gpointer *unused)
+{
+
+#define LINE_GENERATOR_DOC \
+ "LineGenerator gives an interface to all objects which aim to produce" \
+ " content for rendering lines. Such lines can be exported to graphical" \
+ " interfaces or text files.\n" \
+ "\n" \
+ "A typical class declaration for a new implementation looks like:\n" \
+ "\n" \
+ " class NewImplem(GObject.Object, LineGenerator):\n" \
+ " ...\n" \
+ "\n" \
+ "The following methods have to be defined for new implementations:\n" \
+ "* pychrysalide.glibext.LineGenerator._count_lines();\n" \
+ "* pychrysalide.glibext.LineGenerator._compute_cursor();\n" \
+ "* pychrysalide.glibext.LineGenerator._contain_cursor();\n" \
+ "* pychrysalide.glibext.LineGenerator._get_flags();\n" \
+ "* pychrysalide.glibext.LineGenerator._print();\n" \
+
+ iface->count = py_line_generator_count_lines_wrapper;
+ iface->compute = py_line_generator_compute_cursor_wrapper;
+ iface->contains = py_line_generator_contain_cursor_wrapper;
+ iface->get_flags = py_line_generator_get_flags_wrapper;
+ iface->print = py_line_generator_print_wrapper;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : generator = générateur à consulter. *
* *
* Description : Indique le nombre de ligne prêtes à être générées. *
* *
@@ -70,17 +142,46 @@ static PyObject *py_line_generator_print(PyObject *, PyObject *);
* *
******************************************************************************/
-static PyObject *py_line_generator_count_lines(PyObject *self, PyObject *args)
+static size_t py_line_generator_count_lines_wrapper(const GLineGenerator *generator)
{
- PyObject *result; /* Décompte à retourner */
- GLineGenerator *generator; /* Version native */
- size_t count; /* Nombre de lignes présentes */
+ size_t result; /* Décompte à retourner */
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
+ PyObject *pyobj; /* Objet Python concerné */
+ PyObject *pyret; /* Bilan de consultation */
+ int ret; /* Bilan d'une conversion */
- generator = G_LINE_GENERATOR(pygobject_get(self));
+#define LINE_GENERATOR_COUNT_LINES_WRAPPER PYTHON_WRAPPER_DEF \
+( \
+ _count_lines, "$self, /", \
+ METH_NOARGS, \
+ "Abstract method used to count the number of lines produced" \
+ " by the current generator." \
+)
- count = g_line_generator_count_lines(generator);
+ result = 0;
+
+ gstate = PyGILState_Ensure();
+
+ pyobj = pygobject_new(G_OBJECT(generator));
+
+ if (has_python_method(pyobj, "_count_lines"))
+ {
+ pyret = run_python_method(pyobj, "_count_lines", NULL);
+
+ if (pyret != NULL)
+ {
+ ret = PyLong_Check(pyret);
+
+ if (ret)
+ result = PyLong_AsSize_t(pyret);
+
+ Py_DECREF(pyret);
+
+ }
+
+ }
- result = Py_BuildValue("k", count);
+ PyGILState_Release(gstate);
return result;
@@ -89,40 +190,358 @@ static PyObject *py_line_generator_count_lines(PyObject *self, PyObject *args)
/******************************************************************************
* *
+* Paramètres : generator = générateur à consulter. *
+* x = position géographique sur la ligne concernée. *
+* index = indice de cette même ligne dans le tampon global.*
+* repeat = indice d'utilisations successives du générateur. *
+* *
+* Description : Retrouve l'emplacement correspondant à une position donnée. *
+* *
+* Retour : Emplacement constitué. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void py_line_generator_compute_cursor_wrapper(const GLineGenerator *generator, gint x, size_t index, size_t repeat, GLineCursor **cursor)
+{
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
+ PyObject *pyobj; /* Objet Python concerné */
+ PyObject *args; /* Arguments pour l'appel */
+ PyObject *pyret; /* Bilan de consultation */
+ int ret; /* Bilan d'une conversion */
+
+#define LINE_GENERATOR_COMPUTE_CURSOR_WRAPPER PYTHON_WRAPPER_DEF \
+( \
+ _compute_cursor, "$self, x, index, repeat, /", \
+ METH_VARARGS, \
+ "Abstract method used to create a new cursor for a given" \
+ " location inside displayed lines.\n" \
+ "\n" \
+ "The position on the horizontal axis, the line index and the" \
+ " number of repetitions (only relevant if the generator" \
+ " produces several lines) give indications about the active" \
+ " position.\n" \
+ "\n" \
+ "The result has to be a pychrysalide.glibext.LineCursor" \
+ " instance." \
+)
+
+ gstate = PyGILState_Ensure();
+
+ pyobj = pygobject_new(G_OBJECT(generator));
+
+ if (has_python_method(pyobj, "_compute_cursor"))
+ {
+ args = PyTuple_New(3);
+ PyTuple_SetItem(args, 0, PyLong_FromSize_t(x));
+ PyTuple_SetItem(args, 1, PyLong_FromSize_t(index));
+ PyTuple_SetItem(args, 2, PyLong_FromSize_t(repeat));
+
+ pyret = run_python_method(pyobj, "_compute_cursor", args);
+
+ if (pyret != NULL)
+ {
+ ret = convert_to_line_cursor(pyret, cursor);
+
+ if (ret != 1)
+ *cursor = NULL;
+
+ Py_DECREF(pyret);
+
+ }
+
+ Py_DECREF(args);
+
+ }
+
+ PyGILState_Release(gstate);
+
+}
+
+
+/******************************************************************************
+* *
+* 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. *
+* cursor = emplacement à analyser. *
+* *
+* Description : Détermine si le conteneur s'inscrit dans une plage donnée. *
+* *
+* Retour : Bilan de la détermination, utilisable en comparaisons. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_line_generator_contain_cursor_wrapper(const GLineGenerator *generator, size_t index, size_t repeat, const GLineCursor *cursor)
+{
+ int result; /* Bilan d'analyse à retourner */
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
+ PyObject *pyobj; /* Objet Python concerné */
+ PyObject *args; /* Arguments pour l'appel */
+ PyObject *pyret; /* Bilan de consultation */
+ int ret; /* Bilan d'une conversion */
+
+#define LINE_GENERATOR_CONTAIN_CURSOR_WRAPPER PYTHON_WRAPPER_DEF \
+( \
+ _contain_cursor, "$self, index, repeat, cursor, /", \
+ METH_VARARGS, \
+ "Abstract method used to check the position of a cursor in" \
+ " relation to rendering lines.\n" \
+ "\n" \
+ "The line index and the number of repetitions (only relevant" \
+ " if the generator produces several lines) give indications" \
+ " about the active position. The cursor is a" \
+ " pychrysalide.glibext.LineCursor instance.\n" \
+ "\n" \
+ "The result has to be an integer less than, equal to, or" \
+ " greater than zero if the cursor is, respectively, before," \
+ " inside or after the area covered by the generator." \
+)
+
+ result = 0;
+
+ gstate = PyGILState_Ensure();
+
+ pyobj = pygobject_new(G_OBJECT(generator));
+
+ if (has_python_method(pyobj, "_contain_cursor"))
+ {
+ args = PyTuple_New(3);
+ PyTuple_SetItem(args, 0, PyLong_FromSize_t(index));
+ PyTuple_SetItem(args, 1, PyLong_FromSize_t(repeat));
+ PyTuple_SetItem(args, 2, pygobject_new(G_OBJECT(cursor)));
+
+ pyret = run_python_method(pyobj, "_contain_cursor", args);
+
+ if (pyret != NULL)
+ {
+ ret = PyLong_Check(pyret);
+
+ if (ret)
+ result = PyLong_AsLong(pyret);
+
+ Py_DECREF(pyret);
+
+ }
+
+ Py_DECREF(args);
+
+ }
+
+ PyGILState_Release(gstate);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* 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 py_line_generator_get_flags_wrapper(const GLineGenerator *generator, size_t index, size_t repeat)
+{
+ BufferLineFlags result; /* Fanions à retourner */
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
+ PyObject *pyobj; /* Objet Python concerné */
+ PyObject *args; /* Arguments pour l'appel */
+ PyObject *pyret; /* Bilan de consultation */
+ int ret; /* Bilan d'une conversion */
+
+#define LINE_GENERATOR_GET_FLAGS_WRAPPER PYTHON_WRAPPER_DEF \
+( \
+ _get_flags, "$self, index, repeat, /", \
+ METH_VARARGS, \
+ "Abstract method used to provide flags for a given rendering" \
+ " line.\n" \
+ "\n" \
+ "The line index and the number of repetitions (only relevant" \
+ " if the generator produces several lines) give indications" \
+ " about the active position.\n" \
+ "\n" \
+ "The result has to be a" \
+ " pychrysalide.glibext.BufferLine.BufferLineFlags value.\n" \
+)
+
+ result = BLF_NONE;
+
+ gstate = PyGILState_Ensure();
+
+ pyobj = pygobject_new(G_OBJECT(generator));
+
+ if (has_python_method(pyobj, "_get_flags"))
+ {
+ args = PyTuple_New(2);
+ PyTuple_SetItem(args, 0, PyLong_FromSize_t(index));
+ PyTuple_SetItem(args, 1, PyLong_FromSize_t(repeat));
+
+ pyret = run_python_method(pyobj, "_get_flags", args);
+
+ if (pyret != NULL)
+ {
+ ret = convert_to_buffer_line_flags(pyret, &result);
+
+ if (ret != 1)
+ result = BLF_NONE;
+
+ Py_DECREF(pyret);
+
+ }
+
+ Py_DECREF(args);
+
+ }
+
+ PyGILState_Release(gstate);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* 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. *
+* content = éventuel contenu binaire brut à imprimer. *
+* *
+* Description : Imprime dans une ligne de rendu le contenu représenté. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void py_line_generator_print_wrapper(GLineGenerator *generator, GBufferLine *line, size_t index, size_t repeat, const GBinContent *content)
+{
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
+ PyObject *pyobj; /* Objet Python concerné */
+ PyObject *args; /* Arguments pour l'appel */
+ PyObject *pyret; /* Bilan de consultation */
+
+#define LINE_GENERATOR_PRINT_WRAPPER PYTHON_WRAPPER_DEF \
+( \
+ _print, "$self, line, index, repeat, content, /", \
+ METH_VARARGS, \
+ "Abstract method used to generate content into a rendering" \
+ " line, which is a provided pychrysalide.glibext.BufferLine" \
+ " instance.\n" \
+ "\n" \
+ "The line index and the number of repetitions (only relevant" \
+ " if the generator produces several lines) give indications" \
+ " about the current rendering position.\n" \
+ "\n" \
+ "If set, the content is a pychrysalide.analysis.BinContent" \
+ " instance providing access to the processed binary data." \
+)
+
+ gstate = PyGILState_Ensure();
+
+ pyobj = pygobject_new(G_OBJECT(generator));
+
+ if (has_python_method(pyobj, "_print"))
+ {
+ args = PyTuple_New(4);
+ PyTuple_SetItem(args, 0, pygobject_new(G_OBJECT(line)));
+ PyTuple_SetItem(args, 1, PyLong_FromSize_t(index));
+ PyTuple_SetItem(args, 2, PyLong_FromSize_t(repeat));
+ PyTuple_SetItem(args, 3, pygobject_new(G_OBJECT(content)));
+
+ pyret = run_python_method(pyobj, "_print", args);
+
+ Py_DECREF(args);
+
+ Py_XDECREF(pyret);
+
+ }
+
+ PyGILState_Release(gstate);
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* CONNEXION AVEC L'API DE PYTHON */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
* 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 : - *
+* Retour : Emplacement constitué. *
* *
* Remarques : - *
* *
******************************************************************************/
-#if 0
-static PyObject *py_line_generator_compute_addr(PyObject *self, PyObject *args)
+
+static PyObject *py_line_generator_compute_cursor(PyObject *self, PyObject *args)
{
- PyObject *result; /* Localisation à retourner */
- GLineGenerator *generator; /* Version native */
- gint x; /* Position géographique */
+ PyObject *result; /* Propriétés à retourner */
+ int x; /* Position horizontale */
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° */
+ GLineGenerator *generator; /* Version native */
+ GLineCursor *cursor; /* Curseur nouveau obtenu */
+
+#define LINE_GENERATOR_COMPUTE_CURSOR_METHOD PYTHON_METHOD_DEF \
+( \
+ compute_cursor, "$self, x, index, repeat, /", \
+ METH_VARARGS, py_line_generator, \
+ "Create a a new cursor for a given location inside displayed" \
+ " lines.\n" \
+ "\n" \
+ "The position on the horizontal axis, the line index and the" \
+ " number of repetitions (only relevant if the generator" \
+ " produces several lines) give indications about the active" \
+ " position.\n" \
+ "\n" \
+ "The result has to be a pychrysalide.glibext.LineCursor" \
+ " instance." \
+)
+
+ ret = PyArg_ParseTuple(args, "inn", &x, &index, &repeat);
+ if (!ret) return NULL;
generator = G_LINE_GENERATOR(pygobject_get(self));
- ret = PyArg_ParseTuple(args, "ikk", &x, &index, &repeat);
- if (!ret) return NULL;
+ cursor = g_line_generator_compute_cursor(generator, x, index, repeat);
- g_line_generator_compute_addr(generator, x, &addr, index, repeat);
-
- result = build_from_internal_vmpa(&addr);
+ if (cursor != NULL)
+ {
+ result = pygobject_new(G_OBJECT(cursor));
+ g_object_unref(G_OBJECT(cursor));
+ }
+ else
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
return result;
}
-#endif
/******************************************************************************
@@ -137,30 +556,46 @@ static PyObject *py_line_generator_compute_addr(PyObject *self, PyObject *args)
* Remarques : - *
* *
******************************************************************************/
-#if 0
-static PyObject *py_line_generator_contains_addr(PyObject *self, PyObject *args)
+
+static PyObject *py_line_generator_contain_cursor(PyObject *self, PyObject *args)
{
- GLineGenerator *generator; /* Version native */
- PyObject *py_vmpa; /* Localisation version Python */
+ PyObject *result; /* Propriétés à retourner */
size_t index; /* Indice dans le tampon */
size_t repeat; /* Utilisations successives */
+ GLineCursor *cursor; /* Curseur à venir situer */
int ret; /* Bilan de lecture des args. */
- vmpa2t *addr; /* Adresse visée par l'opérat° */
+ GLineGenerator *generator; /* Version native */
+ int status; /* Bilan d'une analyse */
+
+#define LINE_GENERATOR_CONTAIN_CURSOR_METHOD PYTHON_METHOD_DEF \
+( \
+ contain_cursor, "$self, index, repeat, cursor, /", \
+ METH_VARARGS, py_line_generator, \
+ "Check the position of a cursor in relation to rendering" \
+ " lines.\n" \
+ "\n" \
+ "The line index and the number of repetitions (only relevant" \
+ " if the generator produces several lines) give indications" \
+ " about the active position. The cursor is a" \
+ " pychrysalide.glibext.LineCursor instance.\n" \
+ "\n" \
+ "The result has to be an integer less than, equal to, or" \
+ " greater than zero if the cursor is, respectively, before," \
+ " inside or after the area covered by the generator." \
+)
+
+ ret = PyArg_ParseTuple(args, "nnO&", &index, &repeat, convert_to_line_cursor, &cursor);
+ if (!ret) return NULL;
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;
+ status = g_line_generator_contains_cursor(generator, index, repeat, cursor);
- g_line_generator_contains_addr(generator, addr, index, repeat);
+ result = PyLong_FromLong(status);
- Py_RETURN_NONE;
+ return result;
}
-#endif
/******************************************************************************
@@ -179,20 +614,34 @@ static PyObject *py_line_generator_contains_addr(PyObject *self, PyObject *args)
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. */
+ GLineGenerator *generator; /* Version native */
BufferLineFlags flags; /* Propriétés courantes */
- generator = G_LINE_GENERATOR(pygobject_get(self));
-
- ret = PyArg_ParseTuple(args, "kk", &index, &repeat);
+#define LINE_GENERATOR_GET_FLAGS_METHOD PYTHON_METHOD_DEF \
+( \
+ get_flags, "$self, index, repeat, /", \
+ METH_VARARGS, py_line_generator, \
+ "Get the flags of a given position from the generator.\n" \
+ "\n" \
+ "The line index and the number of repetitions (only relevant" \
+ " if the generator produces several lines) give indications" \
+ " about the active position.\n" \
+ "\n" \
+ "The result is a pychrysalide.glibext.BufferLine.BufferLineFlags" \
+ " value." \
+)
+
+ ret = PyArg_ParseTuple(args, "nn", &index, &repeat);
if (!ret) return NULL;
+ generator = G_LINE_GENERATOR(pygobject_get(self));
+
flags = g_line_generator_get_flags(generator, index, repeat);
- result = Py_BuildValue("I", flags);
+ result = cast_with_constants_group_from_type(get_python_buffer_line_type(), "BufferLineFlags", flags);
return result;
@@ -214,19 +663,33 @@ static PyObject *py_line_generator_get_flags(PyObject *self, PyObject *args)
static PyObject *py_line_generator_print(PyObject *self, PyObject *args)
{
- GLineGenerator *generator; /* Version native */
GBufferLine *line; /* Ligne de rendu à compléter */
size_t index; /* Indice dans le tampon */
size_t repeat; /* Utilisations successives */
GBinContent *content; /* Contenu binaire associé */
+ GLineGenerator *generator; /* Version native */
int ret; /* Bilan de lecture des args. */
- generator = G_LINE_GENERATOR(pygobject_get(self));
-
- ret = PyArg_ParseTuple(args, "O&kkO&", convert_to_buffer_line, &line, &index,
+#define LINE_GENERATOR_PRINT_METHOD PYTHON_METHOD_DEF \
+( \
+ print, "$self, line, index, repeat, content, /", \
+ METH_VARARGS, py_line_generator, \
+ "Produce output into a rendering line with optional content.\n" \
+ "\n" \
+ "The line index and the number of repetitions (only relevant" \
+ " if the generator produces several lines) give indications" \
+ " about the current rendering position.\n" \
+ "\n" \
+ "If set, the content is a pychrysalide.analysis.BinContent" \
+ " instance providing access to the processed binary data." \
+)
+
+ ret = PyArg_ParseTuple(args, "O&nnO&", convert_to_buffer_line, &line, &index,
&repeat, convert_to_binary_content, &content);
if (!ret) return NULL;
+ generator = G_LINE_GENERATOR(pygobject_get(self));
+
g_line_generator_print(generator, line, index, repeat, content);
Py_RETURN_NONE;
@@ -234,78 +697,45 @@ static PyObject *py_line_generator_print(PyObject *self, PyObject *args)
}
-
-
-
-
-
-
-
-
-
-
-
-#if 0
-
/******************************************************************************
* *
-* Paramètres : - *
+* Paramètres : self = classe représentant un générateur à manipuler. *
+* closure = non utilisé ici. *
* *
-* Description : Fournit un accès à une définition de type à diffuser. *
+* Description : Indique le nombre de ligne prêtes à être générées. *
* *
-* Retour : - *
+* Retour : Nombre de lignes devant apparaître au final. *
* *
* Remarques : - *
* *
******************************************************************************/
-static void python_line_generator_interface_init(GLineGeneratorIface *iface, PyTypeObject *type)
+static PyObject *py_line_generator_get_lines_count(PyObject *self, void *closure)
{
- 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*/;
+ PyObject *result; /* Décompte à retourner */
+ GLineGenerator *generator; /* Version native */
+ size_t count; /* Nombre de lignes présentes */
- else
- {
- PyErr_Clear();
+#define LINE_GENERATOR_LINES_COUNT_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ lines_count, py_line_generator, \
+ "Quantity of lines produced by the generator.\n" \
+ "\n" \
+ "This number may vary between calls, if a width has changed" \
+ " for instance." \
+)
- if (parent != NULL)
- /*iface->iface_method = parent->iface_method*/;
+ generator = G_LINE_GENERATOR(pygobject_get(self));
- }
+ count = g_line_generator_count_lines(generator);
- Py_XDECREF(method);
+ result = PyLong_FromSize_t(count);
- }
+ return result;
}
-#endif
-
-
-
-
/******************************************************************************
* *
* Paramètres : - *
@@ -321,37 +751,20 @@ static void python_line_generator_interface_init(GLineGeneratorIface *iface, PyT
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."
- },
-#if 0
- {
- "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."
- },
-#endif
- {
- "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."
- },
+ LINE_GENERATOR_COUNT_LINES_WRAPPER,
+ LINE_GENERATOR_COMPUTE_CURSOR_WRAPPER,
+ LINE_GENERATOR_CONTAIN_CURSOR_WRAPPER,
+ LINE_GENERATOR_GET_FLAGS_WRAPPER,
+ LINE_GENERATOR_PRINT_WRAPPER,
+ LINE_GENERATOR_COMPUTE_CURSOR_METHOD,
+ LINE_GENERATOR_CONTAIN_CURSOR_METHOD,
+ LINE_GENERATOR_GET_FLAGS_METHOD,
+ LINE_GENERATOR_PRINT_METHOD,
{ NULL }
};
static PyGetSetDef py_line_generator_getseters[] = {
+ LINE_GENERATOR_LINES_COUNT_ATTRIB,
{ NULL }
};
@@ -360,11 +773,11 @@ PyTypeObject *get_python_line_generator_type(void)
PyVarObject_HEAD_INIT(NULL, 0)
.tp_name = "pychrysalide.glibext.LineGenerator",
- //.tp_basicsize = sizeof(PyGObject),
+ .tp_basicsize = sizeof(PyObject),
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- .tp_doc = "PyChrysalide line content generator",
+ .tp_doc = LINE_GENERATOR_DOC,
.tp_methods = py_line_generator_methods,
.tp_getset = py_line_generator_getseters,
@@ -394,6 +807,14 @@ bool ensure_python_line_generator_is_registered(void)
PyObject *module; /* Module à recompléter */
PyObject *dict; /* Dictionnaire du module */
+ static GInterfaceInfo info = { /* Paramètres d'inscription */
+
+ .interface_init = (GInterfaceInitFunc)py_line_generator_interface_init,
+ .interface_finalize = NULL,
+ .interface_data = NULL,
+
+ };
+
type = get_python_line_generator_type();
if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
@@ -402,7 +823,7 @@ bool ensure_python_line_generator_is_registered(void)
dict = PyModule_GetDict(module);
- if (!register_interface_for_pygobject(dict, G_TYPE_LINE_GENERATOR, type))
+ if (!register_interface_for_pygobject_2(dict, G_TYPE_LINE_GENERATOR, type, &info))
return false;
}
@@ -410,3 +831,48 @@ bool ensure_python_line_generator_is_registered(void)
return true;
}
+
+
+/******************************************************************************
+* *
+* Paramètres : arg = argument quelconque à tenter de convertir. *
+* dst = destination des valeurs récupérées en cas de succès. *
+* *
+* Description : Tente de convertir en générateur de lignes. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_line_generator(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_line_generator_type());
+
+ switch (result)
+ {
+ case -1:
+ /* L'exception est déjà fixée par Python */
+ result = 0;
+ break;
+
+ case 0:
+ PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to line generator");
+ break;
+
+ case 1:
+ *((GLineGenerator **)dst) = G_LINE_GENERATOR(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/glibext/linegen.h b/plugins/pychrysalide/glibext/linegen.h
index 4502347..bfad885 100644
--- a/plugins/pychrysalide/glibext/linegen.h
+++ b/plugins/pychrysalide/glibext/linegen.h
@@ -37,6 +37,9 @@ PyTypeObject *get_python_line_generator_type(void);
/* Prend en charge l'objet 'pychrysalide.glibext.LineGenerator'. */
bool ensure_python_line_generator_is_registered(void);
+/* Tente de convertir en générateur de lignes. */
+int convert_to_line_generator(PyObject *, void *);
+
#endif /* _PLUGINS_PYCHRYSALIDE_GLIBEXT_LINEGEN_H */