From cd583c040d6730d24fdbf4558bd6fdff98303c5b Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Tue, 3 Sep 2024 08:29:44 +0200 Subject: Rename files. --- src/gtkext/Makefile.am | 2 +- src/gtkext/gtkstatusstack.c | 1121 ------------------------------------------- src/gtkext/gtkstatusstack.h | 99 ---- src/gtkext/statusstack.c | 1121 +++++++++++++++++++++++++++++++++++++++++++ src/gtkext/statusstack.h | 99 ++++ 5 files changed, 1221 insertions(+), 1221 deletions(-) delete mode 100644 src/gtkext/gtkstatusstack.c delete mode 100644 src/gtkext/gtkstatusstack.h create mode 100644 src/gtkext/statusstack.c create mode 100644 src/gtkext/statusstack.h diff --git a/src/gtkext/Makefile.am b/src/gtkext/Makefile.am index 57834b2..9f32c7c 100644 --- a/src/gtkext/Makefile.am +++ b/src/gtkext/Makefile.am @@ -14,7 +14,7 @@ libgtkext_la_SOURCES = \ gtkdockable-int.h \ gtkdockable.h gtkdockable.c \ gtkgraphdisplay.h gtkgraphdisplay.c \ - gtkstatusstack.h gtkstatusstack.c \ + statusstack.h statusstack.c \ hexdisplay.h hexdisplay.c \ named-int.h \ named.h named.c \ diff --git a/src/gtkext/gtkstatusstack.c b/src/gtkext/gtkstatusstack.c deleted file mode 100644 index fe4e4d5..0000000 --- a/src/gtkext/gtkstatusstack.c +++ /dev/null @@ -1,1121 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * gtkstatusstack.c - empilement d'informations de statut - * - * Copyright (C) 2015-2019 Cyrille Bagard - * - * This file is part of Chrysalide. - * - * Chrysalide 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. - * - * Chrysalide 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 Chrysalide. If not, see . - */ - - -#include "gtkstatusstack.h" - - -#include -#include -#include -#include - - -#include - - -#include "easygtk.h" -#include "../gui/agroup.h" -#include "../format/format.h" - - - -/* ------------------------- GESTION EXTERIEURE DE LA BARRE ------------------------- */ - - -/* Navigation au sein d'assemblage */ -typedef struct _assembly_info assembly_info; - -/* Mémorisation des progressions */ -typedef struct _progress_info progress_info; - - -/* Abstration d'une gestion de barre de statut (instance) */ -struct _GtkStatusStack -{ - GtkBox parent; /* A laisser en premier */ - - GtkStack *main; /* Pile d'informations associée*/ - - GSourceFunc def_source; /* Appel en fin d'activité */ - - GObject *asm_ref; /* Espace de référencements #1 */ - assembly_info *asm_info; /* Informations courantes #1 */ - - GObject *prog_ref; /* Espace de référencements #2 */ - progress_info *prog_info; /* Informations courantes #2 */ - -}; - -/* Abstration d'une gestion de barre de statut (classe) */ -struct _GtkStatusStackClass -{ - GtkBoxClass parent; /* A laisser en premier */ - -}; - - -/* Initialise la classe des barres de statut améliorées. */ -static void gtk_status_stack_class_init(GtkStatusStackClass *); - -/* Initialise une instance de barre de statut améliorée. */ -static void gtk_status_stack_init(GtkStatusStack *); - -/* Supprime toutes les références externes. */ -static void gtk_status_stack_dispose(GtkStatusStack *); - -/* Procède à la libération totale de la mémoire. */ -static void gtk_status_stack_finalize(GtkStatusStack *); - - - -/* -------------------- STATUT DES INFORMATIONS DE DESASSEMBLAGE -------------------- */ - - -/* Navigation au sein d'assemblage */ -struct _assembly_info -{ - bool reset; /* Réinitialisation */ - - mrange_t current; /* Emplacement correspondant */ - - char *segment; /* Segment d'appartenance */ - - VMPA_BUFFER(phys); /* Localisation physique */ - VMPA_BUFFER(virt); /* Localisation virtuelle */ - - char *symbol; /* Eventuel symbole concerné */ - - const char *encoding; /* Encodage de l'instruction */ - phys_t size; /* Taille de l'instruction */ - -}; - - -/* Supprime l'empreinte mémoire d'informations d'assemblage. */ -static void reset_assembly_info(assembly_info *); - -/* Construit une barre d'état pour language d'assemblage. */ -static GtkWidget *build_assembly_status_stack(GtkStatusStack *); - -/* Réagit à un redimensionnement de la barre de désassemblage. */ -static void on_size_allocate_for_asm_status(GtkWidget *, GdkRectangle *, GObject *); - -/* Réagit à un clic sur l'icône de zoom. */ -static void on_zoom_icon_press(GtkEntry *, GtkEntryIconPosition, GdkEventButton *, GtkStatusStack *); - -/* S'assure de l'affichage à jour de la partie "assemblage". */ -static gboolean gtk_status_stack_show_current_location(GtkStatusStack *); - - - -/* -------------------------- STATUT DES SUIVIS D'ACTIVITE -------------------------- */ - - -/* Informations de progression */ -typedef struct _progress_status -{ - activity_id_t id; /* Identifiant unique */ - - char *message; /* Indication à faire valoir */ - - unsigned long current; /* Position courante */ - unsigned long max; /* Couverture à parcourir */ - - double last_updated; /* Dernière valeur poussée */ - -} progress_status; - -/* Mémorisation des progressions */ -struct _progress_info -{ - activity_id_t generator; /* Générateur de séquence */ - - progress_status *statuses; /* Statuts de progression */ - size_t count; /* Nombre de ces statuts */ - GMutex access; /* Accès à la pile */ - - guint tag; /* Identifiant de mise à jour */ - -}; - - -#define PROGRESS_SIZE 200 - - -/* Supprime l'empreinte mémoire d'informations d'activité. */ -static void reset_progress_info(progress_info *); - -/* Construit une barre d'état pour un suivi d'activité. */ -static GtkWidget *build_progress_status_stack(GtkStatusStack *); - -/* S'assure de l'affichage à jour de la partie "activité". */ -static gboolean gtk_status_stack_show_current_activity(GtkStatusStack *); - - - -/* ---------------------------------------------------------------------------------- */ -/* GESTION EXTERIEURE DE LA BARRE */ -/* ---------------------------------------------------------------------------------- */ - - -/* Détermine le type de la barre de statut améliorée. */ -G_DEFINE_TYPE(GtkStatusStack, gtk_status_stack, GTK_TYPE_BOX) - - -/****************************************************************************** -* * -* Paramètres : klass = classe GTK à initialiser. * -* * -* Description : Initialise la classe des barres de statut améliorées. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void gtk_status_stack_class_init(GtkStatusStackClass *klass) -{ - GObjectClass *object; /* Autre version de la classe */ - - object = G_OBJECT_CLASS(klass); - - object->dispose = (GObjectFinalizeFunc/* ! */)gtk_status_stack_dispose; - object->finalize = (GObjectFinalizeFunc)gtk_status_stack_finalize; - -} - - -/****************************************************************************** -* * -* Paramètres : stack = instance GTK à initialiser. * -* * -* Description : Initialise une instance de barre de statut améliorée. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void gtk_status_stack_init(GtkStatusStack *stack) -{ - GtkWidget *layer; /* Couche à empiler */ - - gtk_orientable_set_orientation(GTK_ORIENTABLE(stack), GTK_ORIENTATION_HORIZONTAL); - - stack->main = GTK_STACK(gtk_stack_new()); - gtk_widget_show(GTK_WIDGET(stack->main)); - gtk_box_pack_start(GTK_BOX(stack), GTK_WIDGET(stack->main), TRUE, TRUE, 8); - - stack->def_source = (GSourceFunc)gtk_status_stack_show_current_location; - - layer = build_assembly_status_stack(stack); - gtk_stack_add_named(stack->main, layer, "asm_info"); - - stack->asm_ref = G_OBJECT(layer); - stack->asm_info = (assembly_info *)calloc(1, sizeof(assembly_info)); - - reset_assembly_info(stack->asm_info); - - layer = build_progress_status_stack(stack); - gtk_stack_add_named(stack->main, layer, "prog_info"); - - stack->prog_ref = G_OBJECT(layer); - stack->prog_info = (progress_info *)calloc(1, sizeof(progress_info)); - - reset_progress_info(stack->prog_info); - - gtk_status_stack_reset_current_location(stack); - -} - - -/****************************************************************************** -* * -* Paramètres : view = instance d'objet GLib à traiter. * -* * -* Description : Supprime toutes les références externes. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void gtk_status_stack_dispose(GtkStatusStack *stack) -{ - G_OBJECT_CLASS(gtk_status_stack_parent_class)->dispose(G_OBJECT(stack)); - -} - - -/****************************************************************************** -* * -* Paramètres : view = instance d'objet GLib à traiter. * -* * -* Description : Procède à la libération totale de la mémoire. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void gtk_status_stack_finalize(GtkStatusStack *stack) -{ - reset_assembly_info(stack->asm_info); - free(stack->asm_info); - - reset_progress_info(stack->prog_info); - free(stack->prog_info); - - G_OBJECT_CLASS(gtk_status_stack_parent_class)->finalize(G_OBJECT(stack)); - -} - - -/****************************************************************************** -* * -* Paramètres : - * -* * -* Description : Crée une nouvelle instance de barre de statut. * -* * -* Retour : Composant GTK mis en place. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GtkStatusStack *gtk_status_stack_new(void) -{ - GtkStatusStack *result; /* Instance à retourner */ - - result = g_object_new(GTK_TYPE_STATUS_STACK, NULL); - - return result; - -} - - - -/* ---------------------------------------------------------------------------------- */ -/* STATUT DES INFORMATIONS DE DESASSEMBLAGE */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* Paramètres : info = informations à réinitialiser. * -* * -* Description : Supprime l'empreinte mémoire d'informations d'assemblage. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void reset_assembly_info(assembly_info *info) -{ - info->reset = true; - - if (info->segment != NULL) - { - free(info->segment); - info->segment = NULL; - } - - if (info->symbol != NULL) - { - free(info->symbol); - info->symbol = NULL; - } - -} - - -/****************************************************************************** -* * -* Paramètres : stack = composant global en cours de construction. * -* * -* Description : Construit une barre d'état pour language d'assemblage. * -* * -* Retour : Composant GTK mis en place. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static GtkWidget *build_assembly_status_stack(GtkStatusStack *stack) -{ - GtkWidget *result; /* Support à retourner */ - GObject *ref; /* Espace de référencements */ - GtkWidget *hbox; /* Sous-division horizontale */ - GtkWidget *label; /* Etiquette pour impression */ - GtkWidget *zoom; /* Sélection du zoom courant */ - - result = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); - gtk_widget_show(result); - - ref = G_OBJECT(result); - - g_signal_connect(result, "size-allocate", G_CALLBACK(on_size_allocate_for_asm_status), ref); - - /* Première partie : navigation */ - - hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 16); - gtk_widget_show(hbox); - gtk_box_pack_start(GTK_BOX(result), hbox, TRUE, TRUE, 8); - - label = qck_create_label(ref, "segment", NULL); - gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); - - label = qck_create_label(ref, "phys", NULL); - gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); - - label = qck_create_label(ref, "virt", NULL); - gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); - - label = qck_create_label(ref, "offset", NULL); - gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); - - /* Seconde partie : architecture */ - - hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8); - g_object_set_data(ref, "arch_box", hbox); - gtk_widget_show(hbox); - gtk_box_pack_start(GTK_BOX(result), hbox, FALSE, TRUE, 8); - - label = qck_create_label(ref, "arch", NULL); - gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); - - label = qck_create_label(ref, "size", NULL); - gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); - - /* Troisième partie : affichage */ - - hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8); - gtk_widget_show(hbox); - gtk_box_pack_start(GTK_BOX(result), hbox, FALSE, FALSE, 8); - - zoom = qck_create_entry(ref, "zoom", "100%"); - gtk_entry_set_icon_from_icon_name(GTK_ENTRY(zoom), GTK_ENTRY_ICON_SECONDARY, "go-up-symbolic"); - - g_signal_connect(zoom, "focus-in-event", G_CALLBACK(track_focus_change_in_text_area), NULL); - g_signal_connect(zoom, "focus-out-event", G_CALLBACK(track_focus_change_in_text_area), NULL); - g_signal_connect(zoom, "icon-press", G_CALLBACK(on_zoom_icon_press), stack); - - gtk_box_pack_start(GTK_BOX(hbox), zoom, FALSE, TRUE, 0); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : widget = composant graphique qui vient d'évoluer. * -* allocation = espace réservé pour le composant visé. * -* ref = espace de référencement global. * -* * -* Description : Réagit à un redimensionnement de la barre de désassemblage. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void on_size_allocate_for_asm_status(GtkWidget *widget, GdkRectangle *allocation, GObject *ref) -{ - GtkWidget *hbox; /* Sous-division horizontale */ - - hbox = GTK_WIDGET(g_object_get_data(ref, "arch_box")); - - gtk_widget_set_size_request(hbox, (allocation->width * 40) / 100, -1); - - /** - * On intervient après que le containeur soit passé collecter les tailles - * de ses enfants lors de son redimensionnement. - * - * Donc on force un prise en compte des changements. - */ - gtk_container_check_resize(GTK_CONTAINER(widget)); - -} - - -/****************************************************************************** -* * -* Paramètres : entry = zone de texte visée par la procédure. * -* icon_pos = position de l'image associée à l'entrée. * -* event = informations liées à l'événement. * -* stack = composant graphique de gestion des statuts. * -* * -* Description : Réagit à un clic sur l'icône de zoom. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void on_zoom_icon_press(GtkEntry *entry, GtkEntryIconPosition icon_pos, GdkEventButton *event, GtkStatusStack *stack) -{ - GtkWidget *popup; /* Popup à faire surgir */ - GdkRectangle rect; /* Zone précise à cibler */ - - if (event->button != GDK_BUTTON_PRIMARY) - return; - - popup = gtk_popover_new(GTK_WIDGET(entry)); - - gtk_entry_get_icon_area(entry, GTK_ENTRY_ICON_SECONDARY, &rect); - gtk_popover_set_pointing_to(GTK_POPOVER(popup), &rect); - - gtk_widget_show(popup); - -} - - -/****************************************************************************** -* * -* Paramètres : stack = barre de statut à actualiser. * -* range = emplacement à mettre en valeur. * -* segment = zone de binaire d'appartenance. * -* symbol = éventuelle position par rapport à un symbole. * -* encoding = encodage d'une éventuelle instruction ou NULL. * -* * -* Description : Actualise les informations liées une position d'assemblage. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void gtk_status_stack_update_current_location(GtkStatusStack *stack, const mrange_t *range, const char *segment, const char *symbol, const char *encoding) -{ - assembly_info *info; /* Informations à constituer */ - const vmpa2t *addr; /* Localisation de départ */ - phys_t size; /* Taille de l'emplacement */ - - info = stack->asm_info; - - /* Bascule vers une zone courante nouvelle ? */ - - addr = get_mrange_addr(range); - size = get_mrange_length(range); - - if (cmp_mrange(&info->current, range) == 0 - && info->size == size - && info->encoding == encoding) - goto useless; - - /* Réinitialisation */ - - reset_assembly_info(info); - - copy_mrange(&info->current, range); - - /* Zone d'appartenance */ - - info->segment = strdup(segment); - - /* Adresses de base */ - - vmpa2_phys_to_string(addr, MDS_UNDEFINED, info->phys, NULL); - - vmpa2_virt_to_string(addr, MDS_UNDEFINED, info->virt, NULL); - - info->encoding = encoding; - info->size = size; - - /* Symbole concerné */ - - if (symbol != NULL) - info->symbol = strdup(symbol); - - /* Nettoyage et conclusion */ - - info->reset = false; - - gtk_status_stack_show_current_location(stack); - - useless: - - ; - -} - - -/****************************************************************************** -* * -* Paramètres : stack = barre de statut à actualiser. * -* * -* Description : Réinitialise les informations associées une position. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void gtk_status_stack_reset_current_location(GtkStatusStack *stack) -{ - assembly_info *info; /* Informations à constituer */ - - info = stack->asm_info; - - reset_assembly_info(info); - - gtk_status_stack_show_current_location(stack); - -} - - -/****************************************************************************** -* * -* Paramètres : stack = pile de statuts à manipuler. * -* * -* Description : S'assure de l'affichage à jour de la partie "assemblage". * -* * -* Retour : G_SOURCE_REMOVE pour une exécution unique. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static gboolean gtk_status_stack_show_current_location(GtkStatusStack *stack) -{ - GObject *ref; /* Espace de référencements */ - assembly_info *info; /* Informations à consulter */ - GtkLabel *label; /* Etiquette à actualiser */ - char raw_pos[6 + VMPA_MAX_LEN + 1]; /* Formatage final en direct */ - char *content; /* Contenu dynamique */ - - stack->def_source = (GSourceFunc)gtk_status_stack_show_current_location; - - gtk_stack_set_visible_child_name(stack->main, "asm_info"); - - ref = stack->asm_ref; - info = stack->asm_info; - - /* Première partie : navigation */ - - if (info->reset) - { - label = GTK_LABEL(g_object_get_data(ref, "segment")); - gtk_label_set_text(label, NULL); - - label = GTK_LABEL(g_object_get_data(ref, "phys")); - gtk_label_set_text(label, NULL); - - label = GTK_LABEL(g_object_get_data(ref, "virt")); - gtk_label_set_text(label, NULL); - - label = GTK_LABEL(g_object_get_data(ref, "offset")); - gtk_label_set_text(label, NULL); - - } - else - { - label = GTK_LABEL(g_object_get_data(ref, "segment")); - gtk_label_set_text(label, info->segment); - - snprintf(raw_pos, sizeof(raw_pos), "phys: %s", info->phys); - - label = GTK_LABEL(g_object_get_data(ref, "phys")); - gtk_label_set_text(label, raw_pos); - - snprintf(raw_pos, sizeof(raw_pos), "virt: %s", info->virt); - - label = GTK_LABEL(g_object_get_data(ref, "virt")); - gtk_label_set_text(label, raw_pos); - - label = GTK_LABEL(g_object_get_data(ref, "offset")); - gtk_label_set_text(label, info->symbol != NULL ? info->symbol : ""); - - } - - /* Seconde partie : architecture */ - - if (info->reset || info->encoding == NULL || info->size == VMPA_NO_PHYSICAL) - { - label = GTK_LABEL(g_object_get_data(ref, "arch")); - gtk_label_set_text(label, NULL); - - label = GTK_LABEL(g_object_get_data(ref, "size")); - gtk_label_set_text(label, NULL); - - } - else - { - label = GTK_LABEL(g_object_get_data(ref, "arch")); - gtk_label_set_text(label, info->encoding); - - if (info->size > 1) - asprintf(&content, "%" PRIu64 " %s", (uint64_t)info->size, _("bytes")); - else - asprintf(&content, "%" PRIu64 " %s", (uint64_t)info->size, _("byte")); - - label = GTK_LABEL(g_object_get_data(ref, "size")); - gtk_label_set_text(label, content); - - free(content); - - } - - return G_SOURCE_REMOVE; - -} - - - -/* ---------------------------------------------------------------------------------- */ -/* STATUT DES SUIVIS D'ACTIVITE */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* Paramètres : info = informations à réinitialiser. * -* * -* Description : Supprime l'empreinte mémoire d'informations d'activité. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void reset_progress_info(progress_info *info) -{ - size_t i; /* Boucle de parcours */ - - if (info->tag != 0) - g_source_remove(info->tag); - - info->tag = 0; - - for (i = 0; i < info->count; i++) - { - if (info->statuses[i].message != NULL) - free(info->statuses[i].message); - } - - if (info->statuses != NULL) - { - free(info->statuses); - info->statuses = NULL; - } - - info->count = 0; - - g_mutex_init(&info->access); - -} - - -/****************************************************************************** -* * -* Paramètres : stack = composant global en cours de construction. * -* * -* Description : Construit une barre d'état pour un suivi d'activité. * -* * -* Retour : Composant GTK mis en place. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static GtkWidget *build_progress_status_stack(GtkStatusStack *stack) -{ - GtkWidget *result; /* Support à retourner */ - GObject *ref; /* Espace de référencements */ - GtkWidget *progress; /* Barre de progression */ - GtkWidget *label; /* Désignation de l'activité */ - - result = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); - gtk_widget_show(result); - - ref = G_OBJECT(result); - - progress = gtk_progress_bar_new(); - g_object_set_data(ref, "progress", progress); - gtk_widget_set_size_request(progress, PROGRESS_SIZE, -1); - gtk_widget_set_valign(progress, GTK_ALIGN_CENTER); - gtk_widget_show(progress); - gtk_box_pack_start(GTK_BOX(result), progress, FALSE, TRUE, 8); - - label = qck_create_label(ref, "message", NULL); - gtk_box_pack_start(GTK_BOX(result), label, TRUE, TRUE, 0); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : stack = barre de statut à actualiser. * -* msg = nouveau message de statut à copier. * -* max = taille de la plage à parcourir. * -* * -* Description : Démarre le suivi d'une nouvelle activité. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -activity_id_t gtk_status_stack_add_activity(GtkStatusStack *stack, const char *msg, unsigned long max) -{ - activity_id_t result; /* Numéro unique à renvoyer */ - progress_info *info; /* Informations à consulter */ - size_t new; /* Indice de l'activité créée */ - - if (stack == NULL) return NO_ACTIVITY_ID; - - info = stack->prog_info; - - g_mutex_lock(&info->access); - - result = ++info->generator; - - new = info->count++; - - info->statuses = (progress_status *)realloc(info->statuses, - info->count * sizeof(progress_status)); - - info->statuses[new].id = result; - - /* Intitulé */ - - if (msg == NULL) - info->statuses[new].message = NULL; - else - info->statuses[new].message = strdup(msg); - - /* Valeur */ - - info->statuses[new].current = 0; - info->statuses[new].max = max; - info->statuses[new].last_updated = 0; - - /* Actualisation */ - - if (info->tag != 0) - g_source_remove(info->tag); - - info->tag = g_idle_add((GSourceFunc)gtk_status_stack_show_current_activity, stack); - - g_mutex_unlock(&info->access); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : stack = barre de statut à actualiser. * -* id = identifiant de l'activité à cibler. * -* extra = nouvelle échéance supplémentaire des traitements. * -* * -* Description : Etend la portée des travaux d'une nouvelle activité. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void gtk_status_stack_extend_activity(GtkStatusStack *stack, activity_id_t id, unsigned long extra) -{ - progress_info *info; /* Informations à consulter */ - size_t i; /* Boucle de parcours */ - - if (stack == NULL) return; - - info = stack->prog_info; - - g_mutex_lock(&info->access); - - for (i = 0; i < info->count; i++) - if (info->statuses[i].id == id) - break; - - assert(i < info->count); - - info->statuses[i].max += extra; - - g_mutex_unlock(&info->access); - -} - - -/****************************************************************************** -* * -* Paramètres : stack = barre de statut à actualiser. * -* id = identifiant de l'activité à cibler. * -* msg = nouveau message de statut à copier. * -* * -* Description : Actualise les informations concernant une activité. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void gtk_status_stack_update_activity(GtkStatusStack *stack, activity_id_t id, const char *msg) -{ - progress_info *info; /* Informations à consulter */ - size_t i; /* Boucle de parcours */ - bool msg_changed; /* Changement d'intitulé */ - - if (stack == NULL) return; - - info = stack->prog_info; - - g_mutex_lock(&info->access); - - for (i = 0; i < info->count; i++) - if (info->statuses[i].id == id) - break; - - assert(i < info->count); - - /* Intitulé */ - - if (info->statuses[i].message != NULL) - { - if (msg == NULL) - msg_changed = true; - else - msg_changed = (strcmp(info->statuses[i].message, msg) != 0); - - free(info->statuses[i].message); - - } - else - msg_changed = (msg != NULL); - - if (msg == NULL) - info->statuses[i].message = NULL; - else - info->statuses[i].message = strdup(msg); - - /* On n'actualise que le sommet de la pile */ - - if ((i + 1) == info->count && msg_changed) - { - if (info->tag != 0) - g_source_remove(info->tag); - - info->tag = g_idle_add((GSourceFunc)gtk_status_stack_show_current_activity, stack); - - } - - g_mutex_unlock(&info->access); - -} - - -/****************************************************************************** -* * -* Paramètres : stack = barre de statut à actualiser. * -* id = identifiant de l'activité à cibler. * -* inc = nouvelle valeur pour une progression donnée. * -* * -* Description : Actualise la progression d'une activité. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void gtk_status_stack_update_activity_value(GtkStatusStack *stack, activity_id_t id, unsigned long inc) -{ - progress_info *info; /* Informations à consulter */ - size_t i; /* Boucle de parcours */ - progress_status *status; /* Raccourci de confort */ - double new; /* Nouvelle progression */ - - if (stack == NULL) return; - - info = stack->prog_info; - - g_mutex_lock(&info->access); - - for (i = 0; i < info->count; i++) - if (info->statuses[i].id == id) - break; - - assert(i < info->count); - - status = &info->statuses[i]; - - /* Valeur */ - - status->current += inc; - - new = (status->current * 1.0) / status->max; - - /* On n'actualise que le sommet de la pile */ - - if ((i + 1) == info->count && (new - status->last_updated) > (1.0 / PROGRESS_SIZE)) - { - status->last_updated = new; - - if (info->tag != 0) - g_source_remove(info->tag); - - info->tag = g_idle_add((GSourceFunc)gtk_status_stack_show_current_activity, stack); - - } - - g_mutex_unlock(&info->access); - -} - - -/****************************************************************************** -* * -* Paramètres : stack = barre de statut à actualiser. * -* * -* Description : Met fin au suivi d'une activité donnée. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void gtk_status_stack_remove_activity(GtkStatusStack *stack, activity_id_t id) -{ - progress_info *info; /* Informations à consulter */ - size_t i; /* Boucle de parcours */ - - if (stack == NULL) return; - - info = stack->prog_info; - - g_mutex_lock(&info->access); - - for (i = 0; i < info->count; i++) - if (info->statuses[i].id == id) - break; - - assert(i < info->count); - - if (info->tag != 0) - g_source_remove(info->tag); - - if (info->statuses[i].message != NULL) - free(info->statuses[i].message); - - if (info->count == 1) - { - free(info->statuses); - info->statuses = NULL; - } - else - { - memmove(&info->statuses[i], &info->statuses[i + 1], - (info->count - i - 1) * sizeof(progress_status)); - - info->statuses = (progress_status *)realloc(info->statuses, - (info->count - 1) * sizeof(progress_status)); - - } - - info->count--; - - if (info->count == 0) - { - info->tag = 0; - g_idle_add(stack->def_source, stack); - } - else - info->tag = g_idle_add((GSourceFunc)gtk_status_stack_show_current_activity, stack); - - g_mutex_unlock(&info->access); - -} - - -/****************************************************************************** -* * -* Paramètres : stack = pile de statuts à manipuler. * -* * -* Description : S'assure de l'affichage à jour de la partie "activité". * -* * -* Retour : G_SOURCE_REMOVE pour une exécution unique. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static gboolean gtk_status_stack_show_current_activity(GtkStatusStack *stack) -{ - GObject *ref; /* Espace de référencements */ - progress_info *info; /* Informations à consulter */ - progress_status *last; /* Dernier statut à traiter */ - GtkProgressBar *progress; /* Barre de progression */ - GtkLabel *label; /* Désignation de l'activité */ - - if (!g_source_is_destroyed(g_main_current_source())) - { - gtk_stack_set_visible_child_name(stack->main, "prog_info"); - - ref = stack->prog_ref; - info = stack->prog_info; - - g_mutex_lock(&info->access); - - info->tag = 0; - - if (info->count > 0) - { - last = &info->statuses[info->count - 1]; - - progress = GTK_PROGRESS_BAR(g_object_get_data(ref, "progress")); - gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress), (last->current * 1.0) / last->max); - - label = GTK_LABEL(g_object_get_data(ref, "message")); - gtk_label_set_text(label, last->message); - - } - - g_mutex_unlock(&info->access); - - } - - return G_SOURCE_REMOVE; - -} diff --git a/src/gtkext/gtkstatusstack.h b/src/gtkext/gtkstatusstack.h deleted file mode 100644 index f419014..0000000 --- a/src/gtkext/gtkstatusstack.h +++ /dev/null @@ -1,99 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * gtkstatusstack.h - prototypes pour un empilement d'informations de statut - * - * Copyright (C) 2015-2019 Cyrille Bagard - * - * This file is part of Chrysalide. - * - * Chrysalide 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. - * - * Chrysalide 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 Chrysalide. If not, see . - */ - - -#ifndef _GTKEXT_GTKSTATUSSTACK_H -#define _GTKEXT_GTKSTATUSSTACK_H - - -#include - - -#include "../arch/vmpa.h" - - - -/* ------------------------- GESTION EXTERIEURE DE LA BARRE ------------------------- */ - - -#define GTK_TYPE_STATUS_STACK (gtk_status_stack_get_type()) -#define GTK_STATUS_STACK(obj) (G_TYPE_CHECK_INSTANCE_CAST(obj, GTK_TYPE_STATUS_STACK, GtkStatusStack)) -#define GTK_STATUS_STACK_CLASS(klass) (G_LOADED_BINARY_GET_CLASS(klass, GTK_TYPE_STATUS_STACK, GtkStatusStackClass)) -#define GTK_IS_STATUS_STACK(obj) (G_TYPE_CHECK_INSTANCE_TYPE(obj, GTK_TYPE_STATUS_STACK)) -#define GTK_IS_STATUS_STACK_CLASS(obj) (G_TYPE_CHECK_INSTANCE_TYPE(obj, GTK_TYPE_STATUS_STACK)) -#define GTK_STATUS_STACK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_STATUS_STACK, GtkStatusStackClass)) - - -/* Abstration d'une gestion de barre de statut (instance) */ -typedef struct _GtkStatusStack GtkStatusStack; - -/* Abstration d'une gestion de barre de statut (classe) */ -typedef struct _GtkStatusStackClass GtkStatusStackClass; - - -/* Détermine le type de la barre de statut améliorée. */ -GType gtk_status_stack_get_type(void); - -/* Crée une nouvelle instance de barre de statut. */ -GtkStatusStack *gtk_status_stack_new(void); - - - -/* -------------------- STATUT DES INFORMATIONS DE DESASSEMBLAGE -------------------- */ - - -/* Actualise les informations liées une position d'assemblage. */ -void gtk_status_stack_update_current_location(GtkStatusStack *, const mrange_t *, const char *, const char *, const char *); - -/* Réinitialise les informations associées une position. */ -void gtk_status_stack_reset_current_location(GtkStatusStack *); - - - -/* -------------------------- STATUT DES SUIVIS D'ACTIVITE -------------------------- */ - - -/* Identifiant unique de rapport de progression */ -typedef unsigned long activity_id_t; - -/* Identifiant particulier pour une absence d'identifiant */ -#define NO_ACTIVITY_ID 0 - - -/* Démarre le suivi d'une nouvelle activité. */ -activity_id_t gtk_status_stack_add_activity(GtkStatusStack *, const char *, unsigned long); - -/* Etend la portée des travaux d'une nouvelle activité. */ -void gtk_status_stack_extend_activity(GtkStatusStack *, activity_id_t, unsigned long); - -/* Actualise les informations concernant une activité. */ -void gtk_status_stack_update_activity(GtkStatusStack *, activity_id_t, const char *); - -/* Actualise la progression d'une activité. */ -void gtk_status_stack_update_activity_value(GtkStatusStack *, activity_id_t, unsigned long); - -/* Met fin au suivi d'une activité donnée. */ -void gtk_status_stack_remove_activity(GtkStatusStack *, activity_id_t); - - - -#endif /* _GTKEXT_GTKSTATUSSTACK_H */ diff --git a/src/gtkext/statusstack.c b/src/gtkext/statusstack.c new file mode 100644 index 0000000..fe4e4d5 --- /dev/null +++ b/src/gtkext/statusstack.c @@ -0,0 +1,1121 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * gtkstatusstack.c - empilement d'informations de statut + * + * Copyright (C) 2015-2019 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide 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. + * + * Chrysalide 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 Chrysalide. If not, see . + */ + + +#include "gtkstatusstack.h" + + +#include +#include +#include +#include + + +#include + + +#include "easygtk.h" +#include "../gui/agroup.h" +#include "../format/format.h" + + + +/* ------------------------- GESTION EXTERIEURE DE LA BARRE ------------------------- */ + + +/* Navigation au sein d'assemblage */ +typedef struct _assembly_info assembly_info; + +/* Mémorisation des progressions */ +typedef struct _progress_info progress_info; + + +/* Abstration d'une gestion de barre de statut (instance) */ +struct _GtkStatusStack +{ + GtkBox parent; /* A laisser en premier */ + + GtkStack *main; /* Pile d'informations associée*/ + + GSourceFunc def_source; /* Appel en fin d'activité */ + + GObject *asm_ref; /* Espace de référencements #1 */ + assembly_info *asm_info; /* Informations courantes #1 */ + + GObject *prog_ref; /* Espace de référencements #2 */ + progress_info *prog_info; /* Informations courantes #2 */ + +}; + +/* Abstration d'une gestion de barre de statut (classe) */ +struct _GtkStatusStackClass +{ + GtkBoxClass parent; /* A laisser en premier */ + +}; + + +/* Initialise la classe des barres de statut améliorées. */ +static void gtk_status_stack_class_init(GtkStatusStackClass *); + +/* Initialise une instance de barre de statut améliorée. */ +static void gtk_status_stack_init(GtkStatusStack *); + +/* Supprime toutes les références externes. */ +static void gtk_status_stack_dispose(GtkStatusStack *); + +/* Procède à la libération totale de la mémoire. */ +static void gtk_status_stack_finalize(GtkStatusStack *); + + + +/* -------------------- STATUT DES INFORMATIONS DE DESASSEMBLAGE -------------------- */ + + +/* Navigation au sein d'assemblage */ +struct _assembly_info +{ + bool reset; /* Réinitialisation */ + + mrange_t current; /* Emplacement correspondant */ + + char *segment; /* Segment d'appartenance */ + + VMPA_BUFFER(phys); /* Localisation physique */ + VMPA_BUFFER(virt); /* Localisation virtuelle */ + + char *symbol; /* Eventuel symbole concerné */ + + const char *encoding; /* Encodage de l'instruction */ + phys_t size; /* Taille de l'instruction */ + +}; + + +/* Supprime l'empreinte mémoire d'informations d'assemblage. */ +static void reset_assembly_info(assembly_info *); + +/* Construit une barre d'état pour language d'assemblage. */ +static GtkWidget *build_assembly_status_stack(GtkStatusStack *); + +/* Réagit à un redimensionnement de la barre de désassemblage. */ +static void on_size_allocate_for_asm_status(GtkWidget *, GdkRectangle *, GObject *); + +/* Réagit à un clic sur l'icône de zoom. */ +static void on_zoom_icon_press(GtkEntry *, GtkEntryIconPosition, GdkEventButton *, GtkStatusStack *); + +/* S'assure de l'affichage à jour de la partie "assemblage". */ +static gboolean gtk_status_stack_show_current_location(GtkStatusStack *); + + + +/* -------------------------- STATUT DES SUIVIS D'ACTIVITE -------------------------- */ + + +/* Informations de progression */ +typedef struct _progress_status +{ + activity_id_t id; /* Identifiant unique */ + + char *message; /* Indication à faire valoir */ + + unsigned long current; /* Position courante */ + unsigned long max; /* Couverture à parcourir */ + + double last_updated; /* Dernière valeur poussée */ + +} progress_status; + +/* Mémorisation des progressions */ +struct _progress_info +{ + activity_id_t generator; /* Générateur de séquence */ + + progress_status *statuses; /* Statuts de progression */ + size_t count; /* Nombre de ces statuts */ + GMutex access; /* Accès à la pile */ + + guint tag; /* Identifiant de mise à jour */ + +}; + + +#define PROGRESS_SIZE 200 + + +/* Supprime l'empreinte mémoire d'informations d'activité. */ +static void reset_progress_info(progress_info *); + +/* Construit une barre d'état pour un suivi d'activité. */ +static GtkWidget *build_progress_status_stack(GtkStatusStack *); + +/* S'assure de l'affichage à jour de la partie "activité". */ +static gboolean gtk_status_stack_show_current_activity(GtkStatusStack *); + + + +/* ---------------------------------------------------------------------------------- */ +/* GESTION EXTERIEURE DE LA BARRE */ +/* ---------------------------------------------------------------------------------- */ + + +/* Détermine le type de la barre de statut améliorée. */ +G_DEFINE_TYPE(GtkStatusStack, gtk_status_stack, GTK_TYPE_BOX) + + +/****************************************************************************** +* * +* Paramètres : klass = classe GTK à initialiser. * +* * +* Description : Initialise la classe des barres de statut améliorées. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_status_stack_class_init(GtkStatusStackClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)gtk_status_stack_dispose; + object->finalize = (GObjectFinalizeFunc)gtk_status_stack_finalize; + +} + + +/****************************************************************************** +* * +* Paramètres : stack = instance GTK à initialiser. * +* * +* Description : Initialise une instance de barre de statut améliorée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_status_stack_init(GtkStatusStack *stack) +{ + GtkWidget *layer; /* Couche à empiler */ + + gtk_orientable_set_orientation(GTK_ORIENTABLE(stack), GTK_ORIENTATION_HORIZONTAL); + + stack->main = GTK_STACK(gtk_stack_new()); + gtk_widget_show(GTK_WIDGET(stack->main)); + gtk_box_pack_start(GTK_BOX(stack), GTK_WIDGET(stack->main), TRUE, TRUE, 8); + + stack->def_source = (GSourceFunc)gtk_status_stack_show_current_location; + + layer = build_assembly_status_stack(stack); + gtk_stack_add_named(stack->main, layer, "asm_info"); + + stack->asm_ref = G_OBJECT(layer); + stack->asm_info = (assembly_info *)calloc(1, sizeof(assembly_info)); + + reset_assembly_info(stack->asm_info); + + layer = build_progress_status_stack(stack); + gtk_stack_add_named(stack->main, layer, "prog_info"); + + stack->prog_ref = G_OBJECT(layer); + stack->prog_info = (progress_info *)calloc(1, sizeof(progress_info)); + + reset_progress_info(stack->prog_info); + + gtk_status_stack_reset_current_location(stack); + +} + + +/****************************************************************************** +* * +* Paramètres : view = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_status_stack_dispose(GtkStatusStack *stack) +{ + G_OBJECT_CLASS(gtk_status_stack_parent_class)->dispose(G_OBJECT(stack)); + +} + + +/****************************************************************************** +* * +* Paramètres : view = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_status_stack_finalize(GtkStatusStack *stack) +{ + reset_assembly_info(stack->asm_info); + free(stack->asm_info); + + reset_progress_info(stack->prog_info); + free(stack->prog_info); + + G_OBJECT_CLASS(gtk_status_stack_parent_class)->finalize(G_OBJECT(stack)); + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Crée une nouvelle instance de barre de statut. * +* * +* Retour : Composant GTK mis en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GtkStatusStack *gtk_status_stack_new(void) +{ + GtkStatusStack *result; /* Instance à retourner */ + + result = g_object_new(GTK_TYPE_STATUS_STACK, NULL); + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* STATUT DES INFORMATIONS DE DESASSEMBLAGE */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : info = informations à réinitialiser. * +* * +* Description : Supprime l'empreinte mémoire d'informations d'assemblage. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void reset_assembly_info(assembly_info *info) +{ + info->reset = true; + + if (info->segment != NULL) + { + free(info->segment); + info->segment = NULL; + } + + if (info->symbol != NULL) + { + free(info->symbol); + info->symbol = NULL; + } + +} + + +/****************************************************************************** +* * +* Paramètres : stack = composant global en cours de construction. * +* * +* Description : Construit une barre d'état pour language d'assemblage. * +* * +* Retour : Composant GTK mis en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GtkWidget *build_assembly_status_stack(GtkStatusStack *stack) +{ + GtkWidget *result; /* Support à retourner */ + GObject *ref; /* Espace de référencements */ + GtkWidget *hbox; /* Sous-division horizontale */ + GtkWidget *label; /* Etiquette pour impression */ + GtkWidget *zoom; /* Sélection du zoom courant */ + + result = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); + gtk_widget_show(result); + + ref = G_OBJECT(result); + + g_signal_connect(result, "size-allocate", G_CALLBACK(on_size_allocate_for_asm_status), ref); + + /* Première partie : navigation */ + + hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 16); + gtk_widget_show(hbox); + gtk_box_pack_start(GTK_BOX(result), hbox, TRUE, TRUE, 8); + + label = qck_create_label(ref, "segment", NULL); + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); + + label = qck_create_label(ref, "phys", NULL); + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); + + label = qck_create_label(ref, "virt", NULL); + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); + + label = qck_create_label(ref, "offset", NULL); + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); + + /* Seconde partie : architecture */ + + hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8); + g_object_set_data(ref, "arch_box", hbox); + gtk_widget_show(hbox); + gtk_box_pack_start(GTK_BOX(result), hbox, FALSE, TRUE, 8); + + label = qck_create_label(ref, "arch", NULL); + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); + + label = qck_create_label(ref, "size", NULL); + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); + + /* Troisième partie : affichage */ + + hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8); + gtk_widget_show(hbox); + gtk_box_pack_start(GTK_BOX(result), hbox, FALSE, FALSE, 8); + + zoom = qck_create_entry(ref, "zoom", "100%"); + gtk_entry_set_icon_from_icon_name(GTK_ENTRY(zoom), GTK_ENTRY_ICON_SECONDARY, "go-up-symbolic"); + + g_signal_connect(zoom, "focus-in-event", G_CALLBACK(track_focus_change_in_text_area), NULL); + g_signal_connect(zoom, "focus-out-event", G_CALLBACK(track_focus_change_in_text_area), NULL); + g_signal_connect(zoom, "icon-press", G_CALLBACK(on_zoom_icon_press), stack); + + gtk_box_pack_start(GTK_BOX(hbox), zoom, FALSE, TRUE, 0); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : widget = composant graphique qui vient d'évoluer. * +* allocation = espace réservé pour le composant visé. * +* ref = espace de référencement global. * +* * +* Description : Réagit à un redimensionnement de la barre de désassemblage. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void on_size_allocate_for_asm_status(GtkWidget *widget, GdkRectangle *allocation, GObject *ref) +{ + GtkWidget *hbox; /* Sous-division horizontale */ + + hbox = GTK_WIDGET(g_object_get_data(ref, "arch_box")); + + gtk_widget_set_size_request(hbox, (allocation->width * 40) / 100, -1); + + /** + * On intervient après que le containeur soit passé collecter les tailles + * de ses enfants lors de son redimensionnement. + * + * Donc on force un prise en compte des changements. + */ + gtk_container_check_resize(GTK_CONTAINER(widget)); + +} + + +/****************************************************************************** +* * +* Paramètres : entry = zone de texte visée par la procédure. * +* icon_pos = position de l'image associée à l'entrée. * +* event = informations liées à l'événement. * +* stack = composant graphique de gestion des statuts. * +* * +* Description : Réagit à un clic sur l'icône de zoom. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void on_zoom_icon_press(GtkEntry *entry, GtkEntryIconPosition icon_pos, GdkEventButton *event, GtkStatusStack *stack) +{ + GtkWidget *popup; /* Popup à faire surgir */ + GdkRectangle rect; /* Zone précise à cibler */ + + if (event->button != GDK_BUTTON_PRIMARY) + return; + + popup = gtk_popover_new(GTK_WIDGET(entry)); + + gtk_entry_get_icon_area(entry, GTK_ENTRY_ICON_SECONDARY, &rect); + gtk_popover_set_pointing_to(GTK_POPOVER(popup), &rect); + + gtk_widget_show(popup); + +} + + +/****************************************************************************** +* * +* Paramètres : stack = barre de statut à actualiser. * +* range = emplacement à mettre en valeur. * +* segment = zone de binaire d'appartenance. * +* symbol = éventuelle position par rapport à un symbole. * +* encoding = encodage d'une éventuelle instruction ou NULL. * +* * +* Description : Actualise les informations liées une position d'assemblage. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void gtk_status_stack_update_current_location(GtkStatusStack *stack, const mrange_t *range, const char *segment, const char *symbol, const char *encoding) +{ + assembly_info *info; /* Informations à constituer */ + const vmpa2t *addr; /* Localisation de départ */ + phys_t size; /* Taille de l'emplacement */ + + info = stack->asm_info; + + /* Bascule vers une zone courante nouvelle ? */ + + addr = get_mrange_addr(range); + size = get_mrange_length(range); + + if (cmp_mrange(&info->current, range) == 0 + && info->size == size + && info->encoding == encoding) + goto useless; + + /* Réinitialisation */ + + reset_assembly_info(info); + + copy_mrange(&info->current, range); + + /* Zone d'appartenance */ + + info->segment = strdup(segment); + + /* Adresses de base */ + + vmpa2_phys_to_string(addr, MDS_UNDEFINED, info->phys, NULL); + + vmpa2_virt_to_string(addr, MDS_UNDEFINED, info->virt, NULL); + + info->encoding = encoding; + info->size = size; + + /* Symbole concerné */ + + if (symbol != NULL) + info->symbol = strdup(symbol); + + /* Nettoyage et conclusion */ + + info->reset = false; + + gtk_status_stack_show_current_location(stack); + + useless: + + ; + +} + + +/****************************************************************************** +* * +* Paramètres : stack = barre de statut à actualiser. * +* * +* Description : Réinitialise les informations associées une position. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void gtk_status_stack_reset_current_location(GtkStatusStack *stack) +{ + assembly_info *info; /* Informations à constituer */ + + info = stack->asm_info; + + reset_assembly_info(info); + + gtk_status_stack_show_current_location(stack); + +} + + +/****************************************************************************** +* * +* Paramètres : stack = pile de statuts à manipuler. * +* * +* Description : S'assure de l'affichage à jour de la partie "assemblage". * +* * +* Retour : G_SOURCE_REMOVE pour une exécution unique. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static gboolean gtk_status_stack_show_current_location(GtkStatusStack *stack) +{ + GObject *ref; /* Espace de référencements */ + assembly_info *info; /* Informations à consulter */ + GtkLabel *label; /* Etiquette à actualiser */ + char raw_pos[6 + VMPA_MAX_LEN + 1]; /* Formatage final en direct */ + char *content; /* Contenu dynamique */ + + stack->def_source = (GSourceFunc)gtk_status_stack_show_current_location; + + gtk_stack_set_visible_child_name(stack->main, "asm_info"); + + ref = stack->asm_ref; + info = stack->asm_info; + + /* Première partie : navigation */ + + if (info->reset) + { + label = GTK_LABEL(g_object_get_data(ref, "segment")); + gtk_label_set_text(label, NULL); + + label = GTK_LABEL(g_object_get_data(ref, "phys")); + gtk_label_set_text(label, NULL); + + label = GTK_LABEL(g_object_get_data(ref, "virt")); + gtk_label_set_text(label, NULL); + + label = GTK_LABEL(g_object_get_data(ref, "offset")); + gtk_label_set_text(label, NULL); + + } + else + { + label = GTK_LABEL(g_object_get_data(ref, "segment")); + gtk_label_set_text(label, info->segment); + + snprintf(raw_pos, sizeof(raw_pos), "phys: %s", info->phys); + + label = GTK_LABEL(g_object_get_data(ref, "phys")); + gtk_label_set_text(label, raw_pos); + + snprintf(raw_pos, sizeof(raw_pos), "virt: %s", info->virt); + + label = GTK_LABEL(g_object_get_data(ref, "virt")); + gtk_label_set_text(label, raw_pos); + + label = GTK_LABEL(g_object_get_data(ref, "offset")); + gtk_label_set_text(label, info->symbol != NULL ? info->symbol : ""); + + } + + /* Seconde partie : architecture */ + + if (info->reset || info->encoding == NULL || info->size == VMPA_NO_PHYSICAL) + { + label = GTK_LABEL(g_object_get_data(ref, "arch")); + gtk_label_set_text(label, NULL); + + label = GTK_LABEL(g_object_get_data(ref, "size")); + gtk_label_set_text(label, NULL); + + } + else + { + label = GTK_LABEL(g_object_get_data(ref, "arch")); + gtk_label_set_text(label, info->encoding); + + if (info->size > 1) + asprintf(&content, "%" PRIu64 " %s", (uint64_t)info->size, _("bytes")); + else + asprintf(&content, "%" PRIu64 " %s", (uint64_t)info->size, _("byte")); + + label = GTK_LABEL(g_object_get_data(ref, "size")); + gtk_label_set_text(label, content); + + free(content); + + } + + return G_SOURCE_REMOVE; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* STATUT DES SUIVIS D'ACTIVITE */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : info = informations à réinitialiser. * +* * +* Description : Supprime l'empreinte mémoire d'informations d'activité. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void reset_progress_info(progress_info *info) +{ + size_t i; /* Boucle de parcours */ + + if (info->tag != 0) + g_source_remove(info->tag); + + info->tag = 0; + + for (i = 0; i < info->count; i++) + { + if (info->statuses[i].message != NULL) + free(info->statuses[i].message); + } + + if (info->statuses != NULL) + { + free(info->statuses); + info->statuses = NULL; + } + + info->count = 0; + + g_mutex_init(&info->access); + +} + + +/****************************************************************************** +* * +* Paramètres : stack = composant global en cours de construction. * +* * +* Description : Construit une barre d'état pour un suivi d'activité. * +* * +* Retour : Composant GTK mis en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GtkWidget *build_progress_status_stack(GtkStatusStack *stack) +{ + GtkWidget *result; /* Support à retourner */ + GObject *ref; /* Espace de référencements */ + GtkWidget *progress; /* Barre de progression */ + GtkWidget *label; /* Désignation de l'activité */ + + result = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); + gtk_widget_show(result); + + ref = G_OBJECT(result); + + progress = gtk_progress_bar_new(); + g_object_set_data(ref, "progress", progress); + gtk_widget_set_size_request(progress, PROGRESS_SIZE, -1); + gtk_widget_set_valign(progress, GTK_ALIGN_CENTER); + gtk_widget_show(progress); + gtk_box_pack_start(GTK_BOX(result), progress, FALSE, TRUE, 8); + + label = qck_create_label(ref, "message", NULL); + gtk_box_pack_start(GTK_BOX(result), label, TRUE, TRUE, 0); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : stack = barre de statut à actualiser. * +* msg = nouveau message de statut à copier. * +* max = taille de la plage à parcourir. * +* * +* Description : Démarre le suivi d'une nouvelle activité. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +activity_id_t gtk_status_stack_add_activity(GtkStatusStack *stack, const char *msg, unsigned long max) +{ + activity_id_t result; /* Numéro unique à renvoyer */ + progress_info *info; /* Informations à consulter */ + size_t new; /* Indice de l'activité créée */ + + if (stack == NULL) return NO_ACTIVITY_ID; + + info = stack->prog_info; + + g_mutex_lock(&info->access); + + result = ++info->generator; + + new = info->count++; + + info->statuses = (progress_status *)realloc(info->statuses, + info->count * sizeof(progress_status)); + + info->statuses[new].id = result; + + /* Intitulé */ + + if (msg == NULL) + info->statuses[new].message = NULL; + else + info->statuses[new].message = strdup(msg); + + /* Valeur */ + + info->statuses[new].current = 0; + info->statuses[new].max = max; + info->statuses[new].last_updated = 0; + + /* Actualisation */ + + if (info->tag != 0) + g_source_remove(info->tag); + + info->tag = g_idle_add((GSourceFunc)gtk_status_stack_show_current_activity, stack); + + g_mutex_unlock(&info->access); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : stack = barre de statut à actualiser. * +* id = identifiant de l'activité à cibler. * +* extra = nouvelle échéance supplémentaire des traitements. * +* * +* Description : Etend la portée des travaux d'une nouvelle activité. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void gtk_status_stack_extend_activity(GtkStatusStack *stack, activity_id_t id, unsigned long extra) +{ + progress_info *info; /* Informations à consulter */ + size_t i; /* Boucle de parcours */ + + if (stack == NULL) return; + + info = stack->prog_info; + + g_mutex_lock(&info->access); + + for (i = 0; i < info->count; i++) + if (info->statuses[i].id == id) + break; + + assert(i < info->count); + + info->statuses[i].max += extra; + + g_mutex_unlock(&info->access); + +} + + +/****************************************************************************** +* * +* Paramètres : stack = barre de statut à actualiser. * +* id = identifiant de l'activité à cibler. * +* msg = nouveau message de statut à copier. * +* * +* Description : Actualise les informations concernant une activité. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void gtk_status_stack_update_activity(GtkStatusStack *stack, activity_id_t id, const char *msg) +{ + progress_info *info; /* Informations à consulter */ + size_t i; /* Boucle de parcours */ + bool msg_changed; /* Changement d'intitulé */ + + if (stack == NULL) return; + + info = stack->prog_info; + + g_mutex_lock(&info->access); + + for (i = 0; i < info->count; i++) + if (info->statuses[i].id == id) + break; + + assert(i < info->count); + + /* Intitulé */ + + if (info->statuses[i].message != NULL) + { + if (msg == NULL) + msg_changed = true; + else + msg_changed = (strcmp(info->statuses[i].message, msg) != 0); + + free(info->statuses[i].message); + + } + else + msg_changed = (msg != NULL); + + if (msg == NULL) + info->statuses[i].message = NULL; + else + info->statuses[i].message = strdup(msg); + + /* On n'actualise que le sommet de la pile */ + + if ((i + 1) == info->count && msg_changed) + { + if (info->tag != 0) + g_source_remove(info->tag); + + info->tag = g_idle_add((GSourceFunc)gtk_status_stack_show_current_activity, stack); + + } + + g_mutex_unlock(&info->access); + +} + + +/****************************************************************************** +* * +* Paramètres : stack = barre de statut à actualiser. * +* id = identifiant de l'activité à cibler. * +* inc = nouvelle valeur pour une progression donnée. * +* * +* Description : Actualise la progression d'une activité. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void gtk_status_stack_update_activity_value(GtkStatusStack *stack, activity_id_t id, unsigned long inc) +{ + progress_info *info; /* Informations à consulter */ + size_t i; /* Boucle de parcours */ + progress_status *status; /* Raccourci de confort */ + double new; /* Nouvelle progression */ + + if (stack == NULL) return; + + info = stack->prog_info; + + g_mutex_lock(&info->access); + + for (i = 0; i < info->count; i++) + if (info->statuses[i].id == id) + break; + + assert(i < info->count); + + status = &info->statuses[i]; + + /* Valeur */ + + status->current += inc; + + new = (status->current * 1.0) / status->max; + + /* On n'actualise que le sommet de la pile */ + + if ((i + 1) == info->count && (new - status->last_updated) > (1.0 / PROGRESS_SIZE)) + { + status->last_updated = new; + + if (info->tag != 0) + g_source_remove(info->tag); + + info->tag = g_idle_add((GSourceFunc)gtk_status_stack_show_current_activity, stack); + + } + + g_mutex_unlock(&info->access); + +} + + +/****************************************************************************** +* * +* Paramètres : stack = barre de statut à actualiser. * +* * +* Description : Met fin au suivi d'une activité donnée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void gtk_status_stack_remove_activity(GtkStatusStack *stack, activity_id_t id) +{ + progress_info *info; /* Informations à consulter */ + size_t i; /* Boucle de parcours */ + + if (stack == NULL) return; + + info = stack->prog_info; + + g_mutex_lock(&info->access); + + for (i = 0; i < info->count; i++) + if (info->statuses[i].id == id) + break; + + assert(i < info->count); + + if (info->tag != 0) + g_source_remove(info->tag); + + if (info->statuses[i].message != NULL) + free(info->statuses[i].message); + + if (info->count == 1) + { + free(info->statuses); + info->statuses = NULL; + } + else + { + memmove(&info->statuses[i], &info->statuses[i + 1], + (info->count - i - 1) * sizeof(progress_status)); + + info->statuses = (progress_status *)realloc(info->statuses, + (info->count - 1) * sizeof(progress_status)); + + } + + info->count--; + + if (info->count == 0) + { + info->tag = 0; + g_idle_add(stack->def_source, stack); + } + else + info->tag = g_idle_add((GSourceFunc)gtk_status_stack_show_current_activity, stack); + + g_mutex_unlock(&info->access); + +} + + +/****************************************************************************** +* * +* Paramètres : stack = pile de statuts à manipuler. * +* * +* Description : S'assure de l'affichage à jour de la partie "activité". * +* * +* Retour : G_SOURCE_REMOVE pour une exécution unique. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static gboolean gtk_status_stack_show_current_activity(GtkStatusStack *stack) +{ + GObject *ref; /* Espace de référencements */ + progress_info *info; /* Informations à consulter */ + progress_status *last; /* Dernier statut à traiter */ + GtkProgressBar *progress; /* Barre de progression */ + GtkLabel *label; /* Désignation de l'activité */ + + if (!g_source_is_destroyed(g_main_current_source())) + { + gtk_stack_set_visible_child_name(stack->main, "prog_info"); + + ref = stack->prog_ref; + info = stack->prog_info; + + g_mutex_lock(&info->access); + + info->tag = 0; + + if (info->count > 0) + { + last = &info->statuses[info->count - 1]; + + progress = GTK_PROGRESS_BAR(g_object_get_data(ref, "progress")); + gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress), (last->current * 1.0) / last->max); + + label = GTK_LABEL(g_object_get_data(ref, "message")); + gtk_label_set_text(label, last->message); + + } + + g_mutex_unlock(&info->access); + + } + + return G_SOURCE_REMOVE; + +} diff --git a/src/gtkext/statusstack.h b/src/gtkext/statusstack.h new file mode 100644 index 0000000..f419014 --- /dev/null +++ b/src/gtkext/statusstack.h @@ -0,0 +1,99 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * gtkstatusstack.h - prototypes pour un empilement d'informations de statut + * + * Copyright (C) 2015-2019 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide 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. + * + * Chrysalide 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 Chrysalide. If not, see . + */ + + +#ifndef _GTKEXT_GTKSTATUSSTACK_H +#define _GTKEXT_GTKSTATUSSTACK_H + + +#include + + +#include "../arch/vmpa.h" + + + +/* ------------------------- GESTION EXTERIEURE DE LA BARRE ------------------------- */ + + +#define GTK_TYPE_STATUS_STACK (gtk_status_stack_get_type()) +#define GTK_STATUS_STACK(obj) (G_TYPE_CHECK_INSTANCE_CAST(obj, GTK_TYPE_STATUS_STACK, GtkStatusStack)) +#define GTK_STATUS_STACK_CLASS(klass) (G_LOADED_BINARY_GET_CLASS(klass, GTK_TYPE_STATUS_STACK, GtkStatusStackClass)) +#define GTK_IS_STATUS_STACK(obj) (G_TYPE_CHECK_INSTANCE_TYPE(obj, GTK_TYPE_STATUS_STACK)) +#define GTK_IS_STATUS_STACK_CLASS(obj) (G_TYPE_CHECK_INSTANCE_TYPE(obj, GTK_TYPE_STATUS_STACK)) +#define GTK_STATUS_STACK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_STATUS_STACK, GtkStatusStackClass)) + + +/* Abstration d'une gestion de barre de statut (instance) */ +typedef struct _GtkStatusStack GtkStatusStack; + +/* Abstration d'une gestion de barre de statut (classe) */ +typedef struct _GtkStatusStackClass GtkStatusStackClass; + + +/* Détermine le type de la barre de statut améliorée. */ +GType gtk_status_stack_get_type(void); + +/* Crée une nouvelle instance de barre de statut. */ +GtkStatusStack *gtk_status_stack_new(void); + + + +/* -------------------- STATUT DES INFORMATIONS DE DESASSEMBLAGE -------------------- */ + + +/* Actualise les informations liées une position d'assemblage. */ +void gtk_status_stack_update_current_location(GtkStatusStack *, const mrange_t *, const char *, const char *, const char *); + +/* Réinitialise les informations associées une position. */ +void gtk_status_stack_reset_current_location(GtkStatusStack *); + + + +/* -------------------------- STATUT DES SUIVIS D'ACTIVITE -------------------------- */ + + +/* Identifiant unique de rapport de progression */ +typedef unsigned long activity_id_t; + +/* Identifiant particulier pour une absence d'identifiant */ +#define NO_ACTIVITY_ID 0 + + +/* Démarre le suivi d'une nouvelle activité. */ +activity_id_t gtk_status_stack_add_activity(GtkStatusStack *, const char *, unsigned long); + +/* Etend la portée des travaux d'une nouvelle activité. */ +void gtk_status_stack_extend_activity(GtkStatusStack *, activity_id_t, unsigned long); + +/* Actualise les informations concernant une activité. */ +void gtk_status_stack_update_activity(GtkStatusStack *, activity_id_t, const char *); + +/* Actualise la progression d'une activité. */ +void gtk_status_stack_update_activity_value(GtkStatusStack *, activity_id_t, unsigned long); + +/* Met fin au suivi d'une activité donnée. */ +void gtk_status_stack_remove_activity(GtkStatusStack *, activity_id_t); + + + +#endif /* _GTKEXT_GTKSTATUSSTACK_H */ -- cgit v0.11.2-87-g4458