From a809d3517eb928d5d7a03d96a85f8af96daa1047 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Fri, 20 Jul 2018 18:43:23 +0200
Subject: Included dynamic items in the view menu.

---
 src/analysis/binary.c         |  46 ++++++-
 src/analysis/loaded-int.h     |   4 +
 src/analysis/loaded.c         |  29 ++++
 src/analysis/loaded.h         |   3 +
 src/glibext/gdisplayoptions.c |  30 ++++
 src/glibext/gdisplayoptions.h |   3 +
 src/gtkext/gtkdisplaypanel.c  |  60 ++++----
 src/gui/editor.c              |   4 +-
 src/gui/menus/menubar.c       |   5 +-
 src/gui/menus/view.c          | 312 +++++++++++++++++++++++++++---------------
 src/gui/menus/view.h          |   7 +-
 11 files changed, 351 insertions(+), 152 deletions(-)

diff --git a/src/analysis/binary.c b/src/analysis/binary.c
index 89370b2..44dfe6c 100644
--- a/src/analysis/binary.c
+++ b/src/analysis/binary.c
@@ -165,6 +165,9 @@ static const char *g_loaded_binary_describe(const GLoadedBinary *, bool);
 /* Détermine le nombre de vues disponibles pour un contenu. */
 static unsigned int g_loaded_binary_count_views(const GLoadedBinary *);
 
+/* Fournit le nom d'une vue donnée d'un contenu chargé. */
+static const char *g_loaded_binary_get_view_name(const GLoadedBinary *, unsigned int);
+
 /* Met en place la vue demandée pour un contenu binaire. */
 static GtkWidget *g_loaded_binary_build_view(GLoadedBinary *, unsigned int);
 
@@ -278,6 +281,7 @@ static void g_loaded_binary_interface_init(GLoadedContentInterface *iface)
     iface->describe = (describe_loaded_fc)g_loaded_binary_describe;
 
     iface->count_views = (count_loaded_views_fc)g_loaded_binary_count_views;
+    iface->get_view_name = (get_loaded_view_name_fc)g_loaded_binary_get_view_name;
     iface->build_view = (build_loaded_view_fc)g_loaded_binary_build_view;
     iface->get_view_index = (get_loaded_view_index_fc)g_loaded_binary_get_view_index;
 
@@ -1641,6 +1645,44 @@ static unsigned int g_loaded_binary_count_views(const GLoadedBinary *binary)
 *  Paramètres  : binary = contenu chargé à consulter.                         *
 *                index  = indice de la vue ciblée.                            *
 *                                                                             *
+*  Description : Fournit le nom d'une vue donnée d'un contenu chargé.         *
+*                                                                             *
+*  Retour      : Désignation humainement lisible.                             *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static const char *g_loaded_binary_get_view_name(const GLoadedBinary *binary, unsigned int index)
+{
+    const char *result;                     /* Désignation à retourner     */
+
+    switch (index)
+    {
+        case BVW_BLOCK:
+            result = _("Text view");
+            break;
+
+        case BVW_GRAPH:
+            result = _("Graph view");
+            break;
+
+        default:
+            assert(false);
+            result = NULL;
+            break;
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : binary = contenu chargé à consulter.                         *
+*                index  = indice de la vue ciblée.                            *
+*                                                                             *
 *  Description : Met en place la vue demandée pour un contenu binaire.        *
 *                                                                             *
 *  Retour      : Composant graphique nouveau.                                 *
@@ -1654,8 +1696,6 @@ static GtkWidget *g_loaded_binary_build_view(GLoadedBinary *binary, unsigned int
     GtkWidget *result;                      /* Support à retourner         */
     GtkWidget *display;                     /* Composant d'affichage       */
 
-    assert(index < g_loaded_binary_count_views(binary));
-
     switch (index)
     {
         case BVW_BLOCK:
@@ -1735,8 +1775,6 @@ static GDisplayOptions *g_loaded_binary_get_display_options(const GLoadedBinary
 {
     GDisplayOptions *result;                /* Instance à renvoyer         */
 
-    assert(index < BVW_COUNT);
-
     if (index < BVW_COUNT)
         result = binary->options[index];
     else
diff --git a/src/analysis/loaded-int.h b/src/analysis/loaded-int.h
index 044dad7..ed7d84a 100644
--- a/src/analysis/loaded-int.h
+++ b/src/analysis/loaded-int.h
@@ -51,6 +51,9 @@ typedef const char * (* describe_loaded_fc) (const GLoadedContent *, bool);
 /* Détermine le nombre de vues disponibles pour un contenu. */
 typedef unsigned int (* count_loaded_views_fc) (const GLoadedContent *);
 
+/* Fournit le nom d'une vue donnée d'un contenu chargé. */
+typedef const char * (* get_loaded_view_name_fc) (const GLoadedContent *, unsigned int);
+
 /* Met en place la vue demandée pour un contenu chargé. */
 typedef GtkWidget * (* build_loaded_view_fc) (GLoadedContent *, unsigned int);
 
@@ -79,6 +82,7 @@ struct _GLoadedContentIface
     describe_loaded_fc describe;            /* Description de contenu      */
 
     count_loaded_views_fc count_views;      /* Compteur de vues            */
+    get_loaded_view_name_fc get_view_name;  /* Désignation d'une vue donnée*/
     build_loaded_view_fc build_view;        /* Mise en place de vues       */
     get_loaded_view_index_fc get_view_index;/* Récupération d'indice de vue*/
 
diff --git a/src/analysis/loaded.c b/src/analysis/loaded.c
index 28aea43..4f8cfea 100644
--- a/src/analysis/loaded.c
+++ b/src/analysis/loaded.c
@@ -403,6 +403,35 @@ unsigned int g_loaded_content_count_views(const GLoadedContent *content)
 *  Paramètres  : content = contenu chargé à consulter.                        *
 *                index   = indice de la vue ciblée.                           *
 *                                                                             *
+*  Description : Fournit le nom d'une vue donnée d'un contenu chargé.         *
+*                                                                             *
+*  Retour      : Désignation humainement lisible.                             *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+const char *g_loaded_content_get_view_name(const GLoadedContent *content, unsigned int index)
+{
+    const char *result;                     /* Désignation à retourner     */
+    GLoadedContentIface *iface;             /* Interface utilisée          */
+
+    iface = G_LOADED_CONTENT_GET_IFACE(content);
+
+    assert(index <= g_loaded_content_count_views(content));
+
+    result = iface->get_view_name(content, index);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : content = contenu chargé à consulter.                        *
+*                index   = indice de la vue ciblée.                           *
+*                                                                             *
 *  Description : Met en place la vue demandée pour un contenu chargé.         *
 *                                                                             *
 *  Retour      : Composant graphique nouveau.                                 *
diff --git a/src/analysis/loaded.h b/src/analysis/loaded.h
index 66d448a..71e1ff6 100644
--- a/src/analysis/loaded.h
+++ b/src/analysis/loaded.h
@@ -87,6 +87,9 @@ const char *g_loaded_content_describe(const GLoadedContent *, bool);
 /* Détermine le nombre de vues disponibles pour un contenu. */
 unsigned int g_loaded_content_count_views(const GLoadedContent *);
 
+/* Fournit le nom d'une vue donnée d'un contenu chargé. */
+const char *g_loaded_content_get_view_name(const GLoadedContent *, unsigned int);
+
 /* Met en place la vue demandée pour un contenu chargé. */
 GtkWidget *g_loaded_content_build_view(GLoadedContent *, unsigned int);
 
diff --git a/src/glibext/gdisplayoptions.c b/src/glibext/gdisplayoptions.c
index 8641f59..9ab2063 100644
--- a/src/glibext/gdisplayoptions.c
+++ b/src/glibext/gdisplayoptions.c
@@ -263,6 +263,36 @@ void g_display_options_add(GDisplayOptions *options, const char *name, bool valu
 *  Paramètres  : options = options à consulter.                               *
 *                index   = indice de l'option concernée.                      *
 *                                                                             *
+*  Description : Fournit la désignation d'une option donnée.                  *
+*                                                                             *
+*  Retour      : Nom humainement lisible.                                     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+const char *g_display_options_get_name(const GDisplayOptions *options, size_t index)
+{
+    char *result;                           /* Désignation à retourner     */
+
+    assert(index < options->count);
+
+    if (index < options->count)
+        result = options->names[index];
+
+    else
+        result = NULL;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : options = options à consulter.                               *
+*                index   = indice de l'option concernée.                      *
+*                                                                             *
 *  Description : Fournit la valeur d'une option donnée.                       *
 *                                                                             *
 *  Retour      : Valeur attribuée.                                            *
diff --git a/src/glibext/gdisplayoptions.h b/src/glibext/gdisplayoptions.h
index 5697385..7549897 100644
--- a/src/glibext/gdisplayoptions.h
+++ b/src/glibext/gdisplayoptions.h
@@ -57,6 +57,9 @@ size_t g_display_options_count(const GDisplayOptions *);
 /* Ajoute une nouvelle option à l'ensemble. */
 void g_display_options_add(GDisplayOptions *, const char *, bool);
 
+/* Fournit la désignation d'une option donnée. */
+const char *g_display_options_get_name(const GDisplayOptions *, size_t);
+
 /* Fournit la valeur d'une option donnée. */
 bool g_display_options_get(const GDisplayOptions *, size_t);
 
diff --git a/src/gtkext/gtkdisplaypanel.c b/src/gtkext/gtkdisplaypanel.c
index 706e8f7..97a4276 100644
--- a/src/gtkext/gtkdisplaypanel.c
+++ b/src/gtkext/gtkdisplaypanel.c
@@ -91,14 +91,14 @@ static void gtk_display_panel_update_adjustment(GtkDisplayPanel *, GtkOrientatio
 /* Réagit à un défilement chez une barre associée au composant.*/
 static void gtk_display_panel_adjustment_value_changed(GtkAdjustment *, GtkDisplayPanel *);
 
-/* Réagit à un changement des règles d'affichage. */
-static void on_view_panel_binary_option_change(GLoadedBinary *, BinaryView, BufferLineColumn, GtkDisplayPanel *);
-
 
 
 /* ----------------------- INTERFACE DE PANNEAU DE CHARGEMENT ----------------------- */
 
 
+/* Réagit à un changement des règles d'affichage. */
+static void on_display_panel_option_change(GDisplayOptions *, size_t, bool, GtkDisplayPanel *);
+
 /* Associe à un panneau d'affichage un binaire chargé. */
 static void gtk_display_panel_set_content(GtkDisplayPanel *, GLoadedContent *);
 
@@ -860,34 +860,6 @@ void gtk_display_panel_draw_border(GtkDisplayPanel *panel, cairo_t *cr)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : binary = bianire dont les consignes d'affichage ont évolué.  *
-*                view   = type d'affichage à considérer.                      *
-*                col    = colonne dont le statut a changé.                    *
-*                panel  = composant GTK à consulter.                          *
-*                                                                             *
-*  Description : Réagit à un changement des règles d'affichage.               *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void on_view_panel_binary_option_change(GLoadedBinary *binary, BinaryView view, BufferLineColumn col, GtkDisplayPanel *panel)
-{
-    if (panel->view_index == view)
-    {
-        gtk_widget_queue_resize(gtk_widget_get_parent(GTK_WIDGET(panel)));
-        gtk_widget_queue_resize(GTK_WIDGET(panel));
-        gtk_widget_queue_draw(GTK_WIDGET(panel));
-
-    }
-
-}
-
-
-/******************************************************************************
-*                                                                             *
 *  Paramètres  : panel = composant GTK à consulter.                           *
 *                                                                             *
 *  Description : Indique la position courante du curseur.                     *
@@ -1047,6 +1019,30 @@ void gtk_display_panel_compute_relative_coords(GtkDisplayPanel *panel, gint *x,
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : options = options à mettre à jour.                           *
+*                index   = indice de l'option concernée.                      *
+*                value   = nouvelle valeur à intégrer.                        *
+*                panel   = composant GTK à consulter.                         *
+*                                                                             *
+*  Description : Réagit à un changement des règles d'affichage.               *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void on_display_panel_option_change(GDisplayOptions *options, size_t index, bool value, GtkDisplayPanel *panel)
+{
+    gtk_widget_queue_resize(gtk_widget_get_parent(GTK_WIDGET(panel)));
+    gtk_widget_queue_resize(GTK_WIDGET(panel));
+    gtk_widget_queue_draw(GTK_WIDGET(panel));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : panel   = composant GTK à mettre à jour.                     *
 *                content = binaire associé à intégrer.                        *
 *                                                                             *
@@ -1069,7 +1065,7 @@ static void gtk_display_panel_set_content(GtkDisplayPanel *panel, GLoadedContent
     if (GTK_DISPLAY_PANEL_GET_CLASS(panel)->attach != NULL) /* REMME */
         GTK_DISPLAY_PANEL_GET_CLASS(panel)->attach(panel, panel->binary);
 
-    g_signal_connect(content, "value-changed", G_CALLBACK(on_view_panel_binary_option_change), panel);
+    g_signal_connect(panel->options, "value-changed", G_CALLBACK(on_display_panel_option_change), panel);
 
 }
 
diff --git a/src/gui/editor.c b/src/gui/editor.c
index 5034104..9fffde8 100644
--- a/src/gui/editor.c
+++ b/src/gui/editor.c
@@ -1391,10 +1391,10 @@ static void on_dock_item_switch(GtkDockStation *station, GtkWidget *widget, gpoi
     GLoadedPanel *panel;                    /* Vue du contenu chargé       */
     GLoadedContent *content;                /* Contenu en cours d'édition  */
 
-    if (GTK_IS_SCROLLED_WINDOW(widget))
+    if (!G_IS_LOADED_PANEL(widget) && GTK_IS_SCROLLED_WINDOW(widget))
         widget = gtk_bin_get_child(GTK_BIN(widget));
 
-    if (GTK_IS_VIEWPORT(widget))
+    if (!G_IS_LOADED_PANEL(widget) && GTK_IS_VIEWPORT(widget))
         widget = gtk_bin_get_child(GTK_BIN(widget));
 
     if (G_IS_LOADED_PANEL(widget))
diff --git a/src/gui/menus/menubar.c b/src/gui/menus/menubar.c
index bc5a045..863ac54 100644
--- a/src/gui/menus/menubar.c
+++ b/src/gui/menus/menubar.c
@@ -282,6 +282,8 @@ GEditorItem *g_menu_bar_new(GObject *ref)
 
 static void change_menubar_current_content(GMenuBar *bar, GLoadedContent *old, GLoadedContent *new)
 {
+    rebuild_menu_view_for_content(bar->view, new);
+
     update_access_for_content_in_menu_binary(new);
 
 }
@@ -305,7 +307,8 @@ static void change_menubar_current_view(GMenuBar *bar, GLoadedPanel *old, GLoade
 {
     update_access_for_view_in_menu_edition(new);
 
-    rebuild_menu_view(bar->view, new, bar);
+    rebuild_menu_view_for_view(bar->view, new);
+
     update_access_for_view_in_menu_view(G_EDITOR_ITEM(bar)->ref, new);
 
 }
diff --git a/src/gui/menus/view.c b/src/gui/menus/view.c
index 31726c7..8c34950 100644
--- a/src/gui/menus/view.c
+++ b/src/gui/menus/view.c
@@ -26,6 +26,8 @@
 
 
 #include <assert.h>
+#include <malloc.h>
+#include <stdio.h>
 
 
 #include <i18n.h>
@@ -38,8 +40,6 @@
 #include "../core/panels.h"
 #include "../../analysis/loaded.h"
 #include "../../gtkext/easygtk.h"
-#include "../../gtkext/gtkblockdisplay.h"
-#include "../../gtkext/gtkgraphdisplay.h"
 
 
 
@@ -90,7 +90,6 @@ GtkWidget *build_menu_view(GObject *ref, GMenuBar *bar)
     GtkWidget *result;                      /* Support à retourner         */
     GtkWidget *menubar;                     /* Support pour éléments       */
     GtkWidget *submenuitem;                 /* Sous-élément de menu        */
-    GSList *rgroup;                         /* Groupe des boutons radio    */
 
     result = gtk_menu_item_new_with_mnemonic(_("_View"));
     gtk_widget_show(result);
@@ -108,26 +107,11 @@ GtkWidget *build_menu_view(GObject *ref, GMenuBar *bar)
     /* Séparation */
 
     submenuitem = qck_create_menu_separator();
+    g_object_set_data(ref, "mnu_view_start_panels", submenuitem);
     gtk_container_add(GTK_CONTAINER(menubar), submenuitem);
 
     /* Types de panneau de code */
 
-    submenuitem = qck_create_radio_menu_item(ref, "mnu_view_switch_textview", NULL, _("Text view"),
-                                             G_CALLBACK(mcb_view_change_support), NULL);
-    add_accelerator_to_widget(submenuitem, "F3");
-    g_object_set_data(G_OBJECT(submenuitem), "kind_of_view", GUINT_TO_POINTER(BVW_BLOCK));
-    g_object_set_data(G_OBJECT(submenuitem), "kind_of_display", GSIZE_TO_POINTER(GTK_TYPE_BLOCK_DISPLAY));
-    gtk_container_add(GTK_CONTAINER(menubar), submenuitem);
-
-    rgroup = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(submenuitem));
-
-    submenuitem = qck_create_radio_menu_item(ref, "mnu_view_switch_graphview", rgroup, _("Graph view"),
-                                             G_CALLBACK(mcb_view_change_support), NULL);
-    add_accelerator_to_widget(submenuitem, "F4");
-    g_object_set_data(G_OBJECT(submenuitem), "kind_of_view", GUINT_TO_POINTER(BVW_GRAPH));
-    g_object_set_data(G_OBJECT(submenuitem), "kind_of_display", GSIZE_TO_POINTER(GTK_TYPE_GRAPH_DISPLAY));
-    gtk_container_add(GTK_CONTAINER(menubar), submenuitem);
-
     submenuitem = qck_create_menu_item(ref, "mcb_view_switch_to_next_support", _("Switch to next"),
                                        G_CALLBACK(mcb_view_switch_to_next_support), NULL);
     add_accelerator_to_widget(submenuitem, "Tab");
@@ -141,23 +125,7 @@ GtkWidget *build_menu_view(GObject *ref, GMenuBar *bar)
     /* Séparation */
 
     submenuitem = qck_create_menu_separator();
-    gtk_container_add(GTK_CONTAINER(menubar), submenuitem);
-
-    /* Affichage des données */
-
-    submenuitem = qck_create_check_menu_item(ref, "mnu_view_display_off", _("Physical offset"),
-                                             G_CALLBACK(mcb_view_display_column), NULL);
-    g_object_set_data(G_OBJECT(submenuitem), "kind_of_opt", GUINT_TO_POINTER(BLC_PHYSICAL));
-    gtk_container_add(GTK_CONTAINER(menubar), submenuitem);
-
-    submenuitem = qck_create_check_menu_item(ref, "mnu_view_display_addr", _("Virtual address"),
-                                             G_CALLBACK(mcb_view_display_column), NULL);
-    g_object_set_data(G_OBJECT(submenuitem), "kind_of_opt", GUINT_TO_POINTER(BLC_VIRTUAL));
-    gtk_container_add(GTK_CONTAINER(menubar), submenuitem);
-
-    submenuitem = qck_create_check_menu_item(ref, "mnu_view_display_code", _("Binary code"),
-                                             G_CALLBACK(mcb_view_display_column), NULL);
-    g_object_set_data(G_OBJECT(submenuitem), "kind_of_opt", GUINT_TO_POINTER(BLC_BINARY));
+    g_object_set_data(ref, "mnu_view_start_options", submenuitem);
     gtk_container_add(GTK_CONTAINER(menubar), submenuitem);
 
     /* Séparation */
@@ -180,10 +148,9 @@ GtkWidget *build_menu_view(GObject *ref, GMenuBar *bar)
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : widget = menu principal à actualiser.                        *
-*                panel  = nouveau panneau d'affichage actif.                  *
-*                bar    = barre de menu parente.                              *
+*                new = nouveau contenu chargé à analyser.                     *
 *                                                                             *
-*  Description : Lance une actualisation du fait d'un changement de vue.      *
+*  Description : Réagit à un changement d'affichage principal de contenu.     *
 *                                                                             *
 *  Retour      : -                                                            *
 *                                                                             *
@@ -191,105 +158,246 @@ GtkWidget *build_menu_view(GObject *ref, GMenuBar *bar)
 *                                                                             *
 ******************************************************************************/
 
-void rebuild_menu_view(GtkWidget *widget, GLoadedPanel *panel, GMenuBar *bar)
+void rebuild_menu_view_for_content(GtkWidget *widget, GLoadedContent *new)
 {
-    GObject *ref;                           /* Espace de référencements    */
-    GtkRadioMenuItem *item;                 /* Elément de menu arbitraire  */
-    GSList *radios;                         /* Liste des menus d'affichage */
-    GSList *found;                          /* Elément de menu à activer   */
-    GLoadedContent *content;                /* Contenu global représenté   */
-    unsigned int view_index;                /* Indice de représentation    */
-    GDisplayOptions *options;               /* Règles d'affichage courantes*/
+    GObject *ref;                           /* Espace de références        */
+    GtkWidget *menubar;                     /* Support pour éléments       */
+    unsigned int i;                         /* Boucle de parcours          */
+    char *key;                              /* Clef pour accès ultérieurs  */
     GtkWidget *submenuitem;                 /* Sous-élément de menu        */
-    bool status;                            /* Consigne d'affichage        */
-
-    ref = g_editor_item_get_global_ref(G_EDITOR_ITEM(bar));
+    void *marker;                           /* Menu de référence           */
+    GList *list;                            /* Liste des éléments en place */
+    gint position;                          /* Point d'insertion           */
+    GList *iter;                            /* Boucle de parcours          */
+    unsigned int count;                     /* Nombre d'itérations à mener */
+    GSList *rgroup;                         /* Groupe des boutons radio    */
 
-    /* Types de panneau de code */
+    ref = get_global_ref();
 
-    item = GTK_RADIO_MENU_ITEM(g_object_get_data(ref, "mnu_view_switch_graphview"));
+    /* Retrait d'éventuels anciens menus */
 
-    radios = gtk_radio_menu_item_get_group(item);
+    menubar = gtk_menu_item_get_submenu(GTK_MENU_ITEM(widget));
 
-    void disconnect_display_radio(GtkWidget *wgt, gpointer unused)
+    for (i = 0; ; i++)
     {
-        g_signal_handlers_disconnect_by_func(wgt, G_CALLBACK(mcb_view_change_support), NULL);
+        asprintf(&key, "mnu_view_panel_%u", i);
 
-    }
+        submenuitem = g_object_get_data(ref, key);
 
-    g_slist_foreach(radios, (GFunc)disconnect_display_radio, NULL);
+        free(key);
 
-    gint find_suitable_display_radio(GObject *rdo, GObject *pnl)
+        if (submenuitem == NULL)
+            break;
+        else
+            gtk_container_remove(GTK_CONTAINER(menubar), GTK_WIDGET(submenuitem));
+
+    }
+
+    if (new != NULL)
     {
-        GType rdo_type;                     /* Type d'affichage supporté   */
-        GType pnl_type;                     /* Type du panneau affiché     */
+        /* Insertion des différentes vues */
+
+        marker = g_object_get_data(ref, "mnu_view_start_panels");
+
+        list = gtk_container_get_children(GTK_CONTAINER(menubar));
 
-        rdo_type = GPOINTER_TO_SIZE(g_object_get_data(rdo, "kind_of_display"));
+        position = 0;
 
-        pnl_type = G_OBJECT_TYPE(pnl);
+        for (iter = list; iter != NULL; iter = g_list_next(iter))
+        {
+            position++;
+
+            if (marker == iter->data)
+                break;
+
+        }
+
+        g_list_free(list);
+
+        count = g_loaded_content_count_views(new);
+
+        rgroup = NULL;
+
+        for (i = 0; i < count; i++)
+        {
+            asprintf(&key, "mnu_view_panel_%u", i);
+
+            submenuitem = qck_create_radio_menu_item(ref, key, rgroup,
+                                                     g_loaded_content_get_view_name(new, i),
+                                                     G_CALLBACK(mcb_view_change_support), NULL);
+            g_object_set_data(G_OBJECT(submenuitem), "kind_of_view", GUINT_TO_POINTER(i));
+
+            free(key);
+
+            asprintf(&key, "F%u", 3 + i);
+
+            add_accelerator_to_widget(submenuitem, key);
+
+            free(key);
+
+            if (rgroup == NULL)
+                rgroup = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(submenuitem));
 
-        return (rdo_type == pnl_type ? 0 : -1);
+            gtk_menu_shell_insert(GTK_MENU_SHELL(menubar), submenuitem, position + i);
+
+        }
 
     }
 
-    found = g_slist_find_custom(radios, G_OBJECT(panel), (GCompareFunc)find_suitable_display_radio);
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : widget = menu principal à actualiser.                        *
+*                new    = nouvelle vue du contenu chargé analysé.             *
+*                                                                             *
+*  Description : Lance une actualisation du fait d'un changement de support.  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void rebuild_menu_view_for_view(GtkWidget *widget, GLoadedPanel *new)
+{
+    GObject *ref;                           /* Espace de références        */
+    GLoadedContent *content;                /* Contenu en cours d'analyse  */
+    unsigned int index;                     /* Indice de la vue            */
+
+    GtkWidget *menubar;                     /* Support pour éléments       */
+    void *marker;                           /* Menu de référence           */
+    size_t i;                               /* Boucle de parcours          */
+    char *key;                              /* Clef pour accès ultérieurs  */
+    GtkWidget *submenuitem;                 /* Sous-élément de menu        */
+
+
+
+    GtkRadioMenuItem *item;                 /* Elément de menu arbitraire  */
+    GSList *radios;                         /* Liste des menus d'affichage */
+
+    GList *list;                            /* Liste des éléments en place */
+    gint position;                          /* Point d'insertion           */
+    GList *iter;                            /* Boucle de parcours          */
+
+    GDisplayOptions *options;               /* Paramètres de rendus        */
+    size_t count;                           /* Nombre d'itérations à mener */
+    bool status;                            /* Consigne d'affichage        */
+
+    ref = get_global_ref();
+
+    content = get_current_content();
+    assert((content == NULL && new == NULL) || (content != NULL && new != NULL));
 
-    assert(found != NULL);
+    /* Retrait d'éventuels anciens menus */
 
-    gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(found->data), TRUE);
+    menubar = gtk_menu_item_get_submenu(GTK_MENU_ITEM(widget));
 
-    void reconnect_display_radio(GtkWidget *wgt, gpointer unused)
+    marker = g_object_get_data(ref, "mnu_view_start_options");
+
+    for (i = 0; ; i++)
     {
-        g_signal_connect(wgt, "toggled", G_CALLBACK(mcb_view_change_support), NULL);
+        asprintf(&key, "mnu_view_display_option_%zu", i);
+
+        submenuitem = g_object_get_data(ref, key);
+
+        free(key);
+
+        if (submenuitem == NULL)
+            break;
+        else
+            gtk_container_remove(GTK_CONTAINER(menubar), GTK_WIDGET(submenuitem));
 
     }
 
-    g_slist_foreach(radios, (GFunc)reconnect_display_radio, NULL);
+    if (content != NULL)
+    {
+        index = g_loaded_content_get_view_index(content, GTK_WIDGET(new));
 
-    /* Séparation */
+        /* Mise à jour du choix de la vue */
 
-    content = g_loaded_panel_get_content(panel);
+        item = GTK_RADIO_MENU_ITEM(g_object_get_data(ref, "mnu_view_panel_0"));
 
-    view_index = g_loaded_content_get_view_index(content, GTK_WIDGET(panel));
+        radios = gtk_radio_menu_item_get_group(item);
 
-    options = g_loaded_content_get_display_options(content, view_index);
+        void disconnect_display_radio(GtkWidget *wgt, gpointer unused)
+        {
+            g_signal_handlers_disconnect_by_func(wgt, G_CALLBACK(mcb_view_change_support), NULL);
+        }
 
-    g_object_unref(G_OBJECT(content));
+        g_slist_foreach(radios, (GFunc)disconnect_display_radio, NULL);
+
+        asprintf(&key, "mnu_view_panel_%u", index);
+
+        item = GTK_RADIO_MENU_ITEM(g_object_get_data(ref, key));
+        gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), TRUE);
+
+        free(key);
 
-    /* Positions physiques */
+        void reconnect_display_radio(GtkWidget *wgt, gpointer unused)
+        {
+            g_signal_connect(wgt, "toggled", G_CALLBACK(mcb_view_change_support), NULL);
+        }
+
+        g_slist_foreach(radios, (GFunc)reconnect_display_radio, NULL);
+
+        /* Insertion des options de rendu */
 
-    submenuitem = g_object_get_data(ref, "mnu_view_display_off");
+        list = gtk_container_get_children(GTK_CONTAINER(menubar));
 
-    g_signal_handlers_disconnect_by_func(submenuitem, G_CALLBACK(mcb_view_display_column), NULL);
+        position = 0;
 
-    status = g_display_options_get(options, BLC_PHYSICAL);
-    gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(submenuitem), status);
+        for (iter = list; iter != NULL; iter = g_list_next(iter))
+        {
+            position++;
 
-    g_signal_connect(submenuitem, "toggled", G_CALLBACK(mcb_view_display_column), NULL);
+            if (marker == iter->data)
+                break;
 
-    /* Adresses virtuelles */
+        }
 
-    submenuitem = g_object_get_data(ref, "mnu_view_display_addr");
+        g_list_free(list);
 
-    g_signal_handlers_disconnect_by_func(submenuitem, G_CALLBACK(mcb_view_display_column), NULL);
+        options = g_loaded_content_get_display_options(content, index);
 
-    status = g_display_options_get(options, BLC_VIRTUAL);
-    gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(submenuitem), status);
+        count = g_display_options_count(options);
 
-    g_signal_connect(submenuitem, "toggled", G_CALLBACK(mcb_view_display_column), NULL);
+        for (i = 0; i < count; i++)
+        {
+            asprintf(&key, "mnu_view_display_option_%zu", i);
 
-    /* Code binaire */
+            submenuitem = qck_create_check_menu_item(ref, key,
+                                                     g_display_options_get_name(options, i),
+                                                     G_CALLBACK(mcb_view_display_column), NULL);
+            g_object_set_data(G_OBJECT(submenuitem), "kind_of_opt", GUINT_TO_POINTER(i));
 
-    submenuitem = g_object_get_data(ref, "mnu_view_display_code");
+            gtk_menu_shell_insert(GTK_MENU_SHELL(menubar), submenuitem, position + i);
 
-    g_signal_handlers_disconnect_by_func(submenuitem, G_CALLBACK(mcb_view_display_column), NULL);
+            free(key);
 
-    status = g_display_options_get(options, BLC_BINARY);
-    gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(submenuitem), status);
+            /**
+             * Un signal va être émis pour le menu, mais il n'ira pas très loin :
+             * l'ensemble des options ne notifie un changement que si changement il y a !
+             */
 
-    g_signal_connect(submenuitem, "toggled", G_CALLBACK(mcb_view_display_column), NULL);
+            status = g_display_options_get(options, i);
+            gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(submenuitem), status);
 
-    g_object_unref(G_OBJECT(options));
+        }
+
+        g_object_unref(G_OBJECT(options));
+
+        g_object_unref(G_OBJECT(content));
+
+    }
+
+    else
+        count = 0;
+
+    /* Utilité de la séparation ? */
+
+    gtk_widget_set_visible(GTK_WIDGET(marker), count > 0);
 
 }
 
@@ -309,28 +417,10 @@ void rebuild_menu_view(GtkWidget *widget, GLoadedPanel *panel, GMenuBar *bar)
 
 void update_access_for_view_in_menu_view(GObject *ref, GLoadedPanel *panel)
 {
-    gboolean access;                        /* Accès à déterminer          */
-    GtkWidget *item;                        /* Elément de menu à traiter   */
-
-    /* Préliminaire */
-
-    access = (panel != NULL);
-
     /* Bascules */
 
     update_switch_access_in_menu_view();
 
-    /* Affichage des données */
-
-    item = GTK_WIDGET(g_object_get_data(ref, "mnu_view_display_off"));
-    gtk_widget_set_sensitive(item, access);
-
-    item = GTK_WIDGET(g_object_get_data(ref, "mnu_view_display_addr"));
-    gtk_widget_set_sensitive(item, access);
-
-    item = GTK_WIDGET(g_object_get_data(ref, "mnu_view_display_code"));
-    gtk_widget_set_sensitive(item, access);
-
 }
 
 
diff --git a/src/gui/menus/view.h b/src/gui/menus/view.h
index fadf881..a6491bd 100644
--- a/src/gui/menus/view.h
+++ b/src/gui/menus/view.h
@@ -37,8 +37,11 @@
 /* Construit le menu "Affichage". */
 GtkWidget *build_menu_view(GObject *, GMenuBar *);
 
-/* Lance une actualisation du fait d'un changement de vue. */
-void rebuild_menu_view(GtkWidget *, GLoadedPanel *, GMenuBar *);
+/* Réagit à un changement d'affichage principal de contenu. */
+void rebuild_menu_view_for_content(GtkWidget *, GLoadedContent *);
+
+/* Lance une actualisation du fait d'un changement de support. */
+void rebuild_menu_view_for_view(GtkWidget *, GLoadedPanel *);
 
 /* Met à jour les accès du menu "Affichage" selon le contenu. */
 void update_access_for_view_in_menu_view(GObject *, GLoadedPanel *);
-- 
cgit v0.11.2-87-g4458