From c3aba0893c29cc098c029306fd7a4c8c1fa2eee2 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Sun, 28 Oct 2012 15:59:12 +0000
Subject: Updated the code of the old panel and displayed found strings again.

git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@276 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
---
 ChangeLog                  |  33 ++++
 src/arch/archbase.c        |   9 +-
 src/format/dex/dex.c       |   8 +
 src/format/dex/pool.c      |  38 +++++
 src/format/dex/pool.h      |   3 +
 src/format/symbol.c        |   2 +-
 src/gtkext/easygtk.c       |  38 +++++
 src/gtkext/easygtk.h       |   3 +
 src/gui/panels/Makefile.am |   1 +
 src/gui/panels/panel-int.h |   2 +-
 src/gui/panels/panel.c     | 206 ++++++++++++++++++------
 src/gui/panels/strings.c   | 392 +++++++++++++++++++++++++++++++++++++++++++++
 src/gui/panels/strings.h   |  65 ++++++++
 src/gui/panels/symbols.c   |   6 +-
 src/gui/panels/symbols.h   |   2 +-
 15 files changed, 753 insertions(+), 55 deletions(-)
 create mode 100644 src/gui/panels/strings.c
 create mode 100644 src/gui/panels/strings.h

diff --git a/ChangeLog b/ChangeLog
index f4f1c1d..af9d3e2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,36 @@
+12-10-28  Cyrille Bagard <nocbos@gmail.com>
+
+	* src/arch/archbase.c:
+	Remove GCC warnings about print format.
+
+	* src/format/dex/dex.c:
+	* src/format/dex/pool.c:
+	* src/format/dex/pool.h:
+	Register all strings found in the Dex pool.
+
+	* src/format/symbol.c:
+	Remove a GCC warning by fixing a typo.
+
+	* src/gtkext/easygtk.c:
+	* src/gtkext/easygtk.h:
+	Provide a function to create menus with image.
+
+	* src/gui/panels/Makefile.am:
+	Add the strings.[ch] files to libguipanels_la_SOURCES.
+
+	* src/gui/panels/panel.c:
+	* src/gui/panels/panel-int.h:
+	Rewrite some parts of the code to improve panel docking.
+
+	* src/gui/panels/strings.c:
+	* src/gui/panels/strings.h:
+	Move entries: update the code of the old panel and display found
+	strings again.
+
+	* src/gui/panels/symbols.c:
+	* src/gui/panels/symbols.h:
+	Typo and clean the code.
+
 12-10-22  Cyrille Bagard <nocbos@gmail.com>
 
 	* src/panel/log.c:
diff --git a/src/arch/archbase.c b/src/arch/archbase.c
index 61e2396..6241164 100644
--- a/src/arch/archbase.c
+++ b/src/arch/archbase.c
@@ -24,6 +24,7 @@
 #include "archbase.h"
 
 
+#include <inttypes.h>
 #include <stdio.h>
 
 
@@ -49,22 +50,22 @@ size_t vmpa_to_string(vmpa_t addr, MemoryDataSize msize, char buffer[VMPA_MAX_SI
     switch (msize)
     {
         case MDS_8_BITS:
-            snprintf(buffer, VMPA_MAX_SIZE,"0x%02llx", addr);
+            snprintf(buffer, VMPA_MAX_SIZE,"0x%02" PRIx64, addr);
             result = 4;
             break;
 
         case MDS_16_BITS:
-            snprintf(buffer, VMPA_MAX_SIZE, "0x%04llx", addr);
+            snprintf(buffer, VMPA_MAX_SIZE, "0x%04" PRIx64, addr);
             result = 6;
             break;
 
         case MDS_32_BITS:
-            snprintf(buffer, VMPA_MAX_SIZE, "0x%08llx", addr);
+            snprintf(buffer, VMPA_MAX_SIZE, "0x%08" PRIx64, addr);
             result = 10;
             break;
 
         case MDS_64_BITS:
-            snprintf(buffer, VMPA_MAX_SIZE, "0x%016llx", addr);
+            snprintf(buffer, VMPA_MAX_SIZE, "0x%016" PRIx64, addr);
             result = 18;
             break;
 
diff --git a/src/format/dex/dex.c b/src/format/dex/dex.c
index b286f7c..f0fb421 100755
--- a/src/format/dex/dex.c
+++ b/src/format/dex/dex.c
@@ -197,6 +197,14 @@ GBinFormat *g_dex_format_new(const bin_t *content, off_t length)
     g_dex_format_find_all_sources(result);
 
 
+
+    if (!find_all_dex_strings(result))
+    {
+        g_object_unref(G_OBJECT(result));
+        return NULL;
+    }
+
+
     return G_BIN_FORMAT(result);
 
 }
diff --git a/src/format/dex/pool.c b/src/format/dex/pool.c
index 9237839..f8c5a4a 100644
--- a/src/format/dex/pool.c
+++ b/src/format/dex/pool.c
@@ -24,6 +24,9 @@
 #include "pool.h"
 
 
+#include <string.h>
+
+
 #include "dex-int.h"
 #include "../mangling/demangler.h"
 
@@ -31,6 +34,41 @@
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : format = description de l'exécutable à analyser.             *
+*                                                                             *
+*  Description : Charge en mémoire toutes les chaînes trouvées.               *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool find_all_dex_strings(GDexFormat *format)
+{
+    uint32_t i;                             /* Boucle de parcours          */
+    const char *text;                       /* Texte issu du binaire       */
+    GBinSymbol *symbol;                     /* Nouveau symbole construit   */
+
+    for (i = 0; i < format->header.string_ids_size; i++)
+    {
+        text = get_string_from_dex_pool(format, i);
+        if (text == NULL) continue;
+
+        symbol = g_binary_symbol_new(STP_STRING, NULL, i);
+        g_binary_symbol_set_alt_name(symbol, strdup(text));
+
+        g_binary_format_add_symbol(G_BIN_FORMAT(format), symbol);
+
+    }
+
+    return true;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : format = représentation interne du format DEX à consulter.   *
 *                index  = index du type recherchée.                           *
 *                                                                             *
diff --git a/src/format/dex/pool.h b/src/format/dex/pool.h
index 6894da1..62c3aef 100644
--- a/src/format/dex/pool.h
+++ b/src/format/dex/pool.h
@@ -30,6 +30,9 @@
 
 
 
+/* Charge en mémoire toutes les chaînes trouvées. */
+bool find_all_dex_strings(GDexFormat *);
+
 /* Extrait une chaîne de caractères d'une table DEX. */
 const char *get_string_from_dex_pool(const GDexFormat *, uint32_t);
 
diff --git a/src/format/symbol.c b/src/format/symbol.c
index 3ac2d6d..986586c 100644
--- a/src/format/symbol.c
+++ b/src/format/symbol.c
@@ -247,7 +247,7 @@ off_t g_binary_symbol_get_size(const GBinSymbol *symbol)
 
 void g_binary_symbol_set_alt_name(GBinSymbol *symbol, char *alt)
 {
-    return symbol->alt = alt;
+    symbol->alt = alt;
 
 }
 
diff --git a/src/gtkext/easygtk.c b/src/gtkext/easygtk.c
index cdf3689..8aea549 100644
--- a/src/gtkext/easygtk.c
+++ b/src/gtkext/easygtk.c
@@ -557,6 +557,44 @@ GtkWidget *qck_create_menu_item(GObject *object, const char *name, const char *c
 *                                                                             *
 *  Paramètres  : object  = espace dédié à l'inscription de références.        *
 *                name    = nom à donner au nouveau composant.                 *
+*                id      = identifiant du menu prédéfini.                     *
+*                handler = éventuelle fonction de sélection associée.         *
+*                data    = données à transmettre avec l'événement si besoin.  *
+*                                                                             *
+*  Description : Crée et enregistre un composant 'GtkImageMenuItem'.          *
+*                                                                             *
+*  Retour      : Simple élément de menu mis en place.                         *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GtkWidget *qck_create_menu_item_with_stock_img(GObject *object, const char *name, const char *id, GCallback handler, gpointer data)
+{
+    GtkWidget *result;                      /* Résultat à renvoyer         */
+
+    result = gtk_image_menu_item_new_from_stock(id, NULL);
+
+    if (G_IS_OBJECT(object) && name != NULL)
+    {
+        g_object_ref(G_OBJECT(result));
+        g_object_set_data_full(object, name, result, (GDestroyNotify)g_object_unref);
+    }
+
+    gtk_widget_show(result);
+
+    if (handler != NULL)
+        g_signal_connect(result, "activate", handler, data);
+
+	return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : object  = espace dédié à l'inscription de références.        *
+*                name    = nom à donner au nouveau composant.                 *
 *                caption = intitulé du menu à créer.                          *
 *                handler = éventuelle fonction de sélection associée.         *
 *                data    = données à transmettre avec l'événement si besoin.  *
diff --git a/src/gtkext/easygtk.h b/src/gtkext/easygtk.h
index e46efee..ea234e0 100644
--- a/src/gtkext/easygtk.h
+++ b/src/gtkext/easygtk.h
@@ -77,6 +77,9 @@ GtkWidget *qck_create_combobox(GObject *, const char *, GCallback, gpointer);
 /* Crée et enregistre un composant 'GtkMenuItem'. */
 GtkWidget *qck_create_menu_item(GObject *, const char *, const char *, GCallback, gpointer);
 
+/* Crée et enregistre un composant 'GtkImageMenuItem'. */
+GtkWidget *qck_create_menu_item_with_stock_img(GObject *, const char *, const char *, GCallback, gpointer);
+
 /* Crée et enregistre un composant 'GtkCheckMenuItem'. */
 GtkWidget *qck_create_check_menu_item(GObject *, const char *, const char *, GCallback, gpointer);
 
diff --git a/src/gui/panels/Makefile.am b/src/gui/panels/Makefile.am
index 2678d54..f2ea661 100644
--- a/src/gui/panels/Makefile.am
+++ b/src/gui/panels/Makefile.am
@@ -4,6 +4,7 @@ noinst_LTLIBRARIES  = libguipanels.la
 libguipanels_la_SOURCES =				\
 	log.h log.c							\
 	panel.h panel.c						\
+	strings.h strings.c					\
 	symbols.h symbols.c					\
 	welcome.h welcome.c
 
diff --git a/src/gui/panels/panel-int.h b/src/gui/panels/panel-int.h
index e1c8932..def1934 100644
--- a/src/gui/panels/panel-int.h
+++ b/src/gui/panels/panel-int.h
@@ -56,7 +56,7 @@ typedef struct _panel_node
 {
     struct _panel_node *parent;             /* Noeud parent                */
 
-    char path;                              /* Chemin du nom courant       */
+    char *path;                             /* Chemin du nom courant       */
     size_t depth;                           /* Profondeur utilisée         */
 
     bool simple;                            /* Noeud sans division         */
diff --git a/src/gui/panels/panel.c b/src/gui/panels/panel.c
index cf4423d..3ad60b6 100644
--- a/src/gui/panels/panel.c
+++ b/src/gui/panels/panel.c
@@ -32,6 +32,7 @@
 
 #include "log.h"
 #include "panel-int.h"
+#include "strings.h"
 #include "symbols.h"
 #include "welcome.h"
 #include "../../gtkext/easygtk.h"
@@ -71,8 +72,14 @@ static void switch_panel_node_into_paned(panel_node *, bool, bool);
 /* Met en place un nouveau noeud dans une division. */
 static void attach_panel_node_to_paned(panel_node *, panel_node *, bool);
 
-/* Indique si un noeud correspond à la branche recherchée. */
-static bool is_panel_node_matching(const panel_node *, char);
+/* Valorise la correspondance entre un noeud et un chemin. */
+static int compute_panel_node_matching_score(const panel_node *, const char *);
+
+/* Calcule la longueur du plus court chemin vers un 'M'. */
+static size_t _compute_panel_node_main_level(const panel_node *);
+
+/* Recherche le noeud constituant la branche principale. */
+static panel_node *find_main_panel_node_branch(panel_node *, panel_node *);
 
 /* Place au bon endroit un panneau donné. */
 static void insert_item_as_panel_node(GPanelItem *, panel_node *, const char *, size_t);
@@ -350,6 +357,9 @@ void load_main_panels(GObject *ref)
     item = create_symbols_panel(ref);
     g_panel_item_dock(item);
 
+    item = create_strings_panel(ref);
+    g_panel_item_dock(item);
+
 }
 
 
@@ -380,7 +390,7 @@ static panel_node *create_simple_panel_node_for_item(GPanelItem *item, const cha
 
     result = (panel_node *)calloc(1, sizeof(panel_node));
 
-    result->path = path[depth];
+    result->path = strdup(path);
     result->depth = depth;
 
     result->simple = true;
@@ -438,7 +448,7 @@ static void switch_panel_node_into_paned(panel_node *current, bool horiz, bool f
 
     /* Achève la transformation */
 
-    current->path = '\0';
+    current->path = NULL;
 
     current->simple = false;
 
@@ -507,7 +517,51 @@ static void attach_panel_node_to_paned(panel_node *parent, panel_node *node, boo
 *  Paramètres  : node   = noeud d'où lancer les recherches.                   *
 *                target = identifiant de la position visée.                   *
 *                                                                             *
-*  Description : Indique si un noeud correspond à la branche recherchée.      *
+*  Description : Valorise la correspondance entre un noeud et un chemin.      *
+*                                                                             *
+*  Retour      : Bilan de l'évaluation.                                       *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static int compute_panel_node_matching_score(const panel_node *node, const char *target)
+{
+    int result;                             /* Bilan à retourner           */
+    size_t len;                             /* Longueur de comparaison     */
+    size_t i;                               /* Boucle de parcours          */
+
+    if (node->simple)
+    {
+        result = 0;
+
+        len = strlen(node->path);
+        len = MIN(len, strlen(target));
+
+        for (i = 0; i < len; i++)
+        {
+            if (node->path[i] != target[i]) break;
+            else result++;
+        }
+
+    }
+
+    else
+    {
+        result = compute_panel_node_matching_score(node->first, target);
+        result = MAX(result, compute_panel_node_matching_score(node->second, target));
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : node   = noeud d'où lancer les recherches.                   *
+*                                                                             *
+*  Description : Calcule la longueur du plus court chemin vers un 'M'.        *
 *                                                                             *
 *  Retour      : Bilan de l'évaluation.                                       *
 *                                                                             *
@@ -515,16 +569,59 @@ static void attach_panel_node_to_paned(panel_node *parent, panel_node *node, boo
 *                                                                             *
 ******************************************************************************/
 
-static bool is_panel_node_matching(const panel_node *node, char target)
+static size_t _compute_panel_node_main_level(const panel_node *node)
 {
-    if (node->path == target)
-        return true;
+    size_t result;                          /* Plus petit chemin à renvoyer*/
 
     if (node->simple)
-        return false;
+    {
+        result = strcspn(&node->path[node->depth], "M");
+
+        if (node->path[node->depth + result] == '\0')
+            result = SIZE_MAX;
 
-    return is_panel_node_matching(node->first, target)
-        || is_panel_node_matching(node->second, target);
+    }
+
+    else
+    {
+        result = _compute_panel_node_main_level(node->first);
+        result = MIN(result, _compute_panel_node_main_level(node->second));
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : a = première branche à analyser.                             *
+*                b = seconde branche à analyser.                              *
+*                                                                             *
+*  Description : Recherche le noeud constituant la branche principale.        *
+*                                                                             *
+*  Retour      : Branche principale ou NULL si aucune n'est idéale.           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static panel_node *find_main_panel_node_branch(panel_node *a, panel_node *b)
+{
+    panel_node *result;                     /* Trouvaille à remonter       */
+    size_t main_a;                          /* Proximité du 'M' côté a     */
+    size_t main_b;                          /* Proximité du 'M' côté b     */
+
+    main_a = _compute_panel_node_main_level(a);
+    main_b = _compute_panel_node_main_level(b);
+
+    if (main_a == SIZE_MAX && main_b == SIZE_MAX)
+        result = NULL;
+
+    else
+        result = (main_a < main_b ? a : b);
+
+    return result;
 
 }
 
@@ -550,15 +647,17 @@ static void insert_item_as_panel_node(GPanelItem *item, panel_node *node, const
     bool horiz;                             /* Traduction en composant     */
     bool first;                             /* Point d'insertion           */
     panel_node *new;                        /* Nouveau noeud créé          */
+    int score1;                             /* Score de la 1ère branche    */
+    int score2;                             /* Score de la 2nde branche    */
     panel_node *support;                    /* Noeud d'accueil désigné     */
 
     if (node->simple)
     {
         /* Si on est sur la bonne voie... */
-        if (path[depth] == '\0' || path[depth] == node->path)
+        if (compute_panel_node_matching_score(node, path) > 0)
         {
             /* Le parcours s'arrête ici ! */
-            if (path[depth] == '\0' || path[depth + 1] == '\0')
+            if (strcmp(node->path, path) == 0)
                 gtk_dock_panel_add_widget(GTK_DOCK_STATION(node->station),
                                           G_EDITOR_ITEM(item)->widget,
                                           G_EDITOR_ITEM(item)->name);
@@ -566,13 +665,13 @@ static void insert_item_as_panel_node(GPanelItem *item, panel_node *node, const
             /* On ne peut aller plus loin, on doit diviser... */
             else
             {
-                div = toupper(path[depth + 1]);
+                div = toupper(path[depth]);
                 first = (div == 'E' || div == 'S');
                 horiz = (div == 'W' || div == 'E');
 
                 switch_panel_node_into_paned(node, horiz, first);
 
-                new = create_simple_panel_node_for_item(item, path, depth + 1);
+                new = create_simple_panel_node_for_item(item, path, depth);
 
                 attach_panel_node_to_paned(node, new, !first);
 
@@ -603,50 +702,64 @@ static void insert_item_as_panel_node(GPanelItem *item, panel_node *node, const
 
     /* On regarde des autres côtés... */
 
-    else if (is_panel_node_matching(node->first, path[depth]))
-        insert_item_as_panel_node(item, node->first, path, depth + (node->first->simple ? 1 : 0));
-
-    else if (is_panel_node_matching(node->second, path[depth]))
-        insert_item_as_panel_node(item, node->second, path, depth + (node->second->simple ? 1 : 0));
-
-    /* On doit diviser qqch... */
     else
     {
-        /* Si l'élément doit passer en force */
-        if (isupper(path[depth]))
-        {
-            div = path[depth];
-            first = (div == 'E' || div == 'S');
-            horiz = (div == 'W' || div == 'E');
+        score1 = compute_panel_node_matching_score(node->first, path);
+        score2 = compute_panel_node_matching_score(node->second, path);
 
-            switch_panel_node_into_paned(node, horiz, first);
-
-            new = create_simple_panel_node_for_item(item, path, depth);
+        /* Si une descente est possible... */
+        if (score1 > 0 || score2 > 0)
+        {
+            if (node->first->simple || node->second->simple)
+                depth++;
 
-            attach_panel_node_to_paned(node, new, !first);
+            if (score1 > score2)
+                insert_item_as_panel_node(item, node->first, path, depth);
 
-            rebuild_panels_interface(node);
+            else
+                insert_item_as_panel_node(item, node->second, path, depth);
 
         }
 
+        /* Sinon, on doit diviser qqch... */
         else
         {
-            if (is_panel_node_matching(node->second, 'M'))
-                support = node->second;
+            /* Si l'élément doit passer en force */
+            if (isupper(path[depth]))
+            {
+                div = path[depth];
+                first = (div == 'E' || div == 'S');
+                horiz = (div == 'W' || div == 'E');
+
+                switch_panel_node_into_paned(node, horiz, first);
+
+                new = create_simple_panel_node_for_item(item, path, depth);
+
+                attach_panel_node_to_paned(node, new, !first);
+
+                rebuild_panels_interface(node);
+
+            }
+
             else
-                support = node->first;
+            {
+                support = find_main_panel_node_branch(node->first, node->second);
+                if (support == NULL)
+                    support = node->first;
 
-            div = toupper(path[depth]);
-            first = (div == 'E' || div == 'S');
-            horiz = (div == 'W' || div == 'E');
+                div = toupper(path[depth]);
+                first = (div == 'E' || div == 'S');
+                horiz = (div == 'W' || div == 'E');
 
-            switch_panel_node_into_paned(support, horiz, first);
+                switch_panel_node_into_paned(support, horiz, first);
 
-            new = create_simple_panel_node_for_item(item, path, depth);
+                new = create_simple_panel_node_for_item(item, path, depth);
 
-            attach_panel_node_to_paned(support, new, !first);
+                attach_panel_node_to_paned(support, new, !first);
 
-            rebuild_panels_interface(support);
+                rebuild_panels_interface(support);
+
+            }
 
         }
 
@@ -796,6 +909,7 @@ static void set_panel_node_size_request(const panel_node *node, const GtkRequisi
     GtkRequisition first_req;               /* Taille demandée par n°1     */
     GtkRequisition second_req;              /* Taille demandée par n°2     */
     gint handle_size;                       /* Taille de la séparation     */
+    panel_node *main_node;                  /* Branche principale          */
     gint position;                          /* Position de la séparation   */
     bool can_lower;                         /* Diminution possible ?       */
     bool can_upper;                         /* Augmentation possible ?     */
@@ -813,8 +927,10 @@ static void set_panel_node_size_request(const panel_node *node, const GtkRequisi
      * Définitions des bornes dans chacun des cas.
      */
 
+    main_node = find_main_panel_node_branch(node->first, node->second);
+
     /* Le premier noeud est le principal... */
-    if (is_panel_node_matching(node->first, 'M'))
+    if (node->first == main_node)
     {
         if (GTK_IS_HPANED(node->paned))
             position = (space->width * MAIN_PART_PERCENT) / 100;
@@ -827,7 +943,7 @@ static void set_panel_node_size_request(const panel_node *node, const GtkRequisi
     }
 
     /* Le second noeud est le principal... */
-    else if (is_panel_node_matching(node->second, 'M'))
+    else if (node->second == main_node)
     {
         if (GTK_IS_HPANED(node->paned))
             position = space->width - (space->width * MAIN_PART_PERCENT) / 100;
diff --git a/src/gui/panels/strings.c b/src/gui/panels/strings.c
new file mode 100644
index 0000000..605a700
--- /dev/null
+++ b/src/gui/panels/strings.c
@@ -0,0 +1,392 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * strings.c - panneau d'affichage des chaînes de caractères
+ *
+ * Copyright (C) 2008-2012 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 "strings.h"
+
+
+#include <inttypes.h>
+
+
+#include "panel-int.h"
+#include "../../common/extstr.h"
+#include "../../gtkext/easygtk.h"
+
+
+
+/* -------------------------- PARTIE PRINCIPALE DU PANNEAU -------------------------- */
+
+
+/* Panneau d'aperçu de graphiques (instance) */
+struct _GStringsPanel
+{
+    GPanelItem parent;                      /* A laisser en premier        */
+
+    GtkTreeView *treeview;                  /* Composant d'affichage       */
+    GtkTreeStore *store;                    /* Modèle de gestion           */
+
+    GLoadedBinary *binary;                  /* Binaire à prendre en compte */
+
+    GtkWidget *menubar;                     /* Support pour l'édition      */
+
+};
+
+
+/* Panneau d'aperçu de graphiques (classe) */
+struct _GStringsPanelClass
+{
+    GPanelItemClass parent;                 /* A laisser en premier        */
+
+};
+
+
+/* Colonnes de la liste des symboles */
+typedef enum _StringsColumn
+{
+    STC_ADDRESS,                            /* Adresse mémoire du symbole  */
+    STC_STRING,                             /* Désignation humaine         */
+    STC_RAW,                                /* Données non retouchées      */
+
+    STC_COUNT                               /* Nombre de colonnes          */
+
+} StringsColumn;
+
+
+/* Réagit à un changement d'affichage principal de contenu. */
+static void change_strings_panel_current_binary(GStringsPanel *, GLoadedBinary *);
+
+
+
+/* ------------------------- GESTIONS DES MENUS CONTEXTUELS ------------------------- */
+
+
+/* Affiche le menu d'édition propre aux chaînes trouvées. */
+static gboolean on_strings_button_press_event(GtkTreeView *, GdkEventButton *, GStringsPanel *);
+
+/* Réagit avec le menu "--- -> Copier". */
+static void mcb_strings_copy(GtkMenuItem *, GtkTreeView *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                            PARTIE PRINCIPALE DU PANNEAU                            */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type définit pour un panneau d'aperçu de graphiques. */
+G_DEFINE_TYPE(GStringsPanel, g_strings_panel, G_TYPE_PANEL_ITEM);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des panneaux d'aperçu de graphiques.    *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_strings_panel_class_init(GStringsPanelClass *klass)
+{
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : panel = instance à initialiser.                              *
+*                                                                             *
+*  Description : Initialise une instance de panneau d'aperçu de graphiques.   *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_strings_panel_init(GStringsPanel *panel)
+{
+    GEditorItem *base;                      /* Version basique d'instance  */
+    GObject *ref;                           /* Espace de référencement     */
+    GtkWidget *scrollwnd;                   /* Support défilant            */
+    GtkTreeStore *store;                    /* Modèle de gestion           */
+    GtkWidget *treeview;                    /* Affichage de la liste       */
+    GtkCellRenderer *renderer;              /* Moteur de rendu de colonne  */
+    GtkTreeViewColumn *column;              /* Colonne de la liste         */
+    GtkWidget *submenuitem;                 /* Sous-élément de menu        */
+
+    base = G_EDITOR_ITEM(panel);
+
+    base->widget = gtk_vbox_new(FALSE, 0);
+    gtk_widget_show(base->widget);
+
+    ref = G_OBJECT(base->widget);
+    g_object_set_data(ref, "panel", panel);
+
+    /* Liste des chaînes */
+
+    scrollwnd = gtk_scrolled_window_new(NULL, NULL);
+    gtk_widget_show(scrollwnd);
+    gtk_box_pack_start(GTK_BOX(base->widget), scrollwnd, TRUE, TRUE, 0);
+
+    gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwnd),
+                                   GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+    gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrollwnd), GTK_SHADOW_IN);
+
+    store = gtk_tree_store_new(STC_COUNT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
+    g_object_set_data(G_OBJECT(panel), "store", store);
+
+    treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
+    gtk_widget_show(treeview);
+    gtk_container_add(GTK_CONTAINER(scrollwnd), treeview);
+
+    g_object_unref(G_OBJECT(store));
+
+    column = gtk_tree_view_column_new();
+    gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
+    gtk_tree_view_set_expander_column(GTK_TREE_VIEW(treeview), column);
+
+    renderer = gtk_cell_renderer_text_new();
+    column = gtk_tree_view_column_new_with_attributes(_("Address"), renderer,
+                                                      "text", STC_ADDRESS, NULL);
+    gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
+
+    renderer = gtk_cell_renderer_text_new();
+    column = gtk_tree_view_column_new_with_attributes(_("String"), renderer,
+                                                      "markup", STC_STRING, NULL);
+    gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
+
+    /* Menu contextuel */
+
+    panel->menubar = gtk_menu_new();
+
+    submenuitem = qck_create_menu_item_with_stock_img(NULL, NULL, GTK_STOCK_COPY,
+                                                      G_CALLBACK(mcb_strings_copy), treeview);
+    gtk_container_add(GTK_CONTAINER(panel->menubar), submenuitem);
+
+    submenuitem = qck_create_menu_item(NULL, NULL, _("Find references..."), NULL, NULL);
+    gtk_container_add(GTK_CONTAINER(panel->menubar), submenuitem);
+
+    g_signal_connect(G_OBJECT(treeview), "button_release_event",
+                     G_CALLBACK(on_strings_button_press_event), panel);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : ref = espace de référencement global.                        *
+*                                                                             *
+*  Description : Crée un panneau d'affichage des symboles.                    *
+*                                                                             *
+*  Retour      : Adresse de la structure mise en place.                       *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GEditorItem *g_strings_panel_new(GObject *ref)
+{
+    GEditorItem *result;                    /* Structure à retourner       */
+
+    result = g_object_new(G_TYPE_STRINGS_PANEL, NULL);
+
+    g_panel_item_init_ext(G_PANEL_ITEM(result), ref, PANEL_STRINGS_ID,
+                          _("Strings"), G_EDITOR_ITEM(result)->widget, "SE");
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : ref = espace de référencement global.                        *
+*                                                                             *
+*  Description : Construit et intègre un panneau d'affichage des symboles.    *
+*                                                                             *
+*  Retour      : Adresse du panneau mis en place.                             *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GPanelItem *create_strings_panel(GObject *ref)
+{
+    GEditorItem *result;                    /* Elément réactif à renvoyer  */
+
+    result = g_strings_panel_new(ref);
+
+    /* Enregistre correctement le tout */
+    result->update_binary = (update_item_binary_fc)change_strings_panel_current_binary;
+    register_editor_item(result);
+
+    return G_PANEL_ITEM(result);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : panel  = panneau à mettre à jour.                            *
+*                binary = nouvelle instance de binaire analysé.               *
+*                                                                             *
+*  Description : Réagit à un changement d'affichage principal de contenu.     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void change_strings_panel_current_binary(GStringsPanel *panel, GLoadedBinary *binary)
+{
+    GtkTreeStore *store;                    /* Modèle de gestion           */
+    GExeFormat *format;                     /* Format de travail           */
+    size_t count;                           /* Nombre des chaînes          */
+    GBinSymbol **symbols;                   /* Liste des chaînes trouvées  */
+    size_t i;                               /* Boucle de parcours          */
+    char address[VMPA_MAX_SIZE];            /* Conversion de l'adresse     */
+    const char *raw;                        /* Texte brut trouvé           */
+    char *text;                             /* Version imprimable du texte */
+    GtkTreeIter iter;                       /* Point d'insertion           */
+
+    store = g_object_get_data(G_OBJECT(panel), "store");
+
+    format = g_loaded_binary_get_format(binary);
+    symbols = g_binary_format_get_symbols(G_BIN_FORMAT(format), &count);
+
+    for (i = 0; i < count; i++)
+    {
+        if (g_binary_symbol_get_target_type(symbols[i]) != STP_STRING) continue;
+
+        /* FIXME : adresses autres que 32 bits */
+        snprintf(address, VMPA_MAX_SIZE, "0x%08" PRIx64, g_binary_symbol_get_address(symbols[i]));
+
+        raw = g_binary_symbol_to_string(symbols[i]);
+
+        text = strdup(raw);
+        text = strrpl(text, "&", "&amp;");
+        text = strrpl(text, "<", "&lt;");
+        text = strrpl(text, ">", "&gt;");
+        text = strrpl(text, "\r", "<b>\\r</b>");
+        text = strrpl(text, "\n", "<b>\\n</b>");
+
+        gtk_tree_store_append(store, &iter, NULL);
+        gtk_tree_store_set(store, &iter,
+                           STC_ADDRESS, address,
+                           STC_STRING, text,
+                           STC_RAW, raw,
+                           -1);
+
+        free(text);
+
+    }
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                           GESTIONS DES MENUS CONTEXTUELS                           */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : treeview = composant GTK visé par l'opération.               *
+*                event    = informations liées à l'événement.                 *
+*                data     = référence vers le panneau contenant le menu.      *
+*                                                                             *
+*  Description : Affiche le menu d'édition propre aux chaînes trouvées.       *
+*                                                                             *
+*  Retour      : FALSE pour poursuivre la propagation de l'événement.         *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static gboolean on_strings_button_press_event(GtkTreeView *treeview, GdkEventButton *event, GStringsPanel *panel)
+{
+    gboolean result;                        /* Bilan d'action à renvoyer   */
+
+    result = FALSE;
+
+    if (event->type == GDK_BUTTON_RELEASE && event->button == 3)
+    {
+        gtk_menu_popup(GTK_MENU(panel->menubar),
+                       NULL, NULL, NULL, NULL,
+                       event->button, event->time);
+
+        result = TRUE;
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : menuitem = élément de menu sélectionné.                      *
+*                treeview = arbre contenant la sélection à exporter.          *
+*                                                                             *
+*  Description : Réagit avec le menu "--- -> Copier".                         *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void mcb_strings_copy(GtkMenuItem *menuitem, GtkTreeView *treeview)
+{
+    GtkTreeSelection *selection;            /* Sélection de l'arbre        */
+    GtkTreeIter iter;                       /* Point de sélection          */
+    GtkTreeModel *model;                    /* Modèle de gestion           */
+    gchar *string;                          /* Chaîne sélectionnée         */
+    GtkClipboard *clipboard;                /* Presse-papiers d'arrivée    */
+
+    selection = gtk_tree_view_get_selection(treeview);
+
+    if (gtk_tree_selection_get_selected(selection, &model, &iter))
+    {
+        gtk_tree_model_get(model, &iter, STC_RAW, &string, -1);
+
+        if (string != NULL)
+        {
+            clipboard = gtk_clipboard_get_for_display(gdk_display_get_default(),
+                                                      GDK_SELECTION_PRIMARY);
+
+            gtk_clipboard_set_text(clipboard, string, strlen(string));
+            g_free(string);
+
+        }
+
+    }
+
+}
diff --git a/src/gui/panels/strings.h b/src/gui/panels/strings.h
new file mode 100644
index 0000000..2ac2fbf
--- /dev/null
+++ b/src/gui/panels/strings.h
@@ -0,0 +1,65 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * strings.h - prototypes pour le panneau d'affichage des chaînes de caractères
+ *
+ * Copyright (C) 2008-2012 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_PANELS_STRINGS_H
+#define _GUI_PANELS_STRINGS_H
+
+
+#include <i18n.h>
+
+
+#include "panel.h"
+
+
+
+#define PANEL_STRINGS_ID _("Strings")
+
+
+#define G_TYPE_STRINGS_PANEL               g_strings_panel_get_type()
+#define G_STRINGS_PANEL(obj)               (G_TYPE_CHECK_INSTANCE_CAST((obj), g_strings_panel_get_type(), GStringsPanel))
+#define G_IS_STRINGS_PANEL(obj)            (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_strings_panel_get_type()))
+#define G_STRINGS_PANEL_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_STRINGS_PANEL, GStringsPanelClass))
+#define G_IS_STRINGS_PANEL_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_STRINGS_PANEL))
+#define G_STRINGS_PANEL_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_STRINGS_PANEL, GStringsPanelClass))
+
+
+/* Panneau d'affichage des symboles (instance) */
+typedef struct _GStringsPanel GStringsPanel;
+
+/* Panneau d'affichage des symboles (classe) */
+typedef struct _GStringsPanelClass GStringsPanelClass;
+
+
+/* Indique le type définit pour un panneau d'affichage des symboles. */
+GType g_strings_panel_get_type(void);
+
+/* Crée un panneau d'affichage des symboles. */
+GEditorItem *g_strings_panel_new(GObject *);
+
+/* Construit et intègre un panneau d'affichage des symboles. */
+GPanelItem *create_strings_panel(GObject *);
+
+
+
+#endif  /* _GUI_PANELS_STRINGS_H */
diff --git a/src/gui/panels/symbols.c b/src/gui/panels/symbols.c
index c51b2d1..87cdfa4 100644
--- a/src/gui/panels/symbols.c
+++ b/src/gui/panels/symbols.c
@@ -84,7 +84,7 @@ static void g_symbols_panel_init(GSymbolsPanel *);
 static void on_symbols_selection_change(GtkTreeSelection *, GSymbolsPanel *);
 
 /* Réagit à un changement d'affichage principal de contenu. */
-void change_symbols_panel_current_binary(GSymbolsPanel *, GLoadedBinary *);
+static void change_symbols_panel_current_binary(GSymbolsPanel *, GLoadedBinary *);
 
 
 
@@ -296,7 +296,7 @@ GEditorItem *g_symbols_panel_new(GObject *ref)
 
     result = g_object_new(G_TYPE_SYMBOLS_PANEL, NULL);
 
-    g_panel_item_init_ext(G_PANEL_ITEM(result), ref, PANEL_SYMBOL_ID,
+    g_panel_item_init_ext(G_PANEL_ITEM(result), ref, PANEL_SYMBOLS_ID,
                           _("Binary symbols"), G_EDITOR_ITEM(result)->widget, "e");
 
     return result;
@@ -383,7 +383,7 @@ static void on_symbols_selection_change(GtkTreeSelection *selection, GSymbolsPan
 *                                                                             *
 ******************************************************************************/
 
-void change_symbols_panel_current_binary(GSymbolsPanel *panel, GLoadedBinary *binary)
+static void change_symbols_panel_current_binary(GSymbolsPanel *panel, GLoadedBinary *binary)
 {
     GtkToggleToolButton *button;            /* Mode de représentation      */
     GtkRequisition req;                     /* Nouvelle taille idéale      */
diff --git a/src/gui/panels/symbols.h b/src/gui/panels/symbols.h
index 182238a..1a9316d 100644
--- a/src/gui/panels/symbols.h
+++ b/src/gui/panels/symbols.h
@@ -33,7 +33,7 @@
 
 
 
-#define PANEL_SYMBOL_ID _("Symbols")
+#define PANEL_SYMBOLS_ID _("Symbols")
 
 
 #define G_TYPE_SYMBOLS_PANEL               g_symbols_panel_get_type()
-- 
cgit v0.11.2-87-g4458