summaryrefslogtreecommitdiff
path: root/src/gtkext
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2015-05-06 00:07:18 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2015-05-06 00:07:18 (GMT)
commitd76e89e102aacfe945b44eb3150cb9f4bbf7b613 (patch)
tree7dda55fabeddcd0dbd1813d9ceef4b905a056c7f /src/gtkext
parent2c6e4f3f3f15d1568e9dae407e32a217d8f7ab19 (diff)
Displayed a tooltip for strings or code symbols in buffer views.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@530 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
Diffstat (limited to 'src/gtkext')
-rw-r--r--src/gtkext/gtkbufferview.c150
1 files changed, 150 insertions, 0 deletions
diff --git a/src/gtkext/gtkbufferview.c b/src/gtkext/gtkbufferview.c
index 86a738a..8e4ffd4 100644
--- a/src/gtkext/gtkbufferview.c
+++ b/src/gtkext/gtkbufferview.c
@@ -27,6 +27,8 @@
#include <gdk/gdkkeysyms.h>
+#include "../arch/target.h"
+#include "../common/extstr.h"
#include "../core/params.h"
#include "../glibext/chrysamarshal.h"
@@ -59,6 +61,9 @@ static gboolean gtk_buffer_view_draw(GtkWidget *, cairo_t *);
/* Prend en compte une frappe de touche sur le composant. */
static gboolean gtk_buffer_view_key_press(GtkWidget *, GdkEventKey *);
+/* Prépare l'affichage d'une astuce. */
+static gboolean gtk_buffer_view_query_tooltip(GtkWidget *, gint, gint, gboolean, GtkTooltip *);
+
/* Indique les dimensions de travail du composant d'affichage. */
static void gtk_buffer_view_compute_requested_size(GtkBufferView *, gint *, gint *);
@@ -135,6 +140,7 @@ static void gtk_buffer_view_class_init(GtkBufferViewClass *class)
widget_class->button_press_event = gtk_buffer_view_button_press;
widget_class->draw = gtk_buffer_view_draw;
widget_class->key_press_event = gtk_buffer_view_key_press;
+ widget_class->query_tooltip = gtk_buffer_view_query_tooltip;
panel_class->compute_size = (compute_requested_size_fc)gtk_buffer_view_compute_requested_size;
panel_class->compute_inc = (compute_scroll_inc_fc)gtk_buffer_view_compute_scroll_inc;
@@ -176,6 +182,12 @@ static void gtk_buffer_view_class_init(GtkBufferViewClass *class)
static void gtk_buffer_view_init(GtkBufferView *view)
{
+ GObject *object; /* Autre version de l'instance */
+
+ object = G_OBJECT(view);
+
+ g_object_set(object, "has-tooltip", TRUE, NULL);
+
view->caret.x = 10;
view->caret.y = 10;
view->caret.width = 100;
@@ -484,7 +496,145 @@ static gboolean gtk_buffer_view_key_press(GtkWidget *widget, GdkEventKey *event)
}
+/******************************************************************************
+* *
+* Paramètres : widget = composant GTK visé par l'opération. *
+* x = abscisse de la position du message. *
+* y = ordonnée de la position du message. *
+* keyboard = indique une demande suite à obtiention du focus. *
+* tooltip = astuce à compléter. [OUT] *
+* *
+* Description : Prépare l'affichage d'une astuce. *
+* *
+* Retour : TRUE pour un affichage validé, FALSE sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static gboolean gtk_buffer_view_query_tooltip(GtkWidget *widget, gint x, gint y, gboolean keyboard, GtkTooltip *tooltip)
+{
+ GtkBufferView *view; /* Autre version du composant */
+ gint real_x; /* Abscisse absolue réelle */
+ gint real_y; /* Ordonnée absolue réelle */
+ GBufferLine *line; /* Ligne en cours de survol */
+ GBufferSegment *segment; /* Segment actif s'il existe */
+ GObject *creator; /* Créateur à l'orgine du seg. */
+ virt_t virt; /* Adresse virtuelle */
+ vmpa2t addr; /* Adresse de destination */
+ GBinFormat *format; /* Format du fichier binaire */
+ GBinSymbol *target_sym; /* Symbole présent à l'adresse */
+ GBinSymbol *next_sym; /* Symbole suivant l'adresse */
+ const vmpa2t *stop_addr; /* Adresse associée, pour fin */
+ const mrange_t *lrange; /* Couverture d'une ligne */
+ size_t count; /* Nbre de lignes max à traiter*/
+ char *markup; /* Description à construire */
+ size_t i; /* Boucle de parcours */
+ size_t index; /* Indice d'une ligne imprimée */
+ char *text; /* Contenu à ajouter */
+
+ if (keyboard) return FALSE;
+
+ view = GTK_BUFFER_VIEW(widget);
+
+ /* Récupération de la destination pointée */
+
+ real_x = x;
+ real_y = y;
+ gtk_view_panel_compute_real_coord(GTK_VIEW_PANEL(view), &real_x, &real_y);
+
+
+ line = g_buffer_view_find_line_and_segment_at(view->buffer_view,
+ &real_x, real_y, NULL,
+ GTK_VIEW_PANEL(view)->display, &segment);
+
+ if (line == NULL || segment == NULL) goto no_tooltip;
+
+ creator = g_buffer_segment_get_creator(segment);
+ if (creator == NULL) goto no_tooltip;
+
+ /**
+ * On fait le pari de reposer uniquement sur des adresses virtuelles !
+ * A changer dans un futur ?
+ */
+
+ virt = VMPA_NO_VIRTUAL;
+
+ if (G_IS_TARGET_OPERAND(creator))
+ virt = g_target_operand_get_addr(G_TARGET_OPERAND(creator));
+
+ else if (G_IS_IMM_OPERAND(creator))
+ {
+ if (!g_imm_operand_to_virt_t(G_IMM_OPERAND(creator), &virt))
+ virt = VMPA_NO_VIRTUAL;
+ }
+
+ if (virt == VMPA_NO_VIRTUAL) goto no_tooltip;
+
+ init_vmpa(&addr, VMPA_NO_PHYSICAL, virt);
+
+ /* Construction du contenu textuel */
+
+ format = G_BIN_FORMAT(g_loaded_binary_get_format(GTK_VIEW_PANEL(view)->binary));
+
+ if (!g_binary_format_find_symbol_at(format, &addr, &target_sym))
+ goto no_tooltip;
+
+ g_object_unref(G_OBJECT(target_sym));
+
+ /* Construction du contenu textuel */
+
+ if (g_binary_format_find_next_symbol_at(format, &addr, &next_sym))
+ stop_addr = get_mrange_addr(g_binary_symbol_get_range(next_sym));
+
+ count = 4;
+
+ markup = NULL;
+
+ for (i = 0, line = g_buffer_view_find_line_by_addr(view->buffer_view, &addr, BLF_NONE, &index);
+ i < count && line != NULL;
+ i++, line = g_buffer_view_find_line_by_index(view->buffer_view, index + i))
+ {
+
+ /* Si on commence à marcher sur les plates-bandes du symbole suivant... */
+ if (next_sym != NULL)
+ {
+ lrange = g_buffer_line_get_range(line);
+
+ if (mrange_contains_addr(lrange, stop_addr))
+ break;
+
+ }
+
+ text = g_buffer_line_get_text(line, BLC_ASSEMBLY_HEAD, BLC_COUNT, true);
+
+ if (markup != NULL)
+ markup = stradd(markup, "\n");
+
+ if (text != NULL)
+ markup = stradd(markup, text);
+
+ free(text);
+
+ }
+
+ if (next_sym != NULL)
+ g_object_unref(G_OBJECT(next_sym));
+
+ if (markup == NULL) goto no_tooltip;
+ /* Impression finale */
+
+ gtk_tooltip_set_markup(tooltip, markup);
+ free(markup);
+
+ return TRUE;
+
+ no_tooltip:
+
+ return FALSE;
+
+}
/******************************************************************************