/* Chrysalide - Outil d'analyse de fichiers binaires * signal.h - prototypes pour un encadrement des signaux supplémentaire par rapport à celui de la GLib * * Copyright (C) 2009-2013 Cyrille Bagard * * This file is part of Chrysalide. * * OpenIDA is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * OpenIDA is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Foobar. If not, see . */ #include "signal.h" #include #include /* Prototype pour le transfert d'exécution. */ typedef void (* GSignalCallback) (gpointer, ...); /* Informations concernant une diffusion de signal */ typedef struct _gsignal_wrapper_info { GConnectFlags flags; /* Ordre des arguments */ GSignalCallback callback; /* Fonction finale de récept° */ gpointer instance; /* Instance GLib initiatrice */ gpointer data; /* Donnée utilisateur associée */ guint n_params; /* Nombre de paramètres */ unsigned long params[0]; /* Paramètres récupérés */ } gsignal_wrapper_info; /* Réceptionne un signal et redirige son exécution. */ static void carry_signal_to_main_thread(gsignal_wrapper_info *, ...); /* Transmet un signal dans le contexte principal. */ static gboolean to_main_wrapper(gsignal_wrapper_info *); /****************************************************************************** * * * Paramètres : info = collecteur d'informations sur la diffusion. * * * * Description : Transmet un signal dans le contexte principal. * * * * Retour : FALSE / G_SOURCE_REMOVE pour arrêter la transmission. * * * * Remarques : - * * * ******************************************************************************/ static gboolean to_main_wrapper(gsignal_wrapper_info *info) { gpointer data1; /* Premier argument à envoyer */ gpointer data2; /* Dernier argument à envoyer */ if (info->flags & G_CONNECT_SWAPPED) { data1 = info->data; data2 = info->instance; } else { data1 = info->instance; data2 = info->data; } switch (info->n_params - 1) { case 0: info->callback(data1, data2); break; } return G_SOURCE_REMOVE; } /****************************************************************************** * * * Paramètres : info = collecteur d'informations sur la diffusion. * * ... = arguments poussés par la GLib sur la pile. * * * * Description : Réceptionne un signal et redirige son exécution. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void carry_signal_to_main_thread(gsignal_wrapper_info *info, ...) { va_list ap; /* Liste d'arguments sur pile */ guint i; /* Boucle de parcours */ va_start(ap, info); for (i = 0; i < info->n_params; i++) info->params[i] = va_arg(ap, unsigned long); va_end(ap); g_idle_add_full(G_PRIORITY_HIGH_IDLE, (GSourceFunc)to_main_wrapper, info, free); } /****************************************************************************** * * * Paramètres : instance = object GLib à l'origine de l'émission. * * signal = identification du signal à réceptionner. * * handler = fonction C servant de réceptacle. * * data = éventuelle donnée de l'utilisateur à ajouter. * * * * Description : Reproduit le comportement de la fonction g_signal_connect(). * * * * Retour : Identifiant supérieur zéro en cas de succès. * * * * Remarques : - * * * ******************************************************************************/ gulong g_signal_connect_to_main(gpointer instance, const gchar *signal, GCallback handler, gpointer data) { guint signal_id; /* Identifiant du signal visé */ GSignalQuery query; /* Information sur le signal */ gsignal_wrapper_info *info; /* Encapsulation des données */ /* Collection d'informations */ signal_id = g_signal_lookup(signal, G_TYPE_FROM_INSTANCE(instance)); g_signal_query(signal_id, &query); /* Allocation adaptée */ info = (gsignal_wrapper_info *)malloc(sizeof(gsignal_wrapper_info) + sizeof(unsigned long) * ++query.n_params); info->flags = 0; info->callback = (GSignalCallback)handler; info->instance = instance; info->data = data; info->n_params = query.n_params; return g_signal_connect_swapped(instance, signal, G_CALLBACK(carry_signal_to_main_thread), info); }