From ea40f74566cd813722f49ae740ca3df04e522bb2 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Mon, 20 Apr 2015 23:09:13 +0000 Subject: Transmitted the focus when a limit has been reached while using he keyboard. git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@514 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a --- ChangeLog | 29 +++++++ src/arch/processor.c | 54 ++++++++++++ src/arch/processor.h | 8 +- src/glibext/gcodebuffer.c | 74 ++++++++-------- src/gtkext/graph/node.c | 2 +- src/gtkext/gtkbufferview-int.h | 1 + src/gtkext/gtkbufferview.c | 186 +++++++++++++++++++++++++++-------------- src/gtkext/gtkbufferview.h | 3 + src/gtkext/gtkgraphview.c | 173 ++++++++++++++++++++++++++++++++++++-- src/gtkext/gtkviewpanel.c | 23 +++++ src/gui/status.c | 11 +++ 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 + + * 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 * 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 + + #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); -- cgit v0.11.2-87-g4458