summaryrefslogtreecommitdiff
path: root/src/glibext
diff options
context:
space:
mode:
Diffstat (limited to 'src/glibext')
-rw-r--r--src/glibext/Makefile.am9
-rw-r--r--src/glibext/gbinportion.c345
-rw-r--r--src/glibext/gbinportion.h4
-rw-r--r--src/glibext/gbuffercache.c1625
-rw-r--r--src/glibext/gbuffercache.h121
-rw-r--r--src/glibext/gbufferline.c176
-rw-r--r--src/glibext/gbufferline.h9
-rw-r--r--src/glibext/gbufferview.c810
-rw-r--r--src/glibext/gbufferview.h47
-rw-r--r--src/glibext/gcodebuffer.c1778
-rw-r--r--src/glibext/gcodebuffer.h155
-rw-r--r--src/glibext/generator-int.h52
-rw-r--r--src/glibext/generators/Makefile.am15
-rw-r--r--src/glibext/generators/prologue.c359
-rw-r--r--src/glibext/generators/prologue.h58
-rw-r--r--src/glibext/generators/rborder.c361
-rw-r--r--src/glibext/generators/rborder.h60
-rw-r--r--src/glibext/gwidthtracker.c59
-rw-r--r--src/glibext/gwidthtracker.h10
-rw-r--r--src/glibext/linecolumn.c2
-rw-r--r--src/glibext/linegen-int.h67
-rw-r--r--src/glibext/linegen.c208
-rw-r--r--src/glibext/linegen.h68
-rw-r--r--src/glibext/linesegment.c9
-rw-r--r--src/glibext/linesegment.h9
25 files changed, 3775 insertions, 2641 deletions
diff --git a/src/glibext/Makefile.am b/src/glibext/Makefile.am
index aa7a9a3..fe7565a 100644
--- a/src/glibext/Makefile.am
+++ b/src/glibext/Makefile.am
@@ -9,16 +9,21 @@ libglibext_la_SOURCES = \
delayed-int.h \
delayed.h delayed.c \
gbinportion.h gbinportion.c \
+ gbuffercache.h gbuffercache.c \
gbufferline.h gbufferline.c \
gbufferview.h gbufferview.c \
- gcodebuffer.h gcodebuffer.c \
gnhash.h gnhash.c \
gwidthtracker.h gwidthtracker.c \
linecolumn.h linecolumn.c \
+ linegen-int.h \
+ linegen.h linegen.c \
linesegment.h linesegment.c \
proto.h \
signal.h signal.c
+libglibext_la_LIBADD = \
+ generators/libglibextgenerators.la
+
libglibext_la_LDFLAGS =
@@ -26,7 +31,7 @@ AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS)
AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
-SUBDIRS =
+SUBDIRS = generators
chrysamarshal.h: chrysamarshal.list
diff --git a/src/glibext/gbinportion.c b/src/glibext/gbinportion.c
index 4137763..eec9651 100644
--- a/src/glibext/gbinportion.c
+++ b/src/glibext/gbinportion.c
@@ -26,6 +26,7 @@
#include <assert.h>
#include <malloc.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -33,8 +34,10 @@
#include <i18n.h>
+#include "../analysis/human/asm/lang.h" // TODO : REMME -> format !
#include "../common/extstr.h"
#include "../common/sort.h"
+#include "../glibext/linegen-int.h"
@@ -49,6 +52,8 @@ struct _GBinPortion
char *code; /* Code de la couleur de fond */
char *desc; /* Désignation humaine */
+ char **text; /* Lignes brutes à représenter */
+ size_t lcount; /* Quantité de ces lignes */
mrange_t range; /* Emplacement dans le code */
@@ -73,6 +78,9 @@ static void g_binary_portion_class_init(GBinPortionClass *);
/* Initialise une instance de portion de données binaires. */
static void g_binary_portion_init(GBinPortion *);
+/* Procède à l'initialisation de l'interface de génération. */
+static void g_binary_portion_interface_init(GLineGeneratorInterface *);
+
/* Supprime toutes les références externes. */
static void g_binary_portion_dispose(GBinPortion *);
@@ -84,6 +92,26 @@ static bool g_binary_portion_compute_sub_area(const GBinPortion *, phys_t, const
+/* ------------------------ OFFRE DE CAPACITES DE GENERATION ------------------------ */
+
+
+/* Indique le nombre de ligne prêtes à être générées. */
+static size_t g_binary_portion_count_lines(const GBinPortion *);
+
+/* Retrouve l'emplacement correspondant à une position donnée. */
+static void g_binary_portion_compute_addr(const GBinPortion *, gint, vmpa2t *, size_t, size_t);
+
+/* Détermine si le conteneur s'inscrit dans une plage donnée. */
+static int g_binary_portion_contains_addr(const GBinPortion *, const vmpa2t *, size_t, size_t);
+
+/* Renseigne sur les propriétés liées à un générateur. */
+static BufferLineFlags g_binary_portion_get_flags(const GBinPortion *, size_t, size_t);
+
+/* Imprime dans une ligne de rendu le contenu représenté. */
+static void g_binary_portion_print(GBinPortion *, GBufferLine *, size_t, size_t);
+
+
+
/* ------------------------ PARCOURS D'ENSEMBLES DE PORTIONS ------------------------ */
@@ -98,7 +126,8 @@ static bool g_portion_layer_contains_addr(const GBinPortion *, const vmpa2t *);
/* Indique le type défini par la GLib pour les portions de données binaires. */
-G_DEFINE_TYPE(GBinPortion, g_binary_portion, G_TYPE_OBJECT);
+G_DEFINE_TYPE_WITH_CODE(GBinPortion, g_binary_portion, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE(G_TYPE_LINE_GENERATOR, g_binary_portion_interface_init));
/******************************************************************************
@@ -140,6 +169,32 @@ static void g_binary_portion_class_init(GBinPortionClass *klass)
static void g_binary_portion_init(GBinPortion *portion)
{
+ portion->desc = NULL;
+ portion->text = NULL;
+ portion->lcount = 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : iface = interface GLib à initialiser. *
+* *
+* Description : Procède à l'initialisation de l'interface de génération. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_binary_portion_interface_init(GLineGeneratorInterface *iface)
+{
+ iface->count = (linegen_count_lines_fc)g_binary_portion_count_lines;
+ iface->compute = (linegen_compute_fc)g_binary_portion_compute_addr;
+ iface->contains = (linegen_contains_fc)g_binary_portion_contains_addr;
+ iface->get_flags = (linegen_get_flags_fc)g_binary_portion_get_flags;
+ iface->print = (linegen_print_fc)g_binary_portion_print;
}
@@ -177,11 +232,19 @@ static void g_binary_portion_dispose(GBinPortion *portion)
static void g_binary_portion_finalize(GBinPortion *portion)
{
+ size_t i; /* Boucle de parcours */
+
free(portion->code);
if (portion->desc != NULL)
free(portion->desc);
+ for (i = 0; i < portion->lcount; i++)
+ free(portion->text[i]);
+
+ if (portion->text != NULL)
+ free(portion->text);
+
G_OBJECT_CLASS(g_binary_portion_parent_class)->finalize(G_OBJECT(portion));
}
@@ -260,9 +323,66 @@ int g_binary_portion_compare(const GBinPortion **a, const GBinPortion **b)
void g_binary_portion_set_desc(GBinPortion *portion, const char *desc)
{
- if (portion->desc != NULL) free(portion->desc);
+ size_t i; /* Boucle de parcours */
+ GCodingLanguage *lang; /* Langage de sortie préféré */
+
+ if (portion->desc != NULL)
+ {
+ free(portion->desc);
+
+ for (i = 0; i < portion->lcount; i++)
+ free(portion->text[i]);
+
+ if (portion->text != NULL)
+ {
+ free(portion->text);
+ portion->text = NULL;
+ }
+
+ }
+
+ if (desc == NULL)
+ portion->desc = NULL;
+
+ else
+ {
+ portion->desc = strdup(desc);
+
+ /* Constitution du rendu */
+
+ portion->text = calloc(4, sizeof(char *));
+ portion->lcount = 4;
+
+ portion->text[0] = strdup("======================================================");
+ portion->text[1] = strdup("");
+
+ asprintf(&portion->text[2], "%s (%s%s%s%s)", portion->desc, _("rights: "),
+ portion->rights & PAC_READ ? "r" : "-",
+ portion->rights & PAC_WRITE ? "w" : "-",
+ portion->rights & PAC_EXEC ? "x" : "-");
- portion->desc = strdup(desc);
+ portion->text[3] = strdup("");
+ portion->text[4] = strdup("======================================================");
+
+ /* Ajout de la touche "commentaires" */
+
+ lang = g_asm_language_new();
+
+ g_coding_language_encapsulate_comments(lang, &portion->text, &portion->lcount);
+
+ g_object_unref(G_OBJECT(lang));
+
+ /* Ajout de deux bordures vides */
+
+ portion->lcount += 2;
+ portion->text = realloc(portion->text, portion->lcount * sizeof(char *));
+
+ memmove(&portion->text[1], &portion->text[0], (portion->lcount - 2) * sizeof(char *));
+
+ portion->text[0] = NULL;
+ portion->text[portion->lcount - 1] = NULL;
+
+ }
}
@@ -346,98 +466,6 @@ PortionAccessRights g_binary_portion_get_rights(const GBinPortion *portion)
/******************************************************************************
* *
-* Paramètres : portion = description de partie à consulter. *
-* buffer = espace où placer ledit contenu. *
-* msize = taille idéale des positions et adresses; *
-* *
-* Description : Insère dans un tampon une description de portion. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_binary_portion_print(const GBinPortion *portion, GCodeBuffer *buffer, MemoryDataSize msize)
-{
- mrange_t range; /* Couverture à fournir */
- GBufferLine *line; /* Nouvelle ligne à éditer */
- char rights[64]; /* Traduction en texte */
-
- /* On ne traite pas les portions anonymes ! */
- if (portion->desc == NULL) return;
-
- init_mrange(&range, get_mrange_addr(&portion->range), 0);
-
- line = g_code_buffer_prepare_new_line(buffer, &range);
- g_buffer_line_fill_mrange(line, msize, msize);
-
- g_buffer_line_add_flag(line, BLF_WIDTH_MANAGER);
-
- g_code_buffer_append_new_line(buffer, line);
-
- /* Séparation */
-
- line = g_code_buffer_prepare_new_line(buffer, &range);
- g_buffer_line_fill_mrange(line, msize, msize);
-
- g_buffer_line_start_merge_at(line, BLC_ASSEMBLY_HEAD);
- g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD,
- "; ======================================================", 56, RTT_COMMENT, NULL);
-
- g_code_buffer_append_new_line(buffer, line);
-
- /* Retour à la ligne */
-
- line = g_code_buffer_prepare_new_line(buffer, &range);
- g_buffer_line_fill_mrange(line, msize, msize);
-
- g_buffer_line_start_merge_at(line, BLC_ASSEMBLY_HEAD);
- g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, "; ", 2, RTT_COMMENT, NULL);
-
- g_code_buffer_append_new_line(buffer, line);
-
- /* Description */
-
- line = g_code_buffer_prepare_new_line(buffer, &range);
- g_buffer_line_fill_mrange(line, msize, msize);
-
- g_buffer_line_start_merge_at(line, BLC_ASSEMBLY_HEAD);
-
- g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, "; ", 2, RTT_COMMENT, NULL);
-
- g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, portion->desc, strlen(portion->desc), RTT_COMMENT, NULL);
-
- snprintf(rights, sizeof(rights), " (%s%s%s%s)",
- _("rights: "),
- portion->rights & PAC_READ ? "r" : "-",
- portion->rights & PAC_WRITE ? "w" : "-",
- portion->rights & PAC_EXEC ? "x" : "-");
-
- g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, rights, strlen(rights), RTT_COMMENT, NULL);
-
- g_code_buffer_append_new_line(buffer, line);
-
- /* Retour à la ligne */
-
- line = g_code_buffer_prepare_new_line(buffer, &range);
- g_buffer_line_fill_mrange(line, msize, msize);
-
- g_buffer_line_start_merge_at(line, BLC_ASSEMBLY_HEAD);
- g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, "; ", 2, RTT_COMMENT, NULL);
-
- g_code_buffer_append_new_line(buffer, line);
-
- line = g_code_buffer_prepare_new_line(buffer, &range);
- g_buffer_line_fill_mrange(line, msize, msize);
- g_code_buffer_append_new_line(buffer, line);
-
-
-}
-
-
-/******************************************************************************
-* *
* Paramètres : portion = description de partie à mettre à jour. *
* tooltip = astuce à compléter. [OUT] *
* *
@@ -724,6 +752,133 @@ bool g_binary_portion_visit(GBinPortion *portion, visit_portion_fc visitor, void
/* ---------------------------------------------------------------------------------- */
+/* OFFRE DE CAPACITES DE GENERATION */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : portion = générateur à consulter. *
+* *
+* Description : Indique le nombre de ligne prêtes à être générées. *
+* *
+* Retour : Nombre de lignes devant apparaître au final. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static size_t g_binary_portion_count_lines(const GBinPortion *portion)
+{
+ return portion->lcount;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : portion = générateur à consulter. *
+* x = position géographique sur la ligne concernée. *
+* addr = position en mémoire à analyser. *
+* index = indice de cette même ligne dans le tampon global. *
+* repeat = indice d'utilisations successives du générateur. *
+* *
+* Description : Retrouve l'emplacement correspondant à une position donnée. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_binary_portion_compute_addr(const GBinPortion *portion, gint x, vmpa2t *addr, size_t index, size_t repeat)
+{
+ copy_vmpa(addr, get_mrange_addr(&portion->range));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : portion = générateur à consulter. *
+* addr = position en mémoire à analyser. *
+* index = indice de cette même ligne dans le tampon global. *
+* repeat = indice d'utilisations successives du générateur. *
+* *
+* Description : Détermine si le conteneur s'inscrit dans une plage donnée. *
+* *
+* Retour : Bilan de la détermination, utilisable en comparaisons. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int g_binary_portion_contains_addr(const GBinPortion *portion, const vmpa2t *addr, size_t index, size_t repeat)
+{
+ int result; /* Conclusion à retourner */
+
+ result = cmp_vmpa(addr, get_mrange_addr(&portion->range));
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : portion = générateur à consulter. *
+* index = indice de cette même ligne dans le tampon global. *
+* repeat = indice d'utilisations successives du générateur. *
+* *
+* Description : Renseigne sur les propriétés liées à un générateur. *
+* *
+* Retour : Propriétés particulières associées. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static BufferLineFlags g_binary_portion_get_flags(const GBinPortion *portion, size_t index, size_t repeat)
+{
+ return (repeat == 0 ? BLF_WIDTH_MANAGER : BLF_HAS_CODE);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : portion = générateur à utiliser pour l'impression. *
+* line = ligne de rendu à compléter. *
+* index = indice de cette même ligne dans le tampon global. *
+* repeat = indice d'utilisations successives du générateur. *
+* *
+* Description : Imprime dans une ligne de rendu le contenu représenté. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_binary_portion_print(GBinPortion *portion, GBufferLine *line, size_t index, size_t repeat)
+{
+ assert(repeat < portion->lcount);
+
+ g_buffer_line_fill_vmpa(line, get_mrange_addr(&portion->range), MDS_32_BITS_UNSIGNED, MDS_32_BITS_UNSIGNED);
+
+ if (portion->text[repeat] != NULL)
+ {
+ g_buffer_line_start_merge_at(line, BLC_ASSEMBLY_HEAD);
+
+ g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, SL(portion->text[repeat]), RTT_COMMENT, NULL);
+
+ }
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
/* PARCOURS D'ENSEMBLES DE PORTIONS */
/* ---------------------------------------------------------------------------------- */
diff --git a/src/glibext/gbinportion.h b/src/glibext/gbinportion.h
index 2aa5e1a..4f4b3be 100644
--- a/src/glibext/gbinportion.h
+++ b/src/glibext/gbinportion.h
@@ -30,7 +30,6 @@
#include <gtk/gtk.h>
-#include "gcodebuffer.h"
#include "../arch/vmpa.h"
#include "../common/fnv1a.h"
@@ -100,9 +99,6 @@ void g_binary_portion_set_rights(GBinPortion *, PortionAccessRights);
/* Fournit les droits associés à une partie de code. */
PortionAccessRights g_binary_portion_get_rights(const GBinPortion *);
-/* Insère dans un tampon une description de portion. */
-void g_binary_portion_print(const GBinPortion *, GCodeBuffer *, MemoryDataSize);
-
/* Prépare une astuce concernant une portion pour son affichage. */
void g_binary_portion_query_tooltip(GBinPortion *, GtkTooltip *);
diff --git a/src/glibext/gbuffercache.c b/src/glibext/gbuffercache.c
new file mode 100644
index 0000000..57a9487
--- /dev/null
+++ b/src/glibext/gbuffercache.c
@@ -0,0 +1,1625 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * gbuffercache.c - affichage à la demande d'un ensemble de lignes
+ *
+ * Copyright (C) 2016 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "gbuffercache.h"
+
+
+#include <assert.h>
+#include <malloc.h>
+#include <stdlib.h>
+
+
+#include "chrysamarshal.h"
+
+
+
+/* --------------------- FONCTIONS AUXILIAIRES DE MANIPULATIONS --------------------- */
+
+
+/* Informations rattachées à la génération d'une ligne */
+typedef struct _generator_link
+{
+ GLineGenerator *instance; /* Fournisseur de contenu */
+ size_t repeat; /* Compteur de successions */
+
+} generator_link;
+
+/* Suivi interne de l'état d'une ligne */
+typedef struct _cache_info
+{
+ union
+ {
+ generator_link generator; /* Générateur unique */
+ generator_link *generators; /* Liste de générateurs */
+ };
+ size_t count; /* Taille de cette liste */
+
+ GBufferLine *line; /* Ligne en place ou NULL */
+
+ BufferLineFlags extra_flags; /* Propriétés supplémentaires */
+
+} cache_info;
+
+
+/* Gros verrou global pour alléger les structures... */
+G_LOCK_DEFINE_STATIC(_line_update);
+
+
+/* Met en place un nouvel ensemble d'information sur une ligne. */
+static void init_cache_info(cache_info *, GLineGenerator *, size_t, BufferLineFlags);
+
+/* Libère la mémoire occupée par des informations sur une ligne. */
+static void release_cache_info(cache_info *);
+
+/* Ajoute un générateur aux informations sur une ligne. */
+static void extend_cache_info(cache_info *, GLineGenerator *);
+
+/* Retire un générateur aux informations d'une ligne. */
+static void remove_from_cache_info(cache_info *, GLineGenerator *);
+
+/* Retrouve l'emplacement correspondant à une position de ligne. */
+static void get_cache_info_addr(const cache_info *, size_t, gint, vmpa2t *);
+
+/* Suivit les variations du compteur de références d'une ligne. */
+static void on_line_ref_toggle(cache_info *, GBufferLine *, gboolean);
+
+/* Fournit la ligne de tampon correspondant aux générateurs. */
+static GBufferLine *get_cache_info_line(cache_info *, size_t);
+
+/* Force la réinitialisation d'une éventuelle ligne cachée. */
+static void reset_cache_info_line(cache_info *);
+
+
+
+/* -------------------------- TAMPON POUR CODE DESASSEMBLE -------------------------- */
+
+
+/* Tampon pour gestion de lignes optimisée (instance) */
+struct _GBufferCache
+{
+ GObject parent; /* A laisser en premier */
+
+ cache_info *lines; /* Liste des lignes intégrées */
+ size_t count; /* Quantité en cache */
+ size_t used; /* Quantité utilisée */
+
+ GWidthTracker *tracker; /* Suivi des largeurs */
+
+};
+
+/* Tampon pour gestion de lignes optimisée (classe) */
+struct _GBufferCacheClass
+{
+ GObjectClass parent; /* A laisser en premier */
+
+ gint line_height; /* Hauteur maximale des lignes */
+ gint left_margin; /* Marge gauche + espace */
+ gint text_pos; /* Début d'impression du code */
+
+ /* Signaux */
+
+ void (* size_changed) (GBufferCache *, bool, size_t, size_t);
+
+};
+
+
+/* Taille des allocations de masse */
+#define LINE_ALLOC_BULK 1000
+
+
+/* Procède à l'initialisation d'une classe de tampon de lignes. */
+static void g_buffer_cache_class_init(GBufferCacheClass *);
+
+/* Procède à l'initialisation d'un tampon de gestion de lignes. */
+static void g_buffer_cache_init(GBufferCache *);
+
+/* Supprime toutes les références externes. */
+static void g_buffer_cache_dispose(GBufferCache *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_buffer_cache_finalize(GBufferCache *);
+
+/* Calcule l'indice d'apparition d'un générateur dans le tampon. */
+static size_t g_buffer_cache_compute_repetition(GBufferCache *, size_t, GLineGenerator *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* FONCTIONS AUXILIAIRES DE MANIPULATIONS */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : info = informations concernant une ligne à constituer. *
+* generator = générateur à associer à toutes les lignes. *
+* repeat = compteur de répétition entre les lignes. *
+* flags = propriétés supplémentaires à associer à la ligne.*
+* *
+* Description : Met en place un nouvel ensemble d'information sur une ligne. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void init_cache_info(cache_info *info, GLineGenerator *generator, size_t repeat, BufferLineFlags flags)
+{
+ info->generator.instance = generator;
+ info->generator.repeat = repeat;
+
+ g_object_ref(G_OBJECT(generator));
+
+ info->count = 1;
+
+ info->line = NULL;
+
+ info->extra_flags = flags;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : info = informations concernant une ligne à constituer. *
+* *
+* Description : Libère la mémoire occupée par des informations sur une ligne.*
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void release_cache_info(cache_info *info)
+{
+ size_t i; /* Boucle de parcours */
+
+ if (info->count == 1)
+ g_object_unref(G_OBJECT(info->generator.instance));
+
+ else
+ for (i = 0; i < info->count; i++)
+ g_object_unref(G_OBJECT(info->generators[i].instance));
+
+ reset_cache_info_line(info);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : info = informations concernant une ligne à actualiser. *
+* generator = générateur à associer à toutes les lignes. *
+* *
+* Description : Ajoute un générateur aux informations sur une ligne. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void extend_cache_info(cache_info *info, GLineGenerator *generator)
+{
+ generator_link first; /* Générateur déjà en place */
+ generator_link *new; /* Nouveau générateur placé */
+
+ if (info->count == 1)
+ {
+ first = info->generator;
+
+ info->generators = (generator_link *)calloc(2, sizeof(generator_link));
+
+ info->generators[0] = first;
+ info->count = 2;
+
+ new = &info->generators[1];
+
+ }
+ else
+ {
+ info->generators = (generator_link *)realloc(info->generators,
+ ++info->count * sizeof(generator_link));
+
+ new = &info->generators[info->count - 1];
+
+ }
+
+ new->instance = generator;
+ new->repeat = 0;
+
+ g_object_ref(G_OBJECT(generator));
+
+ reset_cache_info_line(info);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : info = informations concernant une ligne à actualiser. *
+* generator = générateur à dissocier de toutes les lignes. *
+* *
+* Description : Retire un générateur aux informations d'une ligne. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void remove_from_cache_info(cache_info *info, GLineGenerator *generator)
+{
+ generator_link *link; /* Accès simplifié */
+ size_t i; /* Boucle de parcours */
+ generator_link *old; /* Mémorisation avant opérat° */
+
+ if (info->count == 1)
+ {
+ link = &info->generator;
+
+ assert(link->instance == generator);
+
+ g_object_unref(G_OBJECT(generator));
+
+ info->count = 0;
+
+ }
+
+ else
+ {
+ for (i = 0; i < info->count; i++)
+ {
+ link = &info->generators[i];
+
+ if (link->instance == generator)
+ {
+ if ((i + 1) < info->count)
+ memmove(&info->generators[i], &info->generators[i + 1],
+ (info->count - i - 1) * sizeof(generator_link));
+
+ if (info->count == 2)
+ {
+ old = info->generators;
+
+ info->count = 1;
+ info->generator = info->generators[0];
+
+ free(old);
+
+ }
+ else
+ info->generators = (generator_link *)realloc(info->generators,
+ --info->count * sizeof(generator_link));
+
+ break;
+
+ }
+
+ }
+
+#ifndef NDEBUG
+
+ /**
+ * Attention : si l'élément était en dernière position,
+ * l'indice de parcours est désormais égal au nombre de générateurs présents !
+ */
+ assert(i <= info->count);
+
+ for ( ; i < info->count; i++)
+ {
+ link = &info->generators[i];
+
+ assert(link->instance != generator);
+
+ }
+
+#endif
+
+ }
+
+ reset_cache_info_line(info);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : info = informations sur une ligne à venir consulter. *
+* index = indice de la ligne visée par la consultation. *
+* x = position géographique sur la ligne concernée. *
+* addr = adresse à renseigner. [OUT] *
+* *
+* Description : Retrouve l'emplacement correspondant à une position de ligne.*
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void get_cache_info_addr(const cache_info *info, size_t index, gint x, vmpa2t *addr)
+{
+ const generator_link *generator; /* Générateur retenu */
+
+ if (info->count == 1)
+ generator = &info->generator;
+ else
+ generator = &info->generators[0];
+
+ g_line_generator_compute_addr(generator->instance, x, addr, index, generator->repeat);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : info = informations sur une ligne à venir manipuler. *
+* line = tampon de lignes à venir supprimer au besoin. *
+* last = indication sur la valeur du compteur de références. *
+* *
+* Description : Suivit les variations du compteur de références d'une ligne. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void on_line_ref_toggle(cache_info *info, GBufferLine *line, gboolean last)
+{
+ if (last)
+ {
+ G_LOCK(_line_update);
+
+ assert(info->line != NULL);
+
+ info->line = NULL;
+
+ G_UNLOCK(_line_update);
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : info = informations sur une ligne à venir manipuler. *
+* index = indice de la ligne à constituer. *
+* *
+* Description : Fournit la ligne de tampon correspondant aux générateurs. *
+* *
+* Retour : Ligne déjà en place ou créée pour le besoin. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GBufferLine *get_cache_info_line(cache_info *info, size_t index)
+{
+ GBufferLine *result; /* Construction à retourner */
+ size_t i; /* Boucle de parcours */
+
+ G_LOCK(_line_update);
+
+ result = info->line;
+
+ if (result == NULL)
+ {
+ result = g_buffer_line_new((mrange_t []){ { { 0 }, 0 } }, 0/* !! */);
+
+ g_object_add_toggle_ref(G_OBJECT(result), (GToggleNotify)on_line_ref_toggle, info);
+
+ if (info->count == 1)
+ g_line_generator_print(info->generator.instance, result, index, info->generator.repeat);
+
+ else
+ for (i = 0; i < info->count; i++)
+ g_line_generator_print(info->generators[i].instance, result, index, info->generators[i].repeat);
+
+ info->line = result;
+
+ }
+
+ else
+ g_object_ref(G_OBJECT(result));
+
+ G_UNLOCK(_line_update);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : info = informations sur une ligne à venir manipuler. *
+* *
+* Description : Force la réinitialisation d'une éventuelle ligne cachée. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void reset_cache_info_line(cache_info *info)
+{
+ G_LOCK(_line_update);
+
+ if (info->line != NULL)
+ {
+ g_object_remove_toggle_ref(G_OBJECT(info->line), (GToggleNotify)on_line_ref_toggle, info);
+
+ g_object_unref(G_OBJECT(info->line));
+
+ info->line = NULL;
+
+ }
+
+ G_UNLOCK(_line_update);
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* TAMPON POUR CODE DESASSEMBLE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Détermine le type du composant de tampon pour gestion de lignes optimisée. */
+G_DEFINE_TYPE(GBufferCache, g_buffer_cache, G_TYPE_OBJECT);
+
+
+/******************************************************************************
+* *
+* Paramètres : class = classe de composant GLib à initialiser. *
+* *
+* Description : Procède à l'initialisation d'une classe de tampon de lignes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_buffer_cache_class_init(GBufferCacheClass *class)
+{
+ GObjectClass *object; /* Autre version de la classe */
+
+ object = G_OBJECT_CLASS(class);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_buffer_cache_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_buffer_cache_finalize;
+
+ class->line_height = 17;
+ class->left_margin = 2 * class->line_height;
+ class->text_pos = 2.5 * class->line_height;
+
+ /* Signaux */
+
+ g_signal_new("size-changed",
+ G_TYPE_BUFFER_CACHE,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(GBufferCacheClass, size_changed),
+ NULL, NULL,
+ g_cclosure_user_marshal_VOID__BOOLEAN_ULONG_ULONG,
+ G_TYPE_NONE, 3, G_TYPE_BOOLEAN, G_TYPE_ULONG, G_TYPE_ULONG);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : cache = composant GLib à initialiser. *
+* *
+* Description : Procède à l'initialisation d'un tampon de gestion de lignes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_buffer_cache_init(GBufferCache *cache)
+{
+ cache->tracker = g_width_tracker_new(cache);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : cache = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_buffer_cache_dispose(GBufferCache *cache)
+{
+ size_t i; /* Boucle de parcours #1 */
+ cache_info *info; /* Accès directe à une ligne */
+ size_t j; /* Boucle de parcours #2 */
+
+ for (i = 0; i < cache->used; i++)
+ {
+ info = &cache->lines[i];
+
+ if (info->count == 1)
+ g_object_unref(G_OBJECT(info->generator.instance));
+
+ else
+ for (j = 0; j < info->count; j++)
+ g_object_unref(G_OBJECT(info->generators[j].instance));
+
+ if (info->line)
+ g_object_unref(G_OBJECT(info->line));
+
+ }
+
+ g_object_unref(G_OBJECT(cache->tracker));
+
+ G_OBJECT_CLASS(g_buffer_cache_parent_class)->dispose(G_OBJECT(cache));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : cache = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_buffer_cache_finalize(GBufferCache *cache)
+{
+ size_t i; /* Boucle de parcours */
+ cache_info *info; /* Accès directe à une ligne */
+
+ for (i = 0; i < cache->used; i++)
+ {
+ info = &cache->lines[i];
+
+ if (info->count > 1)
+ free(info->generators);
+
+ }
+
+ if (cache->lines != NULL)
+ free(cache->lines);
+
+ G_OBJECT_CLASS(g_buffer_cache_parent_class)->finalize(G_OBJECT(cache));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Crée un nouveau composant de tampon pour code désassemblé. *
+* *
+* Retour : Composant GLib créé. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GBufferCache *g_buffer_cache_new(void)
+{
+ GBufferCache *result; /* Composant à retourner */
+
+ result = g_object_new(G_TYPE_BUFFER_CACHE, NULL);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : cache = tampon de lignes à consulter. *
+* *
+* Description : Fournit la hauteur d'impression d'une ligne visualisée. *
+* *
+* Retour : Hauteur de ligne en pixels. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+gint g_buffer_cache_get_line_height(const GBufferCache *cache)
+{
+ GBufferCacheClass *class; /* Classe des tampons */
+
+ class = G_BUFFER_CACHE_GET_CLASS(cache);
+
+ return class->line_height;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : cache = tampon de lignes à consulter. *
+* *
+* Description : Fournit la taille réservée pour la marge gauche. *
+* *
+* Retour : Largeur en pixels. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+gint g_buffer_cache_get_left_margin(const GBufferCache *cache)
+{
+ GBufferCacheClass *class; /* Classe des tampons */
+
+ class = G_BUFFER_CACHE_GET_CLASS(cache);
+
+ return class->left_margin;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : cache = tampon de lignes à consulter. *
+* *
+* Description : Fournit la position de départ pour l'impression de texte. *
+* *
+* Retour : Position en pixels. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+gint g_buffer_cache_get_text_position(const GBufferCache *cache)
+{
+ GBufferCacheClass *class; /* Classe des tampons */
+
+ class = G_BUFFER_CACHE_GET_CLASS(cache);
+
+ return class->text_pos;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : cache = instance GLib à consulter. *
+* *
+* Description : Compte le nombre de lignes rassemblées dans un tampon. *
+* *
+* Retour : Nombre de lignes constituant le tampon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+size_t g_buffer_cache_count_lines(const GBufferCache *cache)
+{
+ return cache->used;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : cache = composant GLib à consulter. *
+* *
+* Description : Fournit un lien vers la structure de suivi de largeurs. *
+* *
+* Retour : Gestionnaire de largeurs de lignes. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+const GWidthTracker *g_buffer_cache_get_width_tracker(const GBufferCache *cache)
+{
+ return cache->tracker;
+
+}
+
+
+
+
+
+/******************************************************************************
+* *
+* Paramètres : cache = instance GLib à consulter. *
+* index = indice de la ligne où se trouve le générateur. *
+* generator = générateur associé à au moins une ligne. *
+* *
+* Description : Calcule l'indice d'apparition d'un générateur dans le tampon.*
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static size_t g_buffer_cache_compute_repetition(GBufferCache *cache, size_t index, GLineGenerator *generator)
+{
+ size_t result; /* Compteur à retourner */
+ cache_info *info; /* Accès directe à une ligne */
+ size_t i; /* Boucle de parcours */
+
+ result = 0;
+
+ if (index > 0)
+ {
+ info = &cache->lines[index - 1];
+
+ if (info->count == 1)
+ {
+ if (info->generator.instance == generator)
+ result = info->generator.repeat + 1;
+
+ }
+
+ else
+ for (i = 0; i < info->count; i++)
+ if (info->generators[i].instance == generator)
+ {
+ result = info->generators[i].repeat + 1;
+ break;
+ }
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : cache = instance GLib à modifier. *
+* index = point d'insertion, puis de sauvegarde. *
+* generator = générateur à insérer dans les lignes. *
+* before = précise l'emplacement final des nouvelles lignes.*
+* after = précise l'emplacement final des nouvelles lignes.*
+* *
+* Description : Insère un générateur dans des lignes à une position donnée. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_buffer_cache_insert_at(GBufferCache *cache, size_t index, GLineGenerator *generator, bool before, bool after)
+{
+#ifndef NDEBUG
+ vmpa2t gen_addr; /* Position du générateur */
+ vmpa2t line_addr; /* Position de la ligne */
+#endif
+ size_t needed; /* Emplacements nécessaires */
+ size_t i; /* Boucle de parcours */
+
+ assert(index < cache->used);
+
+ assert(!(before && after));
+
+#ifndef NDEBUG
+
+ g_line_generator_compute_addr(generator, 0, &gen_addr, index, 0);
+
+ get_cache_info_addr(&cache->lines[index], index, 0, &line_addr);
+
+ ///////////////////////////////////////
+ if (cmp_vmpa(&gen_addr, &line_addr) != 0) return;
+
+ assert(cmp_vmpa(&gen_addr, &line_addr) == 0);
+
+#endif
+
+ /* Cas particulier d'ajout en fin de cache... */
+ if (after && (index + 1) == cache->used)
+ {
+ g_buffer_cache_append(cache, generator, BLF_NONE);
+ goto gbcia_done;
+ }
+
+ /* Adaptation de l'espace */
+
+ needed = g_line_generator_count_lines(generator);
+
+ if (before || after)
+ {
+ if ((cache->used + needed) >= cache->count)
+ {
+ cache->count += needed + LINE_ALLOC_BULK;
+ cache->lines = (cache_info *)realloc(cache->lines, cache->count * sizeof(cache_info));
+ }
+ }
+#ifndef NDEBUG
+ else
+ assert(needed == 1);
+#endif
+
+ /* Insertion du générateur */
+
+ if (after)
+ index++;
+
+ if (before || after)
+ {
+ memmove(&cache->lines[index], &cache->lines[index + needed], (cache->used - index) * sizeof(cache_info));
+
+ for (i = 0; i < needed; i++)
+ init_cache_info(&cache->lines[index + i], generator, i, BLF_NONE);
+
+ cache->used += needed;
+
+ g_width_tracker_update_added(cache->tracker, index, needed);
+
+ g_signal_emit_by_name(cache, "size-changed", true, index, needed);
+
+ }
+
+ else
+ {
+ extend_cache_info(&cache->lines[index], generator);
+
+ g_width_tracker_update(cache->tracker, index);
+
+ g_signal_emit_by_name(cache, "size-changed", true, index, 1);
+
+ }
+
+ gbcia_done:
+
+ ;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : cache = instance GLib à modifier. *
+* index = point d'insertion, puis de sauvegarde. *
+* type = type de générateurs à retirer des lignes visées. *
+* before = précise l'emplacement final de l'élément visé. *
+* after = précise l'emplacement final de l'élément visé. *
+* *
+* Description : Retire un type de générateur de lignes. *
+* *
+* Retour : Générateur éventuellement trouvé ou NULL si aucun. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GLineGenerator *g_buffer_cache_delete_type_at(GBufferCache *cache, size_t index, GType type, bool before, bool after)
+{
+ GLineGenerator *result; /* Prédécesseur à retourner */
+ cache_info *info; /* Accès directe à une ligne */
+ generator_link *link; /* Accès simplifié */
+ size_t i; /* Boucle de parcours */
+ size_t count; /* Emplacements occupés */
+ size_t delete; /* Indice de suppression */
+
+ assert(index < cache->used);
+
+ assert(!(before && after));
+
+ result = NULL;
+
+ /* Recherche d'un générateur correspondant */
+
+ if (before)
+ info = &cache->lines[index - 1];
+ else if (after)
+ info = &cache->lines[index + 1];
+ else
+ info = &cache->lines[index];
+
+ if (info->count == 1)
+ {
+ link = &info->generator;
+
+ if (G_OBJECT_TYPE(link->instance) == type)
+ result = link->instance;
+
+ }
+
+ else
+ for (i = 0; i < info->count && result == NULL; i++)
+ {
+ link = &info->generators[i];
+
+ if (G_OBJECT_TYPE(link->instance) == type)
+ result = link->instance;
+
+ }
+
+ /* Retrait de l'instance trouvée */
+
+ if (result != NULL)
+ {
+ count = g_line_generator_count_lines(result);
+
+#ifndef NDEBUG
+ if (!before && !after)
+ assert(count == 1);
+#endif
+
+ g_object_ref(G_OBJECT(result));
+
+ /* Suppression de l'élément */
+
+ for (i = 0; i < count; i++)
+ {
+ if (before)
+ info = &cache->lines[index - 1 - i];
+ else if (after)
+ info = &cache->lines[index + 1 + i];
+ else
+ info = &cache->lines[index];
+
+ remove_from_cache_info(info, result);
+
+ }
+
+ /* Suppression des lignes associées */
+
+ for (i = 0; i < count; i++)
+ {
+ if (before)
+ delete = index - 1;
+ else if (after)
+ delete = index + 1;
+ else
+ delete = index;
+
+ info = &cache->lines[delete];
+
+ if (info->count == 0)
+ {
+ release_cache_info(info);
+
+ if ((delete + 1) < cache->used)
+ memmove(&cache->lines[delete], &cache->lines[delete + 1],
+ (cache->used - delete - 1) * sizeof(cache_info));
+
+ cache->used--;
+
+ g_width_tracker_update_deleted(cache->tracker, delete, delete);
+
+ g_signal_emit_by_name(cache, "size-changed", false, delete, 1);
+
+ }
+
+ }
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : cache = instance GLib à modifier. *
+* generator = générateur à associer à toutes les lignes. *
+* flags = propriétés supplémentaires à associer à la ligne.*
+* *
+* Description : Ajoute en fin de tampon un générateur de lignes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_buffer_cache_append(GBufferCache *cache, GLineGenerator *generator, BufferLineFlags flags)
+{
+ size_t count; /* Nombre de lignes générées */
+ size_t index; /* Point d'insertion */
+ size_t i; /* Boucle de parcours */
+ cache_info *info; /* Accès directe à une ligne */
+
+ count = g_line_generator_count_lines(generator);
+
+ assert(count > 0);
+
+ assert((flags != BLF_NONE && count == 1) || flags == BLF_NONE);
+
+ if ((cache->used + count) > cache->count)
+ {
+ cache->count += count + LINE_ALLOC_BULK;
+ cache->lines = (cache_info *)realloc(cache->lines, cache->count * sizeof(cache_info));
+ }
+
+ index = cache->used;
+
+ for (i = 0; i < count; i++)
+ {
+ info = &cache->lines[index + i];
+
+ info->generator.instance = generator;
+ info->generator.repeat = g_buffer_cache_compute_repetition(cache, index + i, generator);
+
+ g_object_ref(G_OBJECT(generator));
+
+ info->count = 1;
+
+ info->line = NULL;
+
+ info->extra_flags = flags;
+
+ }
+
+ cache->used += count;
+
+ g_object_unref(G_OBJECT(generator));
+
+ g_width_tracker_update_added(cache->tracker, index, count);
+
+ g_signal_emit_by_name(cache, "size-changed", true, index, count);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : cache = instance GLib à modifier. *
+* count = quantité totale de lignes à avoir à disposition. *
+* generator = générateur à associer à toutes les lignes. *
+* *
+* Description : Etend un tampon avec un générateur de lignes unique. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_buffer_cache_extend_with(GBufferCache *cache, size_t count, GLineGenerator *generator)
+{
+ size_t index; /* Point d'insertion */
+ size_t i; /* Boucle de parcours */
+ cache_info *info; /* Accès directe à une ligne */
+ size_t added; /* Nombre d'ajouts effectués */
+
+ assert(count >= cache->used);
+
+ if (count > cache->count)
+ {
+ cache->lines = (cache_info *)realloc(cache->lines, count * sizeof(cache_info));
+ cache->count = count;
+ }
+
+ index = cache->used;
+
+ for (i = index; i < count; i++)
+ {
+ info = &cache->lines[i];
+
+ info->generator.instance = generator;
+ info->generator.repeat = g_buffer_cache_compute_repetition(cache, i, generator);
+
+ g_object_ref(G_OBJECT(generator));
+
+ info->count = 1;
+
+ info->line = NULL;
+
+ }
+
+ added = count - cache->used;
+
+ cache->used = count;
+
+ g_object_unref(G_OBJECT(generator));
+
+ if (added > 0)
+ {
+ g_width_tracker_update_added(cache->tracker, index, added);
+
+ g_signal_emit_by_name(cache, "size-changed", true, index, added);
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : cache = instance GLib à modifier. *
+* max = nombre maximal de lignes à conserver. *
+* *
+* Description : Réduit le tampon à une quantité de lignes précise. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_buffer_cache_truncate(GBufferCache *cache, size_t max)
+{
+ size_t i; /* Boucle de parcours #1 */
+ cache_info *info; /* Accès directe à une ligne */
+ size_t j; /* Boucle de parcours #2 */
+ size_t removed; /* Nombre de retraits effectués*/
+
+ assert(max <= cache->used);
+
+ for (i = max; i < cache->used; i++)
+ {
+ info = &cache->lines[i];
+
+ if (info->count == 1)
+ g_object_unref(G_OBJECT(info->generator.instance));
+
+ else
+ {
+ for (j = 0; j < info->count; j++)
+ g_object_unref(G_OBJECT(info->generators[j].instance));
+
+ free(info->generators);
+
+ }
+
+ reset_cache_info_line(info);
+
+ }
+
+ removed = cache->used - max;
+
+ cache->used = max - 1;
+
+ if (removed > 0)
+ {
+ g_width_tracker_update_deleted(cache->tracker, max, max + removed - 1);
+
+ g_signal_emit_by_name(cache, "size-changed", false, max, removed);
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : cache = tampon de lignes à venir consulter. *
+* index = indice de la ligne visée par la consultation. *
+* x = position géographique sur la ligne concernée. *
+* addr = adresse à renseigner. [OUT] *
+* *
+* Description : Retrouve l'emplacement correspondant à une position de ligne.*
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_buffer_cache_get_line_addr(const GBufferCache *cache, size_t index, gint x, vmpa2t *addr)
+{
+ assert(index < cache->used);
+
+ get_cache_info_addr(&cache->lines[index], index, x, addr);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : cache = tampon de lignes à venir consulter. *
+* index = indice de la ligne visée par la consultation. *
+* *
+* Description : Détermine l'ensemble des propriétés attachées à une ligne. *
+* *
+* Retour : Somme de toutes les propriétés enregistrées. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+BufferLineFlags g_buffer_cache_get_line_flags(const GBufferCache *cache, size_t index)
+{
+ BufferLineFlags result; /* Somme à renvoyer */
+ cache_info *info; /* Accès directe à une ligne */
+ const generator_link *generator; /* Générateur retenu */
+ size_t i; /* Boucle de parcours */
+
+ assert(index < cache->used);
+
+ info = &cache->lines[index];
+
+ result = info->extra_flags;
+
+ if (info->count == 1)
+ {
+ generator = &info->generator;
+ result |= g_line_generator_get_flags(generator->instance, index, generator->repeat);
+ }
+
+ else
+ for (i = 0; i < info->count; i++)
+ {
+ generator = &info->generators[i];
+ result |= g_line_generator_get_flags(generator->instance, index, generator->repeat);
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : cache = tampon de lignes à consulter. *
+* index = indice de la ligne recherchée. *
+* *
+* Description : Retrouve une ligne au sein d'un tampon avec un indice. *
+* *
+* Retour : Line retrouvée ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GBufferLine *g_buffer_cache_find_line_by_index(const GBufferCache *cache, size_t index)
+{
+ GBufferLine *result; /* Ligne trouvée à retourner */
+
+ if (index < cache->used)
+ result = get_cache_info_line(&cache->lines[index], index);
+ else
+ result = NULL;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : cache = tampon de lignes à venir consulter. *
+* index = indice de la ligne à mesurer. *
+* summary = largeurs maximales à faire évoluer. *
+* *
+* Description : Fait remonter les largeurs requises par une ligne donnée. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_buffer_cache_collect_widths(GBufferCache *cache, size_t index, line_width_summary *summary)
+{
+ GBufferLine *line; /* Ligne éphémère à mesurer */
+
+ line = get_cache_info_line(&cache->lines[index], index);
+
+ g_buffer_line_collect_widths(line, summary);
+
+ g_object_unref(G_OBJECT(line));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : cache = visualisation à représenter. *
+* cr = contexte graphique dédié à la procédure. *
+* first = première ligne à dessiner. *
+* last = dernière ligne à dessiner. *
+* area = position et surface à traiter. *
+* display = règles d'affichage des colonnes modulables. *
+* selected = ordonnée d'une ligne sélectionnée ou NULL. *
+* list = liste de contenus à mettre en évidence. *
+* *
+* Description : Imprime une partie choisie du tampon contenant des lignes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_buffer_cache_draw(const GBufferCache *cache, cairo_t *cr, size_t first, size_t last, const cairo_rectangle_int_t *area, const bool *display, const gint *selected, const segcnt_list *list)
+{
+ GBufferCacheClass *class; /* Classe des tampons */
+ gint y; /* Point de départ en ordonnée */
+ bool wait_selection; /* Sélection déjà passée ? */
+ size_t i; /* Boucle de parcours */
+ cache_info *info; /* Accès directe à une ligne */
+ line_width_summary summary; /* Résumé concis des largeurs */
+ GBufferLine *line; /* Ligne à venir dessiner */
+
+ class = G_BUFFER_CACHE_GET_CLASS(cache);
+
+ y = 0;
+
+ wait_selection = true;
+
+ if (cache->used > 0)
+ for (i = first; i <= last; i++)
+ {
+ /* Si sélection, on sousligne la ligne concernée */
+ if (wait_selection && selected != NULL && *selected == y)
+ {
+ cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.05);
+
+ cairo_rectangle(cr, area->x, y, area->width, class->line_height);
+ cairo_fill(cr);
+
+ wait_selection = false;
+
+ }
+
+ info = &cache->lines[i];
+
+ if (i == first || (g_buffer_cache_get_line_flags(cache, i) & BLF_WIDTH_MANAGER))
+ g_width_tracker_get_local_width_summary(cache->tracker, i, &summary);
+
+ line = get_cache_info_line(info, i);
+
+ g_buffer_line_draw(line, cr, &summary, class->text_pos, y, display, list);
+
+ g_object_unref(G_OBJECT(line));
+
+ y += class->line_height;
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : cache = tampon de lignes à consulter. *
+* addr = adresse à retrouver dans le tampon. *
+* first = indique si on l'arrête à la première ou la dernière. *
+* start = borne inférieure des recherches (incluse). *
+* end = borne supérieure des recherches (incluse). *
+* *
+* Description : Indique l'indice correspondant à une adresse donnée. *
+* *
+* Retour : Indice des infos à l'adresse demandée, ou nombre de lignes. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+size_t _g_buffer_cache_find_index_by_addr(const GBufferCache *cache, const vmpa2t *addr, bool first, size_t start, size_t end)
+{
+ size_t result; /* Indice à retourner */
+ cache_info *found; /* Eventuel élément trouvé */
+
+ int find_containing_generator(const vmpa2t *a, const cache_info *i)
+ {
+ const generator_link *generator; /* Générateur retenu */
+
+ if (i->count == 1)
+ generator = &i->generator;
+ else
+ generator = &i->generators[0];
+
+ return g_line_generator_contains_addr(generator->instance, addr,
+ i - cache->lines, generator->repeat);
+
+ }
+
+ found = (cache_info *)bsearch(addr, &cache->lines[start], end - start + 1,
+ sizeof(cache_info), (__compar_fn_t)find_containing_generator);
+
+ if (found == NULL)
+ result = cache->used;
+
+ else
+ {
+ result = (found - cache->lines);
+ assert(start <= result && result <= end);
+
+ /* On s'assure d'un arrêt sur la bonne ligne */
+
+ if (first)
+ for (; result > start; result--)
+ {
+ found = &cache->lines[result - 1];
+
+ if (find_containing_generator(addr, found) != 0)
+ break;
+
+ }
+
+ else
+ for (; result < end; result++)
+ {
+ found = &cache->lines[result + 1];
+
+ if (find_containing_generator(addr, found) != 0)
+ break;
+
+ }
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : cache = tampon de lignes à consulter. *
+* addr = adresse à retrouver dans le tampon. *
+* first = indique si on l'arrête à la première ou la dernière. *
+* *
+* Description : Indique l'indice correspondant à une adresse donnée. *
+* *
+* Retour : Indice des infos à l'adresse demandée, ou nombre de lignes. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+size_t g_buffer_cache_find_index_by_addr(const GBufferCache *cache, const vmpa2t *addr, bool first)
+{
+ size_t result; /* Indice à retourner */
+
+ if (cache->used == 0)
+ result = 0;
+ else
+ result = _g_buffer_cache_find_index_by_addr(cache, addr, first, 0, cache->used - 1);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : cache = tampon de lignes à consulter. *
+* start = point de départ du parcours. *
+* flag = propriétés à retrouver si possible. *
+* *
+* Description : Avance autant que possible vers une ligne idéale. *
+* *
+* Retour : Indice de la ligne recherchée, si elle existe. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+size_t g_buffer_cache_look_for_flag(const GBufferCache *cache, size_t start, BufferLineFlags flag)
+{
+ size_t result; /* Indice de ligne à retourner */
+ vmpa2t start_addr; /* Localisation de départ */
+ size_t i; /* Boucle de parcours */
+ vmpa2t addr; /* Localisation suivante */
+
+ assert(start < cache->used);
+
+ result = start;
+
+ get_cache_info_addr(&cache->lines[start], start, 0, &start_addr);
+
+ for (i = start + 1; i < cache->used; i++)
+ {
+ get_cache_info_addr(&cache->lines[i], i, 0, &addr);
+
+ if (cmp_vmpa(&start_addr, &addr) != 0)
+ break;
+
+ if ((g_buffer_cache_get_line_flags(cache, i) & flag) != 0)
+ {
+ result = i;
+ break;
+ }
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : cache = tampon de lignes à consulter. *
+* addr = adresse à présenter à l'écran. *
+* first = borne inférieure des recherches (incluse). *
+* last = borne supérieure des recherches (incluse). *
+* code = s'arrête si possible à une ligne avec code. *
+* x = position horizontale au sein du composant. [OUT] *
+* y = position verticale au sein du composant. [OUT] *
+* *
+* Description : Indique la position d'affichage d'une adresse donnée. *
+* *
+* Retour : true si l'adresse fait partie du composant, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_buffer_cache_get_address_coordinates(const GBufferCache *cache, const vmpa2t *addr, size_t first, size_t last, bool code, gint *x, gint *y)
+{
+ bool result; /* Bilan à retourner */
+ size_t index; /* Indice de correspondance */
+ gint lheight; /* Hauteur d'une ligne */
+ const cache_info *info; /* Infos sur une ligne donnée */
+ const generator_link *generator; /* Générateur retenu */
+
+ index = _g_buffer_cache_find_index_by_addr(cache, addr, true, first, last);
+
+ result = (index < cache->used);
+
+ if (result)
+ {
+ lheight = G_BUFFER_CACHE_GET_CLASS(cache)->line_height;
+
+ *x = 0;
+ *y = (index - first) * G_BUFFER_CACHE_GET_CLASS(cache)->line_height;
+
+ for (; code && index <= last; index++)
+ {
+ if (g_buffer_cache_get_line_flags(cache, index) & BLF_HAS_CODE)
+ break;
+
+ if (index == last)
+ break;
+
+ info = &cache->lines[index + 1];
+
+ if (info->count == 1)
+ generator = &info->generator;
+ else
+ generator = &info->generators[0];
+
+ if (!g_line_generator_contains_addr(generator->instance, addr, index + 1, generator->repeat))
+ break;
+
+ *y += lheight;
+
+ }
+
+ }
+
+ return result;
+
+}
diff --git a/src/glibext/gbuffercache.h b/src/glibext/gbuffercache.h
new file mode 100644
index 0000000..6e9c314
--- /dev/null
+++ b/src/glibext/gbuffercache.h
@@ -0,0 +1,121 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * gbuffercache.h - prototypes pour l'affichage à la demande d'un ensemble de lignes
+ *
+ * Copyright (C) 2016 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GLIBEXT_GBUFFERCACHE_H
+#define _GLIBEXT_GBUFFERCACHE_H
+
+
+#include <glib-object.h>
+#include <stdbool.h>
+#include <gdk/gdk.h>
+
+
+#include "gwidthtracker.h"
+#include "linegen.h"
+
+
+
+/* -------------------------- TAMPON POUR CODE DESASSEMBLE -------------------------- */
+
+
+#define G_TYPE_BUFFER_CACHE (g_buffer_cache_get_type())
+#define G_BUFFER_CACHE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_CODE_BUFFER, GBufferCache))
+#define G_BUFFER_CACHE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_CODE_BUFFER, GBufferCacheClass))
+#define G_IS_BUFFER_CACHE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_CODE_BUFFER))
+#define G_IS_BUFFER_CACHE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_CODE_BUFFER))
+#define G_BUFFER_CACHE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_CODE_BUFFER, GBufferCacheClass))
+
+
+/* Tampon pour gestion de lignes optimisée (instance) */
+typedef struct _GBufferCache GBufferCache;
+
+/* Tampon pour gestion de lignes optimisée (classe) */
+typedef struct _GBufferCacheClass GBufferCacheClass;
+
+
+/* Détermine le type du composant de tampon pour gestion de lignes optimisée. */
+GType g_buffer_cache_get_type(void);
+
+/* Crée un nouveau composant de tampon pour code désassemblé. */
+GBufferCache *g_buffer_cache_new(void);
+
+/* Fournit la hauteur d'impression d'une ligne visualisée. */
+gint g_buffer_cache_get_line_height(const GBufferCache *);
+
+/* Fournit la taille réservée pour la marge gauche. */
+gint g_buffer_cache_get_left_margin(const GBufferCache *);
+
+/* Fournit la position de départ pour l'impression de texte. */
+gint g_buffer_cache_get_text_position(const GBufferCache *);
+
+/* Compte le nombre de lignes rassemblées dans un tampon. */
+size_t g_buffer_cache_count_lines(const GBufferCache *);
+
+/* Fournit un lien vers la structure de suivi de largeurs. */
+const GWidthTracker *g_buffer_cache_get_width_tracker(const GBufferCache *);
+
+/* Insère un générateur dans des lignes à une position donnée. */
+void g_buffer_cache_insert_at(GBufferCache *, size_t, GLineGenerator *, bool, bool);
+
+/* Retire un type de générateur de lignes. */
+GLineGenerator *g_buffer_cache_delete_type_at(GBufferCache *, size_t, GType, bool, bool);
+
+/* Ajoute en fin de tampon un générateur de lignes. */
+void g_buffer_cache_append(GBufferCache *, GLineGenerator *, BufferLineFlags);
+
+/* Etend un tampon avec un générateur de lignes unique. */
+void g_buffer_cache_extend_with(GBufferCache *, size_t, GLineGenerator *);
+
+/* Réduit le tampon à une quantité de lignes précise. */
+void g_buffer_cache_truncate(GBufferCache *, size_t);
+
+/* Retrouve l'emplacement correspondant à une position de ligne. */
+void g_buffer_cache_get_line_addr(const GBufferCache *, size_t, gint, vmpa2t *);
+
+/* Détermine l'ensemble des propriétés attachées à une ligne. */
+BufferLineFlags g_buffer_cache_get_line_flags(const GBufferCache *, size_t);
+
+/* Retrouve une ligne au sein d'un tampon avec un indice. */
+GBufferLine *g_buffer_cache_find_line_by_index(const GBufferCache *, size_t);
+
+/* Fait remonter les largeurs requises par une ligne donnée. */
+void g_buffer_cache_collect_widths(GBufferCache *, size_t, line_width_summary *);
+
+/* Imprime une partie choisie du tampon contenant des lignes. */
+void g_buffer_cache_draw(const GBufferCache *, cairo_t *, size_t, size_t, const cairo_rectangle_int_t *, const bool *, const gint *, const segcnt_list *);
+
+/* Indique l'indice correspondant à une adresse donnée. */
+size_t _g_buffer_cache_find_index_by_addr(const GBufferCache *, const vmpa2t *, bool, size_t, size_t);
+
+/* Indique l'indice correspondant à une adresse donnée. */
+size_t g_buffer_cache_find_index_by_addr(const GBufferCache *, const vmpa2t *, bool);
+
+/* Avance autant que possible vers une ligne idéale. */
+size_t g_buffer_cache_look_for_flag(const GBufferCache *, size_t, BufferLineFlags);
+
+/* Indique la position d'affichage d'une adresse donnée. */
+bool g_buffer_cache_get_address_coordinates(const GBufferCache *, const vmpa2t *, size_t, size_t, bool, gint *, gint *);
+
+
+
+#endif /* _GLIBEXT_GBUFFERCACHE_H */
diff --git a/src/glibext/gbufferline.c b/src/glibext/gbufferline.c
index 5f1756d..768cbca 100644
--- a/src/glibext/gbufferline.c
+++ b/src/glibext/gbufferline.c
@@ -56,7 +56,7 @@ struct _GBufferLine
mrange_t range; /* Couverture geographique */
BufferLineColumn main_column; /* Colonne principale */
- line_column columns[BLC_COUNT]; /* Répartition du texte */
+ line_column columns[BLC_COUNT]; /* Répartition du texte */
BufferLineColumn merge_start; /* Début de la zone globale */
BufferLineColumn last_used; /* Dernière colonne utilisée */
@@ -72,7 +72,6 @@ struct _GBufferLine
gint max_widths[BLC_COUNT]; /* Taille cachée des colonnes */
gint merged_width; /* Largeur cumulée avant fusion*/
};
- GBufferLine *manager; /* Représentante d'un groupe */
};
};
@@ -214,9 +213,6 @@ static void g_buffer_line_dispose(GBufferLine *line)
{
size_t i; /* Boucle de parcours */
- if (line->flags & BLF_WIDTH_MANAGER)
- g_object_unref(G_OBJECT(line->manager));
-
for (i = 0; i < line->ocount; i++)
g_object_unref(G_OBJECT(line->origins[i].creator));
@@ -298,9 +294,9 @@ const mrange_t *g_buffer_line_get_range(const GBufferLine *line)
/******************************************************************************
* *
-* Paramètres : line = ligne à venir compléter. *
-* psize = taille souhaitée de l'impression des positions. *
-* vsize = taille souhaitée de l'impression des adresses. *
+* Paramètres : line = ligne à venir compléter. *
+* size = taille souhaitée de l'impression des positions. *
+* addr = localisation physique à venir représenter. *
* *
* Description : Construit le tronc commun d'une ligne autour de sa position. *
* *
@@ -310,61 +306,105 @@ const mrange_t *g_buffer_line_get_range(const GBufferLine *line)
* *
******************************************************************************/
-void g_buffer_line_fill_mrange(GBufferLine *line, MemoryDataSize psize, MemoryDataSize vsize)
+void g_buffer_line_fill_phys(GBufferLine *line, MemoryDataSize size, const vmpa2t *addr)
{
+ VMPA_BUFFER(position); /* Emplacement au format texte */
size_t len; /* Taille de l'élément inséré */
- VMPA_BUFFER(address); /* Adresse au format texte */
- size_t i; /* Boucle de parcours */
+ size_t i; /* Boucle de parcours #1 */
- /* Position physique */
+ vmpa2_phys_to_string(addr, size, position, &len);
- if (has_phys_addr(get_mrange_addr(&line->range)))
- {
- mrange_phys_to_string(&line->range, psize, true, address, &len);
+ for (i = 2; i < len; i++)
+ if (position[i] != '0') break;
- for (i = 2; i < len; i++)
- if (address[i] != '0') break;
+ if (i == len)
+ i = len - 1;
- if (i == len)
- g_buffer_line_append_text(line, BLC_PHYSICAL, address, len, RTT_PHYS_ADDR_PAD, NULL);
+ if (i > 0)
+ g_buffer_line_append_text(line, BLC_PHYSICAL, position, i, RTT_PHYS_ADDR_PAD, NULL);
- else
- {
- g_buffer_line_append_text(line, BLC_PHYSICAL, address, 2, RTT_PHYS_ADDR, NULL);
+ g_buffer_line_append_text(line, BLC_PHYSICAL, &position[i], len - i, RTT_PHYS_ADDR, NULL);
- if (i > 2)
- g_buffer_line_append_text(line, BLC_PHYSICAL, &address[2], i - 2, RTT_PHYS_ADDR_PAD, NULL);
+}
- g_buffer_line_append_text(line, BLC_PHYSICAL, &address[i], len - i, RTT_PHYS_ADDR, NULL);
- }
+/******************************************************************************
+* *
+* Paramètres : line = ligne à venir compléter. *
+* size = taille souhaitée de l'impression des positions. *
+* addr = localisation virtuelle à venir représenter. *
+* *
+* Description : Construit le tronc commun d'une ligne autour de sa position. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
- }
+void g_buffer_line_fill_virt(GBufferLine *line, MemoryDataSize size, const vmpa2t *addr)
+{
+ VMPA_BUFFER(position); /* Emplacement au format texte */
+ size_t len; /* Taille de l'élément inséré */
+ size_t i; /* Boucle de parcours #1 */
+
+ vmpa2_virt_to_string(addr, size, position, &len);
+
+ for (i = 2; i < len; i++)
+ if (position[i] != '0') break;
+
+ if (i == len)
+ i = len - 1;
+
+ if (i > 0)
+ g_buffer_line_append_text(line, BLC_VIRTUAL, position, i, RTT_PHYS_ADDR_PAD, NULL);
- /* Adresse virtuelle */
+ g_buffer_line_append_text(line, BLC_VIRTUAL, &position[i], len - i, RTT_PHYS_ADDR, NULL);
+
+}
- if (has_virt_addr(get_mrange_addr(&line->range)))
- {
- mrange_virt_to_string(&line->range, vsize, true, address, &len);
- for (i = 2; i < len; i++)
- if (address[i] != '0') break;
+/******************************************************************************
+* *
+* Paramètres : line = ligne à venir compléter. *
+* addr = localisation à afficher. *
+* psize = taille souhaitée de l'impression des positions. *
+* vsize = taille souhaitée de l'impression des adresses. *
+* *
+* Description : Construit le tronc commun d'une ligne autour de sa position. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
- if (i == len)
- g_buffer_line_append_text(line, BLC_VIRTUAL, address, len, RTT_VIRT_ADDR_PAD, NULL);
+void g_buffer_line_fill_vmpa(GBufferLine *line, const vmpa2t *addr, MemoryDataSize psize, MemoryDataSize vsize)
+{
+ g_buffer_line_fill_phys(line, psize, addr);
- else
- {
- g_buffer_line_append_text(line, BLC_VIRTUAL, address, 2, RTT_VIRT_ADDR, NULL);
+ g_buffer_line_fill_virt(line, vsize, addr);
- if (i > 2)
- g_buffer_line_append_text(line, BLC_VIRTUAL, &address[2], i - 2, RTT_VIRT_ADDR_PAD, NULL);
+}
- g_buffer_line_append_text(line, BLC_VIRTUAL, &address[i], len - i, RTT_VIRT_ADDR, NULL);
- }
+/******************************************************************************
+* *
+* Paramètres : line = ligne à venir compléter. *
+* psize = taille souhaitée de l'impression des positions. *
+* vsize = taille souhaitée de l'impression des adresses. *
+* *
+* Description : Construit le tronc commun d'une ligne autour de sa position. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
- }
+void g_buffer_line_fill_mrange(GBufferLine *line, MemoryDataSize psize, MemoryDataSize vsize)
+{
+ g_buffer_line_fill_vmpa(line, get_mrange_addr(&line->range), psize, vsize);
}
@@ -531,7 +571,7 @@ void g_buffer_line_append_text(GBufferLine *line, BufferLineColumn column, const
assert(length > 0);
if (column == BLC_MAIN)
- column = line->main_column;
+ column = BLC_ASSEMBLY;//line->main_column;
if (column == BLC_LAST_USED)
column = line->last_used;
@@ -938,6 +978,13 @@ void g_buffer_line_collect_widths(GBufferLine *line, line_width_summary *summary
{
width = get_column_width(&line->columns[i]);
+
+ /*
+ if (i == BLC_ASSEMBLY_HEAD)
+ assert(width > 0);
+ */
+
+
if (i < line->merge_start)
summary->max_widths[i] = MAX(summary->max_widths[i], width);
@@ -1008,7 +1055,10 @@ const line_segment *g_buffer_line_get_segment_from_coord(const GBufferLine *line
{
line_segment *result; /* Trouvaille à retourner */
- result = get_line_column_content_from_index(&line->columns[coord->column], coord->index);
+ if (coord->column < BLC_COUNT)
+ result = get_line_column_content_from_index(&line->columns[coord->column], coord->index);
+ else
+ result = false;
return result;
@@ -1069,6 +1119,9 @@ bool g_buffer_line_get_coord_at(const GBufferLine *line, const line_width_summar
{
width = g_buffer_line_compute_max_width(line, i, summary);
+ /* Si la colonne n'est absolument pas visible, on ne s'arrête pas dessus ! */
+ if (width == 0) continue;
+
if ((i + 1) < BLC_COUNT) limit = width + COL_MARGIN / 2;
else limit = width;
@@ -1139,7 +1192,10 @@ bool g_buffer_line_get_coord_at(const GBufferLine *line, const line_width_summar
if ((i - 1) < line->merge_start)
{
width = g_buffer_line_compute_max_width(line, i - 1, summary);
- *base += (width + COL_MARGIN);
+
+ if (width > 0)
+ *base += (width + COL_MARGIN);
+
}
else
*base += get_column_width(&line->columns[i - 1]);
@@ -1183,8 +1239,19 @@ bool g_buffer_line_get_coord_at(const GBufferLine *line, const line_width_summar
}
}
+
+ /* Il n'y a rien sur la ligne ! */
else
- result = false;
+ {
+ result = true;
+
+ *base = 0;
+ *offset = 0;
+
+ coord->column = BLC_COUNT;
+ coord->index = -1;
+
+ }
}
else
@@ -1305,6 +1372,7 @@ bool g_buffer_line_find_near_coord(const GBufferLine *line, col_coord_t *coord,
BufferLineColumn i; /* Boucle de parcours #1 */
bool displayed; /* Confort de lecture */
BufferLineColumn k; /* Boucle de parcours #2 */
+ gint width; /* Largeur d'une colonne donnée*/
result = false;
@@ -1381,8 +1449,14 @@ bool g_buffer_line_find_near_coord(const GBufferLine *line, col_coord_t *coord,
if (displayed)
{
- *offset += g_buffer_line_compute_max_width(line, k, summary);
- if (k < line->merge_start) *offset += COL_MARGIN;
+ width = g_buffer_line_compute_max_width(line, k, summary);
+
+ if (width > 0)
+ {
+ *offset += width;
+ if (k < line->merge_start) *offset += COL_MARGIN;
+ }
+
}
}
@@ -1469,10 +1543,8 @@ void g_buffer_line_draw(GBufferLine *line, cairo_t *cairo, const line_width_summ
{
max_width = g_buffer_line_compute_max_width(line, i, summary);
- x += max_width;
-
if (max_width > 0)
- x += COL_MARGIN;
+ x += max_width + COL_MARGIN;
}
diff --git a/src/glibext/gbufferline.h b/src/glibext/gbufferline.h
index be7e138..a8d2f3f 100644
--- a/src/glibext/gbufferline.h
+++ b/src/glibext/gbufferline.h
@@ -109,6 +109,15 @@ GBufferLine *g_buffer_line_new(const mrange_t *, BufferLineColumn);
const mrange_t *g_buffer_line_get_range(const GBufferLine *);
/* Construit le tronc commun d'une ligne autour de sa position. */
+void g_buffer_line_fill_phys(GBufferLine *, MemoryDataSize, const vmpa2t *);
+
+/* Construit le tronc commun d'une ligne autour de sa position. */
+void g_buffer_line_fill_virt(GBufferLine *, MemoryDataSize, const vmpa2t *);
+
+/* Construit le tronc commun d'une ligne autour de sa position. */
+void g_buffer_line_fill_vmpa(GBufferLine *, const vmpa2t *, MemoryDataSize, MemoryDataSize);
+
+/* Construit le tronc commun d'une ligne autour de sa position. */
void g_buffer_line_fill_mrange(GBufferLine *, MemoryDataSize, MemoryDataSize);
/* Construit le tronc commun d'une ligne d'instruction. */
diff --git a/src/glibext/gbufferview.c b/src/glibext/gbufferview.c
index 20d60ed..cd17191 100644
--- a/src/glibext/gbufferview.c
+++ b/src/glibext/gbufferview.c
@@ -24,14 +24,21 @@
#include "gbufferview.h"
+#include <assert.h>
+
+
/* Vue d'un tampon pour code désassemblé (instance) */
struct _GBufferView
{
GObject parent; /* A laisser en premier */
- GCodeBuffer *buffer; /* Tampon de code visualisé */
+ GBufferCache *cache; /* Tampon du contenu visualisé */
+
+ segcnt_list *highlighted; /* Segments mis en évidence */
+ bool external; /* Note l'origine de la liste */
+ bool unrestricted; /* Validité des informations */
vmpa2t start; /* Première ligne intégrée */
vmpa2t end; /* Dernière ligne intégrée */
@@ -45,11 +52,6 @@ struct _GBufferView
GWidthTracker *tracker; /* Suivi pour usage interne */
};
- bool unrestricted; /* Validité des informations */
-
- segcnt_list *highlighted; /* Segments mis en évidence */
- bool external; /* Note l'origine de la liste */
-
};
/* Vue d'un tampon pour code désassemblé (classe) */
@@ -57,10 +59,6 @@ struct _GBufferViewClass
{
GObjectClass parent; /* A laisser en premier */
- gint line_height; /* Hauteur maximale des lignes */
- gint left_margin; /* Marge gauche + espace */
- gint left_text; /* Début d'impression du code */
-
/* Signaux */
void (* need_redraw) (GBufferView *);
@@ -81,15 +79,23 @@ static void g_buffer_view_dispose(GBufferView *);
static void g_buffer_view_finalize(GBufferView *);
/* Accompagne une variation de la quantité de lignes du tampon. */
-static void on_buffer_size_changed(const GCodeBuffer *, bool, size_t, size_t, GBufferView *);
+static void on_buffer_cache_size_changed(const GBufferCache *, bool, size_t, size_t, GBufferView *);
-/* Réagit à un changement de contenu d'une ligne donnée. */
-static void on_buffer_line_changed(GCodeBuffer *, GBufferLine *, line_segment *, GBufferView *);
+/* Calcule la position idéale de curseur pour un point donné. */
+bool _g_buffer_view_compute_caret_full(GBufferView *, gint, GBufferLine *, size_t, const bool *, GdkRectangle *, vmpa2t *);
/* Déplace le curseur au sein d'une vue de tampon. */
static bool _g_buffer_view_move_caret(GBufferView *, const GBufferLine *, size_t, GdkRectangle *, bool, GdkScrollDirection, const bool *);
+/* Fournit la ligne présente à une ordonnée donnée. */
+static GBufferLine *g_buffer_view_find_line_at(GBufferView *, gint, size_t *);
+
+
+
+
+
+
/* Détermine le type de la vue d'un tampon pour code désassemblé. */
G_DEFINE_TYPE(GBufferView, g_buffer_view, G_TYPE_OBJECT);
@@ -116,10 +122,7 @@ static void g_buffer_view_class_init(GBufferViewClass *class)
object->dispose = (GObjectFinalizeFunc/* ! */)g_buffer_view_dispose;
object->finalize = (GObjectFinalizeFunc)g_buffer_view_finalize;
- class->line_height = 17;
- class->left_margin = 2 * class->line_height;
- class->left_text = 2.5 * class->line_height;
-
+ /* Sigaux */
g_signal_new("need-redraw",
G_TYPE_BUFFER_VIEW,
@@ -146,7 +149,10 @@ static void g_buffer_view_class_init(GBufferViewClass *class)
static void g_buffer_view_init(GBufferView *view)
{
- view->unrestricted = true;
+ /**
+ * Inversion du statut pour forcer l'actualisation lors de la création.
+ */
+ view->unrestricted = false;
}
@@ -165,7 +171,10 @@ static void g_buffer_view_init(GBufferView *view)
static void g_buffer_view_dispose(GBufferView *view)
{
- g_object_unref(G_OBJECT(view->buffer));
+ g_object_unref(G_OBJECT(view->cache));
+
+ if (!view->unrestricted)
+ g_object_unref(G_OBJECT(view->int_tracker));
G_OBJECT_CLASS(g_buffer_view_parent_class)->dispose(G_OBJECT(view));
@@ -207,22 +216,17 @@ static void g_buffer_view_finalize(GBufferView *view)
* *
******************************************************************************/
-GBufferView *g_buffer_view_new(GCodeBuffer *buffer, segcnt_list *highlighted)
+GBufferView *g_buffer_view_new(GBufferCache *cache, segcnt_list *highlighted)
{
GBufferView *result; /* Composant à retourner */
result = g_object_new(G_TYPE_BUFFER_VIEW, NULL);
- g_object_ref(G_OBJECT(buffer));
- result->buffer = buffer;
+ result->cache = cache;
g_buffer_view_restrict(result, NULL, NULL);
- g_code_buffer_register_view_callback(buffer,
- (buffer_size_changed_cb)on_buffer_size_changed,
- G_OBJECT(result));
-
- g_signal_connect(buffer, "line-changed", G_CALLBACK(on_buffer_line_changed), result);
+ g_signal_connect(cache, "size-changed", G_CALLBACK(on_buffer_cache_size_changed), result);
if (highlighted != NULL)
result->highlighted = highlighted;
@@ -238,11 +242,11 @@ GBufferView *g_buffer_view_new(GCodeBuffer *buffer, segcnt_list *highlighted)
/******************************************************************************
* *
-* Paramètres : buffer = tampon de lignes cohérentes à manipuler. *
-* added = indication sur la variation de la taille du tampon. *
-* index = indice de la première ligne à traiter. *
-* count = nombre de lignes à traiter. *
-* view = vue active du tampon de lignes concerné. *
+* Paramètres : cache = tampon de lignes cohérentes à manipuler. *
+* added = indication sur la variation de la taille du tampon. *
+* index = indice de la première ligne à traiter. *
+* count = nombre de lignes à traiter. *
+* view = vue active du tampon de lignes concerné. *
* *
* Description : Accompagne une variation de la quantité de lignes du tampon. *
* *
@@ -252,11 +256,11 @@ GBufferView *g_buffer_view_new(GCodeBuffer *buffer, segcnt_list *highlighted)
* *
******************************************************************************/
-static void on_buffer_size_changed(const GCodeBuffer *buffer, bool added, size_t index, size_t count, GBufferView *view)
+static void on_buffer_cache_size_changed(const GBufferCache *cache, bool added, size_t index, size_t count, GBufferView *view)
{
- size_t i; /* Boucle de parcours */
- GBufferLine *line; /* Ligne à manipuler */
- const vmpa2t *addr; /* Localisation de ligne */
+ //size_t i; /* Boucle de parcours */
+ //GBufferLine *line; /* Ligne à manipuler */
+ //const vmpa2t *addr; /* Localisation de ligne */
/**
* Il n'y a pas besoin de verrou ici car la fonction est appelée directement par le tampon.
@@ -270,6 +274,8 @@ static void on_buffer_size_changed(const GCodeBuffer *buffer, bool added, size_t
else
{
+#if 0
+
/* Avant la zone représentée ? */
if (index < view->first)
{
@@ -281,6 +287,8 @@ static void on_buffer_size_changed(const GCodeBuffer *buffer, bool added, size_t
else if (view->first == index)
for (i = 0; i < count; i++)
{
+ g_buffer_cache_get_line_addr(const GBufferCache *, size_t, gint, vmpa2t *);
+
line = g_code_buffer_find_line_by_index(buffer, index + i);
addr = get_mrange_addr(g_buffer_line_get_range(line));
@@ -302,6 +310,8 @@ static void on_buffer_size_changed(const GCodeBuffer *buffer, bool added, size_t
else if ((view->last + 1) == index)
for (i = 0; i < count; i++)
{
+ g_buffer_cache_get_line_addr(const GBufferCache *, size_t, gint, vmpa2t *);
+
line = g_code_buffer_find_line_by_index(buffer, index + i);
addr = get_mrange_addr(g_buffer_line_get_range(line));
@@ -312,7 +322,8 @@ static void on_buffer_size_changed(const GCodeBuffer *buffer, bool added, size_t
}
- g_width_tracker_update_added(view->int_tracker, index, count);
+ //g_width_tracker_update_added(view->int_tracker, index, count);
+#endif
}
@@ -338,38 +349,36 @@ static void on_buffer_size_changed(const GCodeBuffer *buffer, bool added, size_t
}
- g_width_tracker_update_deleted(view->int_tracker, index, index + count - 1);
+ //g_width_tracker_update_deleted(view->int_tracker, index, index + count - 1);
}
- g_signal_emit_by_name(view, "need-redraw");
+ //g_signal_emit_by_name(view, "need-redraw");
}
/******************************************************************************
* *
-* Paramètres : buffer = tampon de lignes cohérentes à manipuler. *
-* line = ligne dont la définition vient d'évoluer. *
-* segment = éventuel segment qui vient d'évoluer ou NULL. *
-* view = vue active du tampon de lignes concerné. *
+* Paramètres : view = visualisateur à consulter. *
* *
-* Description : Réagit à un changement de contenu d'une ligne donnée. *
+* Description : Fournit le tampon de code lié à un visualisateur donné. *
* *
-* Retour : - *
+* Retour : Tampon de code associé au gestionnaire d'affichage. *
* *
* Remarques : - *
* *
******************************************************************************/
-static void on_buffer_line_changed(GCodeBuffer *buffer, GBufferLine *line, line_segment *segment, GBufferView *view)
+GBufferCache *g_buffer_view_get_cache(const GBufferView *view)
{
- const vmpa2t *addr; /* Localisation de ligne */
+ GBufferCache *result; /* Instance à retourner */
- addr = get_mrange_addr(g_buffer_line_get_range(line));
+ result = view->cache;
- if (cmp_vmpa(&view->start, addr) <= 0 && cmp_vmpa(addr, &view->end) <= 0)
- g_signal_emit_by_name(view, "need-redraw");
+ g_object_ref(G_OBJECT(result));
+
+ return result;
}
@@ -390,33 +399,41 @@ static void on_buffer_line_changed(GCodeBuffer *buffer, GBufferLine *line, line_
void g_buffer_view_restrict(GBufferView *view, const vmpa2t *start, const vmpa2t *end)
{
+ bool state; /* Nouvel état à proclamer */
const GWidthTracker *template; /* Suivi déjà en place */
- if (!view->unrestricted)
- g_object_unref(G_OBJECT(view->int_tracker));
+ state = (start == NULL || end == NULL);
- view->unrestricted = (start == NULL || end == NULL);
+ if (view->unrestricted != state)
+ {
+ view->unrestricted = state;
- template = g_code_buffer_get_width_tracker(view->buffer);
+ template = g_buffer_cache_get_width_tracker(view->cache);
- if (view->unrestricted)
- {
- view->first = 0;
- view->last = g_code_buffer_count_lines(view->buffer) - 1;
+ if (view->unrestricted)
+ {
+ /* Vérification pour le cas particulier du démarrage */
+ if (view->int_tracker != NULL)
+ g_object_unref(G_OBJECT(view->int_tracker));
- view->ext_tracker = template;
+ view->first = 0;
+ view->last = g_buffer_cache_count_lines(view->cache) - 1;
- }
+ view->ext_tracker = template;
- else
- {
- copy_vmpa(&view->start, start);
- copy_vmpa(&view->end, end);
+ }
+
+ else
+ {
+ copy_vmpa(&view->start, start);
+ copy_vmpa(&view->end, end);
+
+ view->first = g_buffer_cache_find_index_by_addr(view->cache, start, true);
+ view->last = g_buffer_cache_find_index_by_addr(view->cache, end, false);
- view->first = g_code_buffer_get_index_from_address(view->buffer, start, true);
- view->last = g_code_buffer_get_index_from_address(view->buffer, end, false);
+ view->ext_tracker = g_width_tracker_new_restricted(template, view->first, view->last);
- view->ext_tracker = g_width_tracker_new_restricted(template, view->first, view->last);
+ }
}
@@ -425,7 +442,7 @@ void g_buffer_view_restrict(GBufferView *view, const vmpa2t *start, const vmpa2t
/******************************************************************************
* *
-* Paramètres : view = visualisateur à mettre à jour. *
+* Paramètres : view = visualisateur à consulter. *
* first = première ligne à imprimer ou NULL. [OUT] *
* last = première ligne hors cadre ou NULL. [OUT] *
* *
@@ -437,7 +454,7 @@ void g_buffer_view_restrict(GBufferView *view, const vmpa2t *start, const vmpa2t
* *
******************************************************************************/
-bool g_buffer_view_get_restrictions(GBufferView *view, vmpa2t *start, vmpa2t *end)
+bool g_buffer_view_get_restrictions(const GBufferView *view, vmpa2t *start, vmpa2t *end)
{
if (!view->unrestricted)
{
@@ -450,44 +467,11 @@ bool g_buffer_view_get_restrictions(GBufferView *view, vmpa2t *start, vmpa2t *en
}
-/******************************************************************************
-* *
-* Paramètres : view = visualisateur à consulter. *
-* *
-* Description : Fournit le tampon de code lié à un visualisateur donné. *
-* *
-* Retour : Tampon de code associé au gestionnaire d'affichage. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GCodeBuffer *g_buffer_view_get_buffer(const GBufferView *view)
-{
- g_object_ref(G_OBJECT(view->buffer));
-
- return view->buffer;
-}
-/******************************************************************************
-* *
-* Paramètres : view = visualisation à consulter. *
-* *
-* Description : Fournit la hauteur d'impression d'une ligne visualisée. *
-* *
-* Retour : Hauteur de ligne en pixel. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-gint g_buffer_view_get_line_height(GBufferView *view)
-{
- return G_BUFFER_VIEW_GET_CLASS(view)->line_height;
-}
/******************************************************************************
@@ -507,7 +491,7 @@ gint g_buffer_view_get_width(GBufferView *view, const bool *display)
{
gint result; /* Taille à retourner */
- result = G_BUFFER_VIEW_GET_CLASS(view)->left_text;
+ result = g_buffer_cache_get_text_position(view->cache);
result += g_width_tracker_get_width(view->tracker, display);
@@ -533,7 +517,7 @@ gint g_buffer_view_get_margin(GBufferView *view, const bool *display)
{
gint result; /* Taille à retourner */
- result = G_BUFFER_VIEW_GET_CLASS(view)->left_text;
+ result = g_buffer_cache_get_text_position(view->cache);
result += g_width_tracker_get_margin(view->tracker, display);
@@ -558,7 +542,7 @@ gint g_buffer_view_get_height(const GBufferView *view)
{
gint result; /* Taille à retourner */
- result = G_BUFFER_VIEW_GET_CLASS(view)->line_height;
+ result = g_buffer_cache_get_line_height(view->cache);
result *= (view->last - view->first + 1);
@@ -567,50 +551,66 @@ gint g_buffer_view_get_height(const GBufferView *view)
}
+
+
+
+
+
+
+
+
+
+
+
/******************************************************************************
* *
* Paramètres : view = vue de tampon à mettre à jour. *
-* x = abscisse de la zone principale à traiter. *
-* y = ordonnée de la zone principale à traiter. *
+* x = abscisse proposée pour le nouvel emplacement. *
+* y = ordonnée proposée pour le nouvel emplacement. *
* display = règles d'affichage des colonnes modulables. *
* caret = position du curseur à construire. [OUT] *
+* addr = adresse correspondant à cette même position. [OUT] *
* *
* Description : Calcule la position idéale de curseur pour un point donné. *
* *
-* Retour : Adresse si une a pu être déterminée, NULL sinon. *
+* Retour : true si les deux derniers arguments ont pu être constitués. *
* *
* Remarques : - *
* *
******************************************************************************/
-const vmpa2t *g_buffer_view_compute_caret(GBufferView *view, gint x, gint y, const bool *display, GdkRectangle *caret)
+bool g_buffer_view_compute_caret_full(GBufferView *view, gint x, gint y, const bool *display, GdkRectangle *caret, vmpa2t *addr)
{
- gint remaining; /* Copie de travail modifiable */
+ bool result; /* Bilan à retourner */
+ gint lheight; /* Hauteur d'une ligne */
size_t index; /* Indice de ligne de tampon */
GBufferLine *line; /* Ligne à la position courante*/
- const line_segment *segment; /* Segment présent sur la place*/
- GBufferViewClass *class; /* Classe pour les vues */
- remaining = x;
+ result = false;
- line = g_buffer_view_find_line_and_segment_at(view, &remaining, y, &index, display, &segment);
+ /* Détermination de la ligne courante */
- /* FIXME : unref() ! */
- if (line == NULL) return NULL;
- if (segment == NULL) printf(" -- no segment\n");
- if (segment == NULL) return NULL;
+ lheight = g_buffer_cache_get_line_height(view->cache);
+ index = y / lheight;
+ index += view->first;
- class = G_BUFFER_VIEW_GET_CLASS(view);
+ if (index > view->last)
+ goto gbvccf_done;
- caret->x = /*view->left_text +*/ (x - remaining) + get_caret_position_from_line_segment(segment, remaining);
+ line = g_buffer_cache_find_line_by_index(view->cache, index);
- caret->y = (index - view->first) * class->line_height;
+ assert(line != NULL);
- caret->width = 2;
- caret->height = class->line_height;
+ /* Calcul d'une position */
+
+ result = _g_buffer_view_compute_caret_full(view, x, line, index, display, caret, addr);
+
+ g_object_unref(G_OBJECT(line));
+
+ gbvccf_done:
- return get_mrange_addr(g_buffer_line_get_range(line));
+ return result;
}
@@ -618,50 +618,69 @@ const vmpa2t *g_buffer_view_compute_caret(GBufferView *view, gint x, gint y, con
/******************************************************************************
* *
* Paramètres : view = vue de tampon à mettre à jour. *
+* x = abscisse proposée pour le nouvel emplacement. *
* line = ligne correspondant à la position. *
* index = indice de cette même ligne dans le tampon. *
-* x = abscisse de la zone principale à traiter. *
* display = règles d'affichage des colonnes modulables. *
* caret = position du curseur à construire. [OUT] *
+* addr = adresse correspondant à cette même position. [OUT] *
* *
* Description : Calcule la position idéale de curseur pour un point donné. *
* *
-* Retour : Adresse si une a pu être déterminée, NULL sinon. *
+* Retour : true si les deux derniers arguments ont pu être constitués. *
* *
* Remarques : - *
* *
******************************************************************************/
-const vmpa2t *g_buffer_view_compute_caret_full(GBufferView *view, GBufferLine *line, size_t index, gint x, const bool *display, GdkRectangle *caret)
+bool _g_buffer_view_compute_caret_full(GBufferView *view, gint x, GBufferLine *line, size_t index, const bool *display, GdkRectangle *caret, vmpa2t *addr)
{
- GBufferViewClass *class; /* Classe pour les vues */
- gint offset; /* Point de travail modifiable */
+ bool result; /* Bilan à retourner */
+ gint text_pos; /* Abscisse de départ du texte */
line_width_summary summary; /* Résumé concis des largeurs */
gint base; /* Position absolue de segment */
bool status; /* Bilan de la localisation */
+ gint lheight; /* Hauteur d'une ligne */
- class = G_BUFFER_VIEW_GET_CLASS(view);
+ result = false;
- offset = x;
+ /* Zone d'intervention bornée ! */
- offset -= class->left_text;
- if (offset < 0) return NULL;
+ text_pos = g_buffer_cache_get_text_position(view->cache);
+
+ if (x < text_pos)
+ goto gbvccf_done;
+
+ /* Calcul d'une position */
g_width_tracker_get_local_width_summary(view->tracker, index, &summary);
- /* Traitement pour mise à jour de l'abscisse uniquement */
- status = g_buffer_line_get_coord_at(line, &summary, display, &base, &offset,
+ x -= text_pos;
+
+ status = g_buffer_line_get_coord_at(line, &summary, display, &base, &x,
GDK_SCROLL_LEFT, true, (col_coord_t []) { { 0 } });
- if (!status) return NULL;
- caret->x = class->left_text + base + offset;
+ if (!status)
+ goto gbvccf_done;
+
+ /* Transmission des informations */
+
+ lheight = g_buffer_cache_get_line_height(view->cache);
- caret->y = (index - view->first) * class->line_height;
+ caret->x = text_pos + base + x;
+
+ caret->y = (index - view->first) * lheight;
caret->width = 2;
- caret->height = class->line_height;
+ caret->height = lheight;
+
+ g_buffer_cache_get_line_addr(view->cache, index, caret->x, addr);
+
+ result = true;
- return get_mrange_addr(g_buffer_line_get_range(line));
+ gbvccf_done:
+
+ return result;
}
@@ -687,16 +706,24 @@ const vmpa2t *g_buffer_view_compute_caret_full(GBufferView *view, GBufferLine *l
static bool _g_buffer_view_move_caret(GBufferView *view, const GBufferLine *line, size_t index, GdkRectangle *caret, bool ctrl, GdkScrollDirection dir, const bool *display)
{
bool result; /* Bilan à retourner */
+ gint text_pos; /* Abscisse de départ du texte */
gint offset; /* Point de travail modifiable */
line_width_summary summary; /* Résumé concis des largeurs */
gint base; /* Position absolue de segment */
col_coord_t coord; /* Coordonnées en interne */
const line_segment *segment; /* Bribe de texte trouvée */
- offset = caret->x;
- offset -= G_BUFFER_VIEW_GET_CLASS(view)->left_text;
- if (offset < 0) return false;
+ result = false;
+
+ /* Zone d'intervention bornée ! */
+
+ text_pos = g_buffer_cache_get_text_position(view->cache);
+
+ if (caret->x < text_pos)
+ goto gbvmc_done;
+
+ offset = caret->x - text_pos;
g_width_tracker_get_local_width_summary(view->tracker, index, &summary);
@@ -725,7 +752,9 @@ static bool _g_buffer_view_move_caret(GBufferView *view, const GBufferLine *line
/* Mise à jour éventuelle */
if (result)
- caret->x = G_BUFFER_VIEW_GET_CLASS(view)->left_text + base + offset;
+ caret->x = text_pos + base + offset;
+
+ gbvmc_done:
return result;
@@ -735,82 +764,35 @@ static bool _g_buffer_view_move_caret(GBufferView *view, const GBufferLine *line
/******************************************************************************
* *
* Paramètres : view = vue de tampon à mettre à jour. *
-* caret = position du curseur à faire évoluer. *
* ctrl = indique la demande d'un parcours rapide. *
* dir = direction du parcours. *
* display = règles d'affichage des colonnes modulables. *
+* caret = position du curseur à faire évoluer. [OUT] *
+* addr = adresse correspondant à cette même position. [OUT] *
* *
* Description : Déplace le curseur au sein d'une vue de tampon. *
* *
-* Retour : Adresse si une a pu être déterminée, VMPA_INVALID sinon. *
+* Retour : true si les deux derniers arguments ont pu être constitués. *
* *
* Remarques : - *
* *
******************************************************************************/
-const vmpa2t *g_buffer_view_move_caret(GBufferView *view, GdkRectangle *caret, bool ctrl, GdkScrollDirection dir, const bool *display)
+bool g_buffer_view_move_caret(GBufferView *view, bool ctrl, GdkScrollDirection dir, const bool *display, GdkRectangle *caret, vmpa2t *addr)
{
- const vmpa2t *result; /* Actualisation à renvoyer */
+ bool result; /* Bilan à retourner */
size_t index; /* Indice de ligne de tampon */
GBufferLine *line; /* Ligne sous le pointeur */
-
-
- line_width_summary summary; /* Résumé concis des largeurs */
- gint left_pos; /* Retour à la ligne */
- gint right_pos; /* Position d'extrème droite */
- BufferLineColumn i; /* Boucle de parcours */
size_t first; /* Première ligne intégrée */
size_t last; /* Dernière ligne intégrée */
-
-
-
-
+ GBufferLine *other; /* Ligne voisine à visiter */
bool moved; /* Mémorisation d'une évolut° */
+ gint text_pos; /* Abscisse de départ du texte */
-
-
-
-
-
-
-
-
- result = NULL;
-
-
+ result = false;
line = g_buffer_view_find_line_at(view, caret->y, &index);
- if (line == NULL) return NULL;
-
- g_width_tracker_get_local_width_summary(view->tracker, index, &summary);
-
- switch (dir)
- {
- case GDK_SCROLL_UP:
- case GDK_SCROLL_DOWN:
- break;
- case GDK_SCROLL_LEFT:
- case GDK_SCROLL_RIGHT:
- left_pos = G_BUFFER_VIEW_GET_CLASS(view)->left_text;
- if (display[BLC_PHYSICAL]) left_pos += summary.max_widths[BLC_PHYSICAL] + COL_MARGIN;
- if (display[BLC_VIRTUAL]) left_pos += summary.max_widths[BLC_VIRTUAL] + COL_MARGIN;
- if (display[BLC_BINARY]) left_pos += summary.max_widths[BLC_BINARY] + COL_MARGIN;
- right_pos = left_pos;
- for (i = BLC_ASSEMBLY_HEAD; i < BLC_COUNT; i++)
- right_pos += summary.max_widths[i] + COL_MARGIN;
-
- /*
-gint g_buffer_line_compute_max_width(const GBufferLine *line, BufferLineColumn index, const gint *max_widths)
-
-BufferLineColumn g_buffer_line_get_merge_start(const GBufferLine *line)
- */
-
- left_pos = G_BUFFER_VIEW_GET_CLASS(view)->left_text;
-
- break;
- default: /* GDK_SCROLL_SMOOTH */
- break;
- }
+ if (line == NULL) goto gbvmc_done;
first = view->first;
last = view->last;
@@ -821,8 +803,12 @@ BufferLineColumn g_buffer_line_get_merge_start(const GBufferLine *line)
if (index > first)
{
- line = g_code_buffer_find_line_by_index(view->buffer, index - 1);
- result = g_buffer_view_compute_caret_full(view, line, index - 1, caret->x, display, caret);
+ index--;
+
+ other = g_buffer_cache_find_line_by_index(view->cache, index);
+ result = _g_buffer_view_compute_caret_full(view, caret->x, other, index, display, caret, addr);
+ g_object_unref(G_OBJECT(other));
+
}
break;
@@ -831,48 +817,58 @@ BufferLineColumn g_buffer_line_get_merge_start(const GBufferLine *line)
if (index < last)
{
- line = g_code_buffer_find_line_by_index(view->buffer, index + 1);
- result = g_buffer_view_compute_caret_full(view, line, index + 1, caret->x, display, caret);
+ index++;
+
+ other = g_buffer_cache_find_line_by_index(view->cache, index);
+ result = _g_buffer_view_compute_caret_full(view, caret->x, other, index, display, caret, addr);
+ g_object_unref(G_OBJECT(other));
+
}
break;
case GDK_SCROLL_LEFT:
- /*
- line = g_buffer_view_find_line_at(view, caret->y, &index);
- if (line == NULL) break;
- */
-
moved = _g_buffer_view_move_caret(view, line, index, caret, ctrl, GDK_SCROLL_LEFT, display);
if (moved)
- result = get_mrange_addr(g_buffer_line_get_range(line));
+ {
+ g_buffer_cache_get_line_addr(view->cache, index, caret->x, addr);
+ result = true;
+ }
else if (index > first)
{
- line = g_code_buffer_find_line_by_index(view->buffer, index - 1);
- result = g_buffer_view_compute_caret_full(view, line, index - 1, INT_MAX, display, caret);
+ index--;
+
+ other = g_buffer_cache_find_line_by_index(view->cache, index);
+ result = _g_buffer_view_compute_caret_full(view, INT_MAX, other, index, display, caret, addr);
+ g_object_unref(G_OBJECT(other));
+
}
break;
case GDK_SCROLL_RIGHT:
- /*
- line = g_buffer_view_find_line_at(view, caret->y, &index);
- if (line == NULL) break;
- */
-
moved = _g_buffer_view_move_caret(view, line, index, caret, ctrl, GDK_SCROLL_RIGHT, display);
if (moved)
- result = get_mrange_addr(g_buffer_line_get_range(line));
+ {
+ g_buffer_cache_get_line_addr(view->cache, index, caret->x, addr);
+ result = true;
+ }
else if (index < last)
{
- line = g_code_buffer_find_line_by_index(view->buffer, index + 1);
- result = g_buffer_view_compute_caret_full(view, line, index + 1, left_pos, display, caret);
+ index++;
+
+ text_pos = g_buffer_cache_get_text_position(view->cache);
+
+ other = g_buffer_cache_find_line_by_index(view->cache, index);
+ result = _g_buffer_view_compute_caret_full(view, text_pos, other, index, display, caret, addr);
+ g_object_unref(G_OBJECT(other));
+
}
break;
@@ -882,11 +878,27 @@ BufferLineColumn g_buffer_line_get_merge_start(const GBufferLine *line)
}
+ g_object_unref(G_OBJECT(line));
+
+ gbvmc_done:
+
return result;
}
+
+
+
+
+
+
+
+
+
+
+
+
/******************************************************************************
* *
* Paramètres : view = vue de tampon à mettre à jour. *
@@ -927,23 +939,64 @@ bool g_buffer_view_unhighlight_segments(GBufferView *view)
bool g_buffer_view_highlight_segments(GBufferView *view, gint x, gint y, const bool *display)
{
- bool need_redraw; /* Besoin d'actualisation ? */
+ bool result; /* Besoin à faire remonter */
+ gint text_pos; /* Abscisse de départ du texte */
+ gint lheight; /* Hauteur d'une ligne */
+ size_t index; /* Indice de ligne de tampon */
+ GBufferLine *line; /* Ligne à la position courante*/
+ line_width_summary summary; /* Résumé concis des largeurs */
const line_segment *segment; /* Segment sélectionnable */
+ /* Réinitialisation */
+
if (view->highlighted != NULL)
- need_redraw = g_buffer_view_unhighlight_segments(view);
+ result = g_buffer_view_unhighlight_segments(view);
else
- need_redraw = false;
+ result = false;
+
+ /* Zone d'intervention bornée ! */
+
+ text_pos = g_buffer_cache_get_text_position(view->cache);
+
+ if (x < text_pos)
+ goto gbvhs_done;
+
+ /* Détermination de la ligne concernée */
- g_buffer_view_find_line_and_segment_at(view, &x, y, NULL, display, &segment);
+ lheight = g_buffer_cache_get_line_height(view->cache);
+ index = y / lheight;
+
+ index += view->first;
+
+ if (index > view->last)
+ goto gbvhs_done;
+
+ line = g_buffer_cache_find_line_by_index(view->cache, index);
+
+ assert(line != NULL);
+
+ /* Recherche d'un segment et de son empreinte */
+
+ g_width_tracker_get_local_width_summary(view->tracker, index, &summary);
+
+ x -= text_pos;
+
+ segment = g_buffer_line_get_segment_at(line, &summary, display,
+ (gint []) { 0 }, &x, GDK_SCROLL_LEFT, true);
- if (segment)
- need_redraw |= add_segment_content_to_selection_list(view->highlighted, segment);
+ g_object_unref(G_OBJECT(line));
- if (need_redraw)
+ /* Conclusion */
+
+ if (segment != NULL)
+ result |= add_segment_content_to_selection_list(view->highlighted, segment);
+
+ if (result)
g_signal_emit_by_name(view, "need-redraw");
- return true;
+ gbvhs_done:
+
+ return result;
}
@@ -952,13 +1005,12 @@ bool g_buffer_view_highlight_segments(GBufferView *view, gint x, gint y, const b
* *
* Paramètres : view = visualisation à représenter. *
* cr = contexte graphique dédié à la procédure. *
-* fake_x = abscisse réelle du point 0 à l'écran. *
-* fake_y = ordonnée réelle du point 0 à l'écran. *
+* virt_y = ordonnée réelle du point 0 à l'écran. *
* area = position et surface à traiter. *
* display = règles d'affichage des colonnes modulables. *
* selected = ordonnée d'une ligne sélectionnée ou NULL. *
* *
-* Description : Imprime la visualisation du tampon de code désassemblé. *
+* Description : Imprime la visualisation du tampon de lignes quelconques. *
* *
* Retour : - *
* *
@@ -966,148 +1018,57 @@ bool g_buffer_view_highlight_segments(GBufferView *view, gint x, gint y, const b
* *
******************************************************************************/
-void g_buffer_view_draw(const GBufferView *view, cairo_t *cr, gint fake_x, gint fake_y, const cairo_rectangle_int_t *area, const bool *display, const gint *selected)
+void g_buffer_view_draw(const GBufferView *view, cairo_t *cr, gint virt_y, const cairo_rectangle_int_t *area, const bool *display, gint *selected)
{
- GBufferViewClass *class; /* Classe pour les vues */
- gint real_x; /* Abscisse réelle pour tampon */
- gint real_y; /* Ordonnée réelle pour tampon */
+ gint line_height; /* Hauteur d'une ligne */
+ gint cr_y; /* Ordonnée pour le dessin */
size_t first; /* Première ligne visée */
- size_t last; /* Dernière ligne visée + 1 */
- gint y; /* Point de départ + décallage */
- bool wait_selection; /* Sélection déjà passée ? */
- gint rel_selected; /* Position relative de sélect°*/
- size_t i; /* Boucle de parcours */
- GBufferLine *line; /* Ligne à dessiner à l'écran */
- line_width_summary summary; /* Résumé concis des largeurs */
+ size_t last; /* Dernière ligne visée */
- class = G_BUFFER_VIEW_GET_CLASS(view);
+ line_height = g_buffer_cache_get_line_height(view->cache);
- real_x = fake_x + class->left_text;
- real_y = fake_y + area->y;
+ /* Indice et point de départ */
first = view->first;
- first += (real_y / class->line_height);
-
- last = first + (area->height / class->line_height);
- if (area->height % class->line_height > 0) last++;
-
- last = MIN(last, view->last);
-
- y = area->y - (real_y % class->line_height);
-
- wait_selection = true;
+ first += (virt_y / line_height);
- if (selected != NULL)
- rel_selected = *selected - fake_y;
-
- if (g_code_buffer_count_lines(view->buffer) > 0)
- for (i = first; i <= last; i++)
- {
- /* Si sélection, on sousligne la ligne concernée */
- if (wait_selection && selected != NULL && rel_selected == y)
- {
- cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.05);
+ cr_y = area->y - (virt_y % line_height);
- cairo_rectangle(cr, area->x, y, area->width, class->line_height);
- cairo_fill(cr);
+ /* Indice de d'arrivée */
- wait_selection = false;
+ last = first + (area->height / line_height);
+ if (area->height % line_height > 0) last++;
- }
+ last = MIN(last, view->last);
- line = g_code_buffer_find_line_by_index(view->buffer, i);
+ /* Phase de dessin ! */
- if (i == first || (g_buffer_line_get_flags(line) & BLF_WIDTH_MANAGER))
- g_width_tracker_get_local_width_summary(view->tracker, i, &summary);
+ /**
+ * Le contexte n'est pas sauvegardé avant modification ici car
+ * l'appelant l'a fait pour nous avant sa translation sur les abscisses.
+ */
- g_buffer_line_draw(line, cr, &summary, real_x, y, display, view->highlighted);
+ cairo_translate(cr, 0, cr_y);
- y += class->line_height;
+ if (selected != NULL)
+ *selected -= cr_y;
- }
+ g_buffer_cache_draw(view->cache, cr, first, last, area, display, selected, view->highlighted);
}
-/******************************************************************************
-* *
-* Paramètres : view = visualisation à consulter. *
-* addr = adresse où retrouver la ligne recherchée. *
-* flags = propriétés à vérifier en tout ou partie. *
-* idx = indice de la ligne trouvée ou NULL. [OUT] *
-* *
-* Description : Retrouve une ligne au sein d'un tampon avec une adresse. *
-* *
-* Retour : Line retrouvée ou NULL en cas d'échec. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GBufferLine *g_buffer_view_find_line_by_addr(const GBufferView *view, const vmpa2t *addr, BufferLineFlags flags, size_t *idx)
-{
- GBufferLine *result; /* Ligne trouvée à retourner */
- phys_t length; /* Taille de la vue */
- mrange_t vrange; /* Couverture de la vue */
- bool allowed; /* Rechercher validée ? */
-
- /* Vérification des bornes */
-
- if (!view->unrestricted)
- {
- length = compute_vmpa_diff(&view->start, &view->end);
- init_mrange(&vrange, &view->start, length);
- allowed = mrange_contains_addr_inclusive(&vrange, addr);
- }
- else allowed = true;
- /* Lancement des recherches ? */
- if (allowed)
- result = g_code_buffer_find_line_by_addr(view->buffer, addr, flags, idx);
- else
- result = NULL;
- return result;
-
-}
-/******************************************************************************
-* *
-* Paramètres : view = visualisation à consulter. *
-* index = indice de la ligne recherchée. *
-* *
-* Description : Retrouve une ligne au sein d'un tampon avec un indice. *
-* *
-* Retour : Line retrouvée ou NULL en cas d'échec. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GBufferLine *g_buffer_view_find_line_by_index(const GBufferView *view, size_t index)
-{
- GBufferLine *result; /* Ligne trouvée à retourner */
- bool allowed; /* Rechercher validée ? */
- /* Vérification des bornes */
- allowed = (view->first <= index && index <= view->last);
- /* Lancement des recherches ? */
-
- if (allowed)
- result = g_code_buffer_find_line_by_index(view->buffer, index);
- else
- result = NULL;
-
- return result;
-
-}
/******************************************************************************
@@ -1124,19 +1085,19 @@ GBufferLine *g_buffer_view_find_line_by_index(const GBufferView *view, size_t in
* *
******************************************************************************/
-GBufferLine *g_buffer_view_find_line_at(GBufferView *view, gint y, size_t *idx)
+static GBufferLine *g_buffer_view_find_line_at(GBufferView *view, gint y, size_t *idx)
{
GBufferLine *result; /* Ligne trouvée à retourner */
gint lheight; /* Hauteur d'une ligne */
size_t index; /* Indice attendu */
- lheight = g_buffer_view_get_line_height(view);
+ lheight = g_buffer_cache_get_line_height(view->cache);
index = y / lheight;
index += view->first;
if (index <= view->last)
- result = g_code_buffer_find_line_by_index(view->buffer, index);
+ result = g_buffer_cache_find_line_by_index(view->cache, index);
else
result = NULL;
@@ -1148,125 +1109,26 @@ GBufferLine *g_buffer_view_find_line_at(GBufferView *view, gint y, size_t *idx)
}
-/******************************************************************************
-* *
-* Paramètres : view = visualisation à consulter. *
-* x = abscisse comprise dans le segment recherché. [OUT] *
-* y = ordonnée comprise dans la ligne recherchée. *
-* idx = indice de la ligne trouvée ou NULL. [OUT] *
-* display = règles d'affichage des colonnes modulables. *
-* segment = portion de texte recherchée ou NULL. [OUT] *
-* *
-* Description : Fournit la ligne et son segment présents à une position. *
-* *
-* Retour : Ligne retrouvée ou NULL si aucune. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GBufferLine *g_buffer_view_find_line_and_segment_at(GBufferView *view, gint *x, gint y, size_t *idx, const bool *display, const line_segment **segment)
-{
- GBufferLine *result; /* Ligne trouvée à retourner */
- size_t index; /* Indice de la ligne trouvée */
- GBufferViewClass *class; /* Classe pour les vues */
- line_width_summary summary; /* Résumé concis des largeurs */
-
- /* Recherche d'une ligne correspondante */
- result = g_buffer_view_find_line_at(view, y, &index);
- if (idx != NULL) *idx = index;
- /* Recherche du segment visé éventuel */
- if (result != NULL && segment != NULL)
- {
- class = G_BUFFER_VIEW_GET_CLASS(view);
- if (*x < class->left_text)
- *segment = NULL;
- else
- {
- g_width_tracker_get_local_width_summary(view->tracker, index, &summary);
- *x -= class->left_text;
- *segment = g_buffer_line_get_segment_at(result, &summary, display,
- (gint []) { 0 }, x, GDK_SCROLL_LEFT, true);
- }
- }
- return result;
-}
/******************************************************************************
* *
-* Paramètres : view = visualisation à consulter. *
-* x = abscisse comprise dans le segment recherché. [OUT] *
-* y = ordonnée comprise dans la ligne recherchée. *
-* idx = indice de la ligne trouvée ou NULL. [OUT] *
-* display = règles d'affichage des colonnes modulables. *
-* creator = instance à l'origine de la représentation. [OUT] *
-* *
-* Description : Fournit la ligne et son segment présents à une position. *
-* *
-* Retour : Ligne retrouvée ou NULL si aucune. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GBufferLine *g_buffer_view_find_line_and_creator_at(GBufferView *view, gint *x, gint y, size_t *idx, const bool *display, GObject **creator)
-{
- GBufferLine *result; /* Ligne trouvée à retourner */
- size_t index; /* Indice de la ligne trouvée */
- GBufferViewClass *class; /* Classe pour les vues */
- line_width_summary summary; /* Résumé concis des largeurs */
-
- /* Recherche d'une ligne correspondante */
-
- result = g_buffer_view_find_line_at(view, y, &index);
-
- if (idx != NULL) *idx = index;
-
- /* Recherche du segment visé éventuel */
-
- if (result != NULL && creator != NULL)
- {
- class = G_BUFFER_VIEW_GET_CLASS(view);
-
- if (*x < class->left_text)
- *creator = NULL;
-
- else
- {
- g_width_tracker_get_local_width_summary(view->tracker, index, &summary);
-
- *x -= class->left_text;
- *creator = g_buffer_line_get_creator_at(result, &summary, display,
- (gint []) { 0 }, x, GDK_SCROLL_LEFT, true);
-
- }
-
- }
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : view = composant GTK à consulter. *
+* Paramètres : view = visualisation à consulter. *
* addr = adresse à présenter à l'écran. *
+* code = s'arrête si possible à une ligne avec code. *
* x = position horizontale au sein du composant. [OUT] *
* y = position verticale au sein du composant. [OUT] *
-* code = s'arrête si possible à une ligne avec code. *
* *
* Description : Indique la position d'affichage d'une adresse donnée. *
* *
@@ -1276,61 +1138,11 @@ GBufferLine *g_buffer_view_find_line_and_creator_at(GBufferView *view, gint *x,
* *
******************************************************************************/
-bool g_buffer_view_get_address_coordinates(GBufferView *view, const vmpa2t *addr, gint *x, gint *y, bool code)
+bool g_buffer_view_get_address_coordinates(GBufferView *view, const vmpa2t *addr, bool code, gint *x, gint *y)
{
bool result; /* Bilan à retourner */
- gint lheight; /* Hauteur d'une ligne */
- size_t i; /* Boucle de parcours */
- GBufferLine *line; /* Ligne à consulter */
- const mrange_t *range; /* Emplacement parcouru */
-
- result = false;
-
- *x = 0;
- *y = 0;
-
- lheight = g_buffer_view_get_line_height(view);
-
- for (i = view->first; i <= view->last; i++)
- {
- /**
- * Si l'adresse recherchée est plus petite que l'adresse de départ,
- * on va effectuer un parcours complet pour rien.
- *
- * On considère cependant que le seul cas où celà peut arriver
- * est lorsque que des découpages en blocs sont impliqués.
- *
- * Les découpages conduisent alors à la formation de petites zones,
- * rapides à parcourir.
- */
-
- line = g_code_buffer_find_line_by_index(view->buffer, i);
- range = g_buffer_line_get_range(line);
-
- result = mrange_contains_addr(range, addr);
- if (result) break;
-
- *y += lheight;
- }
-
- if (result && code)
- for (; i <= view->last; i++)
- {
- line = g_code_buffer_find_line_by_index(view->buffer, i);
-
- if (g_buffer_line_get_flags(line) & BLF_HAS_CODE) break;
-
- if (i == view->last) break;
-
- line = g_code_buffer_find_line_by_index(view->buffer, i + 1);
-
- range = g_buffer_line_get_range(line);
- if (!mrange_contains_addr(range, addr)) break;
-
- *y += lheight;
-
- }
+ result = g_buffer_cache_get_address_coordinates(view->cache, addr, view->first, view->last, code, x, y);
return result;
diff --git a/src/glibext/gbufferview.h b/src/glibext/gbufferview.h
index 0aa26a6..dc1d704 100644
--- a/src/glibext/gbufferview.h
+++ b/src/glibext/gbufferview.h
@@ -28,7 +28,7 @@
#include <glib-object.h>
-#include "gcodebuffer.h"
+#include "gbuffercache.h"
@@ -47,23 +47,22 @@ typedef struct _GBufferView GBufferView;
typedef struct _GBufferViewClass GBufferViewClass;
-/* Détermine le type de la vue d'un tampon pour code désassemblé. */
+/* Détermine le type de la vue d'un tampon pour lignes générées. */
GType g_buffer_view_get_type(void);
-/* Crée une nouvelle vue d'un tampon pour code désassemblé. */
-GBufferView *g_buffer_view_new(GCodeBuffer *, segcnt_list *);
+/* Crée une nouvelle vue d'un tampon pour lignes générées. */
+GBufferView *g_buffer_view_new(GBufferCache *, segcnt_list *);
+
+/* Fournit le tampon de code lié à un visualisateur donné. */
+GBufferCache *g_buffer_view_get_cache(const GBufferView *);
/* Restreint le champ d'application de l'affichage. */
void g_buffer_view_restrict(GBufferView *, const vmpa2t *, const vmpa2t *);
/* Indique le champ d'application de l'affichage. */
-bool g_buffer_view_get_restrictions(GBufferView *, vmpa2t *, vmpa2t *);
+bool g_buffer_view_get_restrictions(const GBufferView *, vmpa2t *, vmpa2t *);
-/* Fournit le tampon de code lié à un visualisateur donné. */
-GCodeBuffer *g_buffer_view_get_buffer(const GBufferView *);
-/* Fournit la hauteur d'impression d'une ligne visualisée. */
-gint g_buffer_view_get_line_height(GBufferView *);
/* Fournit la largeur requise par une visualisation. */
gint g_buffer_view_get_width(GBufferView *, const bool *);
@@ -74,14 +73,18 @@ gint g_buffer_view_get_margin(GBufferView *, const bool *);
/* Fournit la hauteur requise par une visualisation. */
gint g_buffer_view_get_height(const GBufferView *);
-/* Calcule la position idéale de curseur pour un point donné. */
-const vmpa2t *g_buffer_view_compute_caret(GBufferView *, gint, gint, const bool *, GdkRectangle *);
+
+
+
/* Calcule la position idéale de curseur pour un point donné. */
-const vmpa2t *g_buffer_view_compute_caret_full(GBufferView *, GBufferLine *, size_t, gint, const bool *, GdkRectangle *);
+bool g_buffer_view_compute_caret_full(GBufferView *, gint, gint, const bool *, GdkRectangle *, vmpa2t *);
/* Déplace le curseur au sein d'une vue de tampon. */
-const vmpa2t *g_buffer_view_move_caret(GBufferView *, GdkRectangle *, bool, GdkScrollDirection, const bool *);
+bool g_buffer_view_move_caret(GBufferView *, bool, GdkScrollDirection, const bool *, GdkRectangle *, vmpa2t *);
+
+
+
/* Supprime toute mise en évidence de segments. */
bool g_buffer_view_unhighlight_segments(GBufferView *);
@@ -89,26 +92,18 @@ bool g_buffer_view_unhighlight_segments(GBufferView *);
/* Surligne tous les segments similaires à celui sous la souris. */
bool g_buffer_view_highlight_segments(GBufferView *, gint, gint, const bool *);
-/* Imprime la visualisation du tampon de code désassemblé. */
-void g_buffer_view_draw(const GBufferView *, cairo_t *, gint, gint, const cairo_rectangle_int_t *, const bool *, const gint *);
+/* Imprime la visualisation du tampon de lignes quelconques. */
+void g_buffer_view_draw(const GBufferView *, cairo_t *, gint, const cairo_rectangle_int_t *, const bool *, gint *);
-/* Retrouve une ligne au sein d'un tampon avec une adresse. */
-GBufferLine *g_buffer_view_find_line_by_addr(const GBufferView *, const vmpa2t *, BufferLineFlags, size_t *);
-/* Retrouve une ligne au sein d'un tampon avec un indice. */
-GBufferLine *g_buffer_view_find_line_by_index(const GBufferView *, size_t );
-/* Fournit la ligne présente à une ordonnée donnée. */
-GBufferLine *g_buffer_view_find_line_at(GBufferView *, gint, size_t *);
-/* Fournit la ligne et son segment présents à une position. */
-GBufferLine *g_buffer_view_find_line_and_segment_at(GBufferView *, gint *, gint, size_t *, const bool *, const line_segment **);
-/* Fournit la ligne et son segment présents à une position. */
-GBufferLine *g_buffer_view_find_line_and_creator_at(GBufferView *, gint *, gint, size_t *, const bool *, GObject **);
/* Indique la position d'affichage d'une adresse donnée. */
-bool g_buffer_view_get_address_coordinates(GBufferView *, const vmpa2t *, gint *, gint *, bool);
+bool g_buffer_view_get_address_coordinates(GBufferView *, const vmpa2t *, bool, gint *, gint *);
+
+
diff --git a/src/glibext/gcodebuffer.c b/src/glibext/gcodebuffer.c
deleted file mode 100644
index e9f1762..0000000
--- a/src/glibext/gcodebuffer.c
+++ /dev/null
@@ -1,1778 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * gcodebuffer.c - affichage d'un fragment de code d'assemblage
- *
- * Copyright (C) 2010-2014 Cyrille Bagard
- *
- * This file is part of Chrysalide.
- *
- * Chrysalide is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * Chrysalide is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#include "gcodebuffer.h"
-
-
-#include <assert.h>
-#include <malloc.h>
-#include <stdlib.h>
-#include <string.h>
-
-
-#include "chrysamarshal.h"
-#include "delayed-int.h"
-#include "../common/extstr.h"
-
-
-
-/* -------------------------- PARCOURS DU CODE D'UN TAMPON -------------------------- */
-
-
-#define G_TYPE_BUFFER_SCAN g_buffer_scan_get_type()
-#define G_BUFFER_SCAN(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_buffer_scan_get_type(), GDelayedExport))
-#define G_IS_BUFFER_SCAN(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_buffer_scan_get_type()))
-#define G_BUFFER_SCAN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_BUFFER_SCAN, GDelayedExportClass))
-#define G_IS_BUFFER_SCAN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_BUFFER_SCAN))
-#define G_BUFFER_SCAN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_BUFFER_SCAN, GDelayedExportClass))
-
-
-/* Ensembles binaires à désassembler (instance) */
-typedef struct _GBufferScan
-{
- GDelayedWork parent; /* A laisser en premier */
-
- GCodeBuffer *buffer; /* Tampon à manipuler */
-
- vmpa2t start; /* Début du parcours */
- bool has_start; /* Validité des données #1 */
- vmpa2t end; /* Fin du parcours */
- bool has_end; /* Validité des données #2 */
-
- char *message; /* Message de progression */
-
- process_line_fc process; /* Fonction de traitement réel */
- void *user_data; /* Données à faire suivre */
-
-} GBufferScan;
-
-/* Ensembles binaires à désassembler (classe) */
-typedef struct _GBufferScanClass
-{
- GDelayedWorkClass parent; /* A laisser en premier */
-
-} GBufferScanClass;
-
-
-/* Indique le type défini pour les tâches d'exportation différée. */
-static GType g_buffer_scan_get_type(void);
-
-/* Initialise la classe des tâches d'exportation différée. */
-static void g_buffer_scan_class_init(GBufferScanClass *);
-
-/* Initialise une tâche d'exportation différée. */
-static void g_buffer_scan_init(GBufferScan *);
-
-/* Supprime toutes les références externes. */
-static void g_buffer_scan_dispose(GBufferScan *);
-
-/* Procède à la libération totale de la mémoire. */
-static void g_buffer_scan_finalize(GBufferScan *);
-
-/* Crée une tâche d'exportation différée. */
-static GBufferScan *g_buffer_scan_new(GCodeBuffer *, const vmpa2t *, const vmpa2t *, const char *, process_line_fc, void *);
-
-/* Assure l'exportation en différé. */
-static void g_buffer_scan_process(GBufferScan *, GtkStatusStack *);
-
-
-
-/* -------------------------- TAMPON POUR CODE DESASSEMBLE -------------------------- */
-
-
-/* Suivi distant des évolutions */
-typedef struct _view_callback
-{
- buffer_size_changed_cb size_changed; /* Evolution de taille */
- GObject *data; /* Données à associer */
-
-} view_callback;
-
-
-/* Tampon pour code désassemblé (instance) */
-struct _GCodeBuffer
-{
- GObject parent; /* A laisser en premier */
-
- BufferLineColumn main_column; /* Colonne principale */
-
- GBufferLine **lines; /* Liste des lignes intégrées */
- size_t count; /* Quantité en cache */
- size_t used; /* Quantité utilisée */
-
- GWidthTracker *tracker; /* Suivi des largeurs */
-
- size_t indent; /* Indentation des lignes */
-
- view_callback *vcallbacks; /* Vues à mettre à jour */
- size_t vcount; /* Quantité de ces vues */
-
-};
-
-/* Tampon pour code désassemblé (classe) */
-struct _GCodeBufferClass
-{
- GObjectClass parent; /* A laisser en premier */
-
- /* Signaux */
-
- void (* line_changed) (GCodeBuffer *, GBufferLine *, line_segment *);
-
-};
-
-
-/* Taille des allocations de masse */
-#define LINE_ALLOC_BULK 20
-
-
-/* Procède à l'initialisation d'une classe de tampon de code. */
-static void g_code_buffer_class_init(GCodeBufferClass *);
-
-/* Procède à l'initialisation d'un tampon pour code désassemblé. */
-static void g_code_buffer_init(GCodeBuffer *);
-
-/* Réagit à un changement de contenu d'une ligne donnée. */
-static void on_line_content_change(GBufferLine *, line_segment *, GCodeBuffer *);
-
-/* Réagit à un changement de propriété rattachée à une ligne. */
-static void on_line_flag_flip(GBufferLine *, BufferLineFlags, BufferLineFlags, GCodeBuffer *);
-
-/* Ajoute de nouvelles lignes à une position donnée. */
-static void g_code_buffer_insert_lines_at(GCodeBuffer *, GBufferLine **, size_t, size_t);
-
-
-
-/* ------------------------- CONFORTS POUR LES COMMENTAIRES ------------------------- */
-
-
-/* Affiche un commentaire sur une ligne de tampon donnée. */
-static bool _g_code_buffer_write_inlined_comment(GCodeBuffer *, GBufferLine *, const char *, GObject *);
-
-/* Affiche un commentaire sur une ligne de tampon dédiée. */
-static bool _g_code_buffer_write_comment_area(GCodeBuffer *, GBufferLine *, const char *, bool, GObject *);
-
-/* Retrouve la première ligne d'une zone de commentaire. */
-static size_t g_code_buffer_find_first_line_comment(const GCodeBuffer *, size_t);
-
-/* Retrouve la dernière ligne d'une zone de commentaire. */
-static size_t g_code_buffer_find_last_line_comment(const GCodeBuffer *, size_t);
-
-/* Supprime un commentaire existant. */
-static bool _g_code_buffer_delete_lines_comment(GCodeBuffer *, GBufferLine *);
-
-
-
-/* ------------------------- SIGNAUX IMMEDIATS POUR UNE VUE ------------------------- */
-
-
-/* Fait suivre une variation de la quantité de lignes du tampon. */
-static void g_code_buffer_notify_size_changed(const GCodeBuffer *, bool, size_t, size_t);
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* PARCOURS DU CODE D'UN TAMPON */
-/* ---------------------------------------------------------------------------------- */
-
-
-/* Indique le type défini pour les tâches d'exportation différée. */
-G_DEFINE_TYPE(GBufferScan, g_buffer_scan, G_TYPE_DELAYED_WORK);
-
-
-/******************************************************************************
-* *
-* Paramètres : klass = classe à initialiser. *
-* *
-* Description : Initialise la classe des tâches d'exportation différée. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_buffer_scan_class_init(GBufferScanClass *klass)
-{
- GObjectClass *object; /* Autre version de la classe */
- GDelayedWorkClass *work; /* Version en classe parente */
-
- object = G_OBJECT_CLASS(klass);
-
- object->dispose = (GObjectFinalizeFunc/* ! */)g_buffer_scan_dispose;
- object->finalize = (GObjectFinalizeFunc)g_buffer_scan_finalize;
-
- work = G_DELAYED_WORK_CLASS(klass);
-
- work->run = (run_task_fc)g_buffer_scan_process;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : scan = instance à initialiser. *
-* *
-* Description : Initialise une tâche d'exportation différée. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_buffer_scan_init(GBufferScan *scan)
-{
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : scan = instance d'objet GLib à traiter. *
-* *
-* Description : Supprime toutes les références externes. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_buffer_scan_dispose(GBufferScan *scan)
-{
- g_object_unref(G_OBJECT(scan->buffer));
-
- G_OBJECT_CLASS(g_buffer_scan_parent_class)->dispose(G_OBJECT(scan));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : scan = instance d'objet GLib à traiter. *
-* *
-* Description : Procède à la libération totale de la mémoire. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_buffer_scan_finalize(GBufferScan *scan)
-{
- free(scan->message);
-
- G_OBJECT_CLASS(g_buffer_scan_parent_class)->finalize(G_OBJECT(scan));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : buffer = tampon à manipuler. *
-* start = première adresse visée ou NULL. *
-* end = dernière adresse visée ou NULL. *
-* message = message à afficher lors de la progression. *
-* process = fonction assurant le traitement effectif. *
-* data = données utilisateur à faire suivre. *
-* *
-* Description : Crée une tâche d'exportation différée. *
-* *
-* Retour : Tâche créée. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static GBufferScan *g_buffer_scan_new(GCodeBuffer *buffer, const vmpa2t *start, const vmpa2t *end, const char *message, process_line_fc process, void *data)
-{
- GBufferScan *result; /* Tâche à retourner */
-
- result = g_object_new(G_TYPE_BUFFER_SCAN, NULL);
-
- result->buffer = buffer;
- g_object_ref(G_OBJECT(buffer));
-
- result->has_start = (start != NULL);
-
- if (result->has_start)
- copy_vmpa(&result->start, start);
-
- result->has_end = (end != NULL);
-
- if (result->has_end)
- copy_vmpa(&result->end, end);
-
- result->message = strdup(message);
-
- result->process = process;
- result->user_data = data;
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : scan = parcours à mener. *
-* status = barre de statut à tenir informée. *
-* *
-* Description : Assure l'exportation en différé. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_buffer_scan_process(GBufferScan *scan, GtkStatusStack *status)
-{
- size_t first; /* Première ligne visée */
- size_t last; /* Dernière ligne visée + 1 */
- GBufferLine **lines; /* Liste des lignes à traiter */
- //bstatus_id_t id; /* Identifiant de statut */
- size_t i; /* Boucle de parcours */
-
- /* TODO : lock scan->buffer->lines */
-
- if (scan->has_start)
- first = g_code_buffer_get_index_from_address(scan->buffer, &scan->start, true);
- else
- first = 0;
-
- if (scan->has_end)
- last = g_code_buffer_get_index_from_address(scan->buffer, &scan->end, false);
- else
- last = scan->buffer->used - 1;
-
- lines = scan->buffer->lines;
-
- //id = gtk_extended_status_bar_push(statusbar, scan->message, true);
-
- if (scan->buffer->used > 0)
- for (i = first; i <= last; i++)
- {
- if (!scan->process(scan->buffer, lines[i], scan->user_data))
- break;
-
- /*
- gtk_extended_status_bar_update_activity(statusbar, id,
- (i - first) * 1.0 / (last - first));
- */
-
- }
-
- /* TODO : unlock scan->buffer->lines */
-
- //gtk_extended_status_bar_remove(statusbar, id);
-
-}
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* TAMPON POUR CODE DESASSEMBLE */
-/* ---------------------------------------------------------------------------------- */
-
-
-/* Détermine le type du composant de tampon pour code désassemblé. */
-G_DEFINE_TYPE(GCodeBuffer, g_code_buffer, G_TYPE_OBJECT);
-
-
-/******************************************************************************
-* *
-* Paramètres : class = classe de composant GTK à initialiser. *
-* *
-* Description : Procède à l'initialisation d'une classe de tampon de code. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_code_buffer_class_init(GCodeBufferClass *class)
-{
- g_signal_new("line-changed",
- G_TYPE_CODE_BUFFER,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET(GCodeBufferClass, line_changed),
- NULL, NULL,
- g_cclosure_user_marshal_VOID__OBJECT_OBJECT,
- G_TYPE_NONE, 2, G_TYPE_OBJECT, G_TYPE_OBJECT);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : buffer = composant GTK à initialiser. *
-* *
-* Description : Procède à l'initialisation d'un tampon pour code désassemblé.*
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_code_buffer_init(GCodeBuffer *buffer)
-{
- buffer->tracker = g_width_tracker_new(buffer);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : main = colonne à référencer comme étant la principale. *
-* *
-* Description : Crée un nouveau composant de tampon pour code désassemblé. *
-* *
-* Retour : Composant GTK créé. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GCodeBuffer *g_code_buffer_new(BufferLineColumn main)
-{
- GCodeBuffer *result; /* Composant à retourner */
-
- result = g_object_new(G_TYPE_CODE_BUFFER, NULL);
-
- result->main_column = main;
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : buffer = composant GLib à consulter. *
-* *
-* Description : Compte le nombre de lignes rassemblées dans un tampon. *
-* *
-* Retour : Nombre de lignes constituant le tampon. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-size_t g_code_buffer_count_lines(const GCodeBuffer *buffer)
-{
- return buffer->used;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : buffer = composant GLib à consulter. *
-* *
-* Description : Fournit un lien vers la structure de suivi de largeurs. *
-* *
-* Retour : Gestionnaire de largeurs de lignes. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-const GWidthTracker *g_code_buffer_get_width_tracker(const GCodeBuffer *buffer)
-{
- return buffer->tracker;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : buffer = composant GLib à consulter. *
-* range = emplacement où va se situer la ligne. *
-* *
-* Description : Initie une nouvelle ligne devant être insérée dans le tampon.*
-* *
-* Retour : Nouvelle ligne vierge à écrire. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GBufferLine *g_code_buffer_prepare_new_line(GCodeBuffer *buffer, const mrange_t *range)
-{
- GBufferLine *result; /* Instance à retourner */
- size_t i; /* Boucle de parcours */
-
- result = g_buffer_line_new(range, buffer->main_column);
-
- for (i = 0; i < buffer->indent; i++)
- g_buffer_line_append_text(result, BLC_ASSEMBLY_HEAD, " ", 4, RTT_RAW, NULL);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : line = ligne dont la définition vient d'évoluer. *
-* segment = éventuel segment qui vient d'évoluer ou NULL. *
-* buffer = tampon de lignes cohérentes à manipuler. *
-* *
-* Description : Réagit à un changement de contenu d'une ligne donnée. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void on_line_content_change(GBufferLine *line, line_segment *segment, GCodeBuffer *buffer)
-{
- g_signal_emit_by_name(buffer, "line-changed", line, segment);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : line = ligne dont la définition vient d'évoluer. *
-* old = ancien groupe de propriétés associées. *
-* old = nouveau groupe de propriétés associées. *
-* buffer = tampon de lignes cohérentes à manipuler. *
-* *
-* Description : Réagit à un changement de propriété rattachée à une ligne. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void on_line_flag_flip(GBufferLine *line, BufferLineFlags old, BufferLineFlags new, GCodeBuffer *buffer)
-{
- g_signal_emit_by_name(buffer, "line-changed", line, NULL);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : buffer = composant GLib à mettre à jour. *
-* lines = liste de lignes à insérer. *
-* count = taille de cette liste. *
-* index = point d'insertion de la première ligne. *
-* *
-* Description : Ajoute de nouvelles lignes à une position donnée. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_code_buffer_insert_lines_at(GCodeBuffer *buffer, GBufferLine **lines, size_t count, size_t index)
-{
- size_t i; /* Boucle de parcours */
-
- /* Elaboration d'un espace suffisant */
-
- if ((buffer->used + count) > buffer->count)
- {
- if (count > LINE_ALLOC_BULK)
- buffer->count += count;
- else
- buffer->count += LINE_ALLOC_BULK;
-
- buffer->lines = (GBufferLine **)realloc(buffer->lines,
- buffer->count * sizeof(GBufferLine *));
-
- }
-
- /* Insertion des lignes */
-
- if (index < buffer->used)
- {
- memmove(&buffer->lines[index + count], &buffer->lines[index],
- (buffer->used - index) * sizeof(GBufferLine *));
- }
-
- buffer->used += count;
-
- for (i = 0; i < count; i++)
- {
- assert((index + i) < buffer->used);
-
- buffer->lines[index + i] = lines[i];
-
- g_signal_connect(lines[i], "content-changed", G_CALLBACK(on_line_content_change), buffer);
- g_signal_connect(lines[i], "flip-flag", G_CALLBACK(on_line_flag_flip), buffer);
-
- }
-
- /* Recueil initial des largeurs */
-
- g_width_tracker_update_added(buffer->tracker, index, count);
-
- g_code_buffer_notify_size_changed(buffer, true, index, count);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : buffer = composant GLib à mettre à jour. *
-* line = lign à insérer à la fin du tampon. *
-* *
-* Description : Ajoute une nouvelle ligne en fin de tampon. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_code_buffer_append_new_line(GCodeBuffer *buffer, GBufferLine *line)
-{
- g_code_buffer_insert_lines_at(buffer, (GBufferLine *[]) { line }, 1, buffer->used);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : buffer = composant GLib à mettre à jour. *
-* lines = liste de lignes à insérer. *
-* count = taille de cette liste. *
-* point = point d'insertion du bloc de ligne. *
-* before = emplacement de l'insertion par rapport au point. *
-* *
-* Description : Ajoute de nouvelles lignes par rapport à une ligne donnée. *
-* *
-* Retour : Bilan : insertion réussie ou non ? *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-bool g_code_buffer_insert_lines(GCodeBuffer *buffer, GBufferLine **lines, size_t count, const GBufferLine *point, bool before)
-{
- bool result; /* Bilan à retourner */
- size_t index; /* Indice d'insertion final */
-
- result = false;
-
- index = g_code_buffer_find_index_by_line(buffer, point);
-
- if (index == buffer->used)
- goto gcbil_exit;
-
- if (!before)
- index++;
-
- g_code_buffer_insert_lines_at(buffer, lines, count, index);
-
-
-
-
- result = true;
-
- gcbil_exit:
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : buffer = composant GLib à mettre à jour. *
-* start = première ligne devant être supprimée. *
-* end = dernière ligne devant être supprimée. *
-* *
-* Description : Supprime une ou plusieurs lignes du tampon indiqué. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_code_buffer_delete_lines(GCodeBuffer *buffer, size_t start, size_t end)
-{
- size_t i; /* Boucle de parcours */
- GBufferLine *line; /* Ligne en cours de traitement*/
-
- assert(start < buffer->used);
- assert(end < buffer->used);
-
- for (i = start; i <= end; i++)
- {
- line = buffer->lines[i];
-
- g_signal_handlers_disconnect_by_func(line, G_CALLBACK(on_line_content_change), buffer);
- g_signal_handlers_disconnect_by_func(line, G_CALLBACK(on_line_flag_flip), buffer);
-
- g_object_unref(G_OBJECT(line));
-
- }
-
- if ((end + 1) < buffer->used)
- memmove(&buffer->lines[start], &buffer->lines[end + 1],
- (buffer->used - end - 1) * sizeof(GBufferLine *));
-
- buffer->used -= (end - start + 1);
-
- g_width_tracker_update_deleted(buffer->tracker, start, end);
-
- g_code_buffer_notify_size_changed(buffer, false, start, end - start + 1);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : buffer = composant GTK à mettre à jour. *
-* addr = adresse où retrouver la ligne recherchée. *
-* flags = propriétés à vérifier en tout ou partie. *
-* idx = indice de la ligne trouvée ou NULL. [OUT] *
-* *
-* Description : Retrouve une ligne au sein d'un tampon avec une adresse. *
-* *
-* Retour : Line retrouvée ou NULL en cas d'échec. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GBufferLine *g_code_buffer_find_line_by_addr(const GCodeBuffer *buffer, const vmpa2t *addr, BufferLineFlags flags, size_t *idx)
-{
- GBufferLine *result; /* Instance à retourner */
- size_t index; /* Indice de la ligne visée */
-
- index = g_code_buffer_get_index_from_address(buffer, addr, true);
-
- if (index == buffer->used)
- result = NULL;
-
- else
- {
- if (idx != NULL)
- *idx = index;
-
- result = buffer->lines[index];
-
- if (flags != BLF_NONE)
- while ((g_buffer_line_get_flags(result) & flags) != flags)
- {
- if ((index + 1) == buffer->used) break;
-
- /* FIXME : vérifier que l'adresse est toujours celle recherchée ! */
-
- if (idx != NULL)
- (*idx)++;
-
- result = buffer->lines[++index];
-
- }
-
- g_object_ref(G_OBJECT(result));
-
- }
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : buffer = tampon de lignes à consulter. *
-* index = indice de la ligne recherchée. *
-* *
-* Description : Retrouve une ligne au sein d'un tampon avec un indice. *
-* *
-* Retour : Line retrouvée ou NULL en cas d'échec. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GBufferLine *g_code_buffer_find_line_by_index(const GCodeBuffer *buffer, size_t index)
-{
- GBufferLine *result; /* Ligne trouvée à retourner */
-
- /* TODO : ref */
-
- if (index < buffer->used)
- result = buffer->lines[index];
- else
- result = NULL;
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : buffer = composant GTK à mettre à jour. *
-* addr = adresse où va se situer la ligne. *
-* first = indique si on l'arrête à la première ou la dernière.*
-* *
-* Description : Convertit une adresse en indice de ligne. *
-* *
-* Retour : Indice de l'adresse trouvée, ou le nombre de lignes sinon. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-size_t g_code_buffer_get_index_from_address(const GCodeBuffer *buffer, const vmpa2t *addr, bool first)
-{
- size_t result; /* Indice à retourner */
- GBufferLine **found; /* Renvoi vers une trouvaille */
- const mrange_t *range; /* Couverture d'une ligne */
-
- /**
- * Si aucune adresse (ie. aucune limite ?) n'est précisée, on se base sur
- * la direction pour trouver le bon indice.
- */
-
- if (addr == NULL)
- result = (first ? 0 : buffer->used - 1);
-
- /**
- * Sinon on parcourt méthodiquement toutes les lignes !
- */
-
- else
- {
- /* Recherche dichotomique grossière */
-
- int cmp_addr_and_line(const vmpa2t *addr, const GBufferLine **line)
- {
- int status; /* Bilan d'une comparaison */
- const mrange_t *lrange; /* Couverture d'une ligne */
-
- lrange = g_buffer_line_get_range(*line);
-
- status = cmp_mrange_with_vmpa(lrange, addr);
-
- return status;
-
- }
-
- found = bsearch(addr, buffer->lines, buffer->used, sizeof(GBufferLine *),
- (__compar_fn_t)cmp_addr_and_line);
-
- /* Dernier raffinage pour approcher la cible réelle */
-
- if (found == NULL)
- result = buffer->used;
-
- else
- {
- result = found - buffer->lines;
-
- if (first)
- for (; result > 0; result--)
- {
- range = g_buffer_line_get_range(buffer->lines[result - 1]);
- if (!mrange_contains_addr(range, addr)) break;
- }
-
- else
- for (; (result + 1) < buffer->used; result++)
- {
- range = g_buffer_line_get_range(buffer->lines[result + 1]);
- if (!mrange_contains_addr(range, addr)) break;
- }
-
- }
-
- }
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : buffer = tampon de lignes à consulter. *
-* line = ligne dont l'indice est à retrouver. *
-* *
-* Description : Retrouve l'indice associé à une ligne au sein d'un tampon. *
-* *
-* Retour : Indice de l'adresse trouvée, ou le nombre de lignes sinon. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-size_t g_code_buffer_find_index_by_line(const GCodeBuffer *buffer, const GBufferLine *line)
-{
- size_t result; /* Indice trouvé à retourner */
- const mrange_t *range; /* Emplacement de la ligne */
- const mrange_t *next; /* Emplacement suivant */
-
- range = g_buffer_line_get_range(line);
-
- result = g_code_buffer_get_index_from_address(buffer, get_mrange_addr(range), true);
-
- /**
- * Comme plusieurs lignes consécutives peuvent avoir la même adresse,
- * on parcourt les lignes suivantes pour retrouver la ligne recherchée.
- */
-
- if (result < buffer->used)
- {
- while (buffer->lines[result] != line)
- {
- if (++result == buffer->used)
- break;
-
- next = g_buffer_line_get_range(buffer->lines[result]);
-
- if (cmp_vmpa(get_mrange_addr(range), get_mrange_addr(next)) != 0)
- {
- result = buffer->used;
- break;
- }
-
- }
-
- }
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : buffer = composant GTK à mettre à jour. *
-* *
-* Description : Augmente l'indentation des prochaines lignes. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_code_buffer_inc_indentation(GCodeBuffer *buffer)
-{
- buffer->indent++;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : buffer = composant GTK à mettre à jour. *
-* *
-* Description : Diminue l'indentation des prochaines lignes. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_code_buffer_dec_indentation(GCodeBuffer *buffer)
-{
- /* BUG_ON(buffer->indent == 0) */
-
- buffer->indent--;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : buffer = tampon de données à utiliser. *
-* start = première adresse visée ou 0. *
-* end = dernière adresse visée ou VMPA_MAX. *
-* message = message à afficher lors de la progression. *
-* process = fonction assurant le traitement effectif. *
-* data = données utilisateur à faire suivre. *
-* *
-* Description : Lance un parcours des différentes lignes du tampon de code. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GDelayedWork *g_buffer_code_scan(GCodeBuffer *buffer, const vmpa2t *start, const vmpa2t *end, const char *message, process_line_fc process, void *data)
-{
- GBufferScan *result; /* Procédure à créer / renvoyer*/
- GWorkQueue *queue; /* Gestionnaire de différés */
-
- result = g_buffer_scan_new(buffer, start, end, message, process, data);
- g_object_ref(G_OBJECT(result));
-
- queue = get_work_queue();
- g_work_queue_schedule_work(queue, G_DELAYED_WORK(result), DEFAULT_WORK_GROUP);
-
- return G_DELAYED_WORK(result);
-
-}
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* CONFORTS POUR LES COMMENTAIRES */
-/* ---------------------------------------------------------------------------------- */
-
-
-/******************************************************************************
-* *
-* Paramètres : buffer = tampon de lignes à consulter. *
-* line = ligne à l'intérieur d'un commentaire. *
-* comment = nouveau commentaire à inscrire à la ligne donnée. *
-* creator = créateur à l'origine de la construction. *
-* *
-* Description : Affiche un commentaire sur une ligne de tampon donnée. *
-* *
-* Retour : Bilan de l'opération : ajout ou non ? *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static bool _g_code_buffer_write_inlined_comment(GCodeBuffer *buffer, GBufferLine *line, const char *comment, GObject *creator)
-{
- bool result; /* Bilan à retourner */
- const mrange_t *range; /* Emplace de ligne à utiliser */
- char *wcopy; /* Copie de travail */
- GBufferLine **extra; /* Lignes supplémentaires */
- size_t extra_count; /* Quantité de ces lignes */
- char *saveptr; /* Sauvegarde pour la sécurité */
- char *token; /* Fragment à insérer */
- size_t len; /* Taille dudit fragment */
- GBufferLine *new; /* Nouvelle ligne créée */
- size_t i; /* Boucle de parcours */
-
- assert(!g_buffer_line_has_comment(line));
-
- result = false;
-
- range = g_buffer_line_get_range(line);
-
- wcopy = strdup(comment);
-
- extra = NULL;
- extra_count = 0;
-
- for (token = strtok_r(wcopy, COMMENT_LINE_SEP, &saveptr);
- token != NULL;
- token = strtok_r(NULL, COMMENT_LINE_SEP, &saveptr))
- {
- len = strlen(token);
-
- if (!result)
- g_buffer_line_append_text(line, BLC_COMMENTS, token, len, RTT_COMMENT, creator);
-
- else
- {
- new = g_code_buffer_prepare_new_line(buffer, range);
-
- g_buffer_line_append_text(new, BLC_COMMENTS, token, len, RTT_COMMENT, creator);
-
- extra = (GBufferLine **)realloc(extra, ++extra_count * sizeof(GBufferLine *));
-
- extra[extra_count - 1] = new;
-
- }
-
- result = true;
-
- }
-
- free(wcopy);
-
- if (extra_count > 0)
- {
- result &= g_code_buffer_insert_lines(buffer, extra, extra_count, line, false);
-
- if (!result)
- for (i = 0; i < extra_count; i++)
- g_object_unref(G_OBJECT(extra[i]));
-
- free(extra);
-
- }
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : buffer = tampon de lignes à consulter. *
-* line = ligne à l'intérieur d'un commentaire. *
-* comment = nouveau commentaire à inscrire à la ligne donnée. *
-* creator = créateur à l'origine de la construction. *
-* *
-* Description : Affiche un commentaire sur une ligne de tampon donnée. *
-* *
-* Retour : Bilan de l'opération : ajout ou non ? *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-bool g_code_buffer_update_inlined_comment(GCodeBuffer *buffer, GBufferLine *line, const char *comment, GObject *creator)
-{
- bool result; /* Bilan à retourner */
-
- if (g_buffer_line_has_comment(line))
- result = _g_code_buffer_delete_lines_comment(buffer, line);
- else
- result = true;
-
- if (result)
- result = _g_code_buffer_write_inlined_comment(buffer, line, comment, creator);
-
- /* TODO : emit() */
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : buffer = tampon de lignes à consulter. *
-* line = ligne à l'intérieur d'un commentaire. *
-* comment = nouveau commentaire à inscrire à la ligne donnée. *
-* before = précise la position du commentaire. *
-* creator = créateur à l'origine de la construction. *
-* *
-* Description : Affiche un commentaire sur une ligne de tampon dédiée. *
-* *
-* Retour : Bilan de l'opération : ajout ou non ? *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static bool _g_code_buffer_write_comment_area(GCodeBuffer *buffer, GBufferLine *line, const char *comment, bool before, GObject *creator)
-{
- bool result; /* Bilan à retourner */
- const mrange_t *range; /* Emplace de ligne à utiliser */
- char *wcopy; /* Copie de travail */
- GBufferLine **extra; /* Lignes supplémentaires */
- size_t extra_count; /* Quantité de ces lignes */
- char *saveptr; /* Sauvegarde pour la sécurité */
- char *token; /* Fragment à insérer */
- size_t len; /* Taille dudit fragment */
- GBufferLine *new; /* Nouvelle ligne créée */
- size_t i; /* Boucle de parcours */
-
- assert(!g_buffer_line_has_comment(line));
-
- result = false;
-
- range = g_buffer_line_get_range(line);
-
- wcopy = strdup(comment);
-
- extra = NULL;
- extra_count = 0;
-
- for (token = strtok_r(wcopy, COMMENT_LINE_SEP, &saveptr);
- token != NULL;
- token = strtok_r(NULL, COMMENT_LINE_SEP, &saveptr))
- {
- len = strlen(token);
-
- new = g_code_buffer_prepare_new_line(buffer, range);
- g_buffer_line_start_merge_at(new, BLC_DISPLAY);
-
- g_buffer_line_append_text(new, BLC_DISPLAY, token, len, RTT_COMMENT, creator);
-
- extra = (GBufferLine **)realloc(extra, ++extra_count * sizeof(GBufferLine *));
-
- extra[extra_count - 1] = new;
-
- result = true;
-
- }
-
- free(wcopy);
-
- if (extra_count > 0)
- {
- result &= g_code_buffer_insert_lines(buffer, extra, extra_count, line, before);
-
- if (!result)
- for (i = 0; i < extra_count; i++)
- g_object_unref(G_OBJECT(extra[i]));
-
- free(extra);
-
- }
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : buffer = tampon de lignes à consulter. *
-* line = ligne à l'intérieur d'un commentaire. *
-* comment = nouveau commentaire à inscrire à la ligne donnée. *
-* before = précise la position du commentaire. *
-* creator = créateur à l'origine de la construction. *
-* *
-* Description : Affiche un commentaire sur une ligne de tampon dédiée. *
-* *
-* Retour : Bilan de l'opération : ajout ou non ? *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-bool g_code_buffer_update_comment_area(GCodeBuffer *buffer, GBufferLine *line, const char *comment, bool before, GObject *creator)
-{
- bool result; /* Bilan à retourner */
-
- if (g_buffer_line_has_comment(line))
- result = _g_code_buffer_delete_lines_comment(buffer, line);
- else
- result = true;
-
- if (result)
- result = _g_code_buffer_write_comment_area(buffer, line, comment, before, creator);
-
- /* TODO : emit() */
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : buffer = tampon de lignes à consulter. *
-* index = indice de ligne à l'intérieur d'un commentaire. *
-* *
-* Description : Retrouve la première ligne d'une zone de commentaire. *
-* *
-* Retour : Indice de l'adresse trouvée, ou le nombre de lignes sinon. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static size_t g_code_buffer_find_first_line_comment(const GCodeBuffer *buffer, size_t index)
-{
- size_t result; /* Indice trouvé à retourner */
- GBufferLine *prev; /* Ligne précédente */
-
- assert(index < buffer->used);
-
- bool is_first_line_of_comment(const GBufferLine *ln, const GBufferLine *pv)
- {
- bool first; /* Statut à renvoyer */
- BufferLineColumn merge_col; /* Colonne de fusion #1 */
- BufferLineColumn prev_merge_col; /* Colonne de fusion #2 */
-
- merge_col = g_buffer_line_get_merge_start(ln);
-
- /**
- * La ligne consultée contient toujours un commentaire.
- *
- * Deux cas de figures sont possibles ici :
- *
- * - soit du texte est présent dans la colonne "commentaires".
- * Si du texte est présent avant, alors il s'agit forcément de
- * la première (et unique ?) ligne de commentaire.
- *
- * - soit la ligne effectue une fusion des colonnes depuis BLC_DISPLAY.
- * Si la ligne qui précède fait de même, il s'agit alors d'une étiquette
- * ou de l'amont du commentaire.
- *
- */
-
- if (g_buffer_line_has_text(ln, BLC_COMMENTS, BLC_COUNT))
- {
- first = g_buffer_line_has_text(ln, BLC_DISPLAY, BLC_COMMENTS);
-
- if (!first)
- {
- /* La ligne d'avant doit avoir un commentaire ! */
- first = !g_buffer_line_has_text(pv, BLC_COMMENTS, BLC_COUNT);
- }
-
- }
-
- else
- {
- /**
- * Le prologue "merge_col == BLC_FIRST" n'étant pas éditable,
- * la seule fusion possible ici est la suivante.
- */
- assert(merge_col == BLC_DISPLAY);
-
- /**
- * La première ligne d'un tampon est toujours un prologue.
- */
- assert(pv != NULL);
-
- prev_merge_col = g_buffer_line_get_merge_start(pv);
-
- first = (prev_merge_col != BLC_DISPLAY);
-
- if (!first)
- first = (g_buffer_line_get_flags(pv) & BLF_IS_LABEL);
-
- }
-
- return first;
-
- }
-
- for (result = index; result > 0; result--)
- {
- prev = (result > 0 ? buffer->lines[result - 1] : NULL);
-
- if (is_first_line_of_comment(buffer->lines[result], prev))
- break;
-
- }
-
- if (result == 0)
- {
- if (!is_first_line_of_comment(buffer->lines[0], NULL))
- result = buffer->used;
- }
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : buffer = tampon de lignes à consulter. *
-* index = indice de ligne à l'intérieur d'un commentaire. *
-* *
-* Description : Retrouve la dernière ligne d'une zone de commentaire. *
-* *
-* Retour : Indice de l'adresse trouvée, ou le nombre de lignes sinon. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static size_t g_code_buffer_find_last_line_comment(const GCodeBuffer *buffer, size_t index)
-{
- size_t result; /* Indice trouvé à retourner */
- GBufferLine *next; /* Ligne suivante */
-
- assert(index < buffer->used);
-
- bool is_last_line_of_comment(const GBufferLine *ln, const GBufferLine *nx)
- {
- bool last; /* Statut à renvoyer */
- BufferLineColumn merge_col; /* Colonne de fusion #1 */
- BufferLineColumn next_merge_col; /* Colonne de fusion #2 */
-
- merge_col = g_buffer_line_get_merge_start(ln);
-
- /**
- * La ligne consultée contient toujours un commentaire.
- *
- * Deux cas de figures sont possibles ici :
- *
- * - soit du texte est présent dans la colonne "commentaires".
- * Si la ligne suivante est similaire et si du texte est présent avant,
- * alors il s'agit forcément de d'un nouveau commentaire. S'il n'y a
- * aucun texte, il s'agit de la suite du commentaire.
- *
- * - soit la ligne effectue une fusion des colonnes depuis BLC_DISPLAY.
- * Si la ligne qui suit fait de même, il s'agit alors d'une étiquette
- * ou de l'aval du commentaire.
- *
- */
-
- if (g_buffer_line_has_text(ln, BLC_COMMENTS, BLC_COUNT))
- {
- last = !g_buffer_line_has_text(nx, BLC_COMMENTS, BLC_COUNT);
-
- if (!last)
- last = g_buffer_line_has_text(nx, BLC_DISPLAY, BLC_COMMENTS);
-
- }
-
- else
- {
- /**
- * Le prologue "merge_col == BLC_FIRST" n'étant pas éditable,
- * la seule fusion possible ici est la suivante.
- */
- assert(merge_col == BLC_DISPLAY);
-
- if (nx == NULL)
- last = true;
-
- else
- {
- next_merge_col = g_buffer_line_get_merge_start(nx);
-
- last = (next_merge_col != BLC_DISPLAY);
-
- if (!last)
- last = (g_buffer_line_get_flags(nx) & BLF_IS_LABEL);
-
- }
-
- }
-
- return last;
-
- }
-
- for (result = index; result < buffer->used; result++)
- {
- next = ((result + 1) < buffer->used ? buffer->lines[result + 1] : NULL);
-
- if (is_last_line_of_comment(buffer->lines[result], next))
- break;
-
- }
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : buffer = tampon de lignes à consulter. *
-* line = ligne à l'intérieur d'un commentaire. *
-* *
-* Description : Retrouve le créateur d'un commentaire existant. *
-* *
-* Retour : Instance trouvée à déréférencer ensuite ou NULL si aucune. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GObject *g_code_buffer_get_comment_creator(const GCodeBuffer *buffer, const GBufferLine *line)
-{
- GObject *result; /* Instance à retourner */
- BufferLineColumn merge_col; /* Colonne de fusion */
-
- if (g_buffer_line_has_comment(line))
- {
- merge_col = g_buffer_line_get_merge_start(line);
-
- if (merge_col == BLC_DISPLAY)
- result = g_buffer_line_find_first_segment_creator(line, BLC_DISPLAY);
- else
- result = g_buffer_line_find_first_segment_creator(line, BLC_COMMENTS);
-
- }
-
- else
- result = NULL;
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : buffer = tampon de lignes à consulter. *
-* line = ligne à l'intérieur d'un commentaire. *
-* *
-* Description : Récupère le contenu d'un commentaire existant. *
-* *
-* Retour : Commentaire retrouver à libérer ou NULL en cas d'échec. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-char *g_code_buffer_get_lines_comment(const GCodeBuffer *buffer, const GBufferLine *line)
-{
- char *result; /* Contenu à retourner */
- size_t index; /* Indice de la ligne fournie */
- size_t start; /* Ligne de départ */
- size_t end; /* Ligne d'arrivée */
- BufferLineColumn merge_col; /* Colonne de fusion */
- size_t i; /* Boucle de parcours */
- char *extra; /* Commentaire supplémentaire */
-
- /* Pas de prologue ici ! */
- assert(g_buffer_line_has_comment(line));
-
- result = NULL;
-
- index = g_code_buffer_find_index_by_line(buffer, line);
-
- if (index == buffer->used)
- goto gcbglc_exit;
-
- start = g_code_buffer_find_first_line_comment(buffer, index);
-
- if (start == buffer->used)
- goto gcbglc_exit;
-
- end = g_code_buffer_find_last_line_comment(buffer, index);
-
- if (end == buffer->used)
- goto gcbglc_exit;
-
- merge_col = g_buffer_line_get_merge_start(line);
-
- for (i = start; i <= end; i++)
- {
- if (merge_col == BLC_DISPLAY)
- extra = g_buffer_line_get_text(buffer->lines[i], BLC_DISPLAY, BLC_COUNT, false);
-
- else
- extra = g_buffer_line_get_text(buffer->lines[i], BLC_COMMENTS, BLC_COUNT, false);
-
- assert(extra != NULL);
-
- if (result == NULL)
- result = extra;
-
- else
- {
- result = stradd(result, extra);
- free(extra);
- }
-
- }
-
- gcbglc_exit:
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : buffer = tampon de lignes à modifier. *
-* line = ligne à l'intérieur d'un commentaire. *
-* *
-* Description : Supprime un commentaire existant. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static bool _g_code_buffer_delete_lines_comment(GCodeBuffer *buffer, GBufferLine *line)
-{
- bool result; /* Bilan à retourner */
- size_t index; /* Indice de la ligne fournie */
- size_t start; /* Ligne de départ */
- size_t end; /* Ligne d'arrivée */
- BufferLineColumn merge_col; /* Colonne de fusion */
-
- /* Pas de prologue ici ! */
- assert(g_buffer_line_has_comment(line));
-
- result = false;
-
- index = g_code_buffer_find_index_by_line(buffer, line);
-
- if (index == buffer->used)
- goto gcbdlc_exit;
-
- start = g_code_buffer_find_first_line_comment(buffer, index);
-
- if (start == buffer->used)
- goto gcbdlc_exit;
-
- end = g_code_buffer_find_last_line_comment(buffer, index);
-
- if (end == buffer->used)
- goto gcbdlc_exit;
-
- result = true;
-
- merge_col = g_buffer_line_get_merge_start(line);
-
- if (merge_col == BLC_DISPLAY)
- g_code_buffer_delete_lines(buffer, start, end);
-
- else
- {
- g_buffer_line_delete_text(buffer->lines[start], BLC_COMMENTS, BLC_COUNT);
-
- if (end > start)
- g_code_buffer_delete_lines(buffer, start + 1, end);
-
- }
-
- gcbdlc_exit:
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : buffer = tampon de lignes à modifier. *
-* line = ligne à l'intérieur d'un commentaire. *
-* *
-* Description : Supprime un commentaire existant. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-bool g_code_buffer_delete_lines_comment(GCodeBuffer *buffer, GBufferLine *line)
-{
- bool result; /* Bilan à retourner */
-
- result = _g_code_buffer_delete_lines_comment(buffer, line);
-
- /* TODO : emit() */
-
- return result;
-
-}
-
-
-/* ---------------------------------------------------------------------------------- */
-/* SIGNAUX IMMEDIATS POUR UNE VUE */
-/* ---------------------------------------------------------------------------------- */
-
-
-/******************************************************************************
-* *
-* Paramètres : buffer = tampon de lignes à modifier. *
-* cb = fonction à appeler au moment opportun. *
-* data = object GLib à associer à l'appel. *
-* *
-* Description : Enregistre l'adresse d'une fonction de mise à jour de vue. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_code_buffer_register_view_callback(GCodeBuffer *buffer, buffer_size_changed_cb cb, GObject *data)
-{
- view_callback *new; /* Informations sur l'appel */
-
- buffer->vcount++;
-
- buffer->vcallbacks = (view_callback *)realloc(buffer->vcallbacks, buffer->vcount * sizeof(view_callback));
-
- new = &buffer->vcallbacks[buffer->vcount - 1];
-
- new->size_changed = cb;
- new->data = data;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : buffer = tampon de lignes à modifier. *
-* data = object GLib à associer à l'appel. *
-* *
-* Description : Supprime un élément des vues à contacter pour mises à jour. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_code_buffer_unregister_view_callback(GCodeBuffer *buffer, GObject *data)
-{
- size_t i; /* Boucle de parcours */
-
- for (i = 0; i < buffer->vcount; i++)
- if (buffer->vcallbacks[i].data == data)
- {
- if ((i + 1) < buffer->vcount)
- memmove(&buffer->vcallbacks[i], &buffer->vcallbacks[i + 1],
- (buffer->vcount - i - 1) * sizeof(view_callback));
-
- buffer->vcount--;
-
- buffer->vcallbacks = (view_callback *)realloc(buffer->vcallbacks,
- buffer->vcount * sizeof(view_callback));
-
- }
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : buffer = tampon de lignes à diffuser. *
-* added = indication sur la variation de la taille du tampon. *
-* index = indice de la première ligne à traiter. *
-* count = nombre de lignes à traiter. *
-* *
-* Description : Fait suivre une variation de la quantité de lignes du tampon.*
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_code_buffer_notify_size_changed(const GCodeBuffer *buffer, bool added, size_t index, size_t count)
-{
- size_t i; /* Boucle de parcours */
- view_callback *cb; /* Informations sur l'appel */
-
- for (i = 0; i < buffer->vcount; i++)
- {
- cb = &buffer->vcallbacks[i];
-
- cb->size_changed(buffer, added, index, count, cb->data);
-
- }
-
-}
diff --git a/src/glibext/gcodebuffer.h b/src/glibext/gcodebuffer.h
deleted file mode 100644
index f600aee..0000000
--- a/src/glibext/gcodebuffer.h
+++ /dev/null
@@ -1,155 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * gcodebuffer.h - prototypes pour l'affichage d'un fragment de code d'assemblage
- *
- * Copyright (C) 2010-2014 Cyrille Bagard
- *
- * This file is part of Chrysalide.
- *
- * Chrysalide is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * Chrysalide is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#ifndef _GLIBEXT_GCODEBUFFER_H
-#define _GLIBEXT_GCODEBUFFER_H
-
-
-#include <glib-object.h>
-
-
-#include "delayed.h"
-#include "gbufferline.h"
-#include "gwidthtracker.h"
-
-
-
-/* -------------------------- TAMPON POUR CODE DESASSEMBLE -------------------------- */
-
-
-#define G_TYPE_CODE_BUFFER (g_code_buffer_get_type())
-#define G_CODE_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_CODE_BUFFER, GCodeBuffer))
-#define G_CODE_BUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_CODE_BUFFER, GCodeBufferClass))
-#define G_IS_CODE_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_CODE_BUFFER))
-#define G_IS_CODE_BUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_CODE_BUFFER))
-#define G_CODE_BUFFER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_CODE_BUFFER, GCodeBufferClass))
-
-
-/* Tampon pour code désassemblé (instance) */
-typedef struct _GCodeBuffer GCodeBuffer;
-
-/* Tampon pour code désassemblé (classe) */
-typedef struct _GCodeBufferClass GCodeBufferClass;
-
-
-/* Détermine le type du composant de tampon pour code désassemblé. */
-GType g_code_buffer_get_type(void);
-
-/* Crée un nouveau composant de tampon pour code désassemblé. */
-GCodeBuffer *g_code_buffer_new(BufferLineColumn);
-
-/* Compte le nombre de lignes rassemblées dans un tampon. */
-size_t g_code_buffer_count_lines(const GCodeBuffer *);
-
-/* Fournit un lien vers la structure de suivi de largeurs. */
-const GWidthTracker *g_code_buffer_get_width_tracker(const GCodeBuffer *);
-
-/* Initie une nouvelle ligne devant être insérée dans le tampon. */
-GBufferLine *g_code_buffer_prepare_new_line(GCodeBuffer *, const mrange_t *);
-
-/* Ajoute une nouvelle ligne en fin de tampon. */
-void g_code_buffer_append_new_line(GCodeBuffer *, GBufferLine *);
-
-/* Ajoute de nouvelles lignes par rapport à une ligne donnée. */
-bool g_code_buffer_insert_lines(GCodeBuffer *, GBufferLine **, size_t, const GBufferLine *, bool);
-
-/* Supprime une ou plusieurs lignes du tampon indiqué. */
-void g_code_buffer_delete_lines(GCodeBuffer *, size_t, size_t);
-
-
-
-/* FIXME */
-#define g_code_buffer_append_new_line_fixme(b) \
- g_code_buffer_prepare_new_line(b, (mrange_t []){ { 0, 0 }, 0 })
-
-/* FIXME */
-#define g_code_buffer_insert_at(buf, a, b) NULL
-
-
-
-/* Retrouve une ligne au sein d'un tampon avec une adresse. */
-GBufferLine *g_code_buffer_find_line_by_addr(const GCodeBuffer *, const vmpa2t *, BufferLineFlags, size_t *);
-
-/* Retrouve une ligne au sein d'un tampon avec un indice. */
-GBufferLine *g_code_buffer_find_line_by_index(const GCodeBuffer *, size_t);
-
-/* Convertit une adresse en indice de ligne. */
-size_t g_code_buffer_get_index_from_address(const GCodeBuffer *, const vmpa2t *, bool);
-
-/* Retrouve l'indice associé à une ligne au sein d'un tampon. */
-size_t g_code_buffer_find_index_by_line(const GCodeBuffer *, const GBufferLine *);
-
-/* Augmente l'indentation des prochaines lignes. */
-void g_code_buffer_inc_indentation(GCodeBuffer *);
-
-/* Diminue l'indentation des prochaines lignes. */
-void g_code_buffer_dec_indentation(GCodeBuffer *);
-
-/* Traitement d'une ligne parcourue. */
-typedef bool (* process_line_fc) (GCodeBuffer *, GBufferLine *, void *);
-
-/* Lance un parcours des différentes lignes du tampon de code. */
-GDelayedWork *g_buffer_code_scan(GCodeBuffer *, const vmpa2t *, const vmpa2t *, const char *, process_line_fc, void *);
-
-
-
-/* ------------------------- CONFORTS POUR LES COMMENTAIRES ------------------------- */
-
-
-/* Séparateur commun à tous les plateformes */
-#define COMMENT_LINE_SEP "\n"
-
-
-/* Affiche un commentaire sur une ligne de tampon donnée. */
-bool g_code_buffer_update_inlined_comment(GCodeBuffer *, GBufferLine *, const char *, GObject *);
-
-/* Affiche un commentaire sur une ligne de tampon dédiée. */
-bool g_code_buffer_update_comment_area(GCodeBuffer *, GBufferLine *, const char *, bool, GObject *);
-
-/* Retrouve le créateur d'un commentaire existant. */
-GObject *g_code_buffer_get_comment_creator(const GCodeBuffer *, const GBufferLine *);
-
-/* Récupère le contenu d'un commentaire existant. */
-char *g_code_buffer_get_lines_comment(const GCodeBuffer *, const GBufferLine *);
-
-/* Supprime un commentaire existant. */
-bool g_code_buffer_delete_lines_comment(GCodeBuffer *, GBufferLine *);
-
-
-
-/* ------------------------- SIGNAUX IMMEDIATS POUR UNE VUE ------------------------- */
-
-
-/* Accompagne une variation de la quantité de lignes du tampon. */
-typedef void (* buffer_size_changed_cb) (const GCodeBuffer *, bool, size_t, size_t, GObject *);
-
-
-/* Enregistre l'adresse d'une fonction de mise à jour de vue. */
-void g_code_buffer_register_view_callback(GCodeBuffer *, buffer_size_changed_cb, GObject *);
-
-/* Supprime un élément des vues à contacter pour mises à jour. */
-void g_code_buffer_unregister_view_callback(GCodeBuffer *, GObject *);
-
-
-
-#endif /* _GLIBEXT_GCODEBUFFER_H */
diff --git a/src/glibext/generator-int.h b/src/glibext/generator-int.h
new file mode 100644
index 0000000..d284d87
--- /dev/null
+++ b/src/glibext/generator-int.h
@@ -0,0 +1,52 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * generator-int.h - prototypes internes pour la génération de lignes à la volée
+ *
+ * Copyright (C) 2016 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <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 */
diff --git a/src/glibext/generators/Makefile.am b/src/glibext/generators/Makefile.am
new file mode 100644
index 0000000..5dd7133
--- /dev/null
+++ b/src/glibext/generators/Makefile.am
@@ -0,0 +1,15 @@
+
+noinst_LTLIBRARIES = libglibextgenerators.la
+
+libglibextgenerators_la_SOURCES = \
+ prologue.h prologue.c \
+ rborder.h rborder.c
+
+libglibextgenerators_la_LDFLAGS =
+
+
+AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS)
+
+AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
+
+SUBDIRS =
diff --git a/src/glibext/generators/prologue.c b/src/glibext/generators/prologue.c
new file mode 100644
index 0000000..7a4fea5
--- /dev/null
+++ b/src/glibext/generators/prologue.c
@@ -0,0 +1,359 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * prologue.c - génération à la volée de lignes d'introduction
+ *
+ * Copyright (C) 2016 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "prologue.h"
+
+
+#include <assert.h>
+#include <malloc.h>
+
+
+#include "../gbufferline.h"
+#include "../linegen-int.h"
+#include "../linesegment.h"
+
+
+
+/* Tampon pour générateur de lignes en prologue (instance) */
+struct _GIntroGenerator
+{
+ GObject parent; /* A laisser en premier */
+
+ char **text; /* Lignes brutes à représenter */
+ size_t count; /* Quantité de ces lignes */
+
+};
+
+/* Tampon pour générateur de lignes en prologue (classe) */
+struct _GIntroGeneratorClass
+{
+ GObjectClass parent; /* A laisser en premier */
+
+};
+
+
+/* Procède à l'initialisation d'une classe de générateur. */
+static void g_intro_generator_class_init(GIntroGeneratorClass *);
+
+/* Procède à l'initialisation d'un générateur de lignes d'intro. */
+static void g_intro_generator_init(GIntroGenerator *);
+
+/* Procède à l'initialisation de l'interface de génération. */
+static void g_intro_generator_interface_init(GLineGeneratorInterface *);
+
+/* Supprime toutes les références externes. */
+static void g_intro_generator_dispose(GIntroGenerator *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_intro_generator_finalize(GIntroGenerator *);
+
+/* Indique le nombre de ligne prêtes à être générées. */
+static size_t g_intro_generator_count_lines(const GIntroGenerator *);
+
+/* Retrouve l'emplacement correspondant à une position donnée. */
+static void g_intro_generator_compute_addr(const GIntroGenerator *, gint, vmpa2t *, size_t, size_t);
+
+/* Détermine si le conteneur s'inscrit dans une plage donnée. */
+static int g_intro_generator_contains_addr(const GIntroGenerator *, const vmpa2t *, size_t, size_t);
+
+/* Renseigne sur les propriétés liées à un générateur. */
+static BufferLineFlags g_intro_generator_get_flags(const GIntroGenerator *, size_t, size_t);
+
+/* Imprime dans une ligne de rendu le contenu représenté. */
+static void g_intro_generator_print(GIntroGenerator *, GBufferLine *, size_t, size_t);
+
+
+
+/* Détermine le type du générateur de lignes d'introduction à la volée. */
+G_DEFINE_TYPE_WITH_CODE(GIntroGenerator, g_intro_generator, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE(G_TYPE_LINE_GENERATOR, g_intro_generator_interface_init));
+
+
+/******************************************************************************
+* *
+* Paramètres : class = classe de composant GLib à initialiser. *
+* *
+* Description : Procède à l'initialisation d'une classe de générateur. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_intro_generator_class_init(GIntroGeneratorClass *class)
+{
+ GObjectClass *object; /* Autre version de la classe */
+
+ object = G_OBJECT_CLASS(class);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_intro_generator_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_intro_generator_finalize;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : generator = composant GLib à initialiser. *
+* *
+* Description : Procède à l'initialisation d'un générateur de lignes d'intro.*
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_intro_generator_init(GIntroGenerator *generator)
+{
+ generator->text = NULL;
+ generator->count = 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : iface = interface GLib à initialiser. *
+* *
+* Description : Procède à l'initialisation de l'interface de génération. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_intro_generator_interface_init(GLineGeneratorInterface *iface)
+{
+ iface->count = (linegen_count_lines_fc)g_intro_generator_count_lines;
+ iface->compute = (linegen_compute_fc)g_intro_generator_compute_addr;
+ iface->contains = (linegen_contains_fc)g_intro_generator_contains_addr;
+ iface->get_flags = (linegen_get_flags_fc)g_intro_generator_get_flags;
+ iface->print = (linegen_print_fc)g_intro_generator_print;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : generator = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_intro_generator_dispose(GIntroGenerator *generator)
+{
+ G_OBJECT_CLASS(g_intro_generator_parent_class)->dispose(G_OBJECT(generator));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : generator = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_intro_generator_finalize(GIntroGenerator *generator)
+{
+ size_t i; /* Boucle de parcours */
+
+ for (i = 0; i < generator->count; i++)
+ free(generator->text[i]);
+
+ if (generator->text != NULL)
+ free(generator->text);
+
+ G_OBJECT_CLASS(g_intro_generator_parent_class)->finalize(G_OBJECT(generator));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : lang = trauducteur pour l'impression finale. *
+* text = tableau de lignes à conserver. *
+* count = taille du tableau fourni. *
+* *
+* Description : Crée un nouveau générateur de lignes d'introduction. *
+* *
+* Retour : Composant GLib créé. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GIntroGenerator *g_intro_generator_new(const GCodingLanguage *lang, char **text, size_t count)
+{
+ GIntroGenerator *result; /* Composant à retourner */
+
+ result = g_object_new(G_TYPE_INTRO_GENERATOR, NULL);
+
+ result->text = text;
+ result->count = count;
+
+ g_coding_language_encapsulate_comments(lang, &result->text, &result->count);
+
+ result->text = (char **)realloc(result->text, ++result->count * sizeof(char *));
+
+ result->text[result->count - 1] = NULL;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : generator = générateur à consulter. *
+* *
+* Description : Indique le nombre de ligne prêtes à être générées. *
+* *
+* Retour : Nombre de lignes devant apparaître au final. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static size_t g_intro_generator_count_lines(const GIntroGenerator *generator)
+{
+ return generator->count;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : generator = générateur à consulter. *
+* x = position géographique sur la ligne concernée. *
+* addr = position en mémoire à analyser. *
+* index = indice de cette même ligne dans le tampon global.*
+* repeat = indice d'utilisations successives du générateur. *
+* *
+* Description : Retrouve l'emplacement correspondant à une position donnée. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_intro_generator_compute_addr(const GIntroGenerator *generator, gint x, vmpa2t *addr, size_t index, size_t repeat)
+{
+ init_vmpa(addr, 0, 0);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : generator = générateur à consulter. *
+* addr = position en mémoire à analyser. *
+* index = indice de cette même ligne dans le tampon global.*
+* repeat = indice d'utilisations successives du générateur. *
+* *
+* Description : Détermine si le conteneur s'inscrit dans une plage donnée. *
+* *
+* Retour : Bilan de la détermination, utilisable en comparaisons. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int g_intro_generator_contains_addr(const GIntroGenerator *generator, const vmpa2t *addr, size_t index, size_t repeat)
+{
+ /**
+ * Les lignes générées sont purement artificielles et sans attache.
+ * Elles n'existent donc pas.
+ */
+
+ return 1;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : generator = générateur à consulter. *
+* index = indice de cette même ligne dans le tampon global.*
+* repeat = indice d'utilisations successives du générateur. *
+* *
+* Description : Renseigne sur les propriétés liées à un générateur. *
+* *
+* Retour : Propriétés particulières associées. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static BufferLineFlags g_intro_generator_get_flags(const GIntroGenerator *generator, size_t index, size_t repeat)
+{
+ return BLF_NONE;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : generator = générateur à utiliser pour l'impression. *
+* line = ligne de rendu à compléter. *
+* index = indice de cette même ligne dans le tampon global.*
+* repeat = indice d'utilisations successives du générateur. *
+* *
+* Description : Imprime dans une ligne de rendu le contenu représenté. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_intro_generator_print(GIntroGenerator *generator, GBufferLine *line, size_t index, size_t repeat)
+{
+ assert(repeat < generator->count);
+
+ if ((repeat + 1) != generator->count)
+ {
+ g_buffer_line_start_merge_at(line, BLC_PHYSICAL);
+
+ g_buffer_line_append_text(line, BLC_PHYSICAL, SL(generator->text[repeat]), RTT_COMMENT, NULL);
+
+ if (repeat == 0)
+ g_buffer_line_add_flag(line, BLF_WIDTH_MANAGER);
+
+ }
+
+}
diff --git a/src/glibext/generators/prologue.h b/src/glibext/generators/prologue.h
new file mode 100644
index 0000000..40cdce3
--- /dev/null
+++ b/src/glibext/generators/prologue.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * prologue.h - prototypes pour la génération à la volée de lignes d'introduction
+ *
+ * Copyright (C) 2016 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GLIBEXT_GENERATORS_PROLOGUE_H
+#define _GLIBEXT_GENERATORS_PROLOGUE_H
+
+
+#include <glib-object.h>
+
+
+#include "../../analysis/human/lang.h"
+
+
+
+#define G_TYPE_INTRO_GENERATOR (g_intro_generator_get_type())
+#define G_INTRO_GENERATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_CODE_BUFFER, GIntroGenerator))
+#define G_INTRO_GENERATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_CODE_BUFFER, GIntroGeneratorClass))
+#define G_IS_INTRO_GENERATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_CODE_BUFFER))
+#define G_IS_INTRO_GENERATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_CODE_BUFFER))
+#define G_INTRO_GENERATOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_CODE_BUFFER, GIntroGeneratorClass))
+
+
+/* Tampon pour générateur de lignes en prologue (instance) */
+typedef struct _GIntroGenerator GIntroGenerator;
+
+/* Tampon pour générateur de lignes en prologue (classe) */
+typedef struct _GIntroGeneratorClass GIntroGeneratorClass;
+
+
+/* Détermine le type du générateur de lignes d'introduction à la volée. */
+GType g_intro_generator_get_type(void);
+
+/* Crée un nouveau générateur de lignes d'introduction. */
+GIntroGenerator *g_intro_generator_new(const GCodingLanguage *, char **, size_t);
+
+
+
+#endif /* _GLIBEXT_GENERATORS_PROLOGUE_H */
diff --git a/src/glibext/generators/rborder.c b/src/glibext/generators/rborder.c
new file mode 100644
index 0000000..ff34dfb
--- /dev/null
+++ b/src/glibext/generators/rborder.c
@@ -0,0 +1,361 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * prologue.c - génération à la volée de délimitations de routines
+ *
+ * Copyright (C) 2016 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "rborder.h"
+
+
+#include <assert.h>
+#include <malloc.h>
+#include <string.h>
+
+
+#include "../gbufferline.h"
+#include "../linegen-int.h"
+#include "../linesegment.h"
+
+
+
+/* Tampon pour générateur de délimitations de routines (instance) */
+struct _GBorderGenerator
+{
+ GObject parent; /* A laisser en premier */
+
+ GCodingLanguage *lang; /* Traduction de la sortie */
+
+ vmpa2t addr; /* Position de la limite */
+ bool start; /* Début ou fin de routine ? */
+
+ MemoryDataSize msize; /* Taille du bus d'adresses */
+
+};
+
+/* Tampon pour générateur de délimitations de routines (classe) */
+struct _GBorderGeneratorClass
+{
+ GObjectClass parent; /* A laisser en premier */
+
+};
+
+
+#define ROUTINE_INTRO_MSG "--------------- BEGIN OF PROCEDURE ---------------"
+
+#define ROUTINE_OUTRO_MSG "---------------- END OF PROCEDURE ----------------"
+
+
+/* Procède à l'initialisation d'une classe de générateur. */
+static void g_border_generator_class_init(GBorderGeneratorClass *);
+
+/* Procède à l'initialisation d'un générateur de délimitations. */
+static void g_border_generator_init(GBorderGenerator *);
+
+/* Procède à l'initialisation de l'interface de génération. */
+static void g_border_generator_interface_init(GLineGeneratorInterface *);
+
+/* Supprime toutes les références externes. */
+static void g_border_generator_dispose(GBorderGenerator *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_border_generator_finalize(GBorderGenerator *);
+
+/* Indique le nombre de ligne prêtes à être générées. */
+static size_t g_border_generator_count_lines(const GBorderGenerator *);
+
+/* Retrouve l'emplacement correspondant à une position donnée. */
+static void g_border_generator_compute_addr(const GBorderGenerator *, gint, vmpa2t *, size_t, size_t);
+
+/* Détermine si le conteneur s'inscrit dans une plage donnée. */
+static int g_border_generator_contains_addr(const GBorderGenerator *, const vmpa2t *, size_t, size_t);
+
+/* Renseigne sur les propriétés liées à un générateur. */
+static BufferLineFlags g_border_generator_get_flags(const GBorderGenerator *, size_t, size_t);
+
+/* Imprime dans une ligne de rendu le contenu représenté. */
+static void g_border_generator_print(GBorderGenerator *, GBufferLine *, size_t, size_t);
+
+
+
+/* Détermine le type du générateur de délimitations de routines à la volée. */
+G_DEFINE_TYPE_WITH_CODE(GBorderGenerator, g_border_generator, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE(G_TYPE_LINE_GENERATOR, g_border_generator_interface_init));
+
+
+/******************************************************************************
+* *
+* Paramètres : class = classe de composant GLib à initialiser. *
+* *
+* Description : Procède à l'initialisation d'une classe de générateur. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_border_generator_class_init(GBorderGeneratorClass *class)
+{
+ GObjectClass *object; /* Autre version de la classe */
+
+ object = G_OBJECT_CLASS(class);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_border_generator_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_border_generator_finalize;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : generator = composant GLib à initialiser. *
+* *
+* Description : Procède à l'initialisation d'un générateur de délimitations. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_border_generator_init(GBorderGenerator *generator)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : iface = interface GLib à initialiser. *
+* *
+* Description : Procède à l'initialisation de l'interface de génération. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_border_generator_interface_init(GLineGeneratorInterface *iface)
+{
+ iface->count = (linegen_count_lines_fc)g_border_generator_count_lines;
+ iface->compute = (linegen_compute_fc)g_border_generator_compute_addr;
+ iface->contains = (linegen_contains_fc)g_border_generator_contains_addr;
+ iface->get_flags = (linegen_get_flags_fc)g_border_generator_get_flags;
+ iface->print = (linegen_print_fc)g_border_generator_print;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : generator = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_border_generator_dispose(GBorderGenerator *generator)
+{
+ g_object_unref(G_OBJECT(generator->lang));
+
+ G_OBJECT_CLASS(g_border_generator_parent_class)->dispose(G_OBJECT(generator));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : generator = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_border_generator_finalize(GBorderGenerator *generator)
+{
+ G_OBJECT_CLASS(g_border_generator_parent_class)->finalize(G_OBJECT(generator));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : lang = trauducteur pour l'impression finale. *
+* addr = position correspondant à la délimitation à marquer. *
+* start = indique le type de délimitation observée. *
+* msize = taille des adresses représentées. *
+* *
+* Description : Crée un nouveau générateur de délimitations de routines. *
+* *
+* Retour : Composant GLib créé. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GBorderGenerator *g_border_generator_new(GCodingLanguage *lang, const vmpa2t *addr, bool start, MemoryDataSize msize)
+{
+ GBorderGenerator *result; /* Composant à retourner */
+
+ result = g_object_new(G_TYPE_BORDER_GENERATOR, NULL);
+
+ result->lang = lang;
+ g_object_ref(G_OBJECT(lang));
+
+ copy_vmpa(&result->addr, addr);
+ result->start = start;
+
+ result->msize = msize;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : generator = générateur à consulter. *
+* *
+* Description : Indique le nombre de ligne prêtes à être générées. *
+* *
+* Retour : Nombre de lignes devant apparaître au final. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static size_t g_border_generator_count_lines(const GBorderGenerator *generator)
+{
+ return 3;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : generator = générateur à consulter. *
+* x = position géographique sur la ligne concernée. *
+* addr = position en mémoire à analyser. *
+* index = indice de cette même ligne dans le tampon global.*
+* repeat = indice d'utilisations successives du générateur. *
+* *
+* Description : Retrouve l'emplacement correspondant à une position donnée. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_border_generator_compute_addr(const GBorderGenerator *generator, gint x, vmpa2t *addr, size_t index, size_t repeat)
+{
+ copy_vmpa(addr, &generator->addr);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : generator = générateur à consulter. *
+* addr = position en mémoire à analyser. *
+* index = indice de cette même ligne dans le tampon global.*
+* repeat = indice d'utilisations successives du générateur. *
+* *
+* Description : Détermine si le conteneur s'inscrit dans une plage donnée. *
+* *
+* Retour : Bilan de la détermination, utilisable en comparaisons. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int g_border_generator_contains_addr(const GBorderGenerator *generator, const vmpa2t *addr, size_t index, size_t repeat)
+{
+ return cmp_vmpa(addr, &generator->addr);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : generator = générateur à consulter. *
+* index = indice de cette même ligne dans le tampon global.*
+* repeat = indice d'utilisations successives du générateur. *
+* *
+* Description : Renseigne sur les propriétés liées à un générateur. *
+* *
+* Retour : Propriétés particulières associées. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static BufferLineFlags g_border_generator_get_flags(const GBorderGenerator *generator, size_t index, size_t repeat)
+{
+ return BLF_NONE;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : generator = générateur à utiliser pour l'impression. *
+* line = ligne de rendu à compléter. *
+* index = indice de cette même ligne dans le tampon global.*
+* repeat = indice d'utilisations successives du générateur. *
+* *
+* Description : Imprime dans une ligne de rendu le contenu représenté. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_border_generator_print(GBorderGenerator *generator, GBufferLine *line, size_t index, size_t repeat)
+{
+ char *text; /* Texte principal à insérer */
+
+ assert(repeat < 3);
+
+ g_buffer_line_fill_vmpa(line, &generator->addr, generator->msize, generator->msize);
+
+ if (repeat == 1)
+ {
+ text = strdup(generator->start ? ROUTINE_INTRO_MSG : ROUTINE_OUTRO_MSG);
+ g_coding_language_encapsulate_comment(generator->lang, &text);
+
+ g_buffer_line_start_merge_at(line, BLC_ASSEMBLY_HEAD);
+ g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, SL(text), RTT_COMMENT, NULL);
+
+ free(text);
+
+ }
+
+}
diff --git a/src/glibext/generators/rborder.h b/src/glibext/generators/rborder.h
new file mode 100644
index 0000000..fa12734
--- /dev/null
+++ b/src/glibext/generators/rborder.h
@@ -0,0 +1,60 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * rborder.h - prototypes pour la génération à la volée de délimitations de routines
+ *
+ * Copyright (C) 2016 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GLIBEXT_GENERATORS_RBORDER_H
+#define _GLIBEXT_GENERATORS_RBORDER_H
+
+
+#include <glib-object.h>
+#include <stdbool.h>
+
+
+#include "../../analysis/human/lang.h"
+#include "../../arch/vmpa.h"
+
+
+
+#define G_TYPE_BORDER_GENERATOR (g_border_generator_get_type())
+#define G_BORDER_GENERATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_CODE_BUFFER, GBorderGenerator))
+#define G_BORDER_GENERATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_CODE_BUFFER, GBorderGeneratorClass))
+#define G_IS_BORDER_GENERATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_CODE_BUFFER))
+#define G_IS_BORDER_GENERATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_CODE_BUFFER))
+#define G_BORDER_GENERATOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_CODE_BUFFER, GBorderGeneratorClass))
+
+
+/* Tampon pour générateur de délimitations de routines (instance) */
+typedef struct _GBorderGenerator GBorderGenerator;
+
+/* Tampon pour générateur de délimitations de routines (classe) */
+typedef struct _GBorderGeneratorClass GBorderGeneratorClass;
+
+
+/* Détermine le type du générateur de délimitations de routines à la volée. */
+GType g_border_generator_get_type(void);
+
+/* Crée un nouveau générateur de délimitations de routines. */
+GBorderGenerator *g_border_generator_new(GCodingLanguage *, const vmpa2t *, bool, MemoryDataSize);
+
+
+
+#endif /* _GLIBEXT_GENERATORS_RBORDER_H */
diff --git a/src/glibext/gwidthtracker.c b/src/glibext/gwidthtracker.c
index 3a1863e..cd452bc 100644
--- a/src/glibext/gwidthtracker.c
+++ b/src/glibext/gwidthtracker.c
@@ -30,7 +30,7 @@
#include <string.h>
-#include "gcodebuffer.h"
+#include "gbuffercache.h"
@@ -51,7 +51,7 @@ struct _GWidthTracker
{
GObject parent; /* A laisser en premier */
- GCodeBuffer *buffer; /* Ensemble complet de lignes */
+ GBufferCache *cache; /* Ensemble complet de lignes */
common_metrics *portions; /* Portions représentées */
size_t count; /* Quantité de ces portions */
@@ -163,7 +163,7 @@ static void g_width_tracker_init(GWidthTracker *tracker)
static void g_width_tracker_dispose(GWidthTracker *tracker)
{
- g_object_unref(G_OBJECT(tracker->buffer));
+ g_object_unref(G_OBJECT(tracker->cache));
G_OBJECT_CLASS(g_width_tracker_parent_class)->dispose(G_OBJECT(tracker));
@@ -203,14 +203,14 @@ static void g_width_tracker_finalize(GWidthTracker *tracker)
* *
******************************************************************************/
-GWidthTracker *g_width_tracker_new(GCodeBuffer *buffer)
+GWidthTracker *g_width_tracker_new(GBufferCache *cache)
{
GWidthTracker *result; /* Composant à retourner */
result = g_object_new(G_TYPE_WIDTH_TRACKER, NULL);
- g_object_ref(G_OBJECT(buffer));
- result->buffer = buffer;
+ g_object_ref(G_OBJECT(cache));
+ result->cache = cache;
return result;
@@ -240,8 +240,8 @@ GWidthTracker *g_width_tracker_new_restricted(const GWidthTracker *template, siz
result = g_object_new(G_TYPE_WIDTH_TRACKER, NULL);
- g_object_ref(G_OBJECT(template->buffer));
- result->buffer = template->buffer;
+ g_object_ref(G_OBJECT(template->cache));
+ result->cache = template->cache;
start = g_width_tracker_find_metrics(template, first);
assert(start < template->count);
@@ -404,7 +404,6 @@ static const line_width_summary *g_width_tracker_get_up_to_date_widths(GWidthTra
{
common_metrics *portion; /* Portion à actualiser */
size_t i; /* Boucle de parcours */
- GBufferLine *line; /* Ligne à manipuler */
assert(index < tracker->count);
@@ -419,12 +418,7 @@ static const line_width_summary *g_width_tracker_get_up_to_date_widths(GWidthTra
/* Collecte */
for (i = portion->first; i <= portion->last; i++)
- {
- line = g_code_buffer_find_line_by_index(tracker->buffer, i);
-
- g_buffer_line_collect_widths(line, &portion->summary);
-
- }
+ g_buffer_cache_collect_widths(tracker->cache, i, &portion->summary);
/* Marquage pour mémoire */
@@ -441,6 +435,30 @@ static const line_width_summary *g_width_tracker_get_up_to_date_widths(GWidthTra
* *
* Paramètres : tracker = gestionnaire de largeurs de lignes à mettre jour. *
* index = position de la première des lignes à ajouter. *
+* *
+* Description : Prend acte d'un changement sur une ligne pour les largeurs. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_width_tracker_update(GWidthTracker *tracker, size_t index)
+{
+ size_t current; /* Indice de portion visée */
+
+ current = g_width_tracker_find_metrics(tracker, index);
+
+ g_width_tracker_reset_widths(tracker, current);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : tracker = gestionnaire de largeurs de lignes à mettre jour. *
+* index = position de la première des lignes à ajouter. *
* count = quantité de lignes devant être ajoutées. *
* *
* Description : Prend acte de l'ajout de lignes pour les largeurs. *
@@ -457,7 +475,6 @@ void g_width_tracker_update_added(GWidthTracker *tracker, size_t index, size_t c
common_metrics *portion; /* Portion sélectionnée */
size_t next; /* Prochaine portion à décaller*/
size_t i; /* Boucle de parcours */
- GBufferLine *line; /* Ligne à manipuler */
size_t dest; /* Destination d'une recopie */
size_t src; /* Source d'une recopie */
@@ -502,9 +519,7 @@ void g_width_tracker_update_added(GWidthTracker *tracker, size_t index, size_t c
for (i = index + count - 1; i >= index; i--)
{
- line = g_code_buffer_find_line_by_index(tracker->buffer, i);
-
- if (g_buffer_line_get_flags(line) & BLF_WIDTH_MANAGER)
+ if (g_buffer_cache_get_line_flags(tracker->cache, i) & BLF_WIDTH_MANAGER)
{
/* Insertion d'une nouvelle place */
@@ -602,11 +617,11 @@ void g_width_tracker_update_deleted(GWidthTracker *tracker, size_t start, size_t
/* Suppression de portions inutiles ? */
- keep_first = (tracker->portions[first].first > start || end < tracker->portions[first].last);
+ keep_first = (tracker->portions[first].first < start || end < tracker->portions[first].last);
dest = (keep_first ? first + 1 : first);
- keep_last = (tracker->portions[last].first > start || end < tracker->portions[last].last);
+ keep_last = (tracker->portions[last].first < start || end < tracker->portions[last].last);
src = (keep_last ? last : last + 1);
@@ -647,7 +662,7 @@ void g_width_tracker_update_deleted(GWidthTracker *tracker, size_t start, size_t
if (end < tracker->portions[first].last)
tracker->portions[first].last -= diff;
else
- tracker->portions[first].last = start;
+ tracker->portions[first].last = start - 1;
}
if (keep_last && last != first)
diff --git a/src/glibext/gwidthtracker.h b/src/glibext/gwidthtracker.h
index fe22088..b9d22ed 100644
--- a/src/glibext/gwidthtracker.h
+++ b/src/glibext/gwidthtracker.h
@@ -33,9 +33,8 @@
-/* gcodebuffer.h : Tampon pour code désassemblé (instance) */
-typedef struct _GCodeBuffer GCodeBuffer;
-
+/* gbuffercache.h : Tampon pour gestion de lignes optimisée (instance) */
+typedef struct _GBufferCache GBufferCache;
#define G_TYPE_WIDTH_TRACKER (g_width_tracker_get_type())
@@ -57,11 +56,14 @@ typedef struct _GWidthTrackerClass GWidthTrackerClass;
GType g_width_tracker_get_type(void);
/* Crée un nouveau suivi de largeurs au sein de lignes. */
-GWidthTracker *g_width_tracker_new(GCodeBuffer *);
+GWidthTracker *g_width_tracker_new(GBufferCache *);
/* Crée un nouveau suivi de largeurs au sein de lignes. */
GWidthTracker *g_width_tracker_new_restricted(const GWidthTracker *, size_t, size_t);
+/* Prend acte d'un changement sur une ligne pour les largeurs. */
+void g_width_tracker_update(GWidthTracker *, size_t);
+
/* Prend acte de l'ajout de lignes pour les largeurs. */
void g_width_tracker_update_added(GWidthTracker *, size_t, size_t);
diff --git a/src/glibext/linecolumn.c b/src/glibext/linecolumn.c
index 83413cf..5cce969 100644
--- a/src/glibext/linecolumn.c
+++ b/src/glibext/linecolumn.c
@@ -389,7 +389,7 @@ line_segment *get_line_column_content_from_index(const line_column *column, size
{
line_segment *result; /* Trouvaille à retourner */
- assert(index < column->count);
+ assert(index != -1 && index < column->count);
result = column->segments[index];
diff --git a/src/glibext/linegen-int.h b/src/glibext/linegen-int.h
new file mode 100644
index 0000000..f43b2f3
--- /dev/null
+++ b/src/glibext/linegen-int.h
@@ -0,0 +1,67 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * linegen-int.h - définitions internes propres aux intermédiaires de génération de lignes
+ *
+ * Copyright (C) 2016 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GLIBEXT_LINEGEN_INT_H
+#define _GLIBEXT_LINEGEN_INT_H
+
+
+#include "linegen.h"
+
+
+
+/* Indique le nombre de ligne prêtes à être générées. */
+typedef size_t (* linegen_count_lines_fc) (const GLineGenerator *);
+
+/* Retrouve l'emplacement correspondant à une position donnée. */
+typedef void (* linegen_compute_fc) (const GLineGenerator *, gint, vmpa2t *, size_t, size_t);
+
+/* Détermine si le conteneur s'inscrit dans une plage donnée. */
+typedef int (* linegen_contains_fc) (const GLineGenerator *, const vmpa2t *, size_t, size_t);
+
+/* Renseigne sur les propriétés liées à un générateur. */
+typedef BufferLineFlags (* linegen_get_flags_fc) (const GLineGenerator *, size_t, size_t);
+
+/* Imprime dans une ligne de rendu le contenu représenté. */
+typedef void (* linegen_print_fc) (GLineGenerator *, GBufferLine *, size_t, size_t);
+
+
+/* Intermédiaire pour la génération de lignes (interface) */
+struct _GLineGeneratorIface
+{
+ GTypeInterface base_iface; /* A laisser en premier */
+
+ linegen_count_lines_fc count; /* Décompte des lignes */
+ linegen_compute_fc compute; /* Calcul d'emplacement */
+ linegen_contains_fc contains; /* Inclusion de positions */
+ linegen_get_flags_fc get_flags; /* Récupération des drapeaux */
+ linegen_print_fc print; /* Impression d'une ligne */
+
+};
+
+
+/* Redéfinition */
+typedef GLineGeneratorIface GLineGeneratorInterface;
+
+
+
+#endif /* _GLIBEXT_LINEGEN_INT_H */
diff --git a/src/glibext/linegen.c b/src/glibext/linegen.c
new file mode 100644
index 0000000..fc0e01e
--- /dev/null
+++ b/src/glibext/linegen.c
@@ -0,0 +1,208 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * linegen.c - intermédiaires de génération de lignes
+ *
+ * Copyright (C) 2016 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "linegen.h"
+
+
+#include <assert.h>
+
+
+#include "linegen-int.h"
+
+
+
+/* Procède à l'initialisation de l'interface de génération. */
+static void g_line_generator_default_init(GLineGeneratorInterface *);
+
+
+
+/* Détermine le type d'une interface pour la mise en place de lignes. */
+G_DEFINE_INTERFACE(GLineGenerator, g_line_generator, G_TYPE_OBJECT)
+
+
+/******************************************************************************
+* *
+* Paramètres : iface = interface GLib à initialiser. *
+* *
+* Description : Procède à l'initialisation de l'interface de génération. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_line_generator_default_init(GLineGeneratorInterface *iface)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : generator = générateur à consulter. *
+* *
+* Description : Indique le nombre de ligne prêtes à être générées. *
+* *
+* Retour : Nombre de lignes devant apparaître au final. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+size_t g_line_generator_count_lines(const GLineGenerator *generator)
+{
+ size_t result; /* Décompte à retourner */
+ GLineGeneratorIface *iface; /* Interface utilisée */
+
+ iface = G_LINE_GENERATOR_GET_IFACE(generator);
+
+ result = iface->count(generator);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : generator = générateur à consulter. *
+* x = position géographique sur la ligne concernée. *
+* addr = position en mémoire à analyser. *
+* index = indice de cette même ligne dans le tampon global.*
+* repeat = indice d'utilisations successives du générateur. *
+* *
+* Description : Retrouve l'emplacement correspondant à une position donnée. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_line_generator_compute_addr(const GLineGenerator *generator, gint x, vmpa2t *addr, size_t index, size_t repeat)
+{
+ GLineGeneratorIface *iface; /* Interface utilisée */
+
+ iface = G_LINE_GENERATOR_GET_IFACE(generator);
+
+#ifndef NDEBUG
+ if (iface->count != NULL)
+ assert(repeat < g_line_generator_count_lines(generator));
+#endif
+
+ iface->compute(generator, x, addr, index, repeat);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : generator = générateur à consulter. *
+* addr = position en mémoire à analyser. *
+* index = indice de cette même ligne dans le tampon global.*
+* repeat = indice d'utilisations successives du générateur. *
+* *
+* Description : Détermine si le conteneur s'inscrit dans une plage donnée. *
+* *
+* Retour : Bilan de la détermination, utilisable en comparaisons. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int g_line_generator_contains_addr(const GLineGenerator *generator, const vmpa2t *addr, size_t index, size_t repeat)
+{
+ GLineGeneratorIface *iface; /* Interface utilisée */
+
+ iface = G_LINE_GENERATOR_GET_IFACE(generator);
+
+#ifndef NDEBUG
+ if (iface->count != NULL)
+ assert(repeat < g_line_generator_count_lines(generator));
+#endif
+
+ return iface->contains(generator, addr, index, repeat);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : generator = générateur à consulter. *
+* index = indice de cette même ligne dans le tampon global.*
+* repeat = indice d'utilisations successives du générateur. *
+* *
+* Description : Renseigne sur les propriétés liées à un générateur. *
+* *
+* Retour : Propriétés particulières associées. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+BufferLineFlags g_line_generator_get_flags(const GLineGenerator *generator, size_t index, size_t repeat)
+{
+ GLineGeneratorIface *iface; /* Interface utilisée */
+
+ iface = G_LINE_GENERATOR_GET_IFACE(generator);
+
+#ifndef NDEBUG
+ if (iface->count != NULL)
+ assert(repeat < g_line_generator_count_lines(generator));
+#endif
+
+ return iface->get_flags(generator, index, repeat);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : generator = générateur à utiliser pour l'impression. *
+* line = ligne de rendu à compléter. *
+* index = indice de cette même ligne dans le tampon global.*
+* repeat = indice d'utilisations successives du générateur. *
+* *
+* Description : Imprime dans une ligne de rendu le contenu représenté. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_line_generator_print(GLineGenerator *generator, GBufferLine *line, size_t index, size_t repeat)
+{
+ GLineGeneratorIface *iface; /* Interface utilisée */
+
+ iface = G_LINE_GENERATOR_GET_IFACE(generator);
+
+#ifndef NDEBUG
+ if (iface->count != NULL)
+ assert(repeat < g_line_generator_count_lines(generator));
+#endif
+
+ return iface->print(generator, line, index, repeat);
+
+}
diff --git a/src/glibext/linegen.h b/src/glibext/linegen.h
new file mode 100644
index 0000000..c64baaa
--- /dev/null
+++ b/src/glibext/linegen.h
@@ -0,0 +1,68 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * linegen.h - prototypes pour les intermédiaires de génération de lignes
+ *
+ * Copyright (C) 2016 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GLIBEXT_LINEGEN_H
+#define _GLIBEXT_LINEGEN_H
+
+
+
+#include "gbufferline.h"
+
+
+
+#define G_TYPE_LINE_GENERATOR (g_line_generator_get_type())
+#define G_LINE_GENERATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_LINE_GENERATOR, GLineGenerator))
+#define G_LINE_GENERATOR_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST((vtable), G_TYPE_LINE_GENERATOR, GLineGeneratorIface))
+#define GTK_IS_LINE_GENERATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_LINE_GENERATOR))
+#define GTK_IS_LINE_GENERATOR_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE((vtable), G_TYPE_LINE_GENERATOR))
+#define G_LINE_GENERATOR_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), G_TYPE_LINE_GENERATOR, GLineGeneratorIface))
+
+
+/* Intermédiaire pour la génération de lignes (coquille vide) */
+typedef struct _GLineGenerator GLineGenerator;
+
+/* Intermédiaire pour la génération de lignes (interface) */
+typedef struct _GLineGeneratorIface GLineGeneratorIface;
+
+
+/* Détermine le type d'une interface pour la mise en place de lignes. */
+GType g_line_generator_get_type(void) G_GNUC_CONST;
+
+/* Indique le nombre de ligne prêtes à être générées. */
+size_t g_line_generator_count_lines(const GLineGenerator *);
+
+/* Retrouve l'emplacement correspondant à une position donnée. */
+void g_line_generator_compute_addr(const GLineGenerator *, gint, vmpa2t *, size_t, size_t);
+
+/* Détermine si le conteneur s'inscrit dans une plage donnée. */
+int g_line_generator_contains_addr(const GLineGenerator *, const vmpa2t *, size_t, size_t);
+
+/* Renseigne sur les propriétés liées à un générateur. */
+BufferLineFlags g_line_generator_get_flags(const GLineGenerator *, size_t, size_t);
+
+/* Imprime dans une ligne de rendu le contenu représenté. */
+void g_line_generator_print(GLineGenerator *, GBufferLine *, size_t, size_t);
+
+
+
+#endif /* _GLIBEXT_LINEGEN_H */
diff --git a/src/glibext/linesegment.c b/src/glibext/linesegment.c
index 8306320..5208db6 100644
--- a/src/glibext/linesegment.c
+++ b/src/glibext/linesegment.c
@@ -47,7 +47,11 @@
static const char *_segment_names[RTT_COUNT] = {
+ [RTT_NONE] = SEGMENT_NAME("none"),
[RTT_RAW] = SEGMENT_NAME("raw"),
+ [RTT_RAW_NULL] = SEGMENT_NAME("raw-null"),
+ [RTT_PRINTABLE] = SEGMENT_NAME("printable"),
+ [RTT_NOT_PRINTABLE] = SEGMENT_NAME("not-printable"),
[RTT_COMMENT] = SEGMENT_NAME("comment"),
[RTT_INDICATION] = SEGMENT_NAME("indication"),
[RTT_PHYS_ADDR_PAD] = SEGMENT_NAME("phys-addr-padding"),
@@ -55,6 +59,7 @@ static const char *_segment_names[RTT_COUNT] = {
[RTT_VIRT_ADDR_PAD] = SEGMENT_NAME("virt-addr-padding"),
[RTT_VIRT_ADDR] = SEGMENT_NAME("virt-addr"),
[RTT_RAW_CODE] = SEGMENT_NAME("raw-code"),
+ [RTT_RAW_CODE_NULL] = SEGMENT_NAME("raw-code-null"),
[RTT_LABEL] = SEGMENT_NAME("label"),
[RTT_INSTRUCTION] = SEGMENT_NAME("instruction"),
[RTT_IMMEDIATE] = SEGMENT_NAME("immediate"),
@@ -162,6 +167,10 @@ struct _segcnt_list
};
+/* Indique si le contenu d'un segment est notable ou non. */
+bool selection_list_has_segment_content(const segcnt_list *, const line_segment *);
+
+
/* ---------------------------------------------------------------------------------- */
/* NATURE POUR UN FRAGMENT DE TEXTE */
diff --git a/src/glibext/linesegment.h b/src/glibext/linesegment.h
index da43e7e..892dce2 100644
--- a/src/glibext/linesegment.h
+++ b/src/glibext/linesegment.h
@@ -66,7 +66,12 @@ void exit_segment_content_hash_table(void);
/* Types de partie de rendu */
typedef enum _RenderingTagType
{
+ RTT_NONE, /* Espace ou tabulation */
+
RTT_RAW, /* Contenu brut */
+ RTT_RAW_NULL, /* Contenu brut et nul */
+ RTT_PRINTABLE, /* Caractère imprimable */
+ RTT_NOT_PRINTABLE, /* Caractère non imprimable */
RTT_COMMENT, /* Commentaire */
RTT_INDICATION, /* Aide à la lecture */
@@ -76,6 +81,7 @@ typedef enum _RenderingTagType
RTT_VIRT_ADDR_PAD, /* Adresse virtuelle (début) */
RTT_VIRT_ADDR, /* Adresse virtuelle */
RTT_RAW_CODE, /* Code binaire brut */
+ RTT_RAW_CODE_NULL, /* Code binaire brut et nul */
RTT_LABEL, /* Etiquette sur une adresse */
@@ -188,9 +194,6 @@ bool reset_segment_content_list(segcnt_list *);
/* Marque le contenu d'un segment comme remarquable. */
bool add_segment_content_to_selection_list(segcnt_list *, const line_segment *);
-/* Indique si le contenu d'un segment est notable ou non. */
-bool selection_list_has_segment_content(const segcnt_list *, const line_segment *);
-
#endif /* _GLIBEXT_LINESEGMENT_H */