summaryrefslogtreecommitdiff
path: root/src/glibext/gcodebuffer.c
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2016-05-01 01:35:26 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2016-05-01 01:35:26 (GMT)
commitef68a3dd8ff259200ca7f088eecc9ce35e7ffe8f (patch)
treef89cccbe3d0ac421b41cc49a28bee32e8903e45a /src/glibext/gcodebuffer.c
parent89ceb1e27afed0bac789e33c2f10eade01747d88 (diff)
Handled all width measures per view in a dedicated manager.
Diffstat (limited to 'src/glibext/gcodebuffer.c')
-rw-r--r--src/glibext/gcodebuffer.c2245
1 files changed, 519 insertions, 1726 deletions
diff --git a/src/glibext/gcodebuffer.c b/src/glibext/gcodebuffer.c
index 346ce70..c3c5a78 100644
--- a/src/glibext/gcodebuffer.c
+++ b/src/glibext/gcodebuffer.c
@@ -1,6 +1,6 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * gcodebuffer.h - prototypes pour l'affichage d'un fragment de code d'assemblage
+ * gcodebuffer.c - affichage d'un fragment de code d'assemblage
*
* Copyright (C) 2010-2014 Cyrille Bagard
*
@@ -100,6 +100,15 @@ 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
{
@@ -111,8 +120,13 @@ struct _GCodeBuffer
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) */
@@ -137,12 +151,6 @@ 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 *);
-/* Convertit une adresse en indice de ligne. */
-static size_t g_code_buffer_get_index_from_address(const GCodeBuffer *, const vmpa2t *, bool);
-
-/* Actualise les largeurs maximales par groupes de lignes. */
-static void g_code_buffer_update_line_max_widths(const GCodeBuffer *, size_t, size_t);
-
/* Réagit à un changement de contenu d'une ligne donnée. */
static void on_line_content_change(GBufferLine *, GBufferSegment *, GCodeBuffer *);
@@ -174,70 +182,11 @@ static bool _g_code_buffer_delete_lines_comment(GCodeBuffer *, GBufferLine *);
-/* ---------------------- VUE PARTICULIERE D'UN TAMPON DE CODE ---------------------- */
-
-
-/* Vue d'un tampon pour code désassemblé (instance) */
-struct _GBufferView
-{
- GObject parent; /* A laisser en premier */
-
- GCodeBuffer *buffer; /* Tampon de code visualisé */
- vmpa2t *start; /* Première ligne intégrée */
- vmpa2t *end; /* Dernière ligne intégrée */
- size_t first_index; /* Indice de la première ligne */ /* FIXME : utiliser partout ? */
- size_t last_index; /* Indice de la dernière ligne */ /* FIXME : idem */
-
- gint line_height; /* Hauteur maximale des lignes */
- gint left_margin; /* Marge gauche + espace */
- gint left_text; /* Début d'impression du code */
- gint max_widths[BLC_COUNT]; /* Taille cachée des colonnes */
- gint merged_width; /* Plus grande taille de fusion*/
-
- segcnt_list *highlighted; /* Segments mis en évidence */
- bool external; /* Note l'origine de la liste */
-
-};
-
-/* Vue d'un tampon pour code désassemblé (classe) */
-struct _GBufferViewClass
-{
- GObjectClass parent; /* A laisser en premier */
-
- /* Signaux */
-
- void (* need_redraw) (GBufferView *);
-
-};
-
-
-#define HEIGHT_CACHED(view) ((view)->line_height != -1)
-#define WIDTHS_CACHED(view) ((view)->max_widths[0] != -1)
-
+/* ------------------------- SIGNAUX IMMEDIATS POUR UNE VUE ------------------------- */
-/* Procède à l'initialisation d'une classe de vue de tampon. */
-static void g_buffer_view_class_init(GBufferViewClass *);
-/* Procède à l'initialisation d'une vue d'un tampon pour code. */
-static void g_buffer_view_init(GBufferView *);
-
-/* Supprime toutes les références externes. */
-static void g_buffer_view_dispose(GBufferView *);
-
-/* Procède à la libération totale de la mémoire. */
-static void g_buffer_view_finalize(GBufferView *);
-
-/* Réagit à un changement de contenu d'une ligne donnée. */
-static void on_buffer_line_changed(GCodeBuffer *, GBufferLine *, GBufferSegment *, GBufferView *);
-
-/* Réinitialise le cache de la hauteur des lignes. */
-static void g_buffer_view_reset_required_height(GBufferView *);
-
-/* Réinitialise le cache des largeurs de colonne calculées. */
-static void g_buffer_view_reset_required_widths(GBufferView *);
-
-/* Calcule les largeurs requises par une visualisation. */
-static void g_buffer_view_compute_required_widths(GBufferView *, const bool *);
+/* 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);
@@ -444,645 +393,6 @@ static void g_buffer_scan_process(GBufferScan *scan, GtkStatusStack *status)
/* ---------------------------------------------------------------------------------- */
-/* 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 */
- GBufferSegment *segment; /* Segment à marquer au fer */
- 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)
- {
- segment = g_buffer_line_insert_text(line, BLC_COMMENTS, token, len, RTT_COMMENT);
- g_buffer_segment_set_creator(segment, creator);
- }
-
- else
- {
- new = g_code_buffer_prepare_new_line(buffer, range);
-
- segment = g_buffer_line_insert_text(new, BLC_COMMENTS, token, len, RTT_COMMENT);
- g_buffer_segment_set_creator(segment, 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 */
- GBufferSegment *segment; /* Segment à marquer au fer */
- 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);
-
- segment = g_buffer_line_insert_text(new, BLC_DISPLAY, token, len, RTT_COMMENT);
- g_buffer_segment_set_creator(segment, 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;
-
-}
-
-
-
-/* ---------------------------------------------------------------------------------- */
/* TAMPON POUR CODE DESASSEMBLE */
/* ---------------------------------------------------------------------------------- */
@@ -1130,6 +440,7 @@ static void g_code_buffer_class_init(GCodeBufferClass *class)
static void g_code_buffer_init(GCodeBuffer *buffer)
{
+ buffer->tracker = g_width_tracker_new(buffer);
}
@@ -1161,138 +472,38 @@ GCodeBuffer *g_code_buffer_new(BufferLineColumn main)
/******************************************************************************
* *
-* 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.*
+* Paramètres : buffer = composant GLib à consulter. *
* *
-* Description : Convertit une adresse en indice de ligne. *
+* Description : Compte le nombre de lignes rassemblées dans un tampon. *
* *
-* Retour : Indice de l'adresse trouvée, ou le nombre de lignes sinon. *
+* Retour : Nombre de lignes constituant le tampon. *
* *
* Remarques : - *
* *
******************************************************************************/
-static size_t g_code_buffer_get_index_from_address(const GCodeBuffer *buffer, const vmpa2t *addr, bool first)
+size_t g_code_buffer_count_lines(const GCodeBuffer *buffer)
{
- 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;
+ return buffer->used;
}
/******************************************************************************
* *
-* Paramètres : buffer = tampon contentenant un ensemble de lignes. *
-* first = première ligne modifiée à considérer. *
-* last = dernière ligne modifiée à considérer. *
+* Paramètres : buffer = composant GLib à consulter. *
* *
-* Description : Actualise les largeurs maximales par groupes de lignes. *
+* Description : Fournit un lien vers la structure de suivi de largeurs. *
* *
-* Retour : - *
+* Retour : Gestionnaire de largeurs de lignes. *
* *
* Remarques : - *
* *
******************************************************************************/
-static void g_code_buffer_update_line_max_widths(const GCodeBuffer *buffer, size_t first, size_t last)
+const GWidthTracker *g_code_buffer_get_width_tracker(const GCodeBuffer *buffer)
{
- GBufferLine **lines; /* Liste des lignes à traiter */
- size_t start; /* Début de groupe de largeurs */
- size_t end; /* Fin de groupe de largeurs */
- GBufferLine *manager; /* Ligne de gestion de largeurs*/
- size_t i; /* Boucle de parcours */
-
- assert(buffer->used > 0);
-
- lines = buffer->lines;
-
- /* Recherche des bornes du groupe de largeurs courant */
-
- for (start = first; start > 0; start--)
- if (g_buffer_line_get_flags(lines[start]) & BLF_WIDTH_MANAGER)
- break;
-
- for (end = last; end < (buffer->used - 1); end++)
- if (g_buffer_line_get_flags(lines[end + 1]) & BLF_WIDTH_MANAGER)
- break;
-
- /* Réinitialisation ciblée des largeurs */
-
- assert(g_buffer_line_get_flags(lines[start]) & BLF_WIDTH_MANAGER);
-
- manager = NULL;
-
- for (i = start; i <= end; i++)
- {
- if (g_buffer_line_get_flags(lines[i]) & BLF_WIDTH_MANAGER)
- manager = lines[i];
-
- g_buffer_line_update_max_widths(lines[i], manager);
-
- }
+ return buffer->tracker;
}
@@ -1424,11 +635,9 @@ static void g_code_buffer_insert_lines_at(GCodeBuffer *buffer, GBufferLine **lin
/* 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 !
- */
+ g_width_tracker_update_added(buffer->tracker, index, count);
+
+ g_code_buffer_notify_size_changed(buffer, true, index, count);
}
@@ -1448,23 +657,8 @@ static void g_code_buffer_insert_lines_at(GCodeBuffer *buffer, GBufferLine **lin
void g_code_buffer_append_new_line(GCodeBuffer *buffer, GBufferLine *line)
{
- GBufferLine *manager; /* Ligne de gestion de largeurs*/
-
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);
-
}
@@ -1502,7 +696,6 @@ bool g_code_buffer_insert_lines(GCodeBuffer *buffer, GBufferLine **lines, size_t
g_code_buffer_insert_lines_at(buffer, lines, count, index);
- g_code_buffer_update_line_max_widths(buffer, index, index + count);
result = true;
@@ -1547,8 +740,15 @@ void g_code_buffer_delete_lines(GCodeBuffer *buffer, size_t start, size_t end)
}
- memmove(&buffer->lines[start], &buffer->lines[end + 1],
- (buffer->used - end - 1) * sizeof(GBufferLine *));
+ 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);
}
@@ -1625,6 +825,8 @@ GBufferLine *g_code_buffer_find_line_by_index(const GCodeBuffer *buffer, size_t
{
GBufferLine *result; /* Ligne trouvée à retourner */
+ /* TODO : ref */
+
if (index < buffer->used)
result = buffer->lines[index];
else
@@ -1637,6 +839,90 @@ GBufferLine *g_code_buffer_find_line_by_index(const GCodeBuffer *buffer, size_t
/******************************************************************************
* *
+* 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. *
* *
@@ -1762,144 +1048,126 @@ GDelayedWork *g_buffer_code_scan(GCodeBuffer *buffer, const vmpa2t *start, const
/* ---------------------------------------------------------------------------------- */
-/* VUE PARTICULIERE D'UN TAMPON DE CODE */
+/* CONFORTS POUR LES COMMENTAIRES */
/* ---------------------------------------------------------------------------------- */
-/* Détermine le type de la vue d'un tampon pour code désassemblé. */
-G_DEFINE_TYPE(GBufferView, g_buffer_view, G_TYPE_OBJECT);
-
-
/******************************************************************************
* *
-* Paramètres : class = classe de composant GTK à initialiser. *
+* 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 : Procède à l'initialisation d'une classe de vue de tampon. *
+* Description : Affiche un commentaire sur une ligne de tampon donnée. *
* *
-* Retour : - *
+* Retour : Bilan de l'opération : ajout ou non ? *
* *
* Remarques : - *
* *
******************************************************************************/
-static void g_buffer_view_class_init(GBufferViewClass *class)
+static bool _g_code_buffer_write_inlined_comment(GCodeBuffer *buffer, GBufferLine *line, const char *comment, GObject *creator)
{
- GObjectClass *object; /* Autre version de la classe */
+ 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 */
+ GBufferSegment *segment; /* Segment à marquer au fer */
+ GBufferLine *new; /* Nouvelle ligne créée */
+ size_t i; /* Boucle de parcours */
- object = G_OBJECT_CLASS(class);
+ assert(!g_buffer_line_has_comment(line));
- object->dispose = (GObjectFinalizeFunc/* ! */)g_buffer_view_dispose;
- object->finalize = (GObjectFinalizeFunc)g_buffer_view_finalize;
+ result = false;
- g_signal_new("need-redraw",
- G_TYPE_BUFFER_VIEW,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET(GBufferViewClass, need_redraw),
- NULL, NULL,
- g_cclosure_marshal_VOID__OBJECT,
- G_TYPE_NONE, 0);
+ range = g_buffer_line_get_range(line);
-}
+ wcopy = strdup(comment);
+ extra = NULL;
+ extra_count = 0;
-/******************************************************************************
-* *
-* Paramètres : buffer = composant GTK à initialiser. *
-* *
-* Description : Procède à l'initialisation d'une vue d'un tampon pour code. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ for (token = strtok_r(wcopy, COMMENT_LINE_SEP, &saveptr);
+ token != NULL;
+ token = strtok_r(NULL, COMMENT_LINE_SEP, &saveptr))
+ {
+ len = strlen(token);
-static void g_buffer_view_init(GBufferView *buffer)
-{
- buffer->first_index = 0;
+ if (!result)
+ {
+ segment = g_buffer_line_insert_text(line, BLC_COMMENTS, token, len, RTT_COMMENT);
+ g_buffer_segment_set_creator(segment, creator);
+ }
- g_buffer_view_reset_required_height(buffer);
- g_buffer_view_reset_required_widths(buffer);
+ else
+ {
+ new = g_code_buffer_prepare_new_line(buffer, range);
-}
+ segment = g_buffer_line_insert_text(new, BLC_COMMENTS, token, len, RTT_COMMENT);
+ g_buffer_segment_set_creator(segment, creator);
+ extra = (GBufferLine **)realloc(extra, ++extra_count * sizeof(GBufferLine *));
-/******************************************************************************
-* *
-* Paramètres : view = instance d'objet GLib à traiter. *
-* *
-* Description : Supprime toutes les références externes. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ extra[extra_count - 1] = new;
-static void g_buffer_view_dispose(GBufferView *view)
-{
- g_object_unref(G_OBJECT(view->buffer));
+ }
- G_OBJECT_CLASS(g_buffer_view_parent_class)->dispose(G_OBJECT(view));
+ result = true;
-}
+ }
+ free(wcopy);
-/******************************************************************************
-* *
-* Paramètres : view = instance d'objet GLib à traiter. *
-* *
-* Description : Procède à la libération totale de la mémoire. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ if (extra_count > 0)
+ {
+ result &= g_code_buffer_insert_lines(buffer, extra, extra_count, line, false);
-static void g_buffer_view_finalize(GBufferView *view)
-{
- if (!view->external)
- exit_segment_content_list(view->highlighted);
+ if (!result)
+ for (i = 0; i < extra_count; i++)
+ g_object_unref(G_OBJECT(extra[i]));
- G_OBJECT_CLASS(g_buffer_view_parent_class)->finalize(G_OBJECT(view));
+ free(extra);
+
+ }
+
+ return result;
}
/******************************************************************************
* *
-* Paramètres : buffer = tampon à représenter à l'écran. *
-* widget = composant GTK de destination pour le rendu. *
+* 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 : Crée une nouvelle vue d'un tampon pour code désassemblé. *
+* Description : Affiche un commentaire sur une ligne de tampon donnée. *
* *
-* Retour : Composant GTK créé. *
+* Retour : Bilan de l'opération : ajout ou non ? *
* *
* Remarques : - *
* *
******************************************************************************/
-GBufferView *g_buffer_view_new(GCodeBuffer *buffer, segcnt_list *highlighted)
+bool g_code_buffer_update_inlined_comment(GCodeBuffer *buffer, GBufferLine *line, const char *comment, GObject *creator)
{
- GBufferView *result; /* Composant à retourner */
-
- result = g_object_new(G_TYPE_BUFFER_VIEW, NULL);
-
- g_object_ref(G_OBJECT(buffer));
-
- result->buffer = buffer;
-
- g_buffer_view_restrict(result, NULL, NULL);
-
- g_signal_connect(buffer, "line-changed", G_CALLBACK(on_buffer_line_changed), result);
+ bool result; /* Bilan à retourner */
- if (highlighted != NULL)
- result->highlighted = highlighted;
+ if (g_buffer_line_has_comment(line))
+ result = _g_code_buffer_delete_lines_comment(buffer, line);
else
- result->highlighted = init_segment_content_list();
+ result = true;
+
+ if (result)
+ result = _g_code_buffer_write_inlined_comment(buffer, line, comment, creator);
- result->external = (highlighted != NULL);
+ /* TODO : emit() */
return result;
@@ -1908,314 +1176,213 @@ GBufferView *g_buffer_view_new(GCodeBuffer *buffer, segcnt_list *highlighted)
/******************************************************************************
* *
-* 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 : 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 : Réagit à un changement de contenu d'une ligne donnée. *
+* Description : Affiche un commentaire sur une ligne de tampon dédiée. *
* *
-* Retour : - *
+* Retour : Bilan de l'opération : ajout ou non ? *
* *
* Remarques : - *
* *
******************************************************************************/
-static void on_buffer_line_changed(GCodeBuffer *buffer, GBufferLine *line, GBufferSegment *segment, GBufferView *view)
+static bool _g_code_buffer_write_comment_area(GCodeBuffer *buffer, GBufferLine *line, const char *comment, bool before, GObject *creator)
{
- /* TODO : regarder si la vue et concernée et cibler d'avantage l'actualisation */
-
- g_signal_emit_by_name(view, "need-redraw");
+ 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 */
+ GBufferSegment *segment; /* Segment à marquer au fer */
+ size_t i; /* Boucle de parcours */
-}
+ assert(!g_buffer_line_has_comment(line));
+ result = false;
-/******************************************************************************
-* *
-* Paramètres : view = visualisateur à mettre à jour. *
-* first = première ligne à imprimer. *
-* last = première ligne hors cadre. *
-* *
-* Description : Restreint le champ d'application de l'affichage. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ range = g_buffer_line_get_range(line);
-void g_buffer_view_restrict(GBufferView *view, const vmpa2t *start, const vmpa2t *end)
-{
- view->start = (start != NULL ? dup_vmpa(start) : NULL);
- view->end = (end != NULL ? dup_vmpa(end) : NULL);
+ wcopy = strdup(comment);
- view->first_index = g_code_buffer_get_index_from_address(view->buffer, start, true);
- view->last_index = g_code_buffer_get_index_from_address(view->buffer, end, false);
+ 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);
-/******************************************************************************
-* *
-* Paramètres : view = visualisateur à mettre à jour. *
-* first = première ligne à imprimer ou NULL. [OUT] *
-* last = première ligne hors cadre ou NULL. [OUT] *
-* *
-* Description : Indique le champ d'application de l'affichage. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ segment = g_buffer_line_insert_text(new, BLC_DISPLAY, token, len, RTT_COMMENT);
+ g_buffer_segment_set_creator(segment, creator);
-void g_buffer_view_get_restrictions(GBufferView *view, vmpa2t *start, vmpa2t *end)
-{
- /* FIXME view->xxx == NULL -> plantage */
+ extra = (GBufferLine **)realloc(extra, ++extra_count * sizeof(GBufferLine *));
- if (start != NULL) copy_vmpa(start, view->start);
- if (end != NULL) copy_vmpa(end, view->end);
+ extra[extra_count - 1] = new;
-}
+ result = true;
+ }
-/******************************************************************************
-* *
-* 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 : - *
-* *
-******************************************************************************/
+ free(wcopy);
-GCodeBuffer *g_buffer_view_get_buffer(const GBufferView *view)
-{
- return view->buffer;
+ 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);
-/******************************************************************************
-* *
-* Paramètres : view = visualisation à consulter. *
-* *
-* Description : Réinitialise le cache de la hauteur des lignes. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ }
-static void g_buffer_view_reset_required_height(GBufferView *view)
-{
- view->line_height = -1;
+ return result;
}
/******************************************************************************
* *
-* Paramètres : view = visualisation à consulter. *
+* 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 : Réinitialise le cache des largeurs de colonne calculées. *
+* Description : Affiche un commentaire sur une ligne de tampon dédiée. *
* *
-* Retour : - *
+* Retour : Bilan de l'opération : ajout ou non ? *
* *
* Remarques : - *
* *
******************************************************************************/
-static void g_buffer_view_reset_required_widths(GBufferView *view)
+bool g_code_buffer_update_comment_area(GCodeBuffer *buffer, GBufferLine *line, const char *comment, bool before, GObject *creator)
{
- unsigned int i; /* Boucle de parcours */
-
- for (i = 0; i < BLC_COUNT; i++)
- view->max_widths[i] = -1;
-
- view->merged_width = 0;
+ 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);
-/******************************************************************************
-* *
-* Paramètres : view = visualisation à mettre à jour. *
-* *
-* Description : Calcule la hauteur requise par une visualisation. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ /* TODO : emit() */
-static void g_buffer_view_compute_required_height(GBufferView *view)
-{
- view->line_height = 17;
+ return result;
}
/******************************************************************************
* *
-* Paramètres : view = visualisation à mettre à jour. *
-* display = règles d'affichage des colonnes modulables. *
+* Paramètres : buffer = tampon de lignes à consulter. *
+* index = indice de ligne à l'intérieur d'un commentaire. *
* *
-* Description : Calcule les largeurs requises par une visualisation. *
+* Description : Retrouve la première ligne d'une zone de commentaire. *
* *
-* Retour : - *
+* Retour : Indice de l'adresse trouvée, ou le nombre de lignes sinon. *
* *
* Remarques : - *
* *
******************************************************************************/
-static void g_buffer_view_compute_required_widths(GBufferView *view, const bool *display)
+static size_t g_code_buffer_find_first_line_comment(const GCodeBuffer *buffer, size_t index)
{
- GBufferLine **lines; /* Liste des lignes à traiter */
- size_t first; /* Première ligne intégrée */
- size_t last; /* Dernière ligne intégrée */
- size_t i; /* Boucle de parcours */
-
- if (!HEIGHT_CACHED(view))
- g_buffer_view_compute_required_height(view);
-
- lines = view->buffer->lines;
-
- first = g_code_buffer_get_index_from_address(view->buffer, view->start, true);
- last = g_code_buffer_get_index_from_address(view->buffer, view->end, false);
+ size_t result; /* Indice trouvé à retourner */
+ GBufferLine *prev; /* Ligne précédente */
- view->left_margin = 2 * view->line_height;
- view->left_text = 2.5 * view->line_height;
+ assert(index < buffer->used);
- if (view->buffer->used > 0)
+ bool is_first_line_of_comment(const GBufferLine *ln, const GBufferLine *pv)
{
- //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);
-
- }
-
-}
-
-
-/******************************************************************************
-* *
-* 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)
-{
- if (!HEIGHT_CACHED(view))
- g_buffer_view_compute_required_height(view);
+ bool first; /* Statut à renvoyer */
+ BufferLineColumn merge_col; /* Colonne de fusion #1 */
+ BufferLineColumn prev_merge_col; /* Colonne de fusion #2 */
- return view->line_height;
+ 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);
-/******************************************************************************
-* *
-* Paramètres : view = visualisation à consulter. *
-* display = règles d'affichage des colonnes modulables. *
-* *
-* Description : Fournit la largeur requise par une visualisation. *
-* *
-* Retour : Dimension calculée. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ if (!first)
+ {
+ /* La ligne d'avant doit avoir un commentaire ! */
+ first = !g_buffer_line_has_text(pv, BLC_COMMENTS, BLC_COUNT);
+ }
-gint g_buffer_view_get_width(GBufferView *view, const bool *display)
-{
- gint result; /* Taille à retourner */
- gint col_width; /* Calcul selon les colonnes */
- gint full_width; /* Calcul selon les fusions */
- BufferLineColumn i; /* Boucle de parcours */
+ }
- if (!WIDTHS_CACHED(view))
- g_buffer_view_compute_required_widths(view, display);
+ else
+ {
+ /**
+ * Le prologue "merge_col == BLC_FIRST" n'étant pas éditable,
+ * la seule fusion possible ici est la suivante.
+ */
+ assert(merge_col == BLC_DISPLAY);
- result = view->left_text;
+ /**
+ * La première ligne d'un tampon est toujours un prologue.
+ */
+ assert(pv != NULL);
- col_width = 0;
- full_width = 0;
+ prev_merge_col = g_buffer_line_get_merge_start(pv);
- /* Première méthode */
+ first = (prev_merge_col != BLC_DISPLAY);
- for (i = 0; i < BLC_COUNT; i++)
- {
- if (i < BLC_DISPLAY && !display[i]) continue;
+ if (!first)
+ first = (g_buffer_line_get_flags(pv) & BLF_IS_LABEL);
- col_width += view->max_widths[i];
+ }
- if ((i + 1) < BLC_COUNT)
- col_width += COL_MARGIN;
+ return first;
}
- /* Seconde méthode */
-
- for (i = 0; i < BLC_DISPLAY; i++)
+ for (result = index; result > 0; result--)
{
- if (!display[i]) continue;
+ prev = (result > 0 ? buffer->lines[result - 1] : NULL);
- full_width += view->max_widths[i] + COL_MARGIN;
+ if (is_first_line_of_comment(buffer->lines[result], prev))
+ break;
}
- full_width += view->merged_width;
-
- /* Mise en concurrence et poursuite... */
-
- result += + MAX(col_width, full_width);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : view = visualisation à consulter. *
-* display = règles d'affichage des colonnes modulables. *
-* *
-* Description : Fournit la largeur requise pour dépasser les marges gauches. *
-* *
-* Retour : Dimension calculée. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-gint g_buffer_view_get_margin(GBufferView *view, const bool *display)
-{
- gint result; /* Taille à retourner */
- BufferLineColumn i; /* Boucle de parcours */
-
- if (!WIDTHS_CACHED(view))
- g_buffer_view_compute_required_widths(view, display);
-
- result = view->left_text;
-
- for (i = 0; i < BLC_DISPLAY; i++)
+ if (result == 0)
{
- if (!display[i]) continue;
-
- result += view->max_widths[i] + COL_MARGIN;
-
+ if (!is_first_line_of_comment(buffer->lines[0], NULL))
+ result = buffer->used;
}
return result;
@@ -2225,226 +1392,130 @@ gint g_buffer_view_get_margin(GBufferView *view, const bool *display)
/******************************************************************************
* *
-* Paramètres : view = visualisation à consulter. *
-* *
-* Description : Fournit la hauteur requise par une visualisation. *
-* *
-* Retour : Dimension calculée. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-gint g_buffer_view_get_height(const GBufferView *view)
-{
- gint result; /* Taille à retourner */
- size_t first; /* Première ligne intégrée */
- size_t last; /* Dernière ligne intégrée */
-
- result = view->line_height;
-
- first = g_code_buffer_get_index_from_address(view->buffer, view->start, true);
- last = g_code_buffer_get_index_from_address(view->buffer, view->end, false);
-
- result *= (last - first + 1);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : view = vue de tampon à mettre à jour. *
-* x = abscisse de la zone principale à traiter. *
-* y = ordonnée de la zone principale à traiter. *
-* display = règles d'affichage des colonnes modulables. *
-* caret = position du curseur à construire. [OUT] *
+* Paramètres : buffer = tampon de lignes à consulter. *
+* index = indice de ligne à l'intérieur d'un commentaire. *
* *
-* Description : Calcule la position idéale de curseur pour un point donné. *
+* Description : Retrouve la dernière ligne d'une zone de commentaire. *
* *
-* Retour : Adresse si une a pu être déterminée, NULL sinon. *
+* Retour : Indice de l'adresse trouvée, ou le nombre de lignes sinon. *
* *
* Remarques : - *
* *
******************************************************************************/
-const vmpa2t *g_buffer_view_compute_caret(GBufferView *view, gint x, gint y, const bool *display, GdkRectangle *caret)
+static size_t g_code_buffer_find_last_line_comment(const GCodeBuffer *buffer, size_t index)
{
- gint remaining; /* Copie de travail modifiable */
- size_t index; /* Indice de ligne de tampon */
- GBufferLine *line; /* Ligne à la position courante*/
- GBufferSegment *segment; /* Segment présent sur la place*/
-
- remaining = x;
-
- line = g_buffer_view_find_line_and_segment_at(view, &remaining, y, &index, display, &segment);
-
- if (line == NULL) return NULL;
- if (segment == NULL) printf(" -- no segment\n");
- if (segment == NULL) return NULL;
-
-
-
-
-
- printf("\n[BASE] orig = %d tronc = %d reste = %d dernier = %d largeur = %d\n",
- x, x - remaining, remaining, g_buffer_segment_get_caret_position(segment, remaining),
- g_buffer_segment_get_width(segment));
+ size_t result; /* Indice trouvé à retourner */
+ GBufferLine *next; /* Ligne suivante */
- printf(" '%s'\n", g_buffer_segment_get_text(segment, false));
+ 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.
+ *
+ */
- caret->x = /*view->left_text +*/ (x - remaining) + g_buffer_segment_get_caret_position(segment, remaining);
+ if (g_buffer_line_has_text(ln, BLC_COMMENTS, BLC_COUNT))
+ {
+ last = !g_buffer_line_has_text(nx, BLC_COMMENTS, BLC_COUNT);
- caret->y = (index - view->first_index) * view->line_height;
+ if (!last)
+ last = g_buffer_line_has_text(nx, BLC_DISPLAY, BLC_COMMENTS);
- caret->width = 2;
- caret->height = view->line_height;
+ }
- return get_mrange_addr(g_buffer_line_get_range(line));
+ 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);
-/******************************************************************************
-* *
-* Paramètres : view = vue de tampon à mettre à jour. *
-* 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] *
-* *
-* Description : Calcule la position idéale de curseur pour un point donné. *
-* *
-* Retour : Adresse si une a pu être déterminée, NULL sinon. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ last = (next_merge_col != BLC_DISPLAY);
-const vmpa2t *g_buffer_view_compute_caret_full(GBufferView *view, GBufferLine *line, size_t index, gint x, const bool *display, GdkRectangle *caret)
-{
- gint offset; /* Point de travail modifiable */
- gint base; /* Position absolue de segment */
- GBufferSegment *segment; /* Segment visé par le pointeur*/
+ if (!last)
+ last = (g_buffer_line_get_flags(nx) & BLF_IS_LABEL);
- offset = x;
+ }
- offset -= view->left_text;
- if (offset < 0) return NULL;
+ }
- segment = g_buffer_line_get_segment_at(line, view->max_widths, display, &base, &offset, GDK_SCROLL_LEFT, true);
- if (segment == NULL) return NULL;
+ return last;
- caret->x = view->left_text + base + offset;
+ }
- printf("caret Y : %zu -> %zu\n", view->first_index, index);
+ for (result = index; result < buffer->used; result++)
+ {
+ next = ((result + 1) < buffer->used ? buffer->lines[result + 1] : NULL);
- caret->y = (index - view->first_index) * view->line_height;
+ if (is_last_line_of_comment(buffer->lines[result], next))
+ break;
- caret->width = 2;
- caret->height = view->line_height;
+ }
- return get_mrange_addr(g_buffer_line_get_range(line));
+ return result;
}
/******************************************************************************
* *
-* Paramètres : line = ligne à venir consulter. *
-* 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. *
+* Paramètres : buffer = tampon de lignes à consulter. *
+* line = ligne à l'intérieur d'un commentaire. *
* *
-* Description : Déplace le curseur au sein d'une vue de tampon. *
+* Description : Retrouve le créateur d'un commentaire existant. *
* *
-* Retour : true si un déplacement a été effectué, false sinon. *
+* Retour : Instance trouvée à déréférencer ensuite ou NULL si aucune. *
* *
* Remarques : - *
* *
******************************************************************************/
-static bool _g_buffer_view_move_caret(GBufferView *view, const GBufferLine *line, GdkRectangle *caret, bool ctrl, GdkScrollDirection dir, const bool *display)
+GObject *g_code_buffer_get_comment_creator(const GCodeBuffer *buffer, const GBufferLine *line)
{
- bool result; /* Bilan à retourner */
- gint offset; /* Point de travail modifiable */
- gint base; /* Position absolue de segment */
- GBufferSegment *segment; /* Segment visé par le pointeur*/
-
-
-
- offset = caret->x;
-
- offset -= view->left_text;
- if (offset < 0) return false;
-
- segment = g_buffer_line_get_segment_at(line, view->max_widths, display, &base, &offset, dir, false);
-
- if (segment == NULL) printf(" ===== NO SEG...\n");
-
- if (segment == NULL) return false;
-
-
- printf(" ====== FIRST SEG :: %p ('%s')\n", segment, g_buffer_segment_get_text(segment, false));
-
-
-
-
-
-
- //if (dir == GDK_SCROLL_LEFT || dir == GDK_SCROLL_RIGHT)
- result = g_buffer_segment_move_caret(segment, &offset, ctrl, dir);
- //else
- //result = true;
-
- printf(" ====== MOVE 1 ? %d\n", result);
-
- ///////////////////
+ GObject *result; /* Instance à retourner */
+ BufferLineColumn merge_col; /* Colonne de fusion */
- if (!result)
+ if (g_buffer_line_has_comment(line))
{
- base = 0;
-
- segment = g_buffer_line_find_near_segment(line, segment, view->max_widths, display, dir, &offset);
-
-
- printf(" ====== NEAR SEG :: %p ('%s')\n", segment, segment ? g_buffer_segment_get_text(segment, false) : NULL);
-
- if (segment != NULL)
- {
-
- result = true;
- //result = g_buffer_segment_move_caret(segment, &offset, ctrl, dir);
-
- /*
- if (result)
- caret->x -= COL_MARGIN;
- */
-
- printf(" ====== MOVE 2 ? %d (offset=%d)\n", result, offset);
-
-
- }
+ 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);
}
-
- if (result)
- printf(" ====== NEW CARET: %d -> %d\n", caret->x, view->left_text + base + offset);
else
- printf(" ====== NO NEW CARET!\n");
-
-
-
- if (result)
- caret->x = view->left_text + base + offset;
+ result = NULL;
return result;
@@ -2453,192 +1524,71 @@ 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. *
+* Paramètres : buffer = tampon de lignes à consulter. *
+* line = ligne à l'intérieur d'un commentaire. *
* *
-* Description : Déplace le curseur au sein d'une vue de tampon. *
+* Description : Récupère le contenu d'un commentaire existant. *
* *
-* Retour : Adresse si une a pu être déterminée, VMPA_INVALID sinon. *
+* Retour : Commentaire retrouver à libérer ou NULL en cas d'échec. *
* *
* Remarques : - *
* *
******************************************************************************/
-const vmpa2t *g_buffer_view_move_caret(GBufferView *view, GdkRectangle *caret, bool ctrl, GdkScrollDirection dir, const bool *display)
+char *g_code_buffer_get_lines_comment(const GCodeBuffer *buffer, const GBufferLine *line)
{
- const vmpa2t *result; /* Actualisation à renvoyer */
- size_t index; /* Indice de ligne de tampon */
- GBufferLine *line; /* Ligne sous le pointeur */
-
-
- bool computed; /* Récursivité pris en compte */
- gint lheight; /* Hauteur d'une ligne */
- 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 */
-
-
-
-
- bool moved; /* Mémorisation d'une évolut° */
-
-
-
-
-
-
-
+ 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;
- computed = false;
-
-
-
- line = g_buffer_view_find_line_at(view, caret->y, &index);
- if (line == NULL) return NULL;
-
-
- lheight = g_buffer_view_get_line_height(view);
+ index = g_code_buffer_find_index_by_line(buffer, line);
- switch (dir)
- {
- case GDK_SCROLL_UP:
- case GDK_SCROLL_DOWN:
- lheight = g_buffer_view_get_line_height(view);
- break;
- case GDK_SCROLL_LEFT:
- case GDK_SCROLL_RIGHT:
- left_pos = view->left_text;
- if (display[BLC_PHYSICAL]) left_pos += view->max_widths[BLC_PHYSICAL] + COL_MARGIN;
- if (display[BLC_VIRTUAL]) left_pos += view->max_widths[BLC_VIRTUAL] + COL_MARGIN;
- if (display[BLC_BINARY]) left_pos += view->max_widths[BLC_BINARY] + COL_MARGIN;
- right_pos = left_pos;
- for (i = BLC_ASSEMBLY_HEAD; i < BLC_COUNT; i++)
- right_pos += view->max_widths[i] + COL_MARGIN;
+ if (index == buffer->used)
+ goto gcbglc_exit;
- /*
-gint g_buffer_line_compute_max_width(const GBufferLine *line, BufferLineColumn index, const gint *max_widths)
+ start = g_code_buffer_find_first_line_comment(buffer, index);
-BufferLineColumn g_buffer_line_get_merge_start(const GBufferLine *line)
- */
+ if (start == buffer->used)
+ goto gcbglc_exit;
- left_pos = view->left_text;
+ end = g_code_buffer_find_last_line_comment(buffer, index);
- break;
- default: /* GDK_SCROLL_SMOOTH */
- break;
- }
+ if (end == buffer->used)
+ goto gcbglc_exit;
- first = view->first_index;
- last = view->last_index;
+ merge_col = g_buffer_line_get_merge_start(line);
- switch (dir)
+ for (i = start; i <= end; i++)
{
- case GDK_SCROLL_UP:
-
- if (index > first)
- {
- line = view->buffer->lines[index - 1];
- result = g_buffer_view_compute_caret_full(view, line, index - 1, caret->x, display, caret);
- }
-
- break;
-
- case GDK_SCROLL_DOWN:
-
- if (index < last)
- {
- line = view->buffer->lines[index + 1];
- result = g_buffer_view_compute_caret_full(view, line, index + 1, caret->x, display, caret);
- }
-
- 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, caret, ctrl, GDK_SCROLL_LEFT, display);
-
- if (moved)
- result = get_mrange_addr(g_buffer_line_get_range(line));
-
- else if (index > first)
- {
- line = view->buffer->lines[index - 1];
- result = g_buffer_view_compute_caret_full(view, line, index - 1, INT_MAX, display, caret);
- }
-
- 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, caret, ctrl, GDK_SCROLL_RIGHT, display);
+ if (merge_col == BLC_DISPLAY)
+ extra = g_buffer_line_get_text(buffer->lines[i], BLC_DISPLAY, BLC_COUNT, false);
- if (moved)
- result = get_mrange_addr(g_buffer_line_get_range(line));
+ else
+ extra = g_buffer_line_get_text(buffer->lines[i], BLC_COMMENTS, BLC_COUNT, false);
- else if (index < last)
- {
- line = view->buffer->lines[index + 1];
- result = g_buffer_view_compute_caret_full(view, line, index + 1, left_pos, display, caret);
- }
+ assert(extra != NULL);
- break;
+ if (result == NULL)
+ result = extra;
- default: /* GDK_SCROLL_SMOOTH */
- break;
+ else
+ {
+ result = stradd(result, extra);
+ free(extra);
+ }
}
- /*
- printf(" --- CARET --- moved = %d index = %d result = %p\n",
- moved, index, result);
- */
-
-
- /*
- if (result && !computed)
- result = g_buffer_view_compute_caret_full(view, caret->x, caret->y, caret, display, NULL);
- */
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : view = vue de tampon à mettre à jour. *
-* *
-* Description : Supprime toute mise en évidence de segments. *
-* *
-* Retour : true si un besoin d'actualisation d'affichage se fait sentir.*
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-bool g_buffer_view_unhighlight_segments(GBufferView *view)
-{
- bool result; /* Bilan d'action à renvoyer */
-
- result = reset_segment_content_list(view->highlighted);
+ gcbglc_exit:
return result;
@@ -2647,157 +1597,62 @@ bool g_buffer_view_unhighlight_segments(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. *
-* display = règles d'affichage des colonnes modulables. *
-* *
-* Description : Surligne tous les segments similaires à celui sous la souris.*
-* *
-* Retour : true si un besoin d'actualisation d'affichage se fait sentir.*
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-bool g_buffer_view_highlight_segments(GBufferView *view, gint x, gint y, const bool *display)
-{
- bool need_redraw; /* Besoin d'actualisation ? */
- GBufferSegment *segment; /* Segment sélectionnable */
-
- if (view->highlighted != NULL)
- need_redraw = g_buffer_view_unhighlight_segments(view);
- else
- need_redraw = false;
-
- g_buffer_view_find_line_and_segment_at(view, &x, y, NULL, display, &segment);
-
- if (segment)
- need_redraw |= add_segment_content_to_selection_list(view->highlighted, segment);
-
- if (need_redraw)
- g_signal_emit_by_name(view, "need-redraw");
-
- return true;
-
-}
-
-
-/******************************************************************************
-* *
-* 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. *
-* area = position et surface à traiter. *
-* display = règles d'affichage des colonnes modulables. *
-* selected = ordonnée d'une ligne sélectionnée ou NULL. *
+* Paramètres : buffer = tampon de lignes à modifier. *
+* line = ligne à l'intérieur d'un commentaire. *
* *
-* Description : Imprime la visualisation du tampon de code désassemblé. *
+* Description : Supprime un commentaire existant. *
* *
-* Retour : - *
+* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
-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)
+static bool _g_code_buffer_delete_lines_comment(GCodeBuffer *buffer, GBufferLine *line)
{
- gint real_x; /* Abscisse réelle pour tampon */
- gint real_y; /* Ordonnée réelle pour tampon */
- 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 */
- GBufferLine **lines; /* Liste des lignes à traiter */
- bool wait_selection; /* Sélection déjà passée ? */
- gint rel_selected; /* Position relative de sélect°*/
- size_t i; /* Boucle de parcours */
-
- real_x = fake_x + view->left_text;
- real_y = fake_y + area->y;
-
- first = view->first_index;
- first += (real_y / view->line_height);
-
- last = first + (area->height / view->line_height);
- if (area->height % view->line_height > 0) last++;
-
- last = MIN(last, view->last_index);
-
- y = area->y - (real_y % view->line_height);
-
- lines = view->buffer->lines;
-
- wait_selection = true;
-
- if (selected != NULL)
- rel_selected = *selected - fake_y;
-
- if (view->buffer->used > 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);
+ 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 */
- cairo_rectangle(cr, area->x, y, area->width, view->line_height);
- cairo_fill(cr);
+ /* Pas de prologue ici ! */
+ assert(g_buffer_line_has_comment(line));
- wait_selection = false;
+ result = false;
- }
+ index = g_code_buffer_find_index_by_line(buffer, line);
- g_buffer_line_draw(lines[i], cr, view->max_widths, real_x, y, display, view->highlighted);
+ if (index == buffer->used)
+ goto gcbdlc_exit;
- y += view->line_height;
+ 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;
-/******************************************************************************
-* *
-* 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 : - *
-* *
-******************************************************************************/
+ result = true;
-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 ? */
+ merge_col = g_buffer_line_get_merge_start(line);
- /* Vérification des bornes */
+ if (merge_col == BLC_DISPLAY)
+ g_code_buffer_delete_lines(buffer, start, end);
- if (view->start != NULL/* && view->end != NULL*/)
+ else
{
- length = compute_vmpa_diff(view->start, view->end);
-
- init_mrange(&vrange, view->start, length);
+ g_buffer_line_delete_text(buffer->lines[start], BLC_COMMENTS, BLC_COUNT);
- allowed = mrange_contains_addr_inclusive(&vrange, addr);
+ if (end > start)
+ g_code_buffer_delete_lines(buffer, start + 1, end);
}
- else allowed = true;
- /* Lancement des recherches ? */
-
- if (allowed)
- result = g_code_buffer_find_line_by_addr(view->buffer, addr, flags, idx);
- else
- result = NULL;
+ gcbdlc_exit:
return result;
@@ -2806,187 +1661,125 @@ GBufferLine *g_buffer_view_find_line_by_addr(const GBufferView *view, const vmpa
/******************************************************************************
* *
-* Paramètres : view = visualisation à consulter. *
-* index = indice de la ligne recherchée. *
+* Paramètres : buffer = tampon de lignes à modifier. *
+* line = ligne à l'intérieur d'un commentaire. *
* *
-* Description : Retrouve une ligne au sein d'un tampon avec un indice. *
+* Description : Supprime un commentaire existant. *
* *
-* Retour : Line retrouvée ou NULL en cas d'échec. *
+* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
-GBufferLine *g_buffer_view_find_line_by_index(const GBufferView *view, size_t index)
+bool g_code_buffer_delete_lines_comment(GCodeBuffer *buffer, GBufferLine *line)
{
- GBufferLine *result; /* Ligne trouvée à retourner */
- bool allowed; /* Rechercher validée ? */
-
- /* Vérification des bornes */
-
- allowed = (view->first_index <= index && index < view->last_index);
+ bool result; /* Bilan à retourner */
- /* Lancement des recherches ? */
+ result = _g_code_buffer_delete_lines_comment(buffer, line);
- if (allowed)
- result = view->buffer->lines[index];
- else
- result = NULL;
+ /* TODO : emit() */
return result;
}
+/* ---------------------------------------------------------------------------------- */
+/* SIGNAUX IMMEDIATS POUR UNE VUE */
+/* ---------------------------------------------------------------------------------- */
+
+
/******************************************************************************
* *
-* Paramètres : view = visualisation à consulter. *
-* y = ordonnée comprise dans la ligne recherchée. *
-* idx = indice de la ligne trouvée ou NULL. [OUT] *
+* Paramètres : buffer = tampon de lignes à modifier. *
+* cb = fonction à appeler au moment opportun. *
+* data = object GLib à associer à l'appel. *
* *
-* Description : Fournit la ligne présente à une ordonnée donnée. *
+* Description : Enregistre l'adresse d'une fonction de mise à jour de vue. *
* *
-* Retour : Ligne retrouvée ou NULL si aucune. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-GBufferLine *g_buffer_view_find_line_at(GBufferView *view, gint y, size_t *idx)
+void g_code_buffer_register_view_callback(GCodeBuffer *buffer, buffer_size_changed_cb cb, GObject *data)
{
- gint lheight; /* Hauteur d'une ligne */
- size_t index; /* Indice attendu */
+ view_callback *new; /* Informations sur l'appel */
- lheight = g_buffer_view_get_line_height(view);
- index = y / lheight;
+ buffer->vcount++;
- index += view->first_index;
+ buffer->vcallbacks = (view_callback *)realloc(buffer->vcallbacks, buffer->vcount * sizeof(view_callback));
- if (idx != NULL)
- *idx = index;
+ new = &buffer->vcallbacks[buffer->vcount - 1];
- return (index < view->buffer->used ? view->buffer->lines[index] : NULL);
+ new->size_changed = cb;
+ new->data = data;
}
/******************************************************************************
* *
-* 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] *
+* Paramètres : buffer = tampon de lignes à modifier. *
+* data = object GLib à associer à l'appel. *
* *
-* Description : Fournit la ligne et son segment présents à une position. *
+* Description : Supprime un élément des vues à contacter pour mises à jour. *
* *
-* Retour : Ligne retrouvée ou NULL si aucune. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-GBufferLine *g_buffer_view_find_line_and_segment_at(GBufferView *view, gint *x, gint y, size_t *idx, const bool *display, GBufferSegment **segment)
+void g_code_buffer_unregister_view_callback(GCodeBuffer *buffer, GObject *data)
{
- GBufferLine *result; /* Ligne trouvée à retourner */
-
- /* Recherche d'une ligne correspondante */
+ size_t i; /* Boucle de parcours */
- result = g_buffer_view_find_line_at(view, y, idx);
+ 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));
- /* Recherche du segment visé éventuel */
+ buffer->vcount--;
- if (result != NULL && segment != NULL)
- {
- if (*x < view->left_text)
- *segment = NULL;
+ buffer->vcallbacks = (view_callback *)realloc(buffer->vcallbacks,
+ buffer->vcount * sizeof(view_callback));
- else
- {
- *x -= view->left_text;
- *segment = g_buffer_line_get_segment_at(result, view->max_widths, display,
- (gint []) { 0 }, x, GDK_SCROLL_LEFT, true);
}
- }
-
- return result;
-
}
/******************************************************************************
* *
-* Paramètres : view = composant GTK à consulter. *
-* addr = adresse à présenter à l'écran. *
-* x = position horizontale au sein du composant. [OUT] *
-* y = position verticale au sein du composant. [OUT] *
-* code = s'arrête si possible à une ligne avec code. *
+* 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 : Indique la position d'affichage d'une adresse donnée. *
+* Description : Fait suivre une variation de la quantité de lignes du tampon.*
* *
-* Retour : true si l'adresse fait partie du composant, false sinon. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-bool g_buffer_view_get_address_coordinates(GBufferView *view, const vmpa2t *addr, gint *x, gint *y, bool code)
+static void g_code_buffer_notify_size_changed(const GCodeBuffer *buffer, bool added, size_t index, size_t count)
{
- bool result; /* Bilan à retourner */
- gint lheight; /* Hauteur d'une ligne */
- size_t first; /* Première ligne intégrée */
- size_t last; /* Dernière ligne intégrée */
size_t i; /* Boucle de parcours */
- const mrange_t *range; /* Emplacement parcouru */
-
- result = false;
+ view_callback *cb; /* Informations sur l'appel */
- *x = 0;
- *y = 0;
-
- lheight = g_buffer_view_get_line_height(view);
-
- first = g_code_buffer_get_index_from_address(view->buffer, view->start, true);
- last = g_code_buffer_get_index_from_address(view->buffer, view->end, false);
-
- for (i = first; i <= last; i++)
+ for (i = 0; i < buffer->vcount; 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.
- */
-
- range = g_buffer_line_get_range(view->buffer->lines[i]);
-
- result = mrange_contains_addr(range, addr);
- if (result) break;
+ cb = &buffer->vcallbacks[i];
- *y += lheight;
+ cb->size_changed(buffer, added, index, count, cb->data);
}
- if (result && code)
- for (; i <= last; i++)
- {
- if (g_buffer_line_get_flags(view->buffer->lines[i]) & BLF_HAS_CODE) break;
-
- if (i == last) break;
-
- range = g_buffer_line_get_range(view->buffer->lines[i + 1]);
- if (!mrange_contains_addr(range, addr)) break;
-
- *y += lheight;
-
- }
-
- return result;
-
}