diff options
Diffstat (limited to 'src/glibext/gbufferview.c')
-rw-r--r-- | src/glibext/gbufferview.c | 810 |
1 files changed, 311 insertions, 499 deletions
diff --git a/src/glibext/gbufferview.c b/src/glibext/gbufferview.c index 20d60ed..cd17191 100644 --- a/src/glibext/gbufferview.c +++ b/src/glibext/gbufferview.c @@ -24,14 +24,21 @@ #include "gbufferview.h" +#include <assert.h> + + /* Vue d'un tampon pour code désassemblé (instance) */ struct _GBufferView { GObject parent; /* A laisser en premier */ - GCodeBuffer *buffer; /* Tampon de code visualisé */ + GBufferCache *cache; /* Tampon du contenu visualisé */ + + segcnt_list *highlighted; /* Segments mis en évidence */ + bool external; /* Note l'origine de la liste */ + bool unrestricted; /* Validité des informations */ vmpa2t start; /* Première ligne intégrée */ vmpa2t end; /* Dernière ligne intégrée */ @@ -45,11 +52,6 @@ struct _GBufferView GWidthTracker *tracker; /* Suivi pour usage interne */ }; - bool unrestricted; /* Validité des informations */ - - segcnt_list *highlighted; /* Segments mis en évidence */ - bool external; /* Note l'origine de la liste */ - }; /* Vue d'un tampon pour code désassemblé (classe) */ @@ -57,10 +59,6 @@ struct _GBufferViewClass { GObjectClass parent; /* A laisser en premier */ - gint line_height; /* Hauteur maximale des lignes */ - gint left_margin; /* Marge gauche + espace */ - gint left_text; /* Début d'impression du code */ - /* Signaux */ void (* need_redraw) (GBufferView *); @@ -81,15 +79,23 @@ static void g_buffer_view_dispose(GBufferView *); static void g_buffer_view_finalize(GBufferView *); /* Accompagne une variation de la quantité de lignes du tampon. */ -static void on_buffer_size_changed(const GCodeBuffer *, bool, size_t, size_t, GBufferView *); +static void on_buffer_cache_size_changed(const GBufferCache *, bool, size_t, size_t, GBufferView *); -/* Réagit à un changement de contenu d'une ligne donnée. */ -static void on_buffer_line_changed(GCodeBuffer *, GBufferLine *, line_segment *, GBufferView *); +/* Calcule la position idéale de curseur pour un point donné. */ +bool _g_buffer_view_compute_caret_full(GBufferView *, gint, GBufferLine *, size_t, const bool *, GdkRectangle *, vmpa2t *); /* Déplace le curseur au sein d'une vue de tampon. */ static bool _g_buffer_view_move_caret(GBufferView *, const GBufferLine *, size_t, GdkRectangle *, bool, GdkScrollDirection, const bool *); +/* Fournit la ligne présente à une ordonnée donnée. */ +static GBufferLine *g_buffer_view_find_line_at(GBufferView *, gint, size_t *); + + + + + + /* Détermine le type de la vue d'un tampon pour code désassemblé. */ G_DEFINE_TYPE(GBufferView, g_buffer_view, G_TYPE_OBJECT); @@ -116,10 +122,7 @@ static void g_buffer_view_class_init(GBufferViewClass *class) object->dispose = (GObjectFinalizeFunc/* ! */)g_buffer_view_dispose; object->finalize = (GObjectFinalizeFunc)g_buffer_view_finalize; - class->line_height = 17; - class->left_margin = 2 * class->line_height; - class->left_text = 2.5 * class->line_height; - + /* Sigaux */ g_signal_new("need-redraw", G_TYPE_BUFFER_VIEW, @@ -146,7 +149,10 @@ static void g_buffer_view_class_init(GBufferViewClass *class) static void g_buffer_view_init(GBufferView *view) { - view->unrestricted = true; + /** + * Inversion du statut pour forcer l'actualisation lors de la création. + */ + view->unrestricted = false; } @@ -165,7 +171,10 @@ static void g_buffer_view_init(GBufferView *view) static void g_buffer_view_dispose(GBufferView *view) { - g_object_unref(G_OBJECT(view->buffer)); + g_object_unref(G_OBJECT(view->cache)); + + if (!view->unrestricted) + g_object_unref(G_OBJECT(view->int_tracker)); G_OBJECT_CLASS(g_buffer_view_parent_class)->dispose(G_OBJECT(view)); @@ -207,22 +216,17 @@ static void g_buffer_view_finalize(GBufferView *view) * * ******************************************************************************/ -GBufferView *g_buffer_view_new(GCodeBuffer *buffer, segcnt_list *highlighted) +GBufferView *g_buffer_view_new(GBufferCache *cache, segcnt_list *highlighted) { GBufferView *result; /* Composant à retourner */ result = g_object_new(G_TYPE_BUFFER_VIEW, NULL); - g_object_ref(G_OBJECT(buffer)); - result->buffer = buffer; + result->cache = cache; g_buffer_view_restrict(result, NULL, NULL); - g_code_buffer_register_view_callback(buffer, - (buffer_size_changed_cb)on_buffer_size_changed, - G_OBJECT(result)); - - g_signal_connect(buffer, "line-changed", G_CALLBACK(on_buffer_line_changed), result); + g_signal_connect(cache, "size-changed", G_CALLBACK(on_buffer_cache_size_changed), result); if (highlighted != NULL) result->highlighted = highlighted; @@ -238,11 +242,11 @@ GBufferView *g_buffer_view_new(GCodeBuffer *buffer, segcnt_list *highlighted) /****************************************************************************** * * -* Paramètres : buffer = tampon de lignes cohérentes à manipuler. * -* added = indication sur la variation de la taille du tampon. * -* index = indice de la première ligne à traiter. * -* count = nombre de lignes à traiter. * -* view = vue active du tampon de lignes concerné. * +* Paramètres : cache = tampon de lignes cohérentes à manipuler. * +* added = indication sur la variation de la taille du tampon. * +* index = indice de la première ligne à traiter. * +* count = nombre de lignes à traiter. * +* view = vue active du tampon de lignes concerné. * * * * Description : Accompagne une variation de la quantité de lignes du tampon. * * * @@ -252,11 +256,11 @@ GBufferView *g_buffer_view_new(GCodeBuffer *buffer, segcnt_list *highlighted) * * ******************************************************************************/ -static void on_buffer_size_changed(const GCodeBuffer *buffer, bool added, size_t index, size_t count, GBufferView *view) +static void on_buffer_cache_size_changed(const GBufferCache *cache, bool added, size_t index, size_t count, GBufferView *view) { - size_t i; /* Boucle de parcours */ - GBufferLine *line; /* Ligne à manipuler */ - const vmpa2t *addr; /* Localisation de ligne */ + //size_t i; /* Boucle de parcours */ + //GBufferLine *line; /* Ligne à manipuler */ + //const vmpa2t *addr; /* Localisation de ligne */ /** * Il n'y a pas besoin de verrou ici car la fonction est appelée directement par le tampon. @@ -270,6 +274,8 @@ static void on_buffer_size_changed(const GCodeBuffer *buffer, bool added, size_t else { +#if 0 + /* Avant la zone représentée ? */ if (index < view->first) { @@ -281,6 +287,8 @@ static void on_buffer_size_changed(const GCodeBuffer *buffer, bool added, size_t else if (view->first == index) for (i = 0; i < count; i++) { + g_buffer_cache_get_line_addr(const GBufferCache *, size_t, gint, vmpa2t *); + line = g_code_buffer_find_line_by_index(buffer, index + i); addr = get_mrange_addr(g_buffer_line_get_range(line)); @@ -302,6 +310,8 @@ static void on_buffer_size_changed(const GCodeBuffer *buffer, bool added, size_t else if ((view->last + 1) == index) for (i = 0; i < count; i++) { + g_buffer_cache_get_line_addr(const GBufferCache *, size_t, gint, vmpa2t *); + line = g_code_buffer_find_line_by_index(buffer, index + i); addr = get_mrange_addr(g_buffer_line_get_range(line)); @@ -312,7 +322,8 @@ static void on_buffer_size_changed(const GCodeBuffer *buffer, bool added, size_t } - g_width_tracker_update_added(view->int_tracker, index, count); + //g_width_tracker_update_added(view->int_tracker, index, count); +#endif } @@ -338,38 +349,36 @@ static void on_buffer_size_changed(const GCodeBuffer *buffer, bool added, size_t } - g_width_tracker_update_deleted(view->int_tracker, index, index + count - 1); + //g_width_tracker_update_deleted(view->int_tracker, index, index + count - 1); } - g_signal_emit_by_name(view, "need-redraw"); + //g_signal_emit_by_name(view, "need-redraw"); } /****************************************************************************** * * -* Paramètres : buffer = tampon de lignes cohérentes à manipuler. * -* line = ligne dont la définition vient d'évoluer. * -* segment = éventuel segment qui vient d'évoluer ou NULL. * -* view = vue active du tampon de lignes concerné. * +* Paramètres : view = visualisateur à consulter. * * * -* Description : Réagit à un changement de contenu d'une ligne donnée. * +* Description : Fournit le tampon de code lié à un visualisateur donné. * * * -* Retour : - * +* Retour : Tampon de code associé au gestionnaire d'affichage. * * * * Remarques : - * * * ******************************************************************************/ -static void on_buffer_line_changed(GCodeBuffer *buffer, GBufferLine *line, line_segment *segment, GBufferView *view) +GBufferCache *g_buffer_view_get_cache(const GBufferView *view) { - const vmpa2t *addr; /* Localisation de ligne */ + GBufferCache *result; /* Instance à retourner */ - addr = get_mrange_addr(g_buffer_line_get_range(line)); + result = view->cache; - if (cmp_vmpa(&view->start, addr) <= 0 && cmp_vmpa(addr, &view->end) <= 0) - g_signal_emit_by_name(view, "need-redraw"); + g_object_ref(G_OBJECT(result)); + + return result; } @@ -390,33 +399,41 @@ static void on_buffer_line_changed(GCodeBuffer *buffer, GBufferLine *line, line_ void g_buffer_view_restrict(GBufferView *view, const vmpa2t *start, const vmpa2t *end) { + bool state; /* Nouvel état à proclamer */ const GWidthTracker *template; /* Suivi déjà en place */ - if (!view->unrestricted) - g_object_unref(G_OBJECT(view->int_tracker)); + state = (start == NULL || end == NULL); - view->unrestricted = (start == NULL || end == NULL); + if (view->unrestricted != state) + { + view->unrestricted = state; - template = g_code_buffer_get_width_tracker(view->buffer); + template = g_buffer_cache_get_width_tracker(view->cache); - if (view->unrestricted) - { - view->first = 0; - view->last = g_code_buffer_count_lines(view->buffer) - 1; + if (view->unrestricted) + { + /* Vérification pour le cas particulier du démarrage */ + if (view->int_tracker != NULL) + g_object_unref(G_OBJECT(view->int_tracker)); - view->ext_tracker = template; + view->first = 0; + view->last = g_buffer_cache_count_lines(view->cache) - 1; - } + view->ext_tracker = template; - else - { - copy_vmpa(&view->start, start); - copy_vmpa(&view->end, end); + } + + else + { + copy_vmpa(&view->start, start); + copy_vmpa(&view->end, end); + + view->first = g_buffer_cache_find_index_by_addr(view->cache, start, true); + view->last = g_buffer_cache_find_index_by_addr(view->cache, end, false); - view->first = g_code_buffer_get_index_from_address(view->buffer, start, true); - view->last = g_code_buffer_get_index_from_address(view->buffer, end, false); + view->ext_tracker = g_width_tracker_new_restricted(template, view->first, view->last); - view->ext_tracker = g_width_tracker_new_restricted(template, view->first, view->last); + } } @@ -425,7 +442,7 @@ void g_buffer_view_restrict(GBufferView *view, const vmpa2t *start, const vmpa2t /****************************************************************************** * * -* Paramètres : view = visualisateur à mettre à jour. * +* Paramètres : view = visualisateur à consulter. * * first = première ligne à imprimer ou NULL. [OUT] * * last = première ligne hors cadre ou NULL. [OUT] * * * @@ -437,7 +454,7 @@ void g_buffer_view_restrict(GBufferView *view, const vmpa2t *start, const vmpa2t * * ******************************************************************************/ -bool g_buffer_view_get_restrictions(GBufferView *view, vmpa2t *start, vmpa2t *end) +bool g_buffer_view_get_restrictions(const GBufferView *view, vmpa2t *start, vmpa2t *end) { if (!view->unrestricted) { @@ -450,44 +467,11 @@ bool g_buffer_view_get_restrictions(GBufferView *view, vmpa2t *start, vmpa2t *en } -/****************************************************************************** -* * -* Paramètres : view = visualisateur à consulter. * -* * -* Description : Fournit le tampon de code lié à un visualisateur donné. * -* * -* Retour : Tampon de code associé au gestionnaire d'affichage. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GCodeBuffer *g_buffer_view_get_buffer(const GBufferView *view) -{ - g_object_ref(G_OBJECT(view->buffer)); - - return view->buffer; -} -/****************************************************************************** -* * -* Paramètres : view = visualisation à consulter. * -* * -* Description : Fournit la hauteur d'impression d'une ligne visualisée. * -* * -* Retour : Hauteur de ligne en pixel. * -* * -* Remarques : - * -* * -******************************************************************************/ -gint g_buffer_view_get_line_height(GBufferView *view) -{ - return G_BUFFER_VIEW_GET_CLASS(view)->line_height; -} /****************************************************************************** @@ -507,7 +491,7 @@ gint g_buffer_view_get_width(GBufferView *view, const bool *display) { gint result; /* Taille à retourner */ - result = G_BUFFER_VIEW_GET_CLASS(view)->left_text; + result = g_buffer_cache_get_text_position(view->cache); result += g_width_tracker_get_width(view->tracker, display); @@ -533,7 +517,7 @@ gint g_buffer_view_get_margin(GBufferView *view, const bool *display) { gint result; /* Taille à retourner */ - result = G_BUFFER_VIEW_GET_CLASS(view)->left_text; + result = g_buffer_cache_get_text_position(view->cache); result += g_width_tracker_get_margin(view->tracker, display); @@ -558,7 +542,7 @@ gint g_buffer_view_get_height(const GBufferView *view) { gint result; /* Taille à retourner */ - result = G_BUFFER_VIEW_GET_CLASS(view)->line_height; + result = g_buffer_cache_get_line_height(view->cache); result *= (view->last - view->first + 1); @@ -567,50 +551,66 @@ gint g_buffer_view_get_height(const GBufferView *view) } + + + + + + + + + + + /****************************************************************************** * * * Paramètres : view = vue de tampon à mettre à jour. * -* x = abscisse de la zone principale à traiter. * -* y = ordonnée de la zone principale à traiter. * +* x = abscisse proposée pour le nouvel emplacement. * +* y = ordonnée proposée pour le nouvel emplacement. * * display = règles d'affichage des colonnes modulables. * * caret = position du curseur à construire. [OUT] * +* addr = adresse correspondant à cette même position. [OUT] * * * * Description : Calcule la position idéale de curseur pour un point donné. * * * -* Retour : Adresse si une a pu être déterminée, NULL sinon. * +* Retour : true si les deux derniers arguments ont pu être constitués. * * * * Remarques : - * * * ******************************************************************************/ -const vmpa2t *g_buffer_view_compute_caret(GBufferView *view, gint x, gint y, const bool *display, GdkRectangle *caret) +bool g_buffer_view_compute_caret_full(GBufferView *view, gint x, gint y, const bool *display, GdkRectangle *caret, vmpa2t *addr) { - gint remaining; /* Copie de travail modifiable */ + bool result; /* Bilan à retourner */ + gint lheight; /* Hauteur d'une ligne */ size_t index; /* Indice de ligne de tampon */ GBufferLine *line; /* Ligne à la position courante*/ - const line_segment *segment; /* Segment présent sur la place*/ - GBufferViewClass *class; /* Classe pour les vues */ - remaining = x; + result = false; - line = g_buffer_view_find_line_and_segment_at(view, &remaining, y, &index, display, &segment); + /* Détermination de la ligne courante */ - /* FIXME : unref() ! */ - if (line == NULL) return NULL; - if (segment == NULL) printf(" -- no segment\n"); - if (segment == NULL) return NULL; + lheight = g_buffer_cache_get_line_height(view->cache); + index = y / lheight; + index += view->first; - class = G_BUFFER_VIEW_GET_CLASS(view); + if (index > view->last) + goto gbvccf_done; - caret->x = /*view->left_text +*/ (x - remaining) + get_caret_position_from_line_segment(segment, remaining); + line = g_buffer_cache_find_line_by_index(view->cache, index); - caret->y = (index - view->first) * class->line_height; + assert(line != NULL); - caret->width = 2; - caret->height = class->line_height; + /* Calcul d'une position */ + + result = _g_buffer_view_compute_caret_full(view, x, line, index, display, caret, addr); + + g_object_unref(G_OBJECT(line)); + + gbvccf_done: - return get_mrange_addr(g_buffer_line_get_range(line)); + return result; } @@ -618,50 +618,69 @@ const vmpa2t *g_buffer_view_compute_caret(GBufferView *view, gint x, gint y, con /****************************************************************************** * * * Paramètres : view = vue de tampon à mettre à jour. * +* x = abscisse proposée pour le nouvel emplacement. * * line = ligne correspondant à la position. * * index = indice de cette même ligne dans le tampon. * -* x = abscisse de la zone principale à traiter. * * display = règles d'affichage des colonnes modulables. * * caret = position du curseur à construire. [OUT] * +* addr = adresse correspondant à cette même position. [OUT] * * * * Description : Calcule la position idéale de curseur pour un point donné. * * * -* Retour : Adresse si une a pu être déterminée, NULL sinon. * +* Retour : true si les deux derniers arguments ont pu être constitués. * * * * Remarques : - * * * ******************************************************************************/ -const vmpa2t *g_buffer_view_compute_caret_full(GBufferView *view, GBufferLine *line, size_t index, gint x, const bool *display, GdkRectangle *caret) +bool _g_buffer_view_compute_caret_full(GBufferView *view, gint x, GBufferLine *line, size_t index, const bool *display, GdkRectangle *caret, vmpa2t *addr) { - GBufferViewClass *class; /* Classe pour les vues */ - gint offset; /* Point de travail modifiable */ + bool result; /* Bilan à retourner */ + gint text_pos; /* Abscisse de départ du texte */ line_width_summary summary; /* Résumé concis des largeurs */ gint base; /* Position absolue de segment */ bool status; /* Bilan de la localisation */ + gint lheight; /* Hauteur d'une ligne */ - class = G_BUFFER_VIEW_GET_CLASS(view); + result = false; - offset = x; + /* Zone d'intervention bornée ! */ - offset -= class->left_text; - if (offset < 0) return NULL; + text_pos = g_buffer_cache_get_text_position(view->cache); + + if (x < text_pos) + goto gbvccf_done; + + /* Calcul d'une position */ g_width_tracker_get_local_width_summary(view->tracker, index, &summary); - /* Traitement pour mise à jour de l'abscisse uniquement */ - status = g_buffer_line_get_coord_at(line, &summary, display, &base, &offset, + x -= text_pos; + + status = g_buffer_line_get_coord_at(line, &summary, display, &base, &x, GDK_SCROLL_LEFT, true, (col_coord_t []) { { 0 } }); - if (!status) return NULL; - caret->x = class->left_text + base + offset; + if (!status) + goto gbvccf_done; + + /* Transmission des informations */ + + lheight = g_buffer_cache_get_line_height(view->cache); - caret->y = (index - view->first) * class->line_height; + caret->x = text_pos + base + x; + + caret->y = (index - view->first) * lheight; caret->width = 2; - caret->height = class->line_height; + caret->height = lheight; + + g_buffer_cache_get_line_addr(view->cache, index, caret->x, addr); + + result = true; - return get_mrange_addr(g_buffer_line_get_range(line)); + gbvccf_done: + + return result; } @@ -687,16 +706,24 @@ const vmpa2t *g_buffer_view_compute_caret_full(GBufferView *view, GBufferLine *l static bool _g_buffer_view_move_caret(GBufferView *view, const GBufferLine *line, size_t index, GdkRectangle *caret, bool ctrl, GdkScrollDirection dir, const bool *display) { bool result; /* Bilan à retourner */ + gint text_pos; /* Abscisse de départ du texte */ gint offset; /* Point de travail modifiable */ line_width_summary summary; /* Résumé concis des largeurs */ gint base; /* Position absolue de segment */ col_coord_t coord; /* Coordonnées en interne */ const line_segment *segment; /* Bribe de texte trouvée */ - offset = caret->x; - offset -= G_BUFFER_VIEW_GET_CLASS(view)->left_text; - if (offset < 0) return false; + result = false; + + /* Zone d'intervention bornée ! */ + + text_pos = g_buffer_cache_get_text_position(view->cache); + + if (caret->x < text_pos) + goto gbvmc_done; + + offset = caret->x - text_pos; g_width_tracker_get_local_width_summary(view->tracker, index, &summary); @@ -725,7 +752,9 @@ static bool _g_buffer_view_move_caret(GBufferView *view, const GBufferLine *line /* Mise à jour éventuelle */ if (result) - caret->x = G_BUFFER_VIEW_GET_CLASS(view)->left_text + base + offset; + caret->x = text_pos + base + offset; + + gbvmc_done: return result; @@ -735,82 +764,35 @@ static bool _g_buffer_view_move_caret(GBufferView *view, const GBufferLine *line /****************************************************************************** * * * Paramètres : view = vue de tampon à mettre à jour. * -* caret = position du curseur à faire évoluer. * * ctrl = indique la demande d'un parcours rapide. * * dir = direction du parcours. * * display = règles d'affichage des colonnes modulables. * +* caret = position du curseur à faire évoluer. [OUT] * +* addr = adresse correspondant à cette même position. [OUT] * * * * Description : Déplace le curseur au sein d'une vue de tampon. * * * -* Retour : Adresse si une a pu être déterminée, VMPA_INVALID sinon. * +* Retour : true si les deux derniers arguments ont pu être constitués. * * * * Remarques : - * * * ******************************************************************************/ -const vmpa2t *g_buffer_view_move_caret(GBufferView *view, GdkRectangle *caret, bool ctrl, GdkScrollDirection dir, const bool *display) +bool g_buffer_view_move_caret(GBufferView *view, bool ctrl, GdkScrollDirection dir, const bool *display, GdkRectangle *caret, vmpa2t *addr) { - const vmpa2t *result; /* Actualisation à renvoyer */ + bool result; /* Bilan à retourner */ size_t index; /* Indice de ligne de tampon */ GBufferLine *line; /* Ligne sous le pointeur */ - - - line_width_summary summary; /* Résumé concis des largeurs */ - gint left_pos; /* Retour à la ligne */ - gint right_pos; /* Position d'extrème droite */ - BufferLineColumn i; /* Boucle de parcours */ size_t first; /* Première ligne intégrée */ size_t last; /* Dernière ligne intégrée */ - - - - + GBufferLine *other; /* Ligne voisine à visiter */ bool moved; /* Mémorisation d'une évolut° */ + gint text_pos; /* Abscisse de départ du texte */ - - - - - - - - - result = NULL; - - + result = false; line = g_buffer_view_find_line_at(view, caret->y, &index); - if (line == NULL) return NULL; - - g_width_tracker_get_local_width_summary(view->tracker, index, &summary); - - switch (dir) - { - case GDK_SCROLL_UP: - case GDK_SCROLL_DOWN: - break; - case GDK_SCROLL_LEFT: - case GDK_SCROLL_RIGHT: - left_pos = G_BUFFER_VIEW_GET_CLASS(view)->left_text; - if (display[BLC_PHYSICAL]) left_pos += summary.max_widths[BLC_PHYSICAL] + COL_MARGIN; - if (display[BLC_VIRTUAL]) left_pos += summary.max_widths[BLC_VIRTUAL] + COL_MARGIN; - if (display[BLC_BINARY]) left_pos += summary.max_widths[BLC_BINARY] + COL_MARGIN; - right_pos = left_pos; - for (i = BLC_ASSEMBLY_HEAD; i < BLC_COUNT; i++) - right_pos += summary.max_widths[i] + COL_MARGIN; - - /* -gint g_buffer_line_compute_max_width(const GBufferLine *line, BufferLineColumn index, const gint *max_widths) - -BufferLineColumn g_buffer_line_get_merge_start(const GBufferLine *line) - */ - - left_pos = G_BUFFER_VIEW_GET_CLASS(view)->left_text; - - break; - default: /* GDK_SCROLL_SMOOTH */ - break; - } + if (line == NULL) goto gbvmc_done; first = view->first; last = view->last; @@ -821,8 +803,12 @@ BufferLineColumn g_buffer_line_get_merge_start(const GBufferLine *line) if (index > first) { - line = g_code_buffer_find_line_by_index(view->buffer, index - 1); - result = g_buffer_view_compute_caret_full(view, line, index - 1, caret->x, display, caret); + index--; + + other = g_buffer_cache_find_line_by_index(view->cache, index); + result = _g_buffer_view_compute_caret_full(view, caret->x, other, index, display, caret, addr); + g_object_unref(G_OBJECT(other)); + } break; @@ -831,48 +817,58 @@ BufferLineColumn g_buffer_line_get_merge_start(const GBufferLine *line) if (index < last) { - line = g_code_buffer_find_line_by_index(view->buffer, index + 1); - result = g_buffer_view_compute_caret_full(view, line, index + 1, caret->x, display, caret); + index++; + + other = g_buffer_cache_find_line_by_index(view->cache, index); + result = _g_buffer_view_compute_caret_full(view, caret->x, other, index, display, caret, addr); + g_object_unref(G_OBJECT(other)); + } break; case GDK_SCROLL_LEFT: - /* - line = g_buffer_view_find_line_at(view, caret->y, &index); - if (line == NULL) break; - */ - moved = _g_buffer_view_move_caret(view, line, index, caret, ctrl, GDK_SCROLL_LEFT, display); if (moved) - result = get_mrange_addr(g_buffer_line_get_range(line)); + { + g_buffer_cache_get_line_addr(view->cache, index, caret->x, addr); + result = true; + } else if (index > first) { - line = g_code_buffer_find_line_by_index(view->buffer, index - 1); - result = g_buffer_view_compute_caret_full(view, line, index - 1, INT_MAX, display, caret); + index--; + + other = g_buffer_cache_find_line_by_index(view->cache, index); + result = _g_buffer_view_compute_caret_full(view, INT_MAX, other, index, display, caret, addr); + g_object_unref(G_OBJECT(other)); + } break; case GDK_SCROLL_RIGHT: - /* - line = g_buffer_view_find_line_at(view, caret->y, &index); - if (line == NULL) break; - */ - moved = _g_buffer_view_move_caret(view, line, index, caret, ctrl, GDK_SCROLL_RIGHT, display); if (moved) - result = get_mrange_addr(g_buffer_line_get_range(line)); + { + g_buffer_cache_get_line_addr(view->cache, index, caret->x, addr); + result = true; + } else if (index < last) { - line = g_code_buffer_find_line_by_index(view->buffer, index + 1); - result = g_buffer_view_compute_caret_full(view, line, index + 1, left_pos, display, caret); + index++; + + text_pos = g_buffer_cache_get_text_position(view->cache); + + other = g_buffer_cache_find_line_by_index(view->cache, index); + result = _g_buffer_view_compute_caret_full(view, text_pos, other, index, display, caret, addr); + g_object_unref(G_OBJECT(other)); + } break; @@ -882,11 +878,27 @@ BufferLineColumn g_buffer_line_get_merge_start(const GBufferLine *line) } + g_object_unref(G_OBJECT(line)); + + gbvmc_done: + return result; } + + + + + + + + + + + + /****************************************************************************** * * * Paramètres : view = vue de tampon à mettre à jour. * @@ -927,23 +939,64 @@ bool g_buffer_view_unhighlight_segments(GBufferView *view) bool g_buffer_view_highlight_segments(GBufferView *view, gint x, gint y, const bool *display) { - bool need_redraw; /* Besoin d'actualisation ? */ + bool result; /* Besoin à faire remonter */ + gint text_pos; /* Abscisse de départ du texte */ + gint lheight; /* Hauteur d'une ligne */ + size_t index; /* Indice de ligne de tampon */ + GBufferLine *line; /* Ligne à la position courante*/ + line_width_summary summary; /* Résumé concis des largeurs */ const line_segment *segment; /* Segment sélectionnable */ + /* Réinitialisation */ + if (view->highlighted != NULL) - need_redraw = g_buffer_view_unhighlight_segments(view); + result = g_buffer_view_unhighlight_segments(view); else - need_redraw = false; + result = false; + + /* Zone d'intervention bornée ! */ + + text_pos = g_buffer_cache_get_text_position(view->cache); + + if (x < text_pos) + goto gbvhs_done; + + /* Détermination de la ligne concernée */ - g_buffer_view_find_line_and_segment_at(view, &x, y, NULL, display, &segment); + lheight = g_buffer_cache_get_line_height(view->cache); + index = y / lheight; + + index += view->first; + + if (index > view->last) + goto gbvhs_done; + + line = g_buffer_cache_find_line_by_index(view->cache, index); + + assert(line != NULL); + + /* Recherche d'un segment et de son empreinte */ + + g_width_tracker_get_local_width_summary(view->tracker, index, &summary); + + x -= text_pos; + + segment = g_buffer_line_get_segment_at(line, &summary, display, + (gint []) { 0 }, &x, GDK_SCROLL_LEFT, true); - if (segment) - need_redraw |= add_segment_content_to_selection_list(view->highlighted, segment); + g_object_unref(G_OBJECT(line)); - if (need_redraw) + /* Conclusion */ + + if (segment != NULL) + result |= add_segment_content_to_selection_list(view->highlighted, segment); + + if (result) g_signal_emit_by_name(view, "need-redraw"); - return true; + gbvhs_done: + + return result; } @@ -952,13 +1005,12 @@ bool g_buffer_view_highlight_segments(GBufferView *view, gint x, gint y, const b * * * Paramètres : view = visualisation à représenter. * * cr = contexte graphique dédié à la procédure. * -* fake_x = abscisse réelle du point 0 à l'écran. * -* fake_y = ordonnée réelle du point 0 à l'écran. * +* virt_y = ordonnée réelle du point 0 à l'écran. * * area = position et surface à traiter. * * display = règles d'affichage des colonnes modulables. * * selected = ordonnée d'une ligne sélectionnée ou NULL. * * * -* Description : Imprime la visualisation du tampon de code désassemblé. * +* Description : Imprime la visualisation du tampon de lignes quelconques. * * * * Retour : - * * * @@ -966,148 +1018,57 @@ bool g_buffer_view_highlight_segments(GBufferView *view, gint x, gint y, const b * * ******************************************************************************/ -void g_buffer_view_draw(const GBufferView *view, cairo_t *cr, gint fake_x, gint fake_y, const cairo_rectangle_int_t *area, const bool *display, const gint *selected) +void g_buffer_view_draw(const GBufferView *view, cairo_t *cr, gint virt_y, const cairo_rectangle_int_t *area, const bool *display, gint *selected) { - GBufferViewClass *class; /* Classe pour les vues */ - gint real_x; /* Abscisse réelle pour tampon */ - gint real_y; /* Ordonnée réelle pour tampon */ + gint line_height; /* Hauteur d'une ligne */ + gint cr_y; /* Ordonnée pour le dessin */ size_t first; /* Première ligne visée */ - size_t last; /* Dernière ligne visée + 1 */ - gint y; /* Point de départ + décallage */ - bool wait_selection; /* Sélection déjà passée ? */ - gint rel_selected; /* Position relative de sélect°*/ - size_t i; /* Boucle de parcours */ - GBufferLine *line; /* Ligne à dessiner à l'écran */ - line_width_summary summary; /* Résumé concis des largeurs */ + size_t last; /* Dernière ligne visée */ - class = G_BUFFER_VIEW_GET_CLASS(view); + line_height = g_buffer_cache_get_line_height(view->cache); - real_x = fake_x + class->left_text; - real_y = fake_y + area->y; + /* Indice et point de départ */ first = view->first; - first += (real_y / class->line_height); - - last = first + (area->height / class->line_height); - if (area->height % class->line_height > 0) last++; - - last = MIN(last, view->last); - - y = area->y - (real_y % class->line_height); - - wait_selection = true; + first += (virt_y / line_height); - if (selected != NULL) - rel_selected = *selected - fake_y; - - if (g_code_buffer_count_lines(view->buffer) > 0) - for (i = first; i <= last; i++) - { - /* Si sélection, on sousligne la ligne concernée */ - if (wait_selection && selected != NULL && rel_selected == y) - { - cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.05); + cr_y = area->y - (virt_y % line_height); - cairo_rectangle(cr, area->x, y, area->width, class->line_height); - cairo_fill(cr); + /* Indice de d'arrivée */ - wait_selection = false; + last = first + (area->height / line_height); + if (area->height % line_height > 0) last++; - } + last = MIN(last, view->last); - line = g_code_buffer_find_line_by_index(view->buffer, i); + /* Phase de dessin ! */ - if (i == first || (g_buffer_line_get_flags(line) & BLF_WIDTH_MANAGER)) - g_width_tracker_get_local_width_summary(view->tracker, i, &summary); + /** + * Le contexte n'est pas sauvegardé avant modification ici car + * l'appelant l'a fait pour nous avant sa translation sur les abscisses. + */ - g_buffer_line_draw(line, cr, &summary, real_x, y, display, view->highlighted); + cairo_translate(cr, 0, cr_y); - y += class->line_height; + if (selected != NULL) + *selected -= cr_y; - } + g_buffer_cache_draw(view->cache, cr, first, last, area, display, selected, view->highlighted); } -/****************************************************************************** -* * -* Paramètres : view = visualisation à consulter. * -* addr = adresse où retrouver la ligne recherchée. * -* flags = propriétés à vérifier en tout ou partie. * -* idx = indice de la ligne trouvée ou NULL. [OUT] * -* * -* Description : Retrouve une ligne au sein d'un tampon avec une adresse. * -* * -* Retour : Line retrouvée ou NULL en cas d'échec. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GBufferLine *g_buffer_view_find_line_by_addr(const GBufferView *view, const vmpa2t *addr, BufferLineFlags flags, size_t *idx) -{ - GBufferLine *result; /* Ligne trouvée à retourner */ - phys_t length; /* Taille de la vue */ - mrange_t vrange; /* Couverture de la vue */ - bool allowed; /* Rechercher validée ? */ - - /* Vérification des bornes */ - - if (!view->unrestricted) - { - length = compute_vmpa_diff(&view->start, &view->end); - init_mrange(&vrange, &view->start, length); - allowed = mrange_contains_addr_inclusive(&vrange, addr); - } - else allowed = true; - /* Lancement des recherches ? */ - if (allowed) - result = g_code_buffer_find_line_by_addr(view->buffer, addr, flags, idx); - else - result = NULL; - return result; - -} -/****************************************************************************** -* * -* Paramètres : view = visualisation à consulter. * -* index = indice de la ligne recherchée. * -* * -* Description : Retrouve une ligne au sein d'un tampon avec un indice. * -* * -* Retour : Line retrouvée ou NULL en cas d'échec. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GBufferLine *g_buffer_view_find_line_by_index(const GBufferView *view, size_t index) -{ - GBufferLine *result; /* Ligne trouvée à retourner */ - bool allowed; /* Rechercher validée ? */ - /* Vérification des bornes */ - allowed = (view->first <= index && index <= view->last); - /* Lancement des recherches ? */ - - if (allowed) - result = g_code_buffer_find_line_by_index(view->buffer, index); - else - result = NULL; - - return result; - -} /****************************************************************************** @@ -1124,19 +1085,19 @@ GBufferLine *g_buffer_view_find_line_by_index(const GBufferView *view, size_t in * * ******************************************************************************/ -GBufferLine *g_buffer_view_find_line_at(GBufferView *view, gint y, size_t *idx) +static GBufferLine *g_buffer_view_find_line_at(GBufferView *view, gint y, size_t *idx) { GBufferLine *result; /* Ligne trouvée à retourner */ gint lheight; /* Hauteur d'une ligne */ size_t index; /* Indice attendu */ - lheight = g_buffer_view_get_line_height(view); + lheight = g_buffer_cache_get_line_height(view->cache); index = y / lheight; index += view->first; if (index <= view->last) - result = g_code_buffer_find_line_by_index(view->buffer, index); + result = g_buffer_cache_find_line_by_index(view->cache, index); else result = NULL; @@ -1148,125 +1109,26 @@ GBufferLine *g_buffer_view_find_line_at(GBufferView *view, gint y, size_t *idx) } -/****************************************************************************** -* * -* Paramètres : view = visualisation à consulter. * -* x = abscisse comprise dans le segment recherché. [OUT] * -* y = ordonnée comprise dans la ligne recherchée. * -* idx = indice de la ligne trouvée ou NULL. [OUT] * -* display = règles d'affichage des colonnes modulables. * -* segment = portion de texte recherchée ou NULL. [OUT] * -* * -* Description : Fournit la ligne et son segment présents à une position. * -* * -* Retour : Ligne retrouvée ou NULL si aucune. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GBufferLine *g_buffer_view_find_line_and_segment_at(GBufferView *view, gint *x, gint y, size_t *idx, const bool *display, const line_segment **segment) -{ - GBufferLine *result; /* Ligne trouvée à retourner */ - size_t index; /* Indice de la ligne trouvée */ - GBufferViewClass *class; /* Classe pour les vues */ - line_width_summary summary; /* Résumé concis des largeurs */ - - /* Recherche d'une ligne correspondante */ - result = g_buffer_view_find_line_at(view, y, &index); - if (idx != NULL) *idx = index; - /* Recherche du segment visé éventuel */ - if (result != NULL && segment != NULL) - { - class = G_BUFFER_VIEW_GET_CLASS(view); - if (*x < class->left_text) - *segment = NULL; - else - { - g_width_tracker_get_local_width_summary(view->tracker, index, &summary); - *x -= class->left_text; - *segment = g_buffer_line_get_segment_at(result, &summary, display, - (gint []) { 0 }, x, GDK_SCROLL_LEFT, true); - } - } - return result; -} /****************************************************************************** * * -* Paramètres : view = visualisation à consulter. * -* x = abscisse comprise dans le segment recherché. [OUT] * -* y = ordonnée comprise dans la ligne recherchée. * -* idx = indice de la ligne trouvée ou NULL. [OUT] * -* display = règles d'affichage des colonnes modulables. * -* creator = instance à l'origine de la représentation. [OUT] * -* * -* Description : Fournit la ligne et son segment présents à une position. * -* * -* Retour : Ligne retrouvée ou NULL si aucune. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GBufferLine *g_buffer_view_find_line_and_creator_at(GBufferView *view, gint *x, gint y, size_t *idx, const bool *display, GObject **creator) -{ - GBufferLine *result; /* Ligne trouvée à retourner */ - size_t index; /* Indice de la ligne trouvée */ - GBufferViewClass *class; /* Classe pour les vues */ - line_width_summary summary; /* Résumé concis des largeurs */ - - /* Recherche d'une ligne correspondante */ - - result = g_buffer_view_find_line_at(view, y, &index); - - if (idx != NULL) *idx = index; - - /* Recherche du segment visé éventuel */ - - if (result != NULL && creator != NULL) - { - class = G_BUFFER_VIEW_GET_CLASS(view); - - if (*x < class->left_text) - *creator = NULL; - - else - { - g_width_tracker_get_local_width_summary(view->tracker, index, &summary); - - *x -= class->left_text; - *creator = g_buffer_line_get_creator_at(result, &summary, display, - (gint []) { 0 }, x, GDK_SCROLL_LEFT, true); - - } - - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : view = composant GTK à consulter. * +* Paramètres : view = visualisation à consulter. * * addr = adresse à présenter à l'écran. * +* code = s'arrête si possible à une ligne avec code. * * x = position horizontale au sein du composant. [OUT] * * y = position verticale au sein du composant. [OUT] * -* code = s'arrête si possible à une ligne avec code. * * * * Description : Indique la position d'affichage d'une adresse donnée. * * * @@ -1276,61 +1138,11 @@ GBufferLine *g_buffer_view_find_line_and_creator_at(GBufferView *view, gint *x, * * ******************************************************************************/ -bool g_buffer_view_get_address_coordinates(GBufferView *view, const vmpa2t *addr, gint *x, gint *y, bool code) +bool g_buffer_view_get_address_coordinates(GBufferView *view, const vmpa2t *addr, bool code, gint *x, gint *y) { bool result; /* Bilan à retourner */ - gint lheight; /* Hauteur d'une ligne */ - size_t i; /* Boucle de parcours */ - GBufferLine *line; /* Ligne à consulter */ - const mrange_t *range; /* Emplacement parcouru */ - - result = false; - - *x = 0; - *y = 0; - - lheight = g_buffer_view_get_line_height(view); - - for (i = view->first; i <= view->last; i++) - { - /** - * Si l'adresse recherchée est plus petite que l'adresse de départ, - * on va effectuer un parcours complet pour rien. - * - * On considère cependant que le seul cas où celà peut arriver - * est lorsque que des découpages en blocs sont impliqués. - * - * Les découpages conduisent alors à la formation de petites zones, - * rapides à parcourir. - */ - - line = g_code_buffer_find_line_by_index(view->buffer, i); - range = g_buffer_line_get_range(line); - - result = mrange_contains_addr(range, addr); - if (result) break; - - *y += lheight; - } - - if (result && code) - for (; i <= view->last; i++) - { - line = g_code_buffer_find_line_by_index(view->buffer, i); - - if (g_buffer_line_get_flags(line) & BLF_HAS_CODE) break; - - if (i == view->last) break; - - line = g_code_buffer_find_line_by_index(view->buffer, i + 1); - - range = g_buffer_line_get_range(line); - if (!mrange_contains_addr(range, addr)) break; - - *y += lheight; - - } + result = g_buffer_cache_get_address_coordinates(view->cache, addr, view->first, view->last, code, x, y); return result; |