+++ /dev/null
-//
-// dynamicsignal.c: new method of registering GObject signal
-// handlers that uses a default signal handler to read
-// callback argument stack and convert to an array of
-// GValues before running the "generic" signal handler
-//
-// Authors:
-// Aaron Bockover (abockover@novell.com)
-//
-// (C) 2006 Novell, Inc.
-//
-
-#include <stdlib.h>
-#include <string.h>
-
-#include <glib.h>
-#include <glib-object.h>
-#include <gobject/gvaluecollector.h>
-
-typedef void (* DynamicSignalHandler)(GObject *sender, guint argc,
- GValue *argv, gpointer userdata);
-
-//typedef gpointer (* DynamicSignalHandlerGPointer) (GObject *sender, guint argc,
-// GValue *argv, gpointer userdata);
-
-//typedef gint64 (* DynamicSignalHandlerGint64) (GObject *sender, guint argc, GValue *argv, gpointer userdata);
-
-typedef struct {
- GObject *object;
- gpointer userdata;
-
-/*
- typedef union {
- DynamicSignalHandler CBVoid;
- DynamicSignalHandlerGPointer CBGPointer;
- DynamicSignalHandlerGInt64 CBGInt64;
- }
- CallBack;
-*/
- DynamicSignalHandler callback;
-
- guint id;
-
- guint g_signal_id;
- gulong handler_id;
- GSignalQuery signal_details;
-} DynamicSignalEntry;
-
-static GList *dynamic_signal_table = NULL;
-static guint dynamic_signal_last_id = 1;
-
-static DynamicSignalEntry *
-find_entry(GObject *object, guint signal_id)
-{
- GList *current = dynamic_signal_table;
-
- while(current != NULL) {
- DynamicSignalEntry *entry = (DynamicSignalEntry *)current->data;
- if(entry->object == object && entry->g_signal_id == signal_id) {
- return entry;
- }
-
- current = current->next;
- }
-
- return NULL;
-}
-
-static DynamicSignalEntry *
-find_entry_by_name(GObject *object, const gchar *signal_name, guint *signal_id_out)
-{
- guint signal_id;
-
- signal_id = g_signal_lookup(signal_name, G_OBJECT_TYPE(object));
- if(signal_id_out != NULL) {
- *signal_id_out = signal_id;
- }
-
- if(signal_id <= 0) {
- return NULL;
- }
-
- return find_entry(object, signal_id);
-}
-
-static void
-free_entry(DynamicSignalEntry *entry)
-{
- memset(entry, 0, sizeof(DynamicSignalEntry));
- g_free(entry);
-}
-
-static void
-dynamic_signal_handler(DynamicSignalEntry *entry, ...)
-{
- va_list argp;
- GValue *args = NULL;
- guint i, n;
-
- if(entry == NULL) {
- return;
- }
-
- n = entry->signal_details.n_params;
-
- if(n <= 0) {
- entry->callback(entry->object, 0, NULL, entry->userdata);
- return;
- }
-
- args = g_new0(GValue, n);
- va_start(argp, entry);
-
- for(i = 0; i < n; i++) {
- GType type = entry->signal_details.param_types[i];
- GValue *value = &args[i];
- gchar *collect_error = NULL;
-
- if(!G_TYPE_IS_CLASSED(type) && G_TYPE_IS_VALUE_TYPE(type) &&
- !G_TYPE_IS_FUNDAMENTAL(type) && G_TYPE_IS_DERIVED(type) &&
- G_TYPE_HAS_VALUE_TABLE(type)) {
- g_value_init(value, type);
- value->data[0].v_pointer = va_arg(argp, gpointer);
- } else {
- g_value_init(value, type);
- G_VALUE_COLLECT(value, argp, 0, &collect_error);
- }
-
- if(collect_error != NULL) {
- g_warning("Could not collect value: %s", collect_error);
- g_free(collect_error);
- break;
- }
- }
-
- va_end(argp);
- entry->callback(entry->object, n, args, entry->userdata);
-}
-
-DynamicSignalEntry *
-g_dynamic_signal_find_registration(GObject *object, const gchar *signal_name)
-{
- return find_entry_by_name(object, signal_name, NULL);
-}
-
-guint
-g_dynamic_signal_connect(GObject *object, const gchar *signal_name,
- DynamicSignalHandler callback, gboolean after, gpointer userdata)
-{
- DynamicSignalEntry *entry;
- guint signal_id;
-
- entry = find_entry_by_name(object, signal_name, &signal_id);
-
- if(entry != NULL) {
- return entry->id;
- }
-
- entry = g_new0(DynamicSignalEntry, 1);
- entry->id = dynamic_signal_last_id++;
- entry->object = object;
- entry->g_signal_id = signal_id;
- entry->callback = callback;
- entry->userdata = userdata;
- g_signal_query(signal_id, &(entry->signal_details));
-
- dynamic_signal_table = g_list_prepend(dynamic_signal_table, entry);
-
- entry->handler_id = g_signal_connect_data(object, signal_name,
- G_CALLBACK(dynamic_signal_handler), entry, NULL,
- G_CONNECT_SWAPPED | (after ? G_CONNECT_AFTER : 0));
-
- return entry->id;
-}
-
-
-void
-g_dynamic_signal_disconnect(GObject *object, const gchar *signal_name)
-{
- DynamicSignalEntry *entry = find_entry_by_name(object, signal_name, NULL);
-
- if(entry == NULL) {
- return;
- }
-
- g_signal_handler_disconnect(object, entry->handler_id);
-
- dynamic_signal_table = g_list_remove(dynamic_signal_table, entry);
- free_entry(entry);
-
- entry = NULL;
-}
-
-void
-g_dynamic_signal_update_entry_userdata(DynamicSignalEntry *entry, gpointer userdata)
-{
- if(entry != NULL) {
- entry->userdata = userdata;
- }
-}
-
-GType g_value_type(GValue *value)
-{
- return G_VALUE_TYPE(value);
-}
-