summaryrefslogtreecommitdiff
path: root/src/glibext
diff options
context:
space:
mode:
Diffstat (limited to 'src/glibext')
-rw-r--r--src/glibext/gbinportion.c24
-rw-r--r--src/glibext/gbufferline.c106
-rw-r--r--src/glibext/gbufferline.h29
-rw-r--r--src/glibext/gcodebuffer.c806
-rw-r--r--src/glibext/gcodebuffer.h43
5 files changed, 962 insertions, 46 deletions
diff --git a/src/glibext/gbinportion.c b/src/glibext/gbinportion.c
index abdec60..0744a79 100644
--- a/src/glibext/gbinportion.c
+++ b/src/glibext/gbinportion.c
@@ -536,31 +536,37 @@ void g_binary_portion_print(const GBinPortion *portion, GCodeBuffer *buffer, Mem
init_mrange(&range, get_mrange_addr(&portion->range), 0);
- line = g_code_buffer_append_new_line(buffer, &range);
+ 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_append_new_line(buffer, &range);
+ 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_insert_text(line, BLC_ASSEMBLY_HEAD,
"; ======================================================", 56, RTT_COMMENT);
+ g_code_buffer_append_new_line(buffer, line);
+
/* Retour à la ligne */
- line = g_code_buffer_append_new_line(buffer, &range);
+ 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_insert_text(line, BLC_ASSEMBLY_HEAD, "; ", 2, RTT_COMMENT);
+ g_code_buffer_append_new_line(buffer, line);
+
/* Description */
- line = g_code_buffer_append_new_line(buffer, &range);
+ 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);
@@ -577,16 +583,22 @@ void g_binary_portion_print(const GBinPortion *portion, GCodeBuffer *buffer, Mem
g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, rights, strlen(rights), RTT_COMMENT);
+ g_code_buffer_append_new_line(buffer, line);
+
/* Retour à la ligne */
- line = g_code_buffer_append_new_line(buffer, &range);
+ 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_insert_text(line, BLC_ASSEMBLY_HEAD, "; ", 2, RTT_COMMENT);
- line = g_code_buffer_append_new_line(buffer, &range);
+ 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);
+
}
diff --git a/src/glibext/gbufferline.c b/src/glibext/gbufferline.c
index d09758f..2f29ee4 100644
--- a/src/glibext/gbufferline.c
+++ b/src/glibext/gbufferline.c
@@ -170,6 +170,19 @@ static void on_line_segment_changed(GBufferSegment *, GBufferLine *);
static void reset_column(buffer_line_column *column)
{
+ size_t i; /* Boucle de parcours */
+
+ for (i = 0; i < column->count; i++)
+ g_object_unref(G_OBJECT(column->segments[i]));
+
+ if (column->segments != NULL)
+ {
+ free(column->segments);
+ column->segments = NULL;
+ }
+
+ column->count = 0;
+
column->max_width = 0;
}
@@ -1264,6 +1277,37 @@ GBufferSegment *g_buffer_line_insert_text(GBufferLine *line, BufferLineColumn co
* Paramètres : line = ligne à venir consulter. *
* first = première colonne à parcourir. *
* end = colonne de fin de parcours. *
+* *
+* Description : Indique si du texte est présent dans une ligne de tampon. *
+* *
+* Retour : true pour indiquer la présence de texte, false pour du vide. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_buffer_line_has_text(const GBufferLine *line, BufferLineColumn first, BufferLineColumn end)
+{
+ bool result; /* Bilan à retourner */
+ BufferLineColumn i; /* Boucle de parcours */
+
+ result = false;
+
+ assert(first < end);
+
+ for (i = first; i < end && !result; i++)
+ result = (line->columns[i].count > 0);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : line = ligne à venir consulter. *
+* first = première colonne à parcourir. *
+* end = colonne de fin de parcours. *
* markup = indique si le texte doit être décoré ou non. *
* *
* Description : Donne le texte représenté par une ligne de tampon. *
@@ -1311,6 +1355,31 @@ char *g_buffer_line_get_text(const GBufferLine *line, BufferLineColumn first, Bu
}
+/******************************************************************************
+* *
+* Paramètres : line = ligne à venir modifier. *
+* first = première colonne à parcourir. *
+* end = colonne de fin de parcours. *
+* *
+* Description : Supprime du texte représenté par une ligne de tampon. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_buffer_line_delete_text(GBufferLine *line, BufferLineColumn first, BufferLineColumn end)
+{
+ BufferLineColumn i; /* Boucle de parcours #1 */
+
+ assert(first < end);
+
+ for (i = first; i < end; i++)
+ reset_column(&line->columns[i]);
+
+}
+
/******************************************************************************
* *
@@ -1353,7 +1422,8 @@ void g_buffer_line_update_max_widths(GBufferLine *line, GBufferLine *manager)
g_object_ref(G_OBJECT(manager));
line->manager = manager;
- g_object_unref(G_OBJECT(old));
+ if (old != NULL)
+ g_object_unref(G_OBJECT(old));
}
@@ -1388,6 +1458,32 @@ void g_buffer_line_update_max_widths(GBufferLine *line, GBufferLine *manager)
/******************************************************************************
* *
* Paramètres : line = ligne à venir consulter. *
+* *
+* Description : Renvoie la ligne comptabilisant les largeurs pour un groupe. *
+* *
+* Retour : Ligne considérée comme la gestionnaire d'un ensemble. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GBufferLine *g_buffer_line_get_width_manager(GBufferLine *line)
+{
+ GBufferLine *result; /* Gestionnaire à retourner */
+
+ if (line->flags & BLF_WIDTH_MANAGER)
+ result = line;
+ else
+ result = line->manager;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : line = ligne à venir consulter. *
* max_widths = tableau résumant les largeurs maximales. [OUT]*
* merged_width = largeur maximale en cas de fusion. |OUT] *
* *
@@ -1404,10 +1500,7 @@ void g_buffer_line_apply_max_widths(GBufferLine *line, gint *max_widths, gint *m
GBufferLine *manager; /* Gestionnaire de groupe */
BufferLineColumn i; /* Boucle de parcours */
- if (line->flags & BLF_WIDTH_MANAGER)
- manager = line;
- else
- manager = line->manager;
+ manager = g_buffer_line_get_width_manager(line);
for (i = 0; i < BLC_COUNT; i++)
max_widths[i] = MAX(manager->max_widths[i], max_widths[i]);
@@ -1434,6 +1527,7 @@ void g_buffer_line_apply_max_widths(GBufferLine *line, gint *max_widths, gint *m
gint g_buffer_line_compute_max_width(const GBufferLine *line, BufferLineColumn index, const gint *max_widths)
{
gint result; /* Largeur à retourner */
+ //GBufferLine *manager; /* Gestionnaire de groupe */
assert(index < BLC_COUNT);
@@ -1447,6 +1541,8 @@ gint g_buffer_line_compute_max_width(const GBufferLine *line, BufferLineColumn i
else
{
+ //manager = g_buffer_line_get_width_manager(line);
+
if (line->flags & BLF_WIDTH_MANAGER)
result = line->max_widths[index];
else
diff --git a/src/glibext/gbufferline.h b/src/glibext/gbufferline.h
index 643e899..19652ab 100644
--- a/src/glibext/gbufferline.h
+++ b/src/glibext/gbufferline.h
@@ -89,11 +89,12 @@ typedef enum _BufferLineFlags
{
BLF_NONE = 0 << 0, /* Aucune */
BLF_HAS_CODE = 1 << 0, /* La ligne contient du code */
- BLF_ENTRYPOINT = 1 << 1, /* Représentation d'une entrée */
- BLF_BOOKMARK = 1 << 2, /* Signet associé */
- BLF_WIDTH_MANAGER = 1 << 3, /* Début de groupe des largeurs*/
+ BLF_IS_LABEL = 1 << 1, /* Etiquette pour symbole */
+ BLF_ENTRYPOINT = 1 << 2, /* Représentation d'une entrée */
+ BLF_BOOKMARK = 1 << 3, /* Signet associé */
+ BLF_WIDTH_MANAGER = 1 << 4, /* Début de groupe des largeurs*/
- BLF_ALL = ((1 << 4) - 1)
+ BLF_ALL = ((1 << 5) - 1)
} BufferLineFlags;
@@ -125,12 +126,21 @@ GBufferSegment *g_buffer_line_find_segment_from_creator(const GBufferLine *, GOb
/* Ajoute du texte à formater dans une ligne donnée. */
GBufferSegment *g_buffer_line_insert_text(GBufferLine *, BufferLineColumn, const char *, size_t, RenderingTagType);
+/* Indique si du texte est présent dans une ligne de tampon. */
+bool g_buffer_line_has_text(const GBufferLine *, BufferLineColumn, BufferLineColumn);
+
/* Donne le texte représenté par une ligne de tampon. */
char *g_buffer_line_get_text(const GBufferLine *, BufferLineColumn, BufferLineColumn, bool);
+/* Supprime du texte représenté par une ligne de tampon. */
+void g_buffer_line_delete_text(GBufferLine *, BufferLineColumn, BufferLineColumn);
+
/* Retient les largeurs d'une ligne si maximales. */
void g_buffer_line_update_max_widths(GBufferLine *, GBufferLine *);
+/* Renvoie la ligne comptabilisant les largeurs pour un groupe. */
+GBufferLine *g_buffer_line_get_width_manager(GBufferLine *);
+
/* Filtre des largeurs de lignes et ne garde que les maximales. */
void g_buffer_line_apply_max_widths(GBufferLine *, gint *, gint *);
@@ -159,5 +169,16 @@ void g_buffer_line_draw(GBufferLine *, cairo_t *, const gint [BLC_COUNT], gint,
void g_buffer_line_export(GBufferLine *, buffer_export_context *, BufferExportType, const bool *);
+/* Petite aide pour la détection de commentaire */
+#define g_buffer_line_has_comment(ln) \
+ ({ \
+ bool __result; \
+ __result = g_buffer_line_has_text(ln, BLC_COMMENTS, BLC_COUNT); \
+ __result |= (g_buffer_line_get_merge_start(ln) == BLC_DISPLAY \
+ && !(g_buffer_line_get_flags(ln) & BLF_IS_LABEL)); \
+ __result; \
+ })
+
+
#endif /* _GLIBEXT_GBUFFERLINE_H */
diff --git a/src/glibext/gcodebuffer.c b/src/glibext/gcodebuffer.c
index 1d4e6cd..f3634f0 100644
--- a/src/glibext/gcodebuffer.c
+++ b/src/glibext/gcodebuffer.c
@@ -32,6 +32,7 @@
#include "chrysamarshal.h"
#include "delayed-int.h"
+#include "../common/extstr.h"
@@ -148,11 +149,28 @@ static void on_line_content_change(GBufferLine *, GBufferSegment *, GCodeBuffer
/* Réagit à un changement de propriété rattachée à une ligne. */
static void on_line_flag_flip(GBufferLine *, BufferLineFlags, BufferLineFlags, GCodeBuffer *);
-/* Ajoute une nouvelle ligne à une position donnée. */
-static GBufferLine *g_code_buffer_create_new_line(GCodeBuffer *, size_t, const mrange_t *);
+/* Ajoute de nouvelles lignes à une position donnée. */
+static void g_code_buffer_insert_lines_at(GCodeBuffer *, GBufferLine **, size_t, size_t);
-/* Retrouve l'indice associé à une ligne au sein d'un tampon. */
-static size_t g_code_buffer_find_index_by_line(const GCodeBuffer *, const GBufferLine *);
+
+
+/* ------------------------- 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 *);
+
+/* Affiche un commentaire sur une ligne de tampon dédiée. */
+static bool _g_code_buffer_write_comment_area(GCodeBuffer *, GBufferLine *, const char *, bool);
+
+/* 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 *);
@@ -426,6 +444,591 @@ static void g_buffer_scan_process(GBufferScan *scan, GtkExtStatusBar *statusbar)
/* ---------------------------------------------------------------------------------- */
+/* 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. *
+* *
+* 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)
+{
+ 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_insert_text(line, BLC_COMMENTS, token, len, RTT_COMMENT);
+
+ else
+ {
+ new = g_code_buffer_prepare_new_line(buffer, range);
+ g_buffer_line_insert_text(new, BLC_COMMENTS, token, len, RTT_COMMENT);
+
+ 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. *
+* *
+* 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)
+{
+ 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);
+
+ /* 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. *
+* *
+* 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)
+{
+ 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_insert_text(new, BLC_DISPLAY, token, len, RTT_COMMENT);
+
+ 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. *
+* *
+* 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)
+{
+ 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);
+
+ /* 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 : 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)
+{
+ _g_code_buffer_delete_lines_comment(buffer, line);
+
+ /* TODO : emit() */
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
/* TAMPON POUR CODE DESASSEMBLE */
/* ---------------------------------------------------------------------------------- */
@@ -642,6 +1245,34 @@ static void g_code_buffer_update_line_max_widths(const GCodeBuffer *buffer, size
/******************************************************************************
* *
+* 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_insert_text(result, BLC_ASSEMBLY_HEAD, " ", 4, RTT_RAW);
+
+ 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. *
@@ -686,41 +1317,64 @@ static void on_line_flag_flip(GBufferLine *line, BufferLineFlags old, BufferLine
/******************************************************************************
* *
* Paramètres : buffer = composant GLib à mettre à jour. *
-* range = emplacement où va se situer la ligne. *
+* lines = liste de lignes à insérer. *
+* count = taille de cette liste. *
+* index = point d'insertion de la première ligne. *
* *
-* Description : Ajoute une nouvelle ligne à une position donnée. *
+* Description : Ajoute de nouvelles lignes à une position donnée. *
* *
-* Retour : Nouvelle ligne vierge à écrire. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-static GBufferLine *g_code_buffer_create_new_line(GCodeBuffer *buffer, size_t index, const mrange_t *range)
+static void g_code_buffer_insert_lines_at(GCodeBuffer *buffer, GBufferLine **lines, size_t count, size_t index)
{
- GBufferLine *result; /* Instance à retourner */
size_t i; /* Boucle de parcours */
- if (buffer->used == buffer->count)
+ /* Elaboration d'un espace suffisant */
+
+ if ((buffer->used + count) > buffer->count)
{
- buffer->count += LINE_ALLOC_BULK;
+ if (count > LINE_ALLOC_BULK)
+ buffer->count += count;
+ else
+ buffer->count += LINE_ALLOC_BULK;
+
buffer->lines = (GBufferLine **)realloc(buffer->lines,
buffer->count * sizeof(GBufferLine *));
+
}
- buffer->used++;
- assert(index < buffer->used);
+ /* Insertion des lignes */
- result = g_buffer_line_new(range, buffer->main_column);
- buffer->lines[index] = result;
+ if (index < buffer->used)
+ {
+ memmove(&buffer->lines[index + count], &buffer->lines[index],
+ (buffer->used - index) * sizeof(GBufferLine *));
+ }
- for (i = 0; i < buffer->indent; i++)
- g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, " ", 4, RTT_RAW);
+ buffer->used += count;
- g_signal_connect(result, "content-changed", G_CALLBACK(on_line_content_change), buffer);
- g_signal_connect(result, "flip-flag", G_CALLBACK(on_line_flag_flip), buffer);
+ for (i = 0; i < count; i++)
+ {
+ assert((index + i) < buffer->used);
- return result;
+ 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 */
+
+ /**
+ * Comme des optimisations reposant sur des cas particuliers peuvent être
+ * réalisées ici, c'est à l'appelant de prendre cette charge de calculs à
+ * son compte !
+ */
}
@@ -728,21 +1382,78 @@ static GBufferLine *g_code_buffer_create_new_line(GCodeBuffer *buffer, size_t in
/******************************************************************************
* *
* Paramètres : buffer = composant GLib à mettre à jour. *
-* range = emplacement où va se situer la ligne. *
+* line = lign à insérer à la fin du tampon. *
* *
-* Description : Ajoute une nouvelle ligne à un tampon pour code désassemblé. *
+* Description : Ajoute une nouvelle ligne en fin de tampon. *
* *
-* Retour : Nouvelle ligne vierge à écrire. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-GBufferLine *g_code_buffer_append_new_line(GCodeBuffer *buffer, const mrange_t *range)
+void g_code_buffer_append_new_line(GCodeBuffer *buffer, GBufferLine *line)
{
- GBufferLine *result; /* Instance à retourner */
+ GBufferLine *manager; /* Ligne de gestion de largeurs*/
- result = g_code_buffer_create_new_line(buffer, buffer->used, range);
+ g_code_buffer_insert_lines_at(buffer, (GBufferLine *[]) { line }, 1, buffer->used);
+
+ /* Recueil initial des largeurs */
+
+ if (g_buffer_line_get_flags(line) & BLF_WIDTH_MANAGER)
+ manager = line;
+
+ else
+ {
+ assert(buffer->used > 1);
+ manager = g_buffer_line_get_width_manager(buffer->lines[buffer->used - 2]);
+ }
+
+ g_buffer_line_update_max_widths(line, manager);
+
+}
+
+
+/******************************************************************************
+* *
+* 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);
+
+
+ g_code_buffer_update_line_max_widths(buffer, index, index + count);
+
+
+ result = true;
+
+ gcbil_exit:
return result;
@@ -751,6 +1462,45 @@ GBufferLine *g_code_buffer_append_new_line(GCodeBuffer *buffer, const mrange_t *
/******************************************************************************
* *
+* 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));
+
+ }
+
+ memmove(&buffer->lines[start], &buffer->lines[end + 1],
+ (buffer->used - end - 1) * sizeof(GBufferLine *));
+
+}
+
+
+/******************************************************************************
+* *
* 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. *
@@ -844,7 +1594,7 @@ GBufferLine *g_code_buffer_find_line_by_index(const GCodeBuffer *buffer, size_t
* *
******************************************************************************/
-static size_t g_code_buffer_find_index_by_line(const GCodeBuffer *buffer, const GBufferLine *line)
+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 */
@@ -1289,7 +2039,7 @@ static void g_buffer_view_compute_required_widths(GBufferView *view, const bool
if (view->buffer->used > 0)
{
- g_code_buffer_update_line_max_widths(view->buffer, first, last);
+ //g_code_buffer_update_line_max_widths(view->buffer, first, last);
for (i = first; i <= last; i++)
g_buffer_line_apply_max_widths(lines[i], view->max_widths, &view->merged_width);
diff --git a/src/glibext/gcodebuffer.h b/src/glibext/gcodebuffer.h
index 86e94d2..0f2d601 100644
--- a/src/glibext/gcodebuffer.h
+++ b/src/glibext/gcodebuffer.h
@@ -57,22 +57,38 @@ GType g_code_buffer_get_type(void);
/* Crée un nouveau composant de tampon pour code désassemblé. */
GCodeBuffer *g_code_buffer_new(BufferLineColumn);
+/* 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_append_new_line(b, (mrange_t []){ { 0, 0 }, 0 })
-/* Ajoute une nouvelle ligne à un tampon pour code désassemblé. */
-GBufferLine *g_code_buffer_append_new_line(GCodeBuffer *, const mrange_t *);
-
/* 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);
+/* 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 *);
@@ -87,6 +103,27 @@ GDelayedWork *g_buffer_code_scan(GCodeBuffer *, const vmpa2t *, const vmpa2t *,
+/* ------------------------- 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 *);
+
+/* Affiche un commentaire sur une ligne de tampon dédiée. */
+bool g_code_buffer_update_comment_area(GCodeBuffer *, GBufferLine *, const char *, bool);
+
+/* 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 *);
+
+
+
/* ---------------------- VUE PARTICULIERE D'UN TAMPON DE CODE ---------------------- */