From 6876405cab150f08d2a81d5ecd777b4f0b9e8768 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Tue, 2 Jun 2020 16:40:46 +0200
Subject: Made the binary export working again.

---
 src/glibext/linesegment.h       |  12 +-
 src/glibext/seq.c               |   3 +-
 src/gui/dialogs/export_disass.c | 285 +++++++++++++++++++++++++++-------------
 3 files changed, 203 insertions(+), 97 deletions(-)

diff --git a/src/glibext/linesegment.h b/src/glibext/linesegment.h
index cb809fc..3585ffb 100644
--- a/src/glibext/linesegment.h
+++ b/src/glibext/linesegment.h
@@ -152,22 +152,18 @@ typedef enum _BufferExportType
 /* Elements sur lesquels une exportation peut s'appuyer */
 typedef struct _buffer_export_context
 {
-    union
-    {
-        int fd;                             /* Flux ouvert en écriture     */
-
-    };
+    int fd;                                 /* Flux ouvert en écriture     */
 
     union
     {
         /* BET_TEXT */
-        const char *sep;                    /* Séparation entre colonnes   */
+        char *sep;                          /* Séparation entre colonnes   */
 
         /* BET_HTML */
         struct
         {
-            const char *font_name;          /* Police d'impression         */
-            const char *bg_color;           /* Fond du tableau HTML        */
+            char *font_name;                /* Police d'impression         */
+            char *bg_color;                 /* Fond du tableau HTML        */
 
         };
 
diff --git a/src/glibext/seq.c b/src/glibext/seq.c
index 487f4b4..3474d72 100644
--- a/src/glibext/seq.c
+++ b/src/glibext/seq.c
@@ -343,6 +343,7 @@ static void g_seq_work_process(GSeqWork *work, GtkStatusStack *status)
 
         }
 
-    *(work->status) = (i == work->end && state);
+    if (work->type == SWT_BOOLEAN)
+        *(work->status) = (i == work->end && state);
 
 }
diff --git a/src/gui/dialogs/export_disass.c b/src/gui/dialogs/export_disass.c
index 5bf4b80..beaa3c8 100644
--- a/src/gui/dialogs/export_disass.c
+++ b/src/gui/dialogs/export_disass.c
@@ -34,7 +34,12 @@
 #include <i18n.h>
 
 
+#include "../core/global.h"
 #include "../../common/extstr.h"
+#include "../../core/global.h"
+#include "../../core/logs.h"
+#include "../../core/queue.h"
+#include "../../glibext/seq.h"
 #include "../../gtkext/easygtk.h"
 
 
@@ -48,8 +53,27 @@ static void export_assistant_cancel(GtkAssistant *, gpointer);
 /* Ferme l'assistant et déroule la procédure. */
 static void export_assistant_close(GtkAssistant *, GObject *);
 
-/* Réalise l'exportation d'un contenu binaire comme demandé. */
-static void do_binary_export(void/*GCodeBuffer*/ *, const vmpa2t *, const vmpa2t *, buffer_export_context *, BufferExportType, const bool *);
+/* Condensé des informations d'exportation */
+typedef struct _export_info_t
+{
+    GBufferCache *cache;                    /* Tampon à manipuler          */
+
+    buffer_export_context *ctx;             /* Contexte d'exportation      */
+    BufferExportType type;                  /* Type d'exportation menée    */
+    bool display[BLC_COUNT];                /* Paramètres d'affichage      */
+
+    activity_id_t msg;                      /* Message de progression      */
+
+} export_info_t;
+
+/* Lance l'exportation d'un contenu binaire comme demandé. */
+static void start_binary_export(GBufferCache *, buffer_export_context *, BufferExportType, const bool *);
+
+/* Réalise l'exportation d'une ligne particulière. */
+static void export_one_binary_line(const export_info_t *, size_t, GtkStatusStack *, activity_id_t);
+
+/* Acquitte la fin d'une tâche d'exportation complète. */
+static void on_binary_export_completed(GSeqWork *, export_info_t *);
 
 
 
@@ -181,8 +205,6 @@ static void export_assistant_cancel(GtkAssistant *assistant, gpointer data)
 
 static void export_assistant_close(GtkAssistant *assistant, GObject *ref)
 {
-#if 0
-
     GtkComboBox *combo;                     /* Selection du format         */
     BufferExportType type;                  /* Type d'exportation requise  */
     buffer_export_context ctx;              /* Contexte à constituer       */
@@ -191,7 +213,7 @@ static void export_assistant_close(GtkAssistant *assistant, GObject *ref)
     GtkToggleButton *checkbutton;           /* Coche à retrouver           */
     bool display[BLC_DISPLAY];              /* Affichage à garantir        */
     GLoadedBinary *binary;                  /* Binaire chargé à parcourir  */
-    GCodeBuffer *buffer;                    /* Tampon de code à traiter    */
+    GBufferCache *cache;                    /* Tampon de code à traiter    */
     GObject *support;                       /* Support interne à supprimer */
 
     /* Type d'exportation */
@@ -205,22 +227,11 @@ static void export_assistant_close(GtkAssistant *assistant, GObject *ref)
     entry = GTK_ENTRY(g_object_get_data(ref, "filename"));
     filename = gtk_entry_get_text(entry);
 
-    switch (type)
+    ctx.fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR);
+    if (ctx.fd == -1)
     {
-        case BET_TEXT:
-        case BET_HTML:
-            ctx.fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR);
-            if (ctx.fd == -1)
-            {
-                perror("open");
-                return;
-            }
-            break;
-
-        default:
-            assert(false);
-            break;
-
+        perror("open");
+        return;
     }
 
     /* Eléments à afficher */
@@ -240,16 +251,20 @@ static void export_assistant_close(GtkAssistant *assistant, GObject *ref)
     {
         case BET_TEXT:
             entry = GTK_ENTRY(g_object_get_data(ref, "text_separator"));
-            ctx.sep = gtk_entry_get_text(entry);
-            if (strcmp(ctx.sep, "\\t") == 0) ctx.sep = "\t";  
+            ctx.sep = strdup(gtk_entry_get_text(entry));
+            if (strcmp(ctx.sep, "\\t") == 0)
+            {
+                free(ctx.sep);
+                ctx.sep = strdup("\t");
+            }
             break;
 
         case BET_HTML:
             entry = GTK_ENTRY(g_object_get_data(ref, "html_font_name"));
-            ctx.font_name = gtk_entry_get_text(entry);
+            ctx.font_name = strdup(gtk_entry_get_text(entry));
 
             entry = GTK_ENTRY(g_object_get_data(ref, "html_bg_color"));
-            ctx.bg_color = gtk_entry_get_text(entry);
+            ctx.bg_color = strdup(gtk_entry_get_text(entry));
 
             break;
 
@@ -262,30 +277,20 @@ static void export_assistant_close(GtkAssistant *assistant, GObject *ref)
 
     binary = G_LOADED_BINARY(g_object_get_data(ref, "binary"));
 
-    buffer = g_loaded_binary_get_disassembled_buffer(binary);
+    cache = g_loaded_binary_get_disassembly_cache(binary);
 
-    do_binary_export(buffer, NULL, NULL, &ctx, type, display);
+    start_binary_export(cache, &ctx, type, display);
 
-    /* Conclusion */
-
-    switch (type)
-    {
-        case BET_TEXT:
-        case BET_HTML:
-            close(ctx.fd);
-            break;
+    g_object_unref(G_OBJECT(cache));
 
-        default:
-            break;
-
-    }
+    /* Conclusion */
 
     support = G_OBJECT(g_object_get_data(G_OBJECT(assistant), "text_options"));
     if (support != NULL) g_object_unref(support);
 
     support = G_OBJECT(g_object_get_data(G_OBJECT(assistant), "html_options"));
     if (support != NULL) g_object_unref(support);
-#endif
+
     gtk_widget_destroy(GTK_WIDGET(assistant));
 
 }
@@ -293,14 +298,12 @@ static void export_assistant_close(GtkAssistant *assistant, GObject *ref)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : buffer = tampon de données à utiliser.                       *
-*                start   = première adresse visée ou 0.                       *
-*                end     = dernière adresse visée ou VMPA_MAX.                *
-*                ctx     = éléments à disposition pour l'exportation.         *
-*                type    = type d'exportation attendue.                       *
-*                display = règles d'affichage des colonnes modulables.        *
+*  Paramètres  : cache    = tampon de données à utiliser.                     *
+*                template = paramètres dont s'inspirer pour l'exportation.    *
+*                type     = type d'exportation attendue.                      *
+*                display  = règles d'affichage des colonnes modulables.       *
 *                                                                             *
-*  Description : Réalise l'exportation d'un contenu binaire comme demandé.    *
+*  Description : Lance l'exportation d'un contenu binaire comme demandé.      *
 *                                                                             *
 *  Retour      : -                                                            *
 *                                                                             *
@@ -308,75 +311,181 @@ static void export_assistant_close(GtkAssistant *assistant, GObject *ref)
 *                                                                             *
 ******************************************************************************/
 
-static void do_binary_export(void/*GCodeBuffer*/ *buffer, const vmpa2t *start, const vmpa2t *end, buffer_export_context *ctx, BufferExportType type, const bool *display)
+static void start_binary_export(GBufferCache *cache, buffer_export_context *template, BufferExportType type, const bool *display)
 {
-#if 0
-    typedef struct _export_data
+    export_info_t *info;                    /* Infos à faire circuler      */
+    BufferLineColumn i;                     /* Boucle de parcours          */
+    GWorkQueue *queue;                      /* Gestionnaire de différés    */
+    size_t count;                           /* Quantité de lignes à traiter*/
+    GSeqWork *work;                         /* Tâche de chargement à lancer*/
+
+    /* Copie des paramètres d'exportation */
+
+    info = calloc(1, sizeof(export_info_t));
+
+    info->cache = cache;
+    g_object_ref(G_OBJECT(cache));
+
+    info->ctx = malloc(sizeof(buffer_export_context));
+
+    info->ctx->fd = template->fd;
+
+    switch (type)
     {
-        buffer_export_context *ctx;         /* Contexte d'exportation      */
-        BufferExportType type;              /* Type d'exportation menée    */
-        const bool *display;                /* Paramètres d'affichage      */
+        case BET_TEXT:
+            info->ctx->sep = template->sep;
+            break;
 
-    } export_data;
+        case BET_HTML:
+            info->ctx->font_name = template->font_name;
+            info->ctx->bg_color = template->bg_color;
+            break;
 
-    export_data data;                       /* Données à faire suivre      */
-    GDelayedWork *work;                     /* Tâche laborieuse à attendre */
+        default:
+            break;
+
+    }
+
+    info->type = type;
+
+    for (i = 0; i < BLC_DISPLAY; i++)
+        info->display[i] = display[i];
+
+    /* Données exportées initiales */
 
     switch (type)
     {
         case BET_HTML:
-            dprintf(ctx->fd, "<HTML>\n");
-            dprintf(ctx->fd, "<HEAD>\n");
-            dprintf(ctx->fd, "\t<META http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"/>\n");
-            dprintf(ctx->fd, "</HEAD>\n");
-            dprintf(ctx->fd, "<BODY>\n");
-            dprintf(ctx->fd, "<STYLE  type=\"text/css\">\n");
-            dprintf(ctx->fd, "TABLE {\n");
-            dprintf(ctx->fd, "\tbackground-color: %s;\n", ctx->bg_color);
-            dprintf(ctx->fd, "\tborder: 0px;\n");
-            dprintf(ctx->fd, "\tfont-family: %s;\n", ctx->font_name);
-            dprintf(ctx->fd, "}\n");
-            dprintf(ctx->fd, "TD {\n");
-            dprintf(ctx->fd, "\tborder: 0px;\n");
-            dprintf(ctx->fd, "\tpadding-left: 8px;\n");
-            dprintf(ctx->fd, "\tpadding-right: 8px;\n");
-            dprintf(ctx->fd, "}\n");
-            export_line_segment_style(ctx, type);
-            dprintf(ctx->fd, "</STYLE>\n");
-            dprintf(ctx->fd, "<TABLE>\n");
+            dprintf(template->fd, "<HTML>\n");
+            dprintf(template->fd, "<HEAD>\n");
+            dprintf(template->fd, "\t<META http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"/>\n");
+            dprintf(template->fd, "</HEAD>\n");
+            dprintf(template->fd, "<BODY>\n");
+            dprintf(template->fd, "<STYLE  type=\"text/css\">\n");
+            dprintf(template->fd, "TABLE {\n");
+            dprintf(template->fd, "\tbackground-color: %s;\n", template->bg_color);
+            dprintf(template->fd, "\tborder: 0px;\n");
+            dprintf(template->fd, "\tfont-family: %s;\n", template->font_name);
+            dprintf(template->fd, "}\n");
+            dprintf(template->fd, "TD {\n");
+            dprintf(template->fd, "\tborder: 0px;\n");
+            dprintf(template->fd, "\tpadding-left: 8px;\n");
+            dprintf(template->fd, "\tpadding-right: 8px;\n");
+            dprintf(template->fd, "}\n");
+            export_line_segment_style(template, type);
+            dprintf(template->fd, "</STYLE>\n");
+            dprintf(template->fd, "<TABLE>\n");
             break;
+
         default:
             break;
+
     }
 
-    data.ctx = ctx;
-    data.type = type;
-    data.display = display;
+    /* Poursuite de l'opération */
 
-    bool export_line(GCodeBuffer *buf, GBufferLine *ln, export_data *d)
+    queue = get_work_queue();
+
+    g_buffer_cache_lock(cache);
+    count = g_buffer_cache_count_lines(cache);
+
+    info->msg = gtk_status_stack_add_activity(get_global_status(), _("Exporting binary content..."), count);
+
+    work = g_seq_work_new(info, 0, count, info->msg, (seq_work_cb)export_one_binary_line);
+
+    g_signal_connect(work, "work-completed", G_CALLBACK(on_binary_export_completed), info);
+
+    g_work_queue_schedule_work(queue, G_DELAYED_WORK(work), DEFAULT_WORK_GROUP);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : info   = ensemble d'informations utiles à l'opération.       *
+*                i      = indice des éléments à traiter.                      *
+*                status = barre de statut à tenir informée.                   *
+*                id     = identifiant du message affiché à l'utilisateur.     *
+*                                                                             *
+*  Description : Réalise l'exportation d'une ligne particulière.              *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void export_one_binary_line(const export_info_t *info, size_t i, GtkStatusStack *status, activity_id_t id)
+{
+    GBufferLine *line;                      /* Ligne particulière à traiter*/
+
+    line = g_buffer_cache_find_line_by_index(info->cache, i);
+
+    g_buffer_line_export(line, info->ctx, info->type, info->display);
+
+    g_object_unref(G_OBJECT(line));
+
+    gtk_status_stack_update_activity_value(status, id, 1);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : work = tâche de sauvegarde menée à son terme.                *
+*  Paramètres  : info = ensemble d'informations liées à l'opération terminée. *
+*                                                                             *
+*  Description : Acquitte la fin d'une tâche d'exportation complète.          *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void on_binary_export_completed(GSeqWork *work, export_info_t *info)
+{
+    switch (info->type)
     {
-        g_buffer_line_export(ln, d->ctx, d->type, d->display);
+        case BET_HTML:
+            dprintf(info->ctx->fd, "</TABLE>\n");
+            dprintf(info->ctx->fd, "</BODY>\n");
+            dprintf(info->ctx->fd, "</HTML>\n");
+            break;
 
-        return true;
+        default:
+            break;
 
     }
 
-    work = g_buffer_code_scan(buffer, start, end, _("Exporting binary content"),
-                              (process_line_fc)export_line, &data);
+    log_simple_message(LMT_INFO, "Binary content exported!");
 
-    g_delayed_work_wait_for_completion(work);
+    g_buffer_cache_unlock(info->cache);
+    g_object_unref(G_OBJECT(info->cache));
 
-    switch (type)
+    close(info->ctx->fd);
+
+    switch (info->type)
     {
+        case BET_TEXT:
+            free(info->ctx->sep);
+            break;
+
         case BET_HTML:
-            dprintf(ctx->fd, "</TABLE>\n");
-            dprintf(ctx->fd, "</BODY>\n");
-            dprintf(ctx->fd, "</HTML>\n");
+            free(info->ctx->font_name);
+            free(info->ctx->bg_color);
             break;
+
         default:
             break;
+
     }
-#endif
+
+    gtk_status_stack_remove_activity(get_global_status(), info->msg);
+
+    free(info->ctx);
+    free(info);
+
 }
 
 
-- 
cgit v0.11.2-87-g4458