diff options
| -rw-r--r-- | ChangeLog | 5 | ||||
| -rw-r--r-- | src/gui/panels/symbols.c | 236 | 
2 files changed, 190 insertions, 51 deletions
| @@ -1,3 +1,8 @@ +16-09-28  Cyrille Bagard <nocbos@gmail.com> + +	* src/gui/panels/symbols.c: +	Update and improve the symbols panel. +  16-09-27  Cyrille Bagard <nocbos@gmail.com>  	* src/gui/menus/binary.c: diff --git a/src/gui/panels/symbols.c b/src/gui/panels/symbols.c index d1bca91..0cbb9eb 100644 --- a/src/gui/panels/symbols.c +++ b/src/gui/panels/symbols.c @@ -37,6 +37,7 @@  #include "panel-int.h" +#include "../../common/extstr.h"  #include "../../format/format.h"  #include "../../gtkext/easygtk.h"  #include "../../gtkext/support.h" @@ -79,6 +80,7 @@ typedef enum _SymbolsColumn      SBC_PICTURE,                            /* Image de représentation     */      SBC_NAME,                               /* Désignation humaine         */ +    SBC_ORIGINAL,                           /* Version brute d'origine     */      SBC_ADDRESS,                            /* Adresse mémoire du symbole  */      SBC_SECTION,                            /* Section d'appartenance      */ @@ -124,11 +126,11 @@ static void reload_symbols_for_new_list_view(GSymbolsPanel *);  /* S'assure qu'un noeud donné existe bien. */ -#if 0 -static GtkTreeIter ensure_symbol_node_exist(GtkTreeStore *, GtkTreeIter *, const char *); -#endif + +static GtkTreeIter ensure_symbol_node_exist(GSymbolsPanel *, GtkTreeIter *, const char *, const regmatch_t *, size_t); +  /* Détermine le point d'insertion parent d'une routine. */ -static bool find_parent_for_symbol(GtkTreeStore *, const GBinSymbol *, GtkTreeIter *); +static bool find_parent_for_symbol(GSymbolsPanel *, const GBinSymbol *, GtkTreeIter *, const regmatch_t *, size_t *);  /* Réagit à un changement d'affichage principal de contenu. */  static void reload_symbols_for_new_tree_view(GSymbolsPanel *); @@ -151,7 +153,10 @@ static void on_symbols_filter_changed(GtkSearchEntry *, GSymbolsPanel *);  static void do_filtering_on_symbols(GSymbolsPanel *);  /* Détermine si un nom de symbole doit être filtré ou non. */ -static bool is_symbol_filtered(GSymbolsPanel *, const GBinSymbol *); +static bool is_symbol_filtered(GSymbolsPanel *, const GBinSymbol *, regmatch_t *); + +/* Met en évidence le texte recherché en cas de correspondance. */ +static char *build_highlighted_name(const char *, const regmatch_t *, size_t); @@ -338,7 +343,7 @@ static void g_symbols_panel_init(GSymbolsPanel *panel)      gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrollwnd), GTK_SHADOW_IN);      panel->store = gtk_tree_store_new(SBC_COUNT, G_TYPE_OBJECT, CAIRO_GOBJECT_TYPE_SURFACE, G_TYPE_STRING, -                                      G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN); +                                      G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN);      treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(panel->store));      gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(treeview), FALSE); @@ -353,17 +358,18 @@ static void g_symbols_panel_init(GSymbolsPanel *panel)      /* Cellules d'affichage */ +    column = gtk_tree_view_column_new(); +      renderer = gtk_cell_renderer_pixbuf_new(); -    column = gtk_tree_view_column_new_with_attributes("", renderer, -                                                      "surface", SBC_PICTURE, -                                                      NULL); -    gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); +    gtk_tree_view_column_pack_start(column, renderer, FALSE); +    gtk_tree_view_column_add_attribute(column, renderer, "surface", SBC_PICTURE);      renderer = gtk_cell_renderer_text_new(); -    column = gtk_tree_view_column_new_with_attributes(_("Name"), renderer, -                                                      "text", SBC_NAME, -                                                      NULL); +    gtk_tree_view_column_pack_start(column, renderer, TRUE); +    gtk_tree_view_column_add_attribute(column, renderer, "markup", SBC_NAME);      gtk_tree_view_column_set_sort_column_id(column, SBC_NAME); + +    gtk_tree_view_column_set_title(column, _("Name"));      gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);      renderer = gtk_cell_renderer_text_new(); @@ -550,12 +556,16 @@ static void on_symbols_selection_change(GtkTreeSelection *selection, GSymbolsPan      {          gtk_tree_model_get(model, &iter, SBC_SYMBOL, &symbol, -1); -        range = g_binary_symbol_get_range(symbol); +        if (symbol != NULL) +        { +            range = g_binary_symbol_get_range(symbol); + +            vpanel = g_editor_item_get_current_view(G_EDITOR_ITEM(panel)); +            gtk_view_panel_request_move(vpanel, get_mrange_addr(range)); -        vpanel = g_editor_item_get_current_view(G_EDITOR_ITEM(panel)); -        gtk_view_panel_request_move(vpanel, get_mrange_addr(range)); +            g_object_unref(G_OBJECT(symbol)); -        g_object_unref(G_OBJECT(symbol)); +        }      } @@ -632,7 +642,10 @@ static void reload_symbols_for_new_list_view(GSymbolsPanel *panel)      GArchProcessor *proc;                   /* Architecture utilisée       */      MemoryDataSize size;                    /* Taille des localisations    */      size_t i;                               /* Boucle de parcours          */ +    regmatch_t match;                       /* Récupération des trouvailles*/      cairo_surface_t *icon;                  /* Image associée au symbole   */ +    const char *original;                   /* Etiquette brute d'origine   */ +    char *name;                             /* Etiquette mise en relief    */      const vmpa2t *addr;                     /* Localisation d'un symbole   */      char virt[VMPA_MAX_LEN];                /* Version humainement lisible */      GtkTreeIter iter;                       /* Point d'insertion           */ @@ -647,7 +660,7 @@ static void reload_symbols_for_new_list_view(GSymbolsPanel *panel)      for (i = 0; i < sym_count; i++)      { -        if (is_symbol_filtered(panel, symbols[i])) +        if (is_symbol_filtered(panel, symbols[i], &match))              continue;          switch (g_binary_symbol_get_target_type(symbols[i])) @@ -664,6 +677,9 @@ static void reload_symbols_for_new_list_view(GSymbolsPanel *panel)                  break;          } +        original = g_binary_symbol_get_label(symbols[i]); +        name = build_highlighted_name(original, &match, 0); +          addr = get_mrange_addr(g_binary_symbol_get_range(symbols[i]));          vmpa2_virt_to_string(addr, size, virt, NULL); @@ -671,10 +687,13 @@ static void reload_symbols_for_new_list_view(GSymbolsPanel *panel)          gtk_tree_store_set(panel->store, &iter,                             SBC_SYMBOL, symbols[i],                             SBC_PICTURE, icon, -                           SBC_NAME, g_binary_symbol_get_label(symbols[i]), +                           SBC_NAME, name, +                           SBC_ORIGINAL, original,                             SBC_ADDRESS, virt,                             -1); +        free(name); +      }  } @@ -688,9 +707,11 @@ static void reload_symbols_for_new_list_view(GSymbolsPanel *panel)  /******************************************************************************  *                                                                             * -*  Paramètres  : store  = gestion des différents éléments insérés.            * +*  Paramètres  : panel  = panneau en cours de mise à jour.                    *  *                parent = point d'insertion parent à retrouver. [OUT]         * -*                name   = nom du noeud ciblé.                                 * +*                raw    = nom du noeud ciblé.                                 * +*                match  = portion de texte à mettre en évidence.              * +*                start  = position du texte brute dans l'étiquette complète.  *  *                                                                             *  *  Description : S'assure qu'un noeud donné existe bien.                      *  *                                                                             * @@ -699,21 +720,24 @@ static void reload_symbols_for_new_list_view(GSymbolsPanel *panel)  *  Remarques   : -                                                            *  *                                                                             *  ******************************************************************************/ -#if 0 -static GtkTreeIter ensure_symbol_node_exist(GtkTreeStore *store, GtkTreeIter *parent, const char *name) + +static GtkTreeIter ensure_symbol_node_exist(GSymbolsPanel *panel, GtkTreeIter *parent, const char *raw, const regmatch_t *match, size_t start)  { +    GtkTreeStore *store;                    /* Gestionnaire de données     */      bool found;                             /* Bilan des recherches        */      GtkTreeIter iter;                       /* Boucle de parcours          */      gchar *string;                          /* Chaîne sélectionnée         */ -    cairo_surface_t *icon;                  /* Image associée au symbole   */ +    char *name;                             /* Etiquette mise en relief    */ + +    store = panel->store;      found = false;      if (gtk_tree_model_iter_children(GTK_TREE_MODEL(store), &iter, parent))          do          { -            gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, SBC_NAME, &string, -1); -            found = (strcmp(string, name) == 0); +            gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, SBC_ORIGINAL, &string, -1); +            found = (strcmp(string, raw) == 0);              g_free(string);              if (found) break; @@ -723,23 +747,31 @@ static GtkTreeIter ensure_symbol_node_exist(GtkTreeStore *store, GtkTreeIter *pa      if (!found)       { +        name = build_highlighted_name(raw, match, start); +          gtk_tree_store_append(store, &iter, parent);          gtk_tree_store_set(store, &iter,                             SBC_PICTURE, G_SYMBOLS_PANEL_GET_CLASS(panel)->package_img,                             SBC_NAME, name, +                           SBC_ORIGINAL, raw,                             -1); + +        free(name); +      }      return iter;  } -#endif +  /******************************************************************************  *                                                                             * -*  Paramètres  : store  = gestion des différents éléments insérés.            * +*  Paramètres  : panel  = panneau en cours de mise à jour.                    *  *                symbol = routine ou objet à intégrer.                        * -*                parent = point d'insertion parent à constituer.              * +*                parent = point d'insertion parent à constituer. [OUT]        * +*                match = portion de texte à mettre en évidence.               * +*                last   = position du dernier élément du nom de symbole. [OUT]*  *                                                                             *  *  Description : Détermine le point d'insertion parent d'une routine.         *  *                                                                             * @@ -749,33 +781,41 @@ static GtkTreeIter ensure_symbol_node_exist(GtkTreeStore *store, GtkTreeIter *pa  *                                                                             *  ******************************************************************************/ -static bool find_parent_for_symbol(GtkTreeStore *store, const GBinSymbol *symbol, GtkTreeIter *parent) +static bool find_parent_for_symbol(GSymbolsPanel *panel, const GBinSymbol *symbol, GtkTreeIter *parent, const regmatch_t *match, size_t *last)  { -#if 0 -    GDataType *namespace;                   /* Espace d'appartenance       */ -    char *string;                           /* Conversion en chaîne        */ -    char *iter;                             /* Boucle de parcours          */ +    const char *label;                      /* Etiquette immuable          */ +    char *string;                           /* Etiquette modifiable        */ +    const char *sep;                        /* Délimitateur à utiliser     */ +    char *start;                            /* Début de boucle de parcours */      char *token;                            /* Partie de texte isolée      */       char *saveptr;                          /* Ctx. interne de découpage   */ +    char *next;                             /* Prochaine partie à traiter  */ + +    *last = 0; -    namespace = g_binary_routine_get_namespace(routine); -    if (namespace == NULL) return false; +    label = g_binary_symbol_get_label(symbol); +    if (label == NULL) return false; -    string = g_data_type_to_string(namespace); +    string = strdup(label); -    for (iter = string; ; iter = NULL) +    sep = "."/*"::"*/;  /* FIXME */ + +    for (start = string, token = strtok_r(start, sep, &saveptr); ; start = NULL, token = next)      { -        token = strtok_r(iter, "::", &saveptr); -        if (token == NULL) break; +        next = strtok_r(NULL, sep, &saveptr); +        if (next == NULL) +        { +            *last = (token - string); +            break; +        } -        *parent = ensure_symbol_node_exist(store, (iter == string ? NULL : parent), token); +        *parent = ensure_symbol_node_exist(panel, (start == string ? NULL : parent), token, match, token - string);      } -    return true; -#endif +    free(string); -    return false; +    return true;  } @@ -800,8 +840,12 @@ static void reload_symbols_for_new_tree_view(GSymbolsPanel *panel)      GArchProcessor *proc;                   /* Architecture utilisée       */      MemoryDataSize size;                    /* Taille des localisations    */      size_t i;                               /* Boucle de parcours          */ +    regmatch_t match;                       /* Récupération des trouvailles*/      GtkTreeIter parent;                     /* Point d'insertion parent    */ +    size_t last;                            /* Position du dernier élément */      cairo_surface_t *icon;                  /* Image associée au symbole   */ +    const char *original;                   /* Etiquette brute d'origine   */ +    char *name;                             /* Etiquette mise en relief    */      const vmpa2t *addr;                     /* Localisation d'un symbole   */      char virt[VMPA_MAX_LEN];                /* Version humainement lisible */      GtkTreeIter iter;                       /* Point d'insertion           */ @@ -816,10 +860,10 @@ static void reload_symbols_for_new_tree_view(GSymbolsPanel *panel)      for (i = 0; i < sym_count; i++)      { -        if (is_symbol_filtered(panel, symbols[i])) +        if (is_symbol_filtered(panel, symbols[i], &match))              continue; -        if (find_parent_for_symbol(panel->store, symbols[i], &parent)) +        if (find_parent_for_symbol(panel, symbols[i], &parent, &match, &last))          {              gtk_tree_store_set(panel->store, &parent,                                 SBC_PICTURE, G_SYMBOLS_PANEL_GET_CLASS(panel)->class_img, @@ -846,16 +890,22 @@ static void reload_symbols_for_new_tree_view(GSymbolsPanel *panel)                  break;          } +        original = g_binary_symbol_get_label(symbols[i]); +        name = build_highlighted_name(original + last, &match, last); +          addr = get_mrange_addr(g_binary_symbol_get_range(symbols[i]));          vmpa2_virt_to_string(addr, size, virt, NULL);          gtk_tree_store_set(panel->store, &iter,                             SBC_SYMBOL, symbols[i],                             SBC_PICTURE, icon, -                           SBC_NAME, g_binary_symbol_get_label(symbols[i]), +                           SBC_NAME, name, +                           SBC_ORIGINAL, original + last,                             SBC_ADDRESS, virt,                             -1); +        free(name); +      }  } @@ -969,7 +1019,7 @@ static void on_symbols_filter_changed(GtkSearchEntry *entry, GSymbolsPanel *pane      if (strlen(text) > 0)      {          panel->filter = (regex_t *)calloc(1, sizeof(regex_t)); -        ret = regcomp(panel->filter, text, REG_EXTENDED); +        ret = regcomp(panel->filter, text, REG_EXTENDED | REG_ICASE);          if (ret != 0)          { @@ -1020,6 +1070,7 @@ static void do_filtering_on_symbols(GSymbolsPanel *panel)  *                                                                             *  *  Paramètres  : panel  = panneau assurant l'affichage des symboles.          *  *                symbol = symbole à traiter.                                  * +*                match  = récupération des trouvailles. [OUT]                 *  *                                                                             *  *  Description : Détermine si un nom de symbole doit être filtré ou non.      *  *                                                                             * @@ -1029,10 +1080,9 @@ static void do_filtering_on_symbols(GSymbolsPanel *panel)  *                                                                             *  ******************************************************************************/ -static bool is_symbol_filtered(GSymbolsPanel *panel, const GBinSymbol *symbol) +static bool is_symbol_filtered(GSymbolsPanel *panel, const GBinSymbol *symbol, regmatch_t *match)  {      SymbolType type;                        /* Type associé au symbole     */ -    regmatch_t match;                       /* Récupération des trouvailles*/      int ret;                                /* Bilan du filtrage           */      type = g_binary_symbol_get_target_type(symbol); @@ -1040,13 +1090,97 @@ static bool is_symbol_filtered(GSymbolsPanel *panel, const GBinSymbol *symbol)      if (type != STP_ROUTINE && type != STP_ENTRY_POINT && type != STP_OBJECT)          return true; +    memset(match, 0, sizeof(regmatch_t)); +      if (panel->filter == NULL)          return false; -    ret = regexec(panel->filter, g_binary_symbol_get_label(symbol), 1, &match, 0); +    ret = regexec(panel->filter, g_binary_symbol_get_label(symbol), 1, match, 0);      if (ret == REG_NOMATCH)          return true;      return false;  } + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : raw   = bribe de texte à traiter.                            * +*                match = portion de texte à mettre en évidence.               * +*                start = position du texte brute dans l'étiquette complète.   * +*                                                                             * +*  Description : Met en évidence le texte recherché en cas de correspondance. * +*                                                                             * +*  Retour      : Texte final destiné à être inséré, à libérer après usage.    * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static char *build_highlighted_name(const char *raw, const regmatch_t *match, size_t start) +{ +    char *result;                           /* Construction à retourner    */ +    size_t len;                             /* Taille du texte d'entrée    */ +    regmatch_t selection;                   /* Sélection relative au texte */ +    char *valid;                            /* Retouche partielle          */ + +    len = strlen(raw); + +    /* Si aucune sélection ou texte hors champ... */ + +    if ((match->rm_eo - match->rm_so) == 0 || (start + len) <= match->rm_so || match->rm_eo < start) +    { +        result = strdup(raw); +        result = strrpl(result, "<", "<"); +    } + +    /* Sinon, il y a forcément correspondance quelque part ! */ + +    else +    { +        /* Adaptations */ + +        if (match->rm_so < start) +            selection.rm_so = 0; +        else +            selection.rm_so = match->rm_so - start; + +        selection.rm_eo = match->rm_eo - start; + +        if (selection.rm_eo > len) +            selection.rm_eo = len; + +        /* Impressions */ + +        if (selection.rm_so > 0) +        { +            result = strndup(raw, selection.rm_so); +            result = strrpl(result, "<", "<"); +        } +        else +            result = NULL; + +        result = stradd(result, "<b>"); + +        valid = strndup(&raw[selection.rm_so], selection.rm_eo - selection.rm_so); +        valid = strrpl(valid, "<", "<"); + +        result = stradd(result, valid); + +        free(valid); + +        result = stradd(result, "</b>"); + +        valid = strdup(&raw[selection.rm_eo]); +        valid = strrpl(valid, "<", "<"); + +        result = stradd(result, valid); + +        free(valid); + +    } + +    return result; + +} | 
