From d13bccd74759cd1c63a2036c279f04d9f052ecf3 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Sun, 17 Jan 2016 14:45:49 +0100
Subject: Updated access to the Edition menu based on the current selection.

---
 ChangeLog                 |  18 +++++++
 src/gtkext/gtkviewpanel.c |   3 ++
 src/gui/editem-int.h      |   5 ++
 src/gui/editem.c          |  63 +++++++++++++++++++++-
 src/gui/editem.h          |   2 +-
 src/gui/menus/edition.c   | 129 ++++++++++++++++++++++++++++++++++------------
 src/gui/menus/edition.h   |   4 ++
 src/gui/menus/menubar.c   |  29 +++++++++++
 src/gui/status.c          |  58 ++-------------------
 9 files changed, 224 insertions(+), 87 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 2f3e291..98a2406 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+16-01-17  Cyrille Bagard <nocbos@gmail.com>
+
+	* src/gtkext/gtkviewpanel.c:
+	Reset output arguments in gtk_view_panel_get_position() in all cases.
+
+	* src/gui/editem-int.h:
+	* src/gui/editem.c:
+	* src/gui/editem.h:
+	Give a way to all editor items to react on selection changes.
+
+	* src/gui/menus/edition.c:
+	* src/gui/menus/edition.h:
+	Update access to the Edition menu based on the current selection.
+
+	* src/gui/menus/menubar.c:
+	* src/gui/status.c:
+	Update code.
+
 16-01-16  Cyrille Bagard <nocbos@gmail.com>
 
 	* src/analysis/db/collection.c:
diff --git a/src/gtkext/gtkviewpanel.c b/src/gtkext/gtkviewpanel.c
index 091482b..861b46f 100644
--- a/src/gtkext/gtkviewpanel.c
+++ b/src/gtkext/gtkviewpanel.c
@@ -903,6 +903,9 @@ bool gtk_view_panel_get_position(const GtkViewPanel *panel, GBufferLine **line,
 {
     bool result;                            /* Bilan de l'opération        */
 
+    *line = NULL;
+    if (segment != NULL) *segment = NULL;
+
     if (GTK_VIEW_PANEL_GET_CLASS(panel)->get_position == NULL)
         return false;
 
diff --git a/src/gui/editem-int.h b/src/gui/editem-int.h
index b76769f..fa62dc6 100644
--- a/src/gui/editem-int.h
+++ b/src/gui/editem-int.h
@@ -33,6 +33,7 @@
 
 
 #include "../common/dllist.h"
+#include "../gtkext/gtkbufferview.h"
 
 
 
@@ -45,6 +46,9 @@ typedef void (* manage_item_view_fc) (GEditorItem *, GtkViewPanel *, bool);
 /* Réagit à un changement d'affichage principal de contenu. */
 typedef void (* update_item_view_fc) (GEditorItem *, GtkViewPanel *);
 
+/* Suit les changements de position dans du code d'assembleur. */
+typedef void (* track_caret_in_view_fc) (GEditorItem *, GtkBufferView *, const vmpa2t *);
+
 /* Concentre l'attention de l'ensemble sur une adresse donnée. */
 typedef void (* focus_addr_fc) (GEditorItem *, GLoadedBinary *, const vmpa2t *);
 
@@ -75,6 +79,7 @@ struct _GEditorItemClass
     update_item_binary_fc update_binary;    /* Changement de binaire       */
     manage_item_view_fc manage_view;        /* Gestion des vues manipulées */
     update_item_view_fc update_view;        /* Rechargement dû à une vue   */
+    track_caret_in_view_fc track_caret;     /* Suivi des positions         */
     update_item_view_fc update_content;     /* Rechargement dû à un contenu*/
     focus_addr_fc focus_addr;               /* Prête attention à une addr. */
     update_project_fc update_project;       /* Actualisation des binaires  */
diff --git a/src/gui/editem.c b/src/gui/editem.c
index e4c74a9..9f10bec 100644
--- a/src/gui/editem.c
+++ b/src/gui/editem.c
@@ -26,6 +26,7 @@
 
 
 #include "editem-int.h"
+#include "../gtkext/gtkblockview.h"
 
 
 
@@ -43,9 +44,16 @@ static void g_editor_item_init(GEditorItem *);
 /* ---------------------------- MANIPULATION D'ENSEMBLES ---------------------------- */
 
 
-/* liste des éléments enregistrés */
+/* Liste des éléments enregistrés */
 static GEditorItem *_editem_list = NULL;
 
+/* Suivi des changements de position */
+static GObject *_caret_instance = NULL;
+
+
+/* Suit les changements de position dans du code d'assembleur. */
+static void track_caret_address_on_buffer_views(GtkBufferView *, const vmpa2t *, void *);
+
 
 
 /* ---------------------------------------------------------------------------------- */
@@ -252,6 +260,36 @@ void manage_editor_items_view(GtkViewPanel *view, bool created)
         if (klass->manage_view != NULL)
             klass->manage_view(iter, view, created);
 
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : view = composant d'affichage parcouru.                       *
+*                addr = nouvelle adresse du curseur courant.                  *
+*                data = adresse non utilisée ici.                             *
+*                                                                             *
+*  Description : Suit les changements de position dans du code d'assembleur.  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void track_caret_address_on_buffer_views(GtkBufferView *view, const vmpa2t *addr, void *data)
+{
+    GEditorItem *iter;                      /* Boucle de parcours          */
+    GEditorItemClass *klass;                /* Classe correspondante       */
+
+    editem_list_for_each(iter, _editem_list)
+    {
+        klass = G_EDITOR_ITEM_GET_CLASS(iter);
+
+        if (klass->track_caret != NULL)
+            klass->track_caret(iter, view, addr);
 
     }
 
@@ -285,6 +323,29 @@ void change_editor_items_current_view(GObject *ref, GtkViewPanel *view)
         if (klass->update_view != NULL)
             klass->update_view(iter, view);
 
+    }
+
+    if (_caret_instance != NULL)
+    {
+        g_signal_handlers_disconnect_by_func(_caret_instance,
+                                             G_CALLBACK(track_caret_address_on_buffer_views),
+                                             NULL);
+        g_object_unref(_caret_instance);
+        _caret_instance = NULL;
+    }
+
+    if (view != NULL)
+    {
+        if (GTK_IS_BLOCK_VIEW(view))
+        {
+            g_signal_connect(view, "caret-moved",
+                             G_CALLBACK(track_caret_address_on_buffer_views),
+                             NULL);
+
+            _caret_instance = G_OBJECT(view);
+            g_object_ref(_caret_instance);
+
+        }
 
     }
 
diff --git a/src/gui/editem.h b/src/gui/editem.h
index c716337..67bc402 100644
--- a/src/gui/editem.h
+++ b/src/gui/editem.h
@@ -80,7 +80,7 @@ void register_editor_item(GEditorItem *);
 void change_editor_items_current_binary(GObject *, GLoadedBinary *);
 
 /* Lance une actualisation liée à une modification du cheptel. */
-void manage_editor_items_view(GtkViewPanel *, bool);
+void manage_editor_items_view(GtkViewPanel *, bool) __attribute__ ((deprecated));;
 
 /* Lance une actualisation du fait d'un changement de vue. */
 void change_editor_items_current_view(GObject *, GtkViewPanel *);
diff --git a/src/gui/menus/edition.c b/src/gui/menus/edition.c
index c524891..b77f864 100644
--- a/src/gui/menus/edition.c
+++ b/src/gui/menus/edition.c
@@ -100,25 +100,25 @@ GtkWidget *build_menu_edition(GObject *ref, GtkAccelGroup *accgroup, GMenuBar *b
     deepmenubar = gtk_menu_new();
     gtk_menu_item_set_submenu(GTK_MENU_ITEM(submenuitem), deepmenubar);
 
-    deepmenuitem = qck_create_menu_item(NULL, NULL, _("Hexadecimal"),
+    deepmenuitem = qck_create_menu_item(ref, "mnu_edit_switch_hex", _("Hexadecimal"),
                                         G_CALLBACK(mcb_edition_switch_numeric_operand), bar);
     add_accelerator_to_menu_item(deepmenuitem, "H", accgroup);
     g_object_set_data(G_OBJECT(deepmenuitem), "kind_of_switch", GUINT_TO_POINTER(IOD_HEX));
     gtk_container_add(GTK_CONTAINER(deepmenubar), deepmenuitem);
 
-    deepmenuitem = qck_create_menu_item(NULL, NULL, _("Decimal"),
+    deepmenuitem = qck_create_menu_item(ref, "mnu_edit_switch_dec", _("Decimal"),
                                         G_CALLBACK(mcb_edition_switch_numeric_operand), bar);
     add_accelerator_to_menu_item(deepmenuitem, "D", accgroup);
     g_object_set_data(G_OBJECT(deepmenuitem), "kind_of_switch", GUINT_TO_POINTER(IOD_DEC));
     gtk_container_add(GTK_CONTAINER(deepmenubar), deepmenuitem);
 
-    deepmenuitem = qck_create_menu_item(NULL, NULL, _("Octal"),
+    deepmenuitem = qck_create_menu_item(ref, "mnu_edit_switch_oct", _("Octal"),
                                         G_CALLBACK(mcb_edition_switch_numeric_operand), bar);
     add_accelerator_to_menu_item(deepmenuitem, "O", accgroup);
     g_object_set_data(G_OBJECT(deepmenuitem), "kind_of_switch", GUINT_TO_POINTER(IOD_OCT));
     gtk_container_add(GTK_CONTAINER(deepmenubar), deepmenuitem);
 
-    deepmenuitem = qck_create_menu_item(NULL, NULL, _("Binary"),
+    deepmenuitem = qck_create_menu_item(ref, "mnu_edit_switch_bin", _("Binary"),
                                         G_CALLBACK(mcb_edition_switch_numeric_operand), bar);
     add_accelerator_to_menu_item(deepmenuitem, "B", accgroup);
     g_object_set_data(G_OBJECT(deepmenuitem), "kind_of_switch", GUINT_TO_POINTER(IOD_BIN));
@@ -127,7 +127,7 @@ GtkWidget *build_menu_edition(GObject *ref, GtkAccelGroup *accgroup, GMenuBar *b
     deepmenuitem = qck_create_menu_separator();
     gtk_container_add(GTK_CONTAINER(deepmenubar), deepmenuitem);
 
-    deepmenuitem = qck_create_menu_item(NULL, NULL, _("Default"),
+    deepmenuitem = qck_create_menu_item(ref, "mnu_edit_switch_def", _("Default"),
                                         G_CALLBACK(mcb_edition_switch_numeric_operand), bar);
     g_object_set_data(G_OBJECT(deepmenuitem), "kind_of_switch", GUINT_TO_POINTER(IOD_COUNT));
     gtk_container_add(GTK_CONTAINER(deepmenubar), deepmenuitem);
@@ -166,6 +166,77 @@ GtkWidget *build_menu_edition(GObject *ref, GtkAccelGroup *accgroup, GMenuBar *b
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : bar  = barre de menus à actualiser.                          *
+*                addr = nouvelle adresse du curseur courant.                  *
+*                info = barre de statut présentant les informations.          *
+*                                                                             *
+*  Description : Met à jour les accès du menu "Edition" selon une position.   *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void update_access_in_menu_edition(GObject *ref, GtkBufferView *view, const vmpa2t *addr)
+{
+    bool state;                             /* Etat principal à considérer */
+    gboolean access;                        /* Accès à déterminer          */
+    GBufferLine *line;                      /* Ligne de position courante  */
+    GBufferSegment *segment;                /* Segment actif s'il existe   */
+    GObject *creator;                       /* Créateur à l'orgine du seg. */
+    GtkWidget *item;                        /* Elément de menu à traiter   */
+
+    /* Préliminaire */
+
+    if (view == NULL)
+        state = false;
+    else
+        state = gtk_view_panel_get_position(GTK_VIEW_PANEL(view), &line, &segment);
+
+    if (state)
+        creator = g_buffer_segment_get_creator(segment);
+    else
+        creator = NULL;
+
+    /* Bascule des opérandes numériques */
+
+    access = (state && G_IS_IMM_OPERAND(creator));
+
+    item = GTK_WIDGET(g_object_get_data(ref, "mnu_edit_switch_hex"));
+    gtk_widget_set_sensitive(item, access);
+
+    item = GTK_WIDGET(g_object_get_data(ref, "mnu_edit_switch_dec"));
+    gtk_widget_set_sensitive(item, access);
+
+    item = GTK_WIDGET(g_object_get_data(ref, "mnu_edit_switch_oct"));
+    gtk_widget_set_sensitive(item, access);
+
+    item = GTK_WIDGET(g_object_get_data(ref, "mnu_edit_switch_bin"));
+    gtk_widget_set_sensitive(item, access);
+
+    item = GTK_WIDGET(g_object_get_data(ref, "mnu_edit_switch_def"));
+    gtk_widget_set_sensitive(item, access);
+
+    /* Suivi de cibles */
+
+    access = (state && (G_IS_TARGET_OPERAND(creator) || G_IS_IMM_OPERAND(creator)));
+
+    item = GTK_WIDGET(g_object_get_data(ref, "mnu_edit_follow_ref"));
+    gtk_widget_set_sensitive(item, access);
+
+    /* Nettoyage et sortie finale */
+
+    if (creator != NULL) g_object_unref(G_OBJECT(creator));
+
+    if (segment != NULL) g_object_unref(G_OBJECT(segment));
+    if (line != NULL) g_object_unref(G_OBJECT(line));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : menuitem = élément de menu sélectionné.                      *
 *                bar      = barre de menu parente.                            *
 *                                                                             *
@@ -292,40 +363,34 @@ static void mcb_edition_follow_ref(GtkMenuItem *menuitem, GMenuBar *bar)
 
     if (gtk_view_panel_get_position(vpanel, &line, &segment))
     {
-        if (segment != NULL)
-            creator = g_buffer_segment_get_creator(segment);
-        else
-            creator = NULL;
-
-        if (creator != NULL)
-        {
-            /**
-             * On fait le pari de reposer uniquement sur des adresses virtuelles !
-             * A changer dans un futur ?
-             */
-
-            virt = VMPA_NO_VIRTUAL;
+        creator = g_buffer_segment_get_creator(segment);
+        assert(creator != NULL);
 
-            if (G_IS_TARGET_OPERAND(creator))
-                virt = g_target_operand_get_addr(G_TARGET_OPERAND(creator));
+        /**
+         * On fait le pari de reposer uniquement sur des adresses virtuelles !
+         * A changer dans un futur ?
+         */
 
-            else if (G_IS_IMM_OPERAND(creator))
-            {
-                if (!g_imm_operand_to_virt_t(G_IMM_OPERAND(creator), &virt))
-                    virt = VMPA_NO_VIRTUAL;
-            }
+        virt = VMPA_NO_VIRTUAL;
 
-            if (virt != VMPA_NO_VIRTUAL)
-            {
-                init_vmpa(&addr, VMPA_NO_PHYSICAL, virt);
-                gtk_view_panel_scroll_to_address(vpanel, &addr, SPT_CENTER);
-            }
+        if (G_IS_TARGET_OPERAND(creator))
+            virt = g_target_operand_get_addr(G_TARGET_OPERAND(creator));
 
-            g_object_unref(creator);
+        else if (G_IS_IMM_OPERAND(creator))
+        {
+            if (!g_imm_operand_to_virt_t(G_IMM_OPERAND(creator), &virt))
+                virt = VMPA_NO_VIRTUAL;
+        }
 
+        if (virt != VMPA_NO_VIRTUAL)
+        {
+            init_vmpa(&addr, VMPA_NO_PHYSICAL, virt);
+            gtk_view_panel_scroll_to_address(vpanel, &addr, SPT_CENTER);
         }
 
-        if (segment != NULL) g_object_unref(G_OBJECT(segment));
+        g_object_unref(creator);
+
+        g_object_unref(G_OBJECT(segment));
         g_object_unref(G_OBJECT(line));
 
     }
diff --git a/src/gui/menus/edition.h b/src/gui/menus/edition.h
index b430a8b..82a48bd 100644
--- a/src/gui/menus/edition.h
+++ b/src/gui/menus/edition.h
@@ -30,12 +30,16 @@
 
 
 #include "menubar.h"
+#include "../../gtkext/gtkbufferview.h"
 
 
 
 /* Construit le menu "Edition". */
 GtkWidget *build_menu_edition(GObject *, GtkAccelGroup *, GMenuBar *);
 
+/* Met à jour les accès du menu "Edition" selon une position. */
+void update_access_in_menu_edition(GObject *, GtkBufferView *, const vmpa2t *);
+
 
 
 #endif  /* _GUI_MENUS_EDITION_H */
diff --git a/src/gui/menus/menubar.c b/src/gui/menus/menubar.c
index 1fc1b6f..cbb6ae2 100644
--- a/src/gui/menus/menubar.c
+++ b/src/gui/menus/menubar.c
@@ -80,6 +80,9 @@ static void manage_view_in_menu_bar(GMenuBar *, GtkViewPanel *, bool);
 /* Lance une actualisation du fait d'un changement de vue. */
 static void update_menu_bar_for_view(GMenuBar *, GtkViewPanel *);
 
+/* Met à jour les accès aux menus en fonction de la position. */
+static void track_caret_address_for_menu_bar(GMenuBar *, GtkBufferView *, const vmpa2t *);
+
 /* Lance une actualisation relative à l'étendue du projet. */
 static void update_menu_bar_for_project(GMenuBar *, GStudyProject *);
 
@@ -115,6 +118,7 @@ static void g_menu_bar_class_init(GMenuBarClass *klass)
 
     editem->manage_view = (manage_item_view_fc)manage_view_in_menu_bar;
     editem->update_view = (update_item_view_fc)update_menu_bar_for_view;
+    editem->track_caret = (track_caret_in_view_fc)track_caret_address_for_menu_bar;
     editem->update_project = (update_project_fc)update_menu_bar_for_project;
 
 }
@@ -345,6 +349,31 @@ static void update_menu_bar_for_view(GMenuBar *bar, GtkViewPanel *view)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : bar  = barre de menus à actualiser.                          *
+*                addr = nouvelle adresse du curseur courant.                  *
+*                info = barre de statut présentant les informations.          *
+*                                                                             *
+*  Description : Met à jour les accès aux menus en fonction de la position.   *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void track_caret_address_for_menu_bar(GMenuBar *bar, GtkBufferView *view, const vmpa2t *addr)
+{
+    GEditorItem *item;                      /* Autre version de l'élément  */
+
+    item = G_EDITOR_ITEM(bar);
+
+    update_access_in_menu_edition(item->ref, view, addr);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : bar     = barre de menus à actualiser.                       *
 *                project = projet visé par la procédure.                      *
 *                                                                             *
diff --git a/src/gui/status.c b/src/gui/status.c
index de80049..8db4f3a 100644
--- a/src/gui/status.c
+++ b/src/gui/status.c
@@ -46,9 +46,6 @@ struct _GStatusInfo
 {
     GEditorItem parent;                     /* A laisser en premier        */
 
-    GObject *caret_instance;                /* Dernier émetteur de signaux */
-    bstatus_id_t msg_id;                    /* Identifiant du dernier msg. */
-
 };
 
 
@@ -72,11 +69,8 @@ static void g_status_info_dispose(GStatusInfo *);
 /* Procède à la libération totale de la mémoire. */
 static void g_status_info_finalize(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 *, const vmpa2t *, GStatusInfo *);
+static void track_caret_address_for_status_info(GStatusInfo *, GtkBufferView *, const vmpa2t *);
 
 /* Concentre l'attention de l'ensemble sur une adresse donnée. */
 static void focus_address_in_status_info(GStatusInfo *, GLoadedBinary *, const vmpa2t *);
@@ -111,7 +105,7 @@ static void g_status_info_class_init(GStatusInfoClass *klass)
 
     editem = G_EDITOR_ITEM_CLASS(klass);
 
-    editem->update_view = (update_item_view_fc)update_status_info_for_view;
+    editem->track_caret = (track_caret_in_view_fc)track_caret_address_for_status_info;
     editem->focus_addr = (focus_addr_fc)focus_address_in_status_info;
 
 }
@@ -157,14 +151,6 @@ static void g_status_info_init(GStatusInfo *bar)
 
 static void g_status_info_dispose(GStatusInfo *info)
 {
-    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);
-    }
-
     G_OBJECT_CLASS(g_status_info_parent_class)->dispose(G_OBJECT(info));
 
 }
@@ -222,43 +208,9 @@ GEditorItem *g_status_info_new(GObject *ref)
 
 /******************************************************************************
 *                                                                             *
-*  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)
-{
-    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);
-
-    info->caret_instance = G_OBJECT(view);
-    g_object_ref(info->caret_instance);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : view = composant d'affichage parcouru.                       *
+*  Paramètres  : info = barre de statut présentant les informations.          *
+*                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.      *
 *                                                                             *
@@ -268,7 +220,7 @@ static void update_status_info_for_view(GStatusInfo *info, GtkViewPanel *view)
 *                                                                             *
 ******************************************************************************/
 
-static void track_caret_address_on_buffer_views(GtkBufferView *view, const vmpa2t *addr, GStatusInfo *info)
+static void track_caret_address_for_status_info(GStatusInfo *info, GtkBufferView *view, const vmpa2t *addr)
 {
     GEditorItem *item;                      /* Autre version de l'élément  */
     GLoadedBinary *binary;                  /* Binaire courant             */
-- 
cgit v0.11.2-87-g4458