summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog29
-rw-r--r--src/arch/processor.c54
-rw-r--r--src/arch/processor.h8
-rw-r--r--src/glibext/gcodebuffer.c74
-rw-r--r--src/gtkext/graph/node.c2
-rw-r--r--src/gtkext/gtkbufferview-int.h1
-rw-r--r--src/gtkext/gtkbufferview.c186
-rw-r--r--src/gtkext/gtkbufferview.h3
-rw-r--r--src/gtkext/gtkgraphview.c173
-rw-r--r--src/gtkext/gtkviewpanel.c23
-rw-r--r--src/gui/status.c11
11 files changed, 454 insertions, 110 deletions
diff --git a/ChangeLog b/ChangeLog
index 652e345..4ace600 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,32 @@
+15-04-21 Cyrille Bagard <nocbos@gmail.com>
+
+ * src/arch/processor.c:
+ * src/arch/processor.h:
+ Provide the previous and next instructions from an internal list.
+
+ * src/glibext/gcodebuffer.c:
+ Begin to used fast indexes when dealing with view ranges. Always provide
+ an updated address when moving the caret with success. Fix a bug when
+ highlighting segments by providing a return value, as expected.
+
+ * src/gtkext/graph/node.c:
+ Update code.
+
+ * src/gtkext/gtkbufferview.c:
+ * src/gtkext/gtkbufferview.h:
+ * src/gtkext/gtkbufferview-int.h:
+ Handle focus changes properly. Notify when a limit has been reached when
+ navigating using the keyboard.
+
+ * src/gtkext/gtkgraphview.c:
+ Transmit the focus when a limit has been reached while using he keyboard.
+
+ * src/gtkext/gtkviewpanel.c:
+ Receive focus event. Hack the scrolling routine for encapsulated buffer views.
+
+ * src/gui/status.c:
+ Only reset the status bar if there is no current selected address.
+
15-04-17 Cyrille Bagard <nocbos@gmail.com>
* src/gtkext/gtkviewpanel.c:
diff --git a/src/arch/processor.c b/src/arch/processor.c
index c2d190b..25a38b4 100644
--- a/src/arch/processor.c
+++ b/src/arch/processor.c
@@ -441,3 +441,57 @@ GArchInstruction *g_arch_processor_find_instr_by_address(const GArchProcessor *p
return result;
}
+
+
+/******************************************************************************
+* *
+* Paramètres : proc = processeur recensant diverses instructions. *
+* instr = instruction de référence pour un parcours. *
+* *
+* Description : Fournit l'instruction qui en précède une autre. *
+* *
+* Retour : Instruction précédente trouvée, ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GArchInstruction *g_arch_processor_get_prev_instr(const GArchProcessor *proc, const GArchInstruction *instr)
+{
+ GArchInstruction *result; /* Instruction à retourner */
+ GArchInstruction *list; /* Ensemble des instructions */
+
+ list = g_arch_processor_get_disassembled_instructions(proc);
+
+ result = g_arch_instruction_get_prev_iter(list, instr);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : proc = processeur recensant diverses instructions. *
+* instr = instruction de référence pour un parcours. *
+* *
+* Description : Fournit l'instruction qui en suit une autre. *
+* *
+* Retour : Instruction suivante trouvée, ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GArchInstruction *g_arch_processor_get_next_instr(const GArchProcessor *proc, const GArchInstruction *instr)
+{
+ GArchInstruction *result; /* Instruction à retourner */
+ GArchInstruction *list; /* Ensemble des instructions */
+
+ list = g_arch_processor_get_disassembled_instructions(proc);
+
+ result = g_arch_instruction_get_next_iter(list, instr, ~0);
+
+ return result;
+
+}
diff --git a/src/arch/processor.h b/src/arch/processor.h
index 3eeefd5..d650266 100644
--- a/src/arch/processor.h
+++ b/src/arch/processor.h
@@ -87,11 +87,15 @@ void g_arch_processor_set_disassembled_instructions(GArchProcessor *, GArchInstr
/* Fournit les instructions désassemblées pour une architecture. */
GArchInstruction *g_arch_processor_get_disassembled_instructions(const GArchProcessor *);
-
-
/* Recherche une instruction d'après son adresse. */
GArchInstruction *g_arch_processor_find_instr_by_address(const GArchProcessor *, const vmpa2t *);
+/* Fournit l'instruction qui en précède une autre. */
+GArchInstruction *g_arch_processor_get_prev_instr(const GArchProcessor *, const GArchInstruction *);
+
+/* Fournit l'instruction qui en suit une autre. */
+GArchInstruction *g_arch_processor_get_next_instr(const GArchProcessor *, const GArchInstruction *);
+
#endif /* _ARCH_PROCESSOR_H */
diff --git a/src/glibext/gcodebuffer.c b/src/glibext/gcodebuffer.c
index 171ba09..a7e522c 100644
--- a/src/glibext/gcodebuffer.c
+++ b/src/glibext/gcodebuffer.c
@@ -146,6 +146,7 @@ struct _GBufferView
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 */
+ size_t last_index; /* Indice de la dernière ligne */
gint line_height; /* Hauteur maximale des lignes */
gint max_widths[BLC_COUNT]; /* Taille cachée des colonnes */
@@ -623,25 +624,6 @@ static size_t g_code_buffer_get_index_from_address(GCodeBuffer *buffer, const vm
return result;
-
-
-
-
-#if 0
- size_t result; /* Indice à retourner */
-
- result = _g_code_buffer_get_index_from_address(buffer, addr, first);
-
- /**
- * Par commodités, on évite certaines instructions en cas d'échec dans les
- * fonctions d'appels : la condition des boucles utilisant l'indice retourné (0)
- * fait son office directement !
- */
- if (result == buffer->used)
- result = 0;
-
- return result;
-#endif
}
@@ -1002,8 +984,8 @@ GBufferView *g_buffer_view_new(GCodeBuffer *buffer)
g_object_ref(G_OBJECT(buffer));
result->buffer = buffer;
- result->start = NULL;
- result->end = NULL;
+
+ g_buffer_view_restrict(result, NULL, NULL);
return result;
@@ -1026,8 +1008,11 @@ GBufferView *g_buffer_view_new(GCodeBuffer *buffer)
void g_buffer_view_restrict(GBufferView *view, const vmpa2t *start, const vmpa2t *end)
{
- view->start = dup_vmpa(start);
- view->end = dup_vmpa(end);
+ view->start = (start != NULL ? dup_vmpa(start) : NULL);
+ view->end = (end != NULL ? dup_vmpa(end) : NULL);
+
+ 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);
}
@@ -1048,6 +1033,8 @@ void g_buffer_view_restrict(GBufferView *view, const vmpa2t *start, const vmpa2t
void g_buffer_view_get_restrictions(GBufferView *view, vmpa2t *start, vmpa2t *end)
{
+ /* FIXME view->xxx == NULL -> plantage */
+
if (start != NULL) copy_vmpa(start, view->start);
if (end != NULL) copy_vmpa(end, view->end);
@@ -1447,7 +1434,6 @@ const vmpa2t *g_buffer_view_compute_caret_full(GBufferView *view, GBufferLine *l
gint offset; /* Point de travail modifiable */
gint base; /* Position absolue de segment */
GBufferSegment *segment; /* Segment visé par le pointeur*/
- size_t first; /* Première ligne intégrée */
offset = x;
@@ -1459,8 +1445,9 @@ const vmpa2t *g_buffer_view_compute_caret_full(GBufferView *view, GBufferLine *l
caret->x = view->left_text + base + offset;
- first = g_code_buffer_get_index_from_address(view->buffer, view->start, true);
- caret->y = (index - first) * view->line_height;
+ printf("caret Y : %zu -> %zu\n", view->first_index, index);
+
+ caret->y = (index - view->first_index) * view->line_height;
caret->width = 2;
caret->height = view->line_height;
@@ -1588,7 +1575,8 @@ static bool _g_buffer_view_move_caret(GBufferView *view, const GBufferLine *line
const vmpa2t *g_buffer_view_move_caret(GBufferView *view, GdkRectangle *caret, bool ctrl, GdkScrollDirection dir, const bool *display)
{
- vmpa2t *result; /* Actualisation à renvoyer */
+ const vmpa2t *result; /* Actualisation à renvoyer */
+ size_t index; /* Indice de ligne de tampon */
GBufferLine *line; /* Ligne sous le pointeur */
@@ -1600,7 +1588,7 @@ const vmpa2t *g_buffer_view_move_caret(GBufferView *view, GdkRectangle *caret, b
size_t first; /* Première ligne intégrée */
size_t last; /* Dernière ligne intégrée */
- size_t index; /* Indice de ligne de tampon */
+
bool moved; /* Mémorisation d'une évolut° */
@@ -1652,10 +1640,8 @@ const vmpa2t *g_buffer_view_move_caret(GBufferView *view, GdkRectangle *caret, b
break;
}
- 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);
-
- first = 0;
+ first = view->first_index;
+ last = view->last_index;
switch (dir)
{
@@ -1681,12 +1667,17 @@ const vmpa2t *g_buffer_view_move_caret(GBufferView *view, GdkRectangle *caret, b
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 && index > first)
+ 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);
@@ -1696,12 +1687,17 @@ const vmpa2t *g_buffer_view_move_caret(GBufferView *view, GdkRectangle *caret, b
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 (!moved && index < last)
+ if (moved)
+ result = get_mrange_addr(g_buffer_line_get_range(line));
+
+ 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);
@@ -1787,6 +1783,8 @@ bool g_buffer_view_highlight_segments(GBufferView *view, gint x, gint y, const b
if (need_redraw)
g_signal_emit_by_name(view, "need-redraw");
+ return true;
+
}
@@ -1813,7 +1811,6 @@ void g_buffer_view_draw(const GBufferView *view, cairo_t *cr, gint fake_x, gint
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 end; /* Dernière ligne avant limite */
size_t last; /* Dernière ligne visée + 1 */
gint y; /* Point de départ + décallage */
GBufferLine **lines; /* Liste des lignes à traiter */
@@ -1824,14 +1821,13 @@ void g_buffer_view_draw(const GBufferView *view, cairo_t *cr, gint fake_x, gint
real_x = fake_x + view->left_text;
real_y = fake_y + area->y;
- first = g_code_buffer_get_index_from_address(view->buffer, view->start, true);
+ 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++;
- end = g_code_buffer_get_index_from_address(view->buffer, view->end, false);
- last = MIN(last, end);
+ last = MIN(last, view->last_index);
y = area->y - (real_y % view->line_height);
@@ -1960,6 +1956,8 @@ GBufferLine *g_buffer_view_find_line_at(GBufferView *view, gint y, size_t *idx)
lheight = g_buffer_view_get_line_height(view);
index = y / lheight;
+ index += view->first_index;
+
if (idx != NULL)
*idx = index;
diff --git a/src/gtkext/graph/node.c b/src/gtkext/graph/node.c
index 4fd7a8e..9ff66b3 100644
--- a/src/gtkext/graph/node.c
+++ b/src/gtkext/graph/node.c
@@ -507,7 +507,7 @@ GtkBufferView *find_graph_view_by_start_address(GtkBufferView **views, size_t co
for (i = 0; i < count && result == NULL; i++)
{
- buffer = gtk_buffer_view_get_buffer(GTK_BUFFER_VIEW(views[i]));
+ buffer = gtk_buffer_view_get_buffer(views[i]);
g_buffer_view_get_restrictions(buffer, &start, NULL);
if (cmp_vmpa(&start, addr) == 0)
diff --git a/src/gtkext/gtkbufferview-int.h b/src/gtkext/gtkbufferview-int.h
index e8e11a0..105d32b 100644
--- a/src/gtkext/gtkbufferview-int.h
+++ b/src/gtkext/gtkbufferview-int.h
@@ -65,6 +65,7 @@ struct _GtkBufferViewClass
/* Signaux */
void (* caret_moved) (GtkBufferView *, const vmpa2t *);
+ void (* reach_limit) (GtkBufferView *, GdkScrollDirection);
};
diff --git a/src/gtkext/gtkbufferview.c b/src/gtkext/gtkbufferview.c
index 1a1f6f1..54c521e 100644
--- a/src/gtkext/gtkbufferview.c
+++ b/src/gtkext/gtkbufferview.c
@@ -48,7 +48,7 @@ static void gtk_buffer_view_dispose(GtkBufferView *);
static void gtk_buffer_view_finalize(GtkBufferView *);
/* Intègre le focus dans le rendu du composant. */
-static gboolean gtk_buffer_view_focus(GtkWidget *, GtkDirectionType);
+static gboolean gtk_buffer_view_focus(GtkWidget *, GdkEventFocus *);
/* Assure la gestion des clics de souris sur le composant. */
static gboolean gtk_buffer_view_button_press(GtkWidget *, GdkEventButton *);
@@ -82,6 +82,9 @@ static void gtk_buffer_view_cache_glance(GtkBufferView *, cairo_t *, const GtkAl
/* ------------------------------ ANIMATION DU CURSEUR ------------------------------ */
+/* Déplace le curseur à un emplacement défini. */
+static bool _gtk_buffer_view_move_caret_to(GtkBufferView *, gint, gint);
+
/* Déplace le curseur en effaçant son éventuelle position. */
static void gtk_buffer_view_relocate_caret(GtkBufferView *, const GdkRectangle *, const vmpa2t *);
@@ -127,7 +130,8 @@ static void gtk_buffer_view_class_init(GtkBufferViewClass *class)
object->dispose = (GObjectFinalizeFunc/* ! */)gtk_buffer_view_dispose;
object->finalize = (GObjectFinalizeFunc)gtk_buffer_view_finalize;
- widget_class->focus = gtk_buffer_view_focus;
+ widget_class->focus_in_event = gtk_buffer_view_focus;
+ widget_class->focus_out_event = gtk_buffer_view_focus;
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;
@@ -147,6 +151,14 @@ static void gtk_buffer_view_class_init(GtkBufferViewClass *class)
g_cclosure_user_marshal_VOID__UINT64,
G_TYPE_NONE, 1, G_TYPE_UINT64);
+ g_signal_new("reach-limit",
+ GTK_TYPE_BUFFER_VIEW,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(GtkBufferViewClass, reach_limit),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__ENUM,
+ G_TYPE_NONE, 1, GTK_TYPE_SCROLL_TYPE);
+
}
@@ -213,7 +225,7 @@ static void gtk_buffer_view_finalize(GtkBufferView *view)
/******************************************************************************
* *
* Paramètres : widget = composant GTK visé par l'opération. *
-* dir = sens de l'opération : perte ou gain de focus. *
+* event = informations liées à l'événement. *
* *
* Description : Intègre le focus dans le rendu du composant. *
* *
@@ -223,13 +235,13 @@ static void gtk_buffer_view_finalize(GtkBufferView *view)
* *
******************************************************************************/
-static gboolean gtk_buffer_view_focus(GtkWidget *widget, GtkDirectionType direction)
+static gboolean gtk_buffer_view_focus(GtkWidget *widget, GdkEventFocus *event)
{
GtkBufferView *view; /* Autre version du composant */
gboolean has_focus; /* Etat courant */
view = GTK_BUFFER_VIEW(widget);
- has_focus = gtk_widget_is_focus(widget);
+ has_focus = event->in;
if (has_focus)
restart_caret_blinking(view);
@@ -265,16 +277,11 @@ static gboolean gtk_buffer_view_focus(GtkWidget *widget, GtkDirectionType direct
static gboolean gtk_buffer_view_button_press(GtkWidget *widget, GdkEventButton *event)
{
GtkBufferView *view; /* Autre version du composant */
- GtkViewPanel *pview; /* Autre version du composant */
gint real_x; /* Abscisse absolue réelle */
gint real_y; /* Ordonnée absolue réelle */
- size_t index; /* Indice de ligne de tampon */
GBufferLine *line; /* Ligne à la position courante*/
- const vmpa2t *addr; /* Position mémoire associée */
- GdkRectangle new; /* Nouvel emplacement calculé */
view = GTK_BUFFER_VIEW(widget);
- pview = GTK_VIEW_PANEL(widget);
gtk_widget_grab_focus(widget);
@@ -287,32 +294,17 @@ static gboolean gtk_buffer_view_button_press(GtkWidget *widget, GdkEventButton *
real_x, real_y);
-
- line = g_buffer_view_find_line_at(view->buffer_view, real_y, &index);
- if (line == NULL) return FALSE;
-
-
-
- printf(" [init ] %p - line = %p (y=%d)\n", view->buffer_view, line, real_y);
-
-
-
if (real_x < view->left_margin)
{
+ line = g_buffer_view_find_line_at(view->buffer_view, real_y, NULL);
+ if (line == NULL) return FALSE;
-
-
+ /* TODO */
printf("Border Line :: %p\n", line);
-
}
else
- {
- //addr = g_buffer_view_compute_caret_old(view->buffer_view, line, index, real_x, pview->display, &new);
- //addr = g_buffer_view_compute_caret(view->buffer_view, real_x, real_y, pview->display, &new);
- addr = g_buffer_view_compute_caret_full(view->buffer_view, line, index, real_x, pview->display, &new);
- gtk_buffer_view_relocate_caret(view, &new, addr);
- }
+ _gtk_buffer_view_move_caret_to(view, real_x, real_y);
return FALSE;
@@ -472,77 +464,67 @@ static gboolean gtk_buffer_view_draw(GtkWidget *widget, cairo_t *cr)
static gboolean gtk_buffer_view_key_press(GtkWidget *widget, GdkEventKey *event)
{
gboolean result; /* Suites à renvoyer */
-
GtkBufferView *view; /* Autre version du composant */
GtkViewPanel *pview; /* Autre version du composant */
-
-
bool ctrl; /* Statut de la touche Contrôle*/
-
-
- GdkRectangle area;
-
- const vmpa2t *addr;
-
+ GdkScrollDirection dir; /* Direction du déplacement */
+ GdkRectangle area; /* Emplacement de curseur */
+ const vmpa2t *addr; /* Adresse du nouveau curseur */
result = FALSE;
-
-
view = GTK_BUFFER_VIEW(widget);
pview = GTK_VIEW_PANEL(widget);
-
- area = view->caret;
-
-
- ctrl = (event->state & GDK_CONTROL_MASK);
-
switch (event->keyval)
{
case GDK_KEY_Left:
- printf("LEFT\n");
- addr = g_buffer_view_move_caret(view->buffer_view, &area, ctrl, GDK_SCROLL_LEFT, pview->display);
- gtk_buffer_view_relocate_caret(view, &area, view->caret_addr);
+ dir = GDK_SCROLL_LEFT;
result = TRUE;
break;
case GDK_KEY_Up:
- printf("UP\n");
- addr = g_buffer_view_move_caret(view->buffer_view, &area, ctrl, GDK_SCROLL_UP, pview->display);
- gtk_buffer_view_relocate_caret(view, &area, view->caret_addr);
+ dir = GDK_SCROLL_UP;
result = TRUE;
break;
case GDK_KEY_Right:
- printf("RIGHT\n");
- addr = g_buffer_view_move_caret(view->buffer_view, &area, ctrl, GDK_SCROLL_RIGHT, pview->display);
- gtk_buffer_view_relocate_caret(view, &area, view->caret_addr);
+ dir = GDK_SCROLL_RIGHT;
result = TRUE;
break;
case GDK_KEY_Down:
- printf("DOWN\n");
- addr = g_buffer_view_move_caret(view->buffer_view, &area, ctrl, GDK_SCROLL_DOWN, pview->display);
- gtk_buffer_view_relocate_caret(view, &area, view->caret_addr);
+ dir = GDK_SCROLL_DOWN;
result = TRUE;
break;
default:
- addr = NULL;
break;
}
+ if (result)
+ {
+ area = view->caret;
+ ctrl = (event->state & GDK_CONTROL_MASK);
+
+ addr = g_buffer_view_move_caret(view->buffer_view, &area, ctrl, dir, pview->display);
+
+ if (addr != NULL)
+ {
+ gtk_buffer_view_relocate_caret(view, &area, addr);
+ gtk_view_panel_scroll_to_address(pview, addr, SPT_RAW);
+ }
+ else
+ g_signal_emit_by_name(view, "reach-limit", dir);
- printf("ctrl ? %d -- keyval = %d -->> %d\n", ctrl, event->keyval, result);
- if (addr != NULL) gtk_view_panel_scroll_to_address(pview, addr, SPT_RAW);
+ //if (addr == NULL) return FALSE;
- printf("\n");
+ }
return result;
@@ -815,6 +797,8 @@ void gtk_buffer_view_attach_buffer(GtkBufferView *view, GBufferView *buffer)
GBufferView *gtk_buffer_view_get_buffer(const GtkBufferView *view)
{
+ /* TODO : ref... */
+
return view->buffer_view;
}
@@ -862,6 +846,84 @@ void gtk_buffer_view_compute_relative_coords(GtkBufferView *view, gint *x, gint
/******************************************************************************
* *
* Paramètres : view = composant GTK à manipuler. *
+* x = abscisse proposée pour le nouvel emplacement. *
+* y = ordonnée proposée pour le nouvel emplacement. *
+* *
+* Description : Déplace le curseur à un emplacement défini. *
+* *
+* Retour : true si un traitement a été effectué, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool _gtk_buffer_view_move_caret_to(GtkBufferView *view, gint x, gint y)
+{
+ size_t index; /* Indice de ligne de tampon */
+ GBufferLine *line; /* Ligne à la position courante*/
+ GtkViewPanel *pview; /* Autre version du composant */
+ const vmpa2t *addr; /* Position mémoire associée */
+ GdkRectangle new; /* Nouvel emplacement calculé */
+
+ if (x < view->left_margin) return false;
+
+ line = g_buffer_view_find_line_at(view->buffer_view, y, &index);
+ if (line == NULL) return false;
+
+ pview = GTK_VIEW_PANEL(view);
+
+ addr = g_buffer_view_compute_caret_full(view->buffer_view, line, index, x, pview->display, &new);
+
+ if (addr != NULL)
+ gtk_buffer_view_relocate_caret(view, &new, addr);
+
+ return (addr != NULL);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : view = composant GTK à manipuler. *
+* beginning = précise le coin où se retrouvera le curseur. *
+* same_x = tente de conserver une même abscisse ou NULL ? *
+* *
+* Description : Déplace le curseur à un emplacement en extrémité. *
+* *
+* Retour : true si un traitement a été effectué, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool gtk_buffer_view_move_caret_to(GtkBufferView *view, bool beginning, gint *same_x)
+{
+ bool result; /* Bilan à remonter */
+ gint x; /* Abscisse d'emplacement */
+ gint y; /* Ordonnée d'emplacement */
+
+ if (beginning)
+ {
+ x = same_x != NULL ? *same_x : view->left_margin * 2;
+ y = 0;
+ }
+ else
+ {
+ if (same_x != NULL) x = *same_x;
+ gtk_buffer_view_compute_requested_size(view, same_x != NULL ? NULL : &x, &y);
+ y--;
+ }
+
+ result = _gtk_buffer_view_move_caret_to(view, x, y);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : view = composant GTK à manipuler. *
* area = emplacement pour le dessin d'un curseur. *
* addr = position dans la mémoire représentée du curseur. *
* *
diff --git a/src/gtkext/gtkbufferview.h b/src/gtkext/gtkbufferview.h
index 0cdcf4f..ed26fd5 100644
--- a/src/gtkext/gtkbufferview.h
+++ b/src/gtkext/gtkbufferview.h
@@ -70,6 +70,9 @@ void gtk_buffer_view_compute_relative_coords(GtkBufferView *, gint *, gint *);
/* ------------------------------ ANIMATION DU CURSEUR ------------------------------ */
+/* Déplace le curseur à un emplacement en extrémité. */
+bool gtk_buffer_view_move_caret_to(GtkBufferView *, bool, gint *);
+
/* Indique la position courante du curseur. */
const vmpa2t *gtk_buffer_view_get_caret_location(const GtkBufferView *);
diff --git a/src/gtkext/gtkgraphview.c b/src/gtkext/gtkgraphview.c
index 875c1b4..6d7ab0d 100644
--- a/src/gtkext/gtkgraphview.c
+++ b/src/gtkext/gtkgraphview.c
@@ -24,6 +24,9 @@
#include "gtkgraphview.h"
+#include <assert.h>
+
+
#include "gtkblockview.h"
#include "gtkbufferview.h"
#include "gtkviewpanel-int.h"
@@ -43,7 +46,7 @@ struct _GtkGraphView
vmpa_t start; /* Début de la portion vue */ /* FIXME : à garder ? */
vmpa_t end; /* Fin de la portion affichée */ /* FIXME : à garder ? */
- GtkViewPanel **children; /* Liste des sous-blocs */
+ GtkBufferView **children; /* Liste des sous-blocs */
GtkAllocation *allocs; /* Emplacements prévisibles */
size_t children_count; /* Taille de cette liste */
@@ -93,10 +96,11 @@ static void gtk_graph_view_cache_glance(GtkGraphView *, cairo_t *, const GtkAllo
/* Supprime tout contenu de l'afficheur de code en graphique. */
static void gtk_graph_view_reset(GtkGraphView *);
-/* Définit la liste complète des éléments du futur graphique. *
-* *
-* Retour : Liste d'éléments du graphique à placer. */
-static GtkViewPanel **gtk_graph_view_load_nodes(GtkGraphView *, GLoadedBinary *, const GBinRoutine *);
+/* Définit la liste complète des éléments du futur graphique. */
+static GtkBufferView **gtk_graph_view_load_nodes(GtkGraphView *, GLoadedBinary *, const GBinRoutine *);
+
+/* Notifie une incapacité de déplacement au sein d'un noeud. */
+static void gtk_graph_view_reach_caret_limit(GtkBufferView *, GdkScrollDirection, GtkGraphView *);
@@ -423,7 +427,7 @@ static void gtk_graph_view_cache_glance(GtkGraphView *view, cairo_t *cairo, cons
sub_area.width = view->allocs[i].width * scale + 1;
sub_area.height = view->allocs[i].height * scale + 1;
- gtk_view_panel_cache_glance(view->children[i], cairo, &sub_area, scale);
+ gtk_view_panel_cache_glance(GTK_VIEW_PANEL(view->children[i]), cairo, &sub_area, scale);
}
@@ -554,7 +558,10 @@ static void gtk_graph_view_reset(GtkGraphView *view)
*/
for (i = 0; i < view->children_count; i++)
+ {
+ g_signal_handlers_disconnect_by_func(view->children[i], gtk_graph_view_reach_caret_limit, view);
gtk_widget_destroy(GTK_WIDGET(view->children[i]));
+ }
if (view->children_count > 0)
{
@@ -583,7 +590,7 @@ static void gtk_graph_view_reset(GtkGraphView *view)
* *
******************************************************************************/
-static GtkViewPanel **gtk_graph_view_load_nodes(GtkGraphView *view, GLoadedBinary *binary, const GBinRoutine *routine)
+static GtkBufferView **gtk_graph_view_load_nodes(GtkGraphView *view, GLoadedBinary *binary, const GBinRoutine *routine)
{
GtkViewPanel **result; /* Liste à retourner */
GCodeBuffer *buffer; /* Tampon brut à découper */
@@ -610,6 +617,8 @@ static GtkViewPanel **gtk_graph_view_load_nodes(GtkGraphView *view, GLoadedBinar
for (i = 0; i < *count; i++)
{
result[i] = GTK_VIEW_PANEL(gtk_block_view_new());
+ g_signal_connect(result[i], "reach-limit", G_CALLBACK(gtk_graph_view_reach_caret_limit), view);
+
gtk_widget_show(GTK_WIDGET(result[i]));
gtk_view_panel_attach_binary(result[i], binary, BVW_BLOCK);
@@ -626,3 +635,153 @@ static GtkViewPanel **gtk_graph_view_load_nodes(GtkGraphView *view, GLoadedBinar
return result;
}
+
+
+/******************************************************************************
+* *
+* Paramètres : node = composant d'affichage GTK impliqué dans la procédure. *
+* dir = direction du déplacement souhaité et impossible. *
+* view = support graphique de tous les noeuds. *
+* *
+* Description : Notifie une incapacité de déplacement au sein d'un noeud. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_graph_view_reach_caret_limit(GtkBufferView *node, GdkScrollDirection dir, GtkGraphView *view)
+{
+ GBufferView *bview; /* Vue d'un tampon global */
+ vmpa2t first; /* Début d'un groupe de lignes */
+ vmpa2t last; /* Fin d'un groupe de lignes */
+ const mrange_t *range; /* Couverture courante */
+ GArchProcessor *proc; /* Processeur pour instructions*/
+ GArchInstruction *ref; /* Point de référence */
+#ifndef NDEBUG
+ bool is_return; /* Est-ce une instruc. finale ?*/
+#endif
+ vmpa2t iaddr; /* Position de l'instructin */
+ size_t i; /* Boucle de parcours */
+ bool updated; /* Besoin d'une mise à jour ? */
+
+ /* Détermination de l'instruction à cibler */
+
+ bview = gtk_buffer_view_get_buffer(node);
+ g_buffer_view_get_restrictions(bview, &first, &last);
+
+ range = g_binary_routine_get_range(view->routine);
+
+ proc = g_loaded_binary_get_processor(GTK_VIEW_PANEL(view)->binary);
+
+ ref = NULL;
+
+#ifndef NDEBUG
+ is_return = false;
+#endif
+
+ switch (dir)
+ {
+ case GDK_SCROLL_LEFT:
+ case GDK_SCROLL_UP:
+ if (cmp_vmpa(get_mrange_addr(range), &first) != 0)
+ {
+ ref = g_arch_processor_find_instr_by_address(proc, &first);
+
+ if (ref != NULL)
+ ref = g_arch_processor_get_prev_instr(proc, ref);
+
+ /* TODO : boucler si !HAS_CODE */
+
+ if (ref != NULL)
+ copy_vmpa(&iaddr, get_mrange_addr(g_arch_instruction_get_range(ref)));
+
+ }
+ break;
+
+ case GDK_SCROLL_RIGHT:
+ case GDK_SCROLL_DOWN:
+
+ ref = g_arch_processor_find_instr_by_address(proc, &last);
+
+#ifndef NDEBUG
+ if (ref != NULL)
+ is_return = g_arch_instruction_is_return(ref);
+#endif
+
+ if (ref != NULL)
+ ref = g_arch_processor_get_next_instr(proc, ref);
+
+ /* TODO : boucler si !HAS_CODE */
+
+ if (ref != NULL)
+ {
+ copy_vmpa(&iaddr, get_mrange_addr(g_arch_instruction_get_range(ref)));
+
+ if (!mrange_contains_addr(range, &iaddr))
+ ref = NULL;
+
+ }
+
+ break;
+
+ }
+
+ g_object_unref(G_OBJECT(proc));
+
+ /* Recherche du bloc parent */
+
+ if (ref == NULL)
+ return;
+
+ for (i = 0; i < view->children_count; i++)
+ {
+ bview = gtk_buffer_view_get_buffer(view->children[i]);
+ g_buffer_view_get_restrictions(bview, &first, &last);
+
+ if (cmp_vmpa(&first, &iaddr) <= 0 && cmp_vmpa(&iaddr, &last) <= 0)
+ {
+ assert(node != view->children[i]);
+ break;
+ }
+
+ }
+
+ assert(i < view->children_count || is_return);
+
+ /* Affichage du nouveau curseur */
+
+ /**
+ * Il se peut qu'aucune adresse suivante ne soit disponible : c'est typiquement
+ * le cas sous ARM, avec les valeurs brutes référencées dans le code. Ces valeurs
+ * sont incluses dans la surface couverte par la routine concernée, mais ne sont
+ * pas intégrées dans les blocs basiques associés.
+ */
+
+ if (i == view->children_count)
+ return;
+
+ gtk_widget_grab_focus(GTK_WIDGET(view->children[i]));
+
+ switch (dir)
+ {
+ case GDK_SCROLL_LEFT:
+ updated = gtk_buffer_view_move_caret_to(view->children[i], false, NULL);
+ break;
+
+ case GDK_SCROLL_UP:
+ break;
+
+ case GDK_SCROLL_RIGHT:
+ updated = gtk_buffer_view_move_caret_to(view->children[i], true, NULL);
+ break;
+
+ case GDK_SCROLL_DOWN:
+ break;
+
+ }
+
+ /* TODO : scrolling... */
+
+}
diff --git a/src/gtkext/gtkviewpanel.c b/src/gtkext/gtkviewpanel.c
index 7f29574..e36da71 100644
--- a/src/gtkext/gtkviewpanel.c
+++ b/src/gtkext/gtkviewpanel.c
@@ -297,6 +297,7 @@ static void gtk_view_panel_realize(GtkWidget *widget)
attributes.event_mask = gtk_widget_get_events(widget)
| GDK_EXPOSURE_MASK
| GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK
+ | GDK_FOCUS_CHANGE_MASK
| GDK_SCROLL_MASK | GDK_SMOOTH_SCROLL_MASK;
attributes_mask = GDK_WA_X | GDK_WA_Y;
@@ -792,6 +793,8 @@ static void on_view_panel_binary_display_change(GLoadedBinary *binary, BinaryVie
GLoadedBinary *gtk_view_panel_get_binary(const GtkViewPanel *panel)
{
+ /* TODO : ref */
+
return panel->binary;
}
@@ -836,6 +839,7 @@ bool gtk_view_panel_contain_address(const GtkViewPanel *panel, vmpa_t addr)
void gtk_view_panel_scroll_to_address(GtkViewPanel *panel, const vmpa2t *addr, ScrollPositionTweak tweak)
{
+ GtkWidget *parent; /* Support parent à valider */
gint x; /* Abscisse à garantir */
gint y; /* Ordonnée à garantir */
GtkWidget *viewport; /* Parent avec défilement */
@@ -844,6 +848,25 @@ void gtk_view_panel_scroll_to_address(GtkViewPanel *panel, const vmpa2t *addr, S
gdouble page_size; /* Taille de l'affichage */
double value; /* Valeur courante */
+ /**
+ * Si une vue partielle se déplacer via cette fonction, il faut potentiellement
+ * rediriger l'appel vers la vue en graphiques parente.
+ */
+
+ parent = gtk_widget_get_parent(GTK_WIDGET(panel));
+ parent = gtk_widget_get_parent(GTK_WIDGET(parent));
+
+ printf(" Widgets : %s -> %s\n",
+ G_OBJECT_TYPE_NAME(parent), G_OBJECT_TYPE_NAME(panel));
+
+ if (GTK_IS_VIEW_PANEL(parent))
+ {
+ printf("reparent !\n");
+ panel = GTK_VIEW_PANEL(parent);
+ }
+ else
+ printf("no need reparent !\n");
+
if (GTK_VIEW_PANEL_GET_CLASS(panel)->define != NULL)
GTK_VIEW_PANEL_GET_CLASS(panel)->define(panel, addr);
diff --git a/src/gui/status.c b/src/gui/status.c
index 07e8254..2637f28 100644
--- a/src/gui/status.c
+++ b/src/gui/status.c
@@ -288,6 +288,17 @@ static void track_caret_address_on_buffer_views(GtkBufferView *view, const vmpa2
msize = g_arch_processor_get_memory_size(proc);
g_object_unref(G_OBJECT(proc));
+ /* Réinitiation seule si il n'y a plus d'adresse... */
+
+ if (addr == NULL)
+ {
+ if (info->msg_id > 0)
+ gtk_extended_status_bar_remove(GTK_EXT_STATUS_BAR(item->widget), info->msg_id);
+
+ return;
+
+ }
+
/* Adresse brute */
msize = g_arch_processor_get_memory_size(proc);