diff options
-rw-r--r-- | ChangeLog | 25 | ||||
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | src/arch/archbase.h | 4 | ||||
-rw-r--r-- | src/editor.c | 15 | ||||
-rw-r--r-- | src/glibext/gbufferline.c | 65 | ||||
-rw-r--r-- | src/glibext/gbufferline.h | 5 | ||||
-rw-r--r-- | src/glibext/gbuffersegment.c | 51 | ||||
-rw-r--r-- | src/glibext/gbuffersegment.h | 3 | ||||
-rw-r--r-- | src/glibext/gcodebuffer.c | 180 | ||||
-rw-r--r-- | src/glibext/gcodebuffer.h | 8 | ||||
-rw-r--r-- | src/gtkext/gtkbufferview-int.h | 9 | ||||
-rw-r--r-- | src/gtkext/gtkbufferview.c | 313 | ||||
-rw-r--r-- | src/gtkext/gtkextstatusbar.c | 12 | ||||
-rw-r--r-- | src/gtkext/gtkextstatusbar.h | 6 | ||||
-rw-r--r-- | src/gtkext/gtkviewpanel.c | 1 | ||||
-rw-r--r-- | src/gui/Makefile.am | 3 | ||||
-rw-r--r-- | src/gui/status.c | 266 | ||||
-rw-r--r-- | src/gui/status.h | 56 |
18 files changed, 988 insertions, 36 deletions
@@ -1,3 +1,28 @@ +13-06-02 Cyrille Bagard <nocbos@gmail.com> + + * configure.ac: + * src/arch/archbase.h: + * src/editor.c: + * src/glibext/gbufferline.c: + * src/glibext/gbufferline.h: + * src/glibext/gbuffersegment.c: + * src/glibext/gbuffersegment.h: + * src/glibext/gcodebuffer.c: + * src/glibext/gcodebuffer.h: + * src/gtkext/gtkbufferview.c: + * src/gtkext/gtkbufferview-int.h: + * src/gtkext/gtkextstatusbar.c: + * src/gtkext/gtkextstatusbar.h: + * src/gtkext/gtkviewpanel.c: + Save some progress about edition views. + + * src/gui/Makefile.am: + Add the 'status.[ch]' files to libgui_la_SOURCES. + + * src/gui/status.c: + * src/gui/status.h: + New entries: put the status bar in a better place. + 13-05-26 Cyrille Bagard <nocbos@gmail.com> * src/gtkext/graph/layout.c: diff --git a/configure.ac b/configure.ac index 51aa8e3..0ada63a 100644 --- a/configure.ac +++ b/configure.ac @@ -234,7 +234,7 @@ AC_SUBST(LIBGRAPH_LIBS) AC_CONFIG_FILES([stamp-h po/Makefile.in], [echo timestamp > stamp-h]) -AC_CONFIG_COMMANDS([marshal], [echo -e "VOID:UINT64,UINT64\nVOID:INT,UINT64,INT\nVOID:OBJECT\nVOID:OBJECT,OBJECT" > src/glibext/chrysamarshal.list]) +AC_CONFIG_COMMANDS([marshal], [echo -e "VOID:UINT64\nVOID:UINT64,UINT64\nVOID:INT,UINT64,INT\nVOID:OBJECT\nVOID:OBJECT,OBJECT" > src/glibext/chrysamarshal.list]) AC_CONFIG_FILES([Makefile pixmaps/Makefile diff --git a/src/arch/archbase.h b/src/arch/archbase.h index ee12674..1169c16 100644 --- a/src/arch/archbase.h +++ b/src/arch/archbase.h @@ -38,6 +38,10 @@ typedef uint64_t vmpa_t; #define VMPA_MAX 0xffffffffffffffffull +#define VMPA_INVALID 0xffffffffffffffffull + +#define VMPA_FMT "0x%llx" +#define VMPA_FMT_LONG "0x%08llx" #define VMPA_MAX_SIZE 19 diff --git a/src/editor.c b/src/editor.c index c533a64..6386858 100644 --- a/src/editor.c +++ b/src/editor.c @@ -31,8 +31,8 @@ #include "project.h" #include "gtkext/easygtk.h" #include "gtkext/gtkdockstation.h" -#include "gtkext/gtkextstatusbar.h" #include "gtkext/support.h" +#include "gui/status.h" #include "gui/menus/menubar.h" #include "gui/panels/panel.h" #include "gui/tb/source.h" @@ -137,13 +137,13 @@ GtkWidget *create_editor(void) GtkWidget *toolbar; /* Barre d'outils */ GtkWidget *vbox1; - GtkWidget *statusbar; + GtkAccelGroup *accgroup; + GtkWidget *widget; /* Composant à intégrer */ - GtkAccelGroup *accgroup; @@ -206,12 +206,13 @@ GtkWidget *create_editor(void) - statusbar = gtk_extended_status_bar_new(); - g_object_set_data(ref, "statusbar", statusbar); + /* Barre de statut générale */ - gtk_widget_show(statusbar); + editem = g_status_info_new(ref); + register_editor_item(editem); - gtk_box_pack_start(GTK_BOX(vbox1), statusbar, FALSE, FALSE, 0); + widget = g_editor_item_get_widget(editem); + gtk_box_pack_start(GTK_BOX(vbox1), widget, FALSE, FALSE, 0); diff --git a/src/glibext/gbufferline.c b/src/glibext/gbufferline.c index 95d6126..18f8a2a 100644 --- a/src/glibext/gbufferline.c +++ b/src/glibext/gbufferline.c @@ -61,7 +61,7 @@ static gint get_column_width(buffer_line_column *); static void add_segment_to_column(buffer_line_column *, GBufferSegment *); /* Donne le segment d'une colonne présent à une abscisse donnée. */ -static GBufferSegment *get_segment_at(const buffer_line_column *, gint); +static GBufferSegment *get_segment_at(const buffer_line_column *, gint *, bool); /* Met en surbrillance des segments similaires. */ GSList *highlight_all_same_segments(const buffer_line_column *, GSList *, const GBufferSegment *); @@ -194,7 +194,8 @@ static void add_segment_to_column(buffer_line_column *column, GBufferSegment *se /****************************************************************************** * * * Paramètres : column = colonne de ligne de texte à consulter. * -* x = position de recherche à ajuster. * +* x = position de recherche à ajuster. [OUT] * +* force = accepte les segments en bordure au pire. * * * * Description : Donne le segment d'une colonne présent à une abscisse donnée.* * * @@ -204,7 +205,7 @@ static void add_segment_to_column(buffer_line_column *column, GBufferSegment *se * * ******************************************************************************/ -static GBufferSegment *get_segment_at(const buffer_line_column *column, gint x) +static GBufferSegment *get_segment_at(const buffer_line_column *column, gint *x, bool force) { GBufferSegment *result; /* Trouvaille à retourner */ size_t i; /* Boucle de parcours */ @@ -216,11 +217,11 @@ static GBufferSegment *get_segment_at(const buffer_line_column *column, gint x) { width = g_buffer_segment_get_width(column->segments[i]); - if (width <= x) - x -= width; + if (width > *x || ((i + 1) == column->count && force)) + result = column->segments[i]; else - result = column->segments[i]; + *x -= width; } @@ -552,7 +553,8 @@ void g_buffer_line_add_segment(GBufferLine *line, BufferLineColumn index, GBuffe * * * Paramètres : line = ligne à venir consulter. * * max_widths = largeurs de colonne à respecter. * -* x = position à la colonne visée par la procédure. * +* x = position à la colonne visée. [OUT] * +* force = accepte les segments en bordure au pire. * * * * Description : Donne le segment présent à une abscisse donnée. * * * @@ -562,7 +564,7 @@ void g_buffer_line_add_segment(GBufferLine *line, BufferLineColumn index, GBuffe * * ******************************************************************************/ -GBufferSegment *g_buffer_line_get_segment_at(const GBufferLine *line, const gint max_widths[BLC_COUNT], gint x) +GBufferSegment *g_buffer_line_get_segment_at(const GBufferLine *line, const gint max_widths[BLC_COUNT], gint *x, bool force) { GBufferSegment *result; /* Trouvaille à retourner */ BufferLineColumn i; /* Boucle de parcours */ @@ -570,11 +572,22 @@ GBufferSegment *g_buffer_line_get_segment_at(const GBufferLine *line, const gint result = NULL; for (i = BLC_ADDRESS; i < BLC_COUNT; i++) - if (x < max_widths[i]) break; - else x -= (max_widths[i] + COL_MARGIN); + { + /* FIXME : addr/code */ + + if (*x < max_widths[i]) break; + else *x -= (max_widths[i] + COL_MARGIN); + + } + + if (i == BLC_COUNT && force) + { + i = BLC_COUNT - 1; + *x += (max_widths[i] + COL_MARGIN); + } if (i < BLC_COUNT) - result = get_segment_at(&line->columns[i], x); + result = get_segment_at(&line->columns[i], x, force); return result; @@ -583,6 +596,36 @@ GBufferSegment *g_buffer_line_get_segment_at(const GBufferLine *line, const gint /****************************************************************************** * * +* Paramètres : line = ligne à venir consulter. * +* caret = position du curseur à faire évoluer. * +* ctrl = indique la demande d'un parcours rapide. * +* dir = direction du parcours. * +* addr = indique si les positions doivent être affichées. * +* code = indique si le code binaire doit être affiché. * +* * +* Description : Déplace le curseur au sein d'une vue de tampon. * +* * +* Retour : true si un déplacement a été effectué, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_buffer_line_move_caret(const GBufferLine *line, GdkRectangle *caret, bool ctrl, GdkScrollDirection dir, bool addr, bool code) +{ + + caret->x += (dir == GDK_SCROLL_RIGHT ? 10 : -10); + + return true; + + + return false; + +} + + +/****************************************************************************** +* * * Paramètres : line = ligne à venir consulter. * * list = liste de segments identiques à constituer. * * ref = segment de référence à comparer avec tous les autres. * diff --git a/src/glibext/gbufferline.h b/src/glibext/gbufferline.h index 6eb4e27..2a46b5a 100644 --- a/src/glibext/gbufferline.h +++ b/src/glibext/gbufferline.h @@ -129,8 +129,11 @@ vmpa_t g_buffer_line_get_address(const GBufferLine *); /* Ajoute un fragment de texte à une colonne de ligne. */ void g_buffer_line_add_segment(GBufferLine *, BufferLineColumn, GBufferSegment *) __attribute__ ((deprecated)); +/* Déplace le curseur au sein d'une vue de tampon. */ +bool g_buffer_line_move_caret(const GBufferLine *, GdkRectangle *, bool, GdkScrollDirection, bool, bool); + /* Donne le segment présent à une abscisse donnée. */ -GBufferSegment *g_buffer_line_get_segment_at(const GBufferLine *, const gint [BLC_COUNT], gint); +GBufferSegment *g_buffer_line_get_segment_at(const GBufferLine *, const gint [BLC_COUNT], gint *, bool); /* Met en surbrillance des segments similaires. */ GSList *g_buffer_line_highlight_all_same_segments(const GBufferLine *, GSList *, const GBufferSegment *); diff --git a/src/glibext/gbuffersegment.c b/src/glibext/gbuffersegment.c index 861c7cb..031075c 100644 --- a/src/glibext/gbuffersegment.c +++ b/src/glibext/gbuffersegment.c @@ -478,6 +478,57 @@ gint g_buffer_segment_get_width(const GBufferSegment *segment) /****************************************************************************** * * +* Paramètres : segment = fragment de texte à consulter. * +* x = position horizontale au niveau du segment. * +* * +* Description : Fournit la position idéale pour un marqueur. * +* * +* Retour : Position dans le segment donné. * +* * +* Remarques : - * +* * +******************************************************************************/ + +gint g_buffer_segment_get_caret_position(const GBufferSegment *segment, gint x) +{ + gint result; /* Position à retourner */ + gint width; /* Largeur du segment */ + gint char_width; /* Largeur de police fixe */ + + width = g_buffer_segment_get_width(segment); + + printf("(seg) x=%d width=%d\n", x, width); + + if (x <= 0) + result = 0; + + else if (x >= width) + result = width; + + else + { + if (strlen(segment->text) != segment->glyphs->num_glyphs) + { + + printf("STOP ::: %d vs %d\n", strlen(segment->text), segment->glyphs->num_glyphs); + exit(0); + } + + char_width = width / segment->glyphs->num_glyphs; + + result = (x / char_width) * char_width; + if ((x % char_width) > (char_width / 2)) + result += char_width; + + } + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : segment = fragment de texte à manipuler. * * * * Description : (Re)charge les couleurs à partir de la liste d'attributs. * diff --git a/src/glibext/gbuffersegment.h b/src/glibext/gbuffersegment.h index 96011bb..bc0d512 100644 --- a/src/glibext/gbuffersegment.h +++ b/src/glibext/gbuffersegment.h @@ -86,6 +86,9 @@ const char *g_buffer_segment_get_text(const GBufferSegment *); /* Fournit la quantité de pixels requise pour l'impression. */ gint g_buffer_segment_get_width(const GBufferSegment *); +/* Fournit la position idéale pour un marqueur. */ +gint g_buffer_segment_get_caret_position(const GBufferSegment *, gint); + /* (Re)charge les couleurs à partir de la liste d'attributs. */ void g_buffer_segment_cache_colors(GBufferSegment *); diff --git a/src/glibext/gcodebuffer.c b/src/glibext/gcodebuffer.c index e81966e..920b17c 100644 --- a/src/glibext/gcodebuffer.c +++ b/src/glibext/gcodebuffer.c @@ -123,7 +123,7 @@ static void g_code_buffer_class_init(GCodeBufferClass *); static void g_code_buffer_init(GCodeBuffer *); /* Convertit une adresse en indice de ligne. */ -static size_t _g_code_buffer_get_index_from_address(GCodeBuffer *, vmpa_t, bool); +static size_t _g_code_buffer_get_index_from_address(const GCodeBuffer *, vmpa_t, bool); /* Convertit une adresse en indice de ligne. */ static size_t g_code_buffer_get_index_from_address(GCodeBuffer *, vmpa_t, bool); @@ -411,7 +411,7 @@ GCodeBuffer *g_code_buffer_new(BufferLineColumn main) * * ******************************************************************************/ -static size_t _g_code_buffer_get_index_from_address(GCodeBuffer *buffer, vmpa_t addr, bool first) +static size_t _g_code_buffer_get_index_from_address(const GCodeBuffer *buffer, vmpa_t addr, bool first) { size_t result; /* Indice à retourner */ @@ -1053,6 +1053,172 @@ void g_buffer_view_get_size(GBufferView *view, gint *width, gint *height, bool a /****************************************************************************** * * +* Paramètres : view = vue de tampon à mettre à jour. * +* x = abscisse de la zone principale à traiter. * +* y = ordonnée de la zone principale à traiter. * +* caret = position du curseur à construire. [OUT] * +* * +* Description : Calcule la position idéale de curseur pour un point donné. * +* * +* Retour : Adresse si une a pu être déterminée, VMPA_INVALID sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +vmpa_t g_buffer_view_compute_caret(GBufferView *view, gint x, gint y, GdkRectangle *caret) +{ + size_t index; /* Indice de la ligne trouvée */ + GBufferLine *line; /* Ligne sous le pointeur */ + gint tmp_x; /* Copie de travail modifiable */ + GBufferSegment *segment; /* Segment visé par le pointeur*/ + size_t first; /* Première ligne intégrée */ + + line = g_buffer_view_find_line_at(view, y, &index); + if (line == NULL) return VMPA_INVALID; + + tmp_x = x; + + tmp_x -= view->left_text; + if (tmp_x < 0) return VMPA_INVALID; + + segment = g_buffer_line_get_segment_at(line, view->max_widths, &tmp_x, true); + if (segment == NULL) printf("no segment\n"); + if (segment == NULL) return VMPA_INVALID; + + caret->x = (x - tmp_x) + g_buffer_segment_get_caret_position(segment, tmp_x); + + first = g_code_buffer_get_index_from_address(view->buffer, view->start, true); + caret->y = (index - first) * view->line_height; + + caret->width = 2; + caret->height = view->line_height; + + return g_buffer_line_get_address(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. * +* addr = indique si les positions doivent être affichées. * +* code = indique si le code binaire doit être affiché. * +* * +* 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. * +* * +* Remarques : - * +* * +******************************************************************************/ + +vmpa_t g_buffer_view_move_caret(GBufferView *view, GdkRectangle *caret, bool ctrl, GdkScrollDirection dir, bool addr, bool code) +{ + bool result; /* Actualisation à renvoyer */ + bool computed; /* Récursivité pris en compte */ + gint lheight; /* Hauteur d'une ligne */ + gint left_pos; /* Retour à la ligne */ + gint right_pos; /* Position d'extrème droite */ + BufferLineColumn i; /* Boucle de parcours */ + size_t first; /* Première ligne intégrée */ + size_t last; /* Dernière ligne intégrée */ + GBufferLine *line; /* Ligne sous le pointeur */ + + result = VMPA_INVALID; + computed = false; + + switch (dir) + { + case GDK_SCROLL_UP: + case GDK_SCROLL_DOWN: + lheight = g_buffer_view_get_line_height(view); + break; + case GDK_SCROLL_LEFT: + case GDK_SCROLL_RIGHT: + left_pos = view->left_text; + if (addr) left_pos += view->max_widths[BLC_ADDRESS] + COL_MARGIN; + if (code) left_pos += view->max_widths[BLC_BINARY] + COL_MARGIN; + right_pos = left_pos; + for (i = BLC_ASSEMBLY_HEAD; i < BLC_COUNT; i++) + right_pos += view->max_widths[i] + COL_MARGIN; + 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); + + switch (dir) + { + case GDK_SCROLL_UP: + result = (caret->y >= (first * lheight)); + if (result) + caret->y -= lheight; + break; + + case GDK_SCROLL_DOWN: + result = ((caret->y + lheight) < (last * lheight)); + if (result) + caret->y += lheight; + break; + + case GDK_SCROLL_LEFT: + line = g_buffer_view_find_line_at(view, caret->y, NULL); + if (line == NULL) break; + + result = g_buffer_line_move_caret(line, caret, ctrl, GDK_SCROLL_LEFT, addr, code); + + if (caret->x < left_pos) + { + caret->x = right_pos; + + result = g_buffer_view_move_caret(view, caret, ctrl, GDK_SCROLL_UP, addr, code); + + if (result == VMPA_INVALID) + caret->x = left_pos; + else + computed = true; + + } + + break; + + case GDK_SCROLL_RIGHT: + line = g_buffer_view_find_line_at(view, caret->y, NULL); + if (line == NULL) break; + + result = g_buffer_line_move_caret(line, caret, ctrl, GDK_SCROLL_RIGHT, addr, code); + + if (!result) + { + caret->x = left_pos; + + result = g_buffer_view_move_caret(view, caret, ctrl, GDK_SCROLL_DOWN, addr, code); + + if (result == VMPA_INVALID) + caret->x = right_pos; + else + computed = true; + + } + + break; + + } + + if (result && !computed) + result = g_buffer_view_compute_caret(view, caret->x, caret->y, caret); + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : view = vue de tampon à mettre à jour. * * * * Description : Supprime toute mise en évidence de segments. * @@ -1110,7 +1276,7 @@ void g_buffer_view_highlight_segments(GBufferView *view, gint x, gint y) size_t last; /* Dernière ligne intégrée */ size_t i; /* Boucle de parcours */ - line = g_buffer_view_find_line_at(view, y); + line = g_buffer_view_find_line_at(view, y, NULL); if (line == NULL) return; @@ -1127,7 +1293,7 @@ void g_buffer_view_highlight_segments(GBufferView *view, gint x, gint y) x -= view->left_text; if (x < 0) return; - segment = g_buffer_line_get_segment_at(line, view->max_widths, x); + segment = g_buffer_line_get_segment_at(line, view->max_widths, &x, false); printf(" ... seg @%d ? %p\n", x, segment); if (segment == NULL) return; @@ -1259,6 +1425,7 @@ void g_buffer_view_draw(const GBufferView *view, const GdkEventExpose *event, Gd * * * Paramètres : view = visualisation à consulter. * * y = ordonnée comprise dans la ligne recherchée. * +* idx = indice de la ligne trouvée ou NULL. [OUT] * * * * Description : Fournit la ligne présente à une ordonnée donnée. * * * @@ -1268,7 +1435,7 @@ void g_buffer_view_draw(const GBufferView *view, const GdkEventExpose *event, Gd * * ******************************************************************************/ -GBufferLine *g_buffer_view_find_line_at(GBufferView *view, gint y) +GBufferLine *g_buffer_view_find_line_at(GBufferView *view, gint y, size_t *idx) { gint lheight; /* Hauteur d'une ligne */ size_t index; /* Indice attendu */ @@ -1276,6 +1443,9 @@ GBufferLine *g_buffer_view_find_line_at(GBufferView *view, gint y) lheight = g_buffer_view_get_line_height(view); index = y / lheight; + if (idx != NULL) + *idx = index; + return (index < view->buffer->used ? view->buffer->lines[index] : NULL); } diff --git a/src/glibext/gcodebuffer.h b/src/glibext/gcodebuffer.h index fc4bc66..4ae5c58 100644 --- a/src/glibext/gcodebuffer.h +++ b/src/glibext/gcodebuffer.h @@ -124,6 +124,12 @@ gint g_buffer_view_get_line_height(GBufferView *); /* Fournit les dimensions requises par une visualisation. */ void g_buffer_view_get_size(GBufferView *, gint *, gint *, bool, bool); +/* Calcule la position idéale de curseur pour un point donné. */ +vmpa_t g_buffer_view_compute_caret(GBufferView *, gint, gint, GdkRectangle *); + +/* Déplace le curseur au sein d'une vue de tampon. */ +vmpa_t g_buffer_view_move_caret(GBufferView *, GdkRectangle *, bool, GdkScrollDirection, bool, bool); + /* Supprime toute mise en évidence de segments. */ bool g_buffer_view_unhighlight_segments(GBufferView *); @@ -137,7 +143,7 @@ void g_buffer_view_define_extra_drawing(GBufferView *, buffer_line_draw_fc, void void g_buffer_view_draw(const GBufferView *, const GdkEventExpose *, GdkGC *, gint, gint, bool, bool); /* Fournit la ligne présente à une ordonnée donnée. */ -GBufferLine *g_buffer_view_find_line_at(GBufferView *, gint); +GBufferLine *g_buffer_view_find_line_at(GBufferView *, gint, size_t *); /* Indique la position d'affichage d'une adresse donnée. */ bool g_buffer_view_get_address_coordinates(GBufferView *, vmpa_t, gint *, gint *); diff --git a/src/gtkext/gtkbufferview-int.h b/src/gtkext/gtkbufferview-int.h index 5d5a407..f57e78a 100644 --- a/src/gtkext/gtkbufferview-int.h +++ b/src/gtkext/gtkbufferview-int.h @@ -44,6 +44,11 @@ struct _GtkBufferView gint left_margin; /* Marge gauche + espace */ gint left_text; /* Début d'impression du code */ + GdkRectangle caret; /* Emplacement du curseur */ + vmpa_t caret_addr; /* Position mémoire du curseur */ + guint caret_timer; /* Identifiant du chronomètre */ + bool show_caret; /* Bascule entre les affichages*/ + }; /* Composant d'affichage de tampon de lignes (classe) */ @@ -51,6 +56,10 @@ struct _GtkBufferViewClass { GtkViewPanelClass parent; /* A laisser en premier */ + /* Signaux */ + + void (* caret_moved) (GtkBufferView *, vmpa_t); + }; diff --git a/src/gtkext/gtkbufferview.c b/src/gtkext/gtkbufferview.c index 62a861a..6556eb8 100644 --- a/src/gtkext/gtkbufferview.c +++ b/src/gtkext/gtkbufferview.c @@ -24,6 +24,12 @@ #include "gtkbufferview-int.h" +#include <gdk/gdkkeysyms.h> + + +#include "../glibext/chrysamarshal.h" + + /* -------------------------- INTERACTION DIRECTE AVEC GTK -------------------------- */ @@ -34,6 +40,12 @@ static void gtk_buffer_view_class_init(GtkBufferViewClass *); /* Procède à l'initialisation de l'afficheur de tampons. */ static void gtk_buffer_view_init(GtkBufferView *); +/* Intègre le focus dans le rendu du composant. */ +static gboolean gtk_buffer_view_focus(GtkWidget *, GtkDirectionType); + +/* Assure la gestion des clics de souris sur le composant. */ +static gboolean gtk_buffer_view_button_press(GtkWidget *, GdkEventButton *); + /* Fournit la taille de composant requise pour un plein rendu. */ static void gtk_buffer_view_size_request(GtkWidget *, GtkRequisition *); @@ -43,6 +55,9 @@ static void gtk_buffer_view_size_allocate(GtkWidget *, GtkAllocation *); /* Met à jour l'affichage de la visualisation de code buffer. */ static gboolean gtk_buffer_view_expose(GtkWidget *, GdkEventExpose *); +/* Prend en compte une frappe de touche sur le composant. */ +static gboolean gtk_buffer_view_key_press(GtkWidget *, GdkEventKey *); + /* Indique la position d'affichage d'une adresse donnée. */ static bool gtk_buffer_view_get_address_coordinates(const GtkBufferView *, vmpa_t, gint *, gint *); @@ -54,6 +69,17 @@ static void gtk_buffer_view_cache_glance(GtkBufferView *, cairo_t *, const GtkAl +/* ------------------------------ ANIMATION DU CURSEUR ------------------------------ */ + + +/* Redémarre l'affichage du curseur à l'emplacement courant. */ +static void restart_caret_blinking(GtkBufferView *); + +/* Bascule et relance l'affichage du curseur. */ +static gboolean gtk_buffer_view_refresh_caret(GtkBufferView *); + + + /* ---------------------------------------------------------------------------------- */ /* INTERACTION DIRECTE AVEC GTK */ /* ---------------------------------------------------------------------------------- */ @@ -81,9 +107,20 @@ static void gtk_buffer_view_class_init(GtkBufferViewClass *class) widget_class = GTK_WIDGET_CLASS(class); + widget_class->focus = gtk_buffer_view_focus; + widget_class->button_press_event = gtk_buffer_view_button_press; widget_class->size_request = gtk_buffer_view_size_request; widget_class->size_allocate = gtk_buffer_view_size_allocate; widget_class->expose_event = gtk_buffer_view_expose; + widget_class->key_press_event = gtk_buffer_view_key_press; + + g_signal_new("caret-moved", + GTK_TYPE_BUFFER_VIEW, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(GtkBufferViewClass, caret_moved), + NULL, NULL, + g_cclosure_user_marshal_VOID__UINT64, + G_TYPE_NONE, 1, G_TYPE_UINT64); } @@ -110,6 +147,108 @@ static void gtk_buffer_view_init(GtkBufferView *view) viewpanel->scroll = (scroll_fc)gtk_buffer_view_scroll; viewpanel->cache_glance = (cache_glance_fc)gtk_buffer_view_cache_glance; + view->caret.x = 10; + view->caret.y = 10; + view->caret.width = 100; + view->caret.height = 100; + +} + + +/****************************************************************************** +* * +* Paramètres : widget = composant GTK visé par l'opération. * +* dir = sens de l'opération : perte ou gain de focus. * +* * +* Description : Intègre le focus dans le rendu du composant. * +* * +* Retour : FALSE pour poursuivre la propagation de l'événement. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static gboolean gtk_buffer_view_focus(GtkWidget *widget, GtkDirectionType direction) +{ + GtkBufferView *view; /* Autre version du composant */ + gboolean has_focus; /* Etat courant */ + + view = GTK_BUFFER_VIEW(widget); + has_focus = gtk_widget_is_focus(widget); + + if (has_focus) + restart_caret_blinking(view); + + else if (view->caret_timer != 0) + { + g_source_remove(view->caret_timer); + view->caret_timer = 0; + + view->show_caret = true; + gtk_buffer_view_refresh_caret(view); + + } + + return TRUE; + +} + + +/****************************************************************************** +* * +* Paramètres : widget = composant GTK visé par l'opération. * +* event = informations liées à l'événement. * +* * +* Description : Assure la gestion des clics de souris sur le composant. * +* * +* Retour : FALSE pour poursuivre la propagation de l'événement. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static gboolean gtk_buffer_view_button_press(GtkWidget *widget, GdkEventButton *event) +{ + GtkBufferView *view; /* Autre version du composant */ + gint real_x; /* Abscisse absolue réelle */ + gint real_y; /* Ordonnée absolue réelle */ + vmpa_t addr; /* Position mémoire associée */ + GdkRectangle new; /* Nouvel emplacement calculé */ + + view = GTK_BUFFER_VIEW(widget); + + gtk_widget_grab_focus(widget); + + real_x = event->x; + real_y = event->y; + gtk_buffer_view_compute_real_coord(view, &real_x, &real_y); + + printf(" mouse :: (%g ; %g) -> (%d ; %d)\n", + event->x, event->y, + real_x, real_y); + + addr = g_buffer_view_compute_caret(view->buffer_view, real_x, real_y, &new); + + if (addr != VMPA_INVALID) + { + //gtk_buffer_view_compute_fake_coord(view, &view->caret.x, &view->caret.y); + + + printf(" mouse --old-- :: (%d ; %d)\n", + view->caret.x, view->caret.y); + + gtk_widget_queue_draw_area(GTK_WIDGET(view), view->caret.x, view->caret.y, + view->caret.width, view->caret.height); + + view->caret = new; + view->caret_addr = addr; + + restart_caret_blinking(view); + + } + + return FALSE; + } @@ -341,6 +480,53 @@ static gboolean gtk_buffer_view_expose(GtkWidget *widget, GdkEventExpose *event) /****************************************************************************** * * +* Paramètres : widget = composant visé par l'opération. * +* event = informations liées à l'événement. * +* * +* Description : Prend en compte une frappe de touche sur le composant. * +* * +* Retour : FALSE pour poursuivre la propagation de l'événement. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static gboolean gtk_buffer_view_key_press(GtkWidget *widget, GdkEventKey *event) +{ + gboolean result; /* Suites à renvoyer */ + bool ctrl; /* Statut de la touche Contrôle*/ + + result = FALSE; + + ctrl = (event->state & GDK_CONTROL_MASK); + + switch (event->keyval) + { + case GDK_KEY_Left: + result = TRUE; + break; + case GDK_KEY_Up: + result = TRUE; + break; + case GDK_KEY_Right: + result = TRUE; + break; + case GDK_KEY_Down: + result = TRUE; + break; + } + + + printf("ctrl ? %d -- keyval = %d -->> %d\n", ctrl, event->keyval, result); + + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : view = composant GTK à consulter. * * addr = adresse à présenter à l'écran. * * x = position horizontale au sein du composant. [OUT] * @@ -480,3 +666,130 @@ GBufferView *gtk_buffer_view_get_buffer(const GtkBufferView *view) return view->buffer_view; } + + + + + +/* ---------------------------------------------------------------------------------- */ +/* CONVERSIONS DE COORDONNEES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : view = composant GTK à consulter. * +* x = abscisse à ajuster. [OUT] * +* x = ordonnée à ajuster. [OUT] * +* * +* Description : Transcrit les coordonnées absolues en coordonnées à l'écran. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void gtk_buffer_view_compute_relative_coords(GtkBufferView *view, gint *x, gint *y) +{ + if (x != NULL && GTK_VIEW_PANEL(view)->hadjustment != NULL) + *x -= gtk_adjustment_get_value(GTK_VIEW_PANEL(view)->hadjustment); + + if (y != NULL && GTK_VIEW_PANEL(view)->vadjustment != NULL) + *y -= gtk_adjustment_get_value(GTK_VIEW_PANEL(view)->vadjustment); + +} + + + + + +/* ---------------------------------------------------------------------------------- */ +/* ANIMATION DU CURSEUR */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : view = composant GTK à manipuler. * +* * +* Description : Redémarre l'affichage du curseur à l'emplacement courant. * +* * +* Retour : TRUE pour poursuivre les basculements automatiques. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void restart_caret_blinking(GtkBufferView *view) +{ + if (view->caret_addr == VMPA_INVALID) + return; + + if (view->caret_timer != 0) + g_source_remove(view->caret_timer); + + view->caret_timer = g_timeout_add_seconds(1, (GSourceFunc)gtk_buffer_view_refresh_caret, view); + + view->show_caret = false; + gtk_buffer_view_refresh_caret(view); + + g_signal_emit_by_name(view, "caret-moved", view->caret_addr); + +} + + +/****************************************************************************** +* * +* Paramètres : view = composant GTK à manipuler. * +* * +* Description : Bascule et relance l'affichage du curseur. * +* * +* Retour : TRUE pour poursuivre les basculements automatiques. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static gboolean gtk_buffer_view_refresh_caret(GtkBufferView *view) +{ + GtkWidget *widget; /* Autre version du composant */ + GdkRectangle area; /* Région adaptée à traiter */ + GdkDrawable *drawable; /* Surface de dessin */ + GtkStyle *style; /* Style associé au composant */ + GtkStateType state; /* Etat du composant */ + GdkGC *gc; /* Contexte graphique */ + + widget = GTK_WIDGET(view); + + area = view->caret; + gtk_buffer_view_compute_relative_coords(view, &area.x, &area.y); + + /* Réinitialisation de la surface */ + if (view->show_caret) + { + view->show_caret = false; + gtk_widget_queue_draw_area(widget, area.x, area.y, area.width, area.height); + } + + /* Dessin */ + else + { + view->show_caret = true; + + drawable = GDK_DRAWABLE(widget->window); + state = gtk_widget_get_state(widget); + style = gtk_widget_get_style(widget); + + gc = gdk_gc_new(drawable); + gdk_gc_set_foreground(gc, &style->text[state]); + + gdk_draw_rectangle(drawable, gc, TRUE, area.x, area.y, area.width, area.height); + + gdk_gc_destroy(gc); + + } + + return TRUE; + +} diff --git a/src/gtkext/gtkextstatusbar.c b/src/gtkext/gtkextstatusbar.c index dfb08d7..47fc154 100644 --- a/src/gtkext/gtkextstatusbar.c +++ b/src/gtkext/gtkextstatusbar.c @@ -124,7 +124,7 @@ guint gtk_extended_status_bar_push(GtkExtStatusBar *bar, const gchar *message, g { guint result; /* Identifiant à retourner */ - gdk_threads_enter(); + //gdk_threads_enter(); result = gtk_statusbar_push(GTK_STATUSBAR(bar), bar->context, message); @@ -145,8 +145,8 @@ guint gtk_extended_status_bar_push(GtkExtStatusBar *bar, const gchar *message, g } else gtk_widget_hide(GTK_WIDGET(bar->progress)); - gdk_flush(); - gdk_threads_leave(); + //gdk_flush(); + //gdk_threads_leave(); return result; @@ -210,7 +210,7 @@ void gtk_extended_status_bar_remove(GtkExtStatusBar *bar, guint id) { size_t i; /* Boucle de parcours */ - gdk_threads_enter(); + //gdk_threads_enter(); gtk_statusbar_remove(GTK_STATUSBAR(bar), bar->context, id); @@ -234,7 +234,7 @@ void gtk_extended_status_bar_remove(GtkExtStatusBar *bar, guint id) else gtk_widget_hide(GTK_WIDGET(bar->progress)); - gdk_flush(); - gdk_threads_leave(); + //gdk_flush(); + //gdk_threads_leave(); } diff --git a/src/gtkext/gtkextstatusbar.h b/src/gtkext/gtkextstatusbar.h index 4cba821..b5fe210 100644 --- a/src/gtkext/gtkextstatusbar.h +++ b/src/gtkext/gtkextstatusbar.h @@ -34,9 +34,9 @@ G_BEGIN_DECLS #define GTK_TYPE_EXT_STATUS_BAR (gtk_extended_status_bar_get_type()) -#define GTK_EXT_STATUS_BAR(obj) GTK_CHECK_CAST(obj, gtk_extended_status_bar_get_type (), GtkExtStatusBar) -#define GTK_EXT_STATUS_BAR_CLASS(klass) GTK_CHECK_CLASS_CAST(klass, gtk_extended_status_bar_get_type(), GtkExtStatusBarClass) -#define GTK_IS_EXT_STATUS_BAR(obj) GTK_CHECK_TYPE(obj, gtk_extended_status_bar_get_type()) +#define GTK_EXT_STATUS_BAR(obj) (G_TYPE_CHECK_INSTANCE_CAST(obj, gtk_extended_status_bar_get_type (), GtkExtStatusBar)) +#define GTK_IS_EXT_STATUS_BAR(obj) (G_TYPE_CHECK_INSTANCE_TYPE(obj, gtk_extended_status_bar_get_type())) +#define GTK_EXT_STATUS_BAR_CLASS(klass) (G_LOADED_BINARY_GET_CLASS(klass, gtk_extended_status_bar_get_type(), GtkExtStatusBarClass)) typedef struct _GtkExtStatusBar GtkExtStatusBar; diff --git a/src/gtkext/gtkviewpanel.c b/src/gtkext/gtkviewpanel.c index 6d10009..ef1f94d 100644 --- a/src/gtkext/gtkviewpanel.c +++ b/src/gtkext/gtkviewpanel.c @@ -105,6 +105,7 @@ static void gtk_view_panel_class_init(GtkViewPanelClass *class) static void gtk_view_panel_init(GtkViewPanel *panel) { gtk_widget_set_has_window(GTK_WIDGET(panel), TRUE); + gtk_widget_set_can_focus(GTK_WIDGET(panel), TRUE); } diff --git a/src/gui/Makefile.am b/src/gui/Makefile.am index c0a03f0..2e2bc1c 100644 --- a/src/gui/Makefile.am +++ b/src/gui/Makefile.am @@ -3,7 +3,8 @@ noinst_LTLIBRARIES = libgui.la libgui_la_SOURCES = \ editem-int.h \ - editem.h editem.c + editem.h editem.c \ + status.h status.c libgui_la_LIBADD = \ menus/libguimenus.la \ diff --git a/src/gui/status.c b/src/gui/status.c new file mode 100644 index 0000000..16a3ff8 --- /dev/null +++ b/src/gui/status.c @@ -0,0 +1,266 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * status.c - affichage d'informations de statut dans la fenêtre principale + * + * Copyright (C) 2013 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * OpenIDA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "status.h" + + +#include <string.h> + + +#include <i18n.h> + + +#include "editem-int.h" +#include "../common/extstr.h" +#include "../gtkext/gtkbufferview.h" +#include "../gtkext/gtkblockview.h" +#include "../gtkext/gtkextstatusbar.h" + + + +/* Barre de statut de la fenêtre principale (instance) */ +struct _GStatusInfo +{ + GEditorItem parent; /* A laisser en premier */ + + GObject *caret_instance; /* Dernier émetteur de signaux */ + guint msg_id; /* Identifiant du dernier msg. */ + +}; + + +/* Barre de statut de la fenêtre principale (classe) */ +struct _GStatusInfoClass +{ + GEditorItemClass parent; /* A laisser en premier */ + +}; + + +/* Initialise la classe de la barre de statut de l'éditeur. */ +static void g_status_info_class_init(GStatusInfoClass *); + +/* Initialise une instance de la barre de statut pour l'éditeur. */ +static void g_status_info_init(GStatusInfo *); + +/* Lance une actualisation du fait d'un changement de vue. */ +static void update_status_info_for_view(GStatusInfo *, GtkViewPanel *); + +/* Imprime la position du parcours courant dans le statut. */ +static void track_caret_address_on_buffer_views(GtkBufferView *, vmpa_t, GStatusInfo *); + + + + +/* Indique le type défini pour la barre de statut de la fenêtre principale. */ +G_DEFINE_TYPE(GStatusInfo, g_status_info, G_TYPE_EDITOR_ITEM); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe de la barre de statut de l'éditeur. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_status_info_class_init(GStatusInfoClass *klass) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : bar = instance à initialiser. * +* * +* Description : Initialise une instance de la barre de statut pour l'éditeur.* +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_status_info_init(GStatusInfo *bar) +{ + GEditorItem *item; /* Autre version de l'élément */ + + item = G_EDITOR_ITEM(bar); + + item->name = "status"; + + item->widget = gtk_extended_status_bar_new(); + gtk_widget_show(item->widget); + + item->update_view = (update_item_view_fc)update_status_info_for_view; + +} + + +/****************************************************************************** +* * +* Paramètres : ref = espace de référencement global. * +* * +* Description : Compose la barre de statut principale. * +* * +* Retour : Adresse de la structure mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GEditorItem *g_status_info_new(GObject *ref) +{ + GStatusInfo *result; /* Structure à retourner */ + GEditorItem *item; /* Autre version de l'élément */ + + result = g_object_new(G_TYPE_STATUS_INFO, NULL); + + item = G_EDITOR_ITEM(result); + + g_object_ref(ref); + item->ref = ref; + + g_object_set_data(ref, "statusbar", item->widget); + + return G_EDITOR_ITEM(result); + +} + + +/****************************************************************************** +* * +* Paramètres : info = barre de statut à actualiser. * +* view = nouveau panneau d'affichage actif. * +* * +* Description : Lance une actualisation du fait d'un changement de vue. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void update_status_info_for_view(GStatusInfo *info, GtkViewPanel *view) +{ + printf("new view :: %p\n", view); + + //track_caret_address_on_buffer_views + + if (info->caret_instance != NULL) + { + g_signal_handlers_disconnect_by_func(info->caret_instance, + G_CALLBACK(track_caret_address_on_buffer_views), + info); + g_object_unref(info->caret_instance); + } + + if (GTK_IS_BLOCK_VIEW(view)) + g_signal_connect(view, "caret-moved", + G_CALLBACK(track_caret_address_on_buffer_views), + info); + + else + return; + + info->caret_instance = G_OBJECT(view); + g_object_ref(info->caret_instance); + +} + + +/****************************************************************************** +* * +* Paramètres : view = composant d'affichage parcouru. * +* addr = nouvelle adresse du curseur courant. * +* info = barre de statut présentant les informations. * +* * +* Description : Imprime la position du parcours courant dans le statut. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void track_caret_address_on_buffer_views(GtkBufferView *view, vmpa_t addr, GStatusInfo *info) +{ + GEditorItem *item; /* Autre version de l'élément */ + char *msg; /* Message à transmettre */ + char tmp[VMPA_MAX_SIZE]; /* Zone de conversion */ + GLoadedBinary *binary; /* Binaire courant */ + GExeFormat *format; /* Format associé au binaire */ + vmpa_t rel; /* Adresse relative à un symb. */ + const char *label; /* Désignation d'un symbole */ + + item = G_EDITOR_ITEM(info); + + /* Adresse brute */ + + msg = strdup(_("Address ")); + + snprintf(tmp, VMPA_MAX_SIZE, VMPA_FMT_LONG, addr); + msg = stradd(msg, tmp); + + /* Relation avec les symboles */ + + binary = G_LOADED_BINARY(g_object_get_data(item->ref, "current_binary")); + format = g_loaded_binary_get_format(binary); + + rel = addr; + + if (g_binary_format_resolve_relative_routine(G_BIN_FORMAT(format), &label, &rel)) + { + msg = stradd(msg, _(" at ")); + msg = stradd(msg, label); + msg = stradd(msg, _("+")); + + snprintf(tmp, VMPA_MAX_SIZE, VMPA_FMT, rel); + msg = stradd(msg, tmp); + + } + + /* Impression */ + + if (info->msg_id > 0) + gtk_extended_status_bar_remove(GTK_EXT_STATUS_BAR(item->widget), info->msg_id); + + info->msg_id = gtk_extended_status_bar_push(GTK_EXT_STATUS_BAR(item->widget), msg, FALSE); + + + printf("---- moved to 0x%08llx\n", addr); + + printf(" MSG '%s'\n", msg); + + //update_menu_project_for_project(bar->project, project, bar); + + + free(msg); + +} diff --git a/src/gui/status.h b/src/gui/status.h new file mode 100644 index 0000000..277df4c --- /dev/null +++ b/src/gui/status.h @@ -0,0 +1,56 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * status.h - prototypes pour l'affichage d'informations de statut dans la fenêtre principale + * + * Copyright (C) 2013 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * OpenIDA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _GUI_STATUS_H +#define _GUI_STATUS_H + + +#include "editem.h" + + + +#define G_TYPE_STATUS_INFO g_status_info_get_type() +#define G_STATUS_INFO(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_status_info_get_type(), GStatusInfo)) +#define G_IS_STATUS_INFO(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_status_info_get_type())) +#define G_STATUS_INFO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_STATUS_INFO, GStatusInfoClass)) +#define G_IS_STATUS_INFO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_STATUS_INFO)) +#define G_STATUS_INFO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_STATUS_INFO, GStatusInfoClass)) + + +/* Barre de statut de la fenêtre principale (instance) */ +typedef struct _GStatusInfo GStatusInfo; + +/* Barre de statut de la fenêtre principale (classe) */ +typedef struct _GStatusInfoClass GStatusInfoClass; + + +/* Indique le type défini pour la barre de statut de la fenêtre principale. */ +GType g_status_info_get_type(void); + +/* Compose la barre de statut principale. */ +GEditorItem *g_status_info_new(GObject *); + + + +#endif /* _GUI_MENUS_MENUBAR_H */ |