X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtksignal.c;h=c855582da52456731835298e6c2fa46b918126e7;hb=3dc377a2ca46531acc864c18c516c7d81f0c25e0;hp=18f938ae0c3af499b44d82bdaaaa0bb65aae7bf3;hpb=3f7c856606609a77e94c5b7975ab88a49a8887c3;p=~andy%2Fgtk diff --git a/gtk/gtksignal.c b/gtk/gtksignal.c index 18f938ae0..c855582da 100644 --- a/gtk/gtksignal.c +++ b/gtk/gtksignal.c @@ -2,1973 +2,393 @@ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald * * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public + * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 - * Library General Public License for more details. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * You should have received a copy of the GNU Library General Public + * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ -#include -#include -#include -#include "gtksignal.h" -#include "gtkargcollector.c" +#undef GTK_DISABLE_DEPRECATED -#define SIGNAL_BLOCK_SIZE (100) -#define HANDLER_BLOCK_SIZE (200) -#define EMISSION_BLOCK_SIZE (100) -#define DISCONNECT_INFO_BLOCK_SIZE (64) -#define MAX_SIGNAL_PARAMS (31) +#include +#include "gtksignal.h" +#include "gtkalias.h" -enum -{ - EMISSION_CONTINUE, - EMISSION_RESTART, - EMISSION_DONE -}; - -#define GTK_RUN_TYPE(x) ((x) & GTK_RUN_BOTH) - - -typedef struct _GtkSignal GtkSignal; -typedef struct _GtkSignalHash GtkSignalHash; -typedef struct _GtkHandler GtkHandler; -typedef struct _GtkEmission GtkEmission; -typedef union _GtkEmissionAllocator GtkEmissionAllocator; -typedef struct _GtkDisconnectInfo GtkDisconnectInfo; - -typedef void (*GtkSignalMarshaller0) (GtkObject *object, - gpointer data); - -struct _GtkSignal -{ - guint signal_id; - GtkType object_type; - gchar *name; - guint function_offset; - GtkSignalMarshaller marshaller; - GtkType return_val; - GtkSignalRunType signal_flags : 16; - guint nparams : 16; - GtkType *params; - GHookList *hook_list; -}; - -struct _GtkSignalHash -{ - GtkType object_type; - GQuark quark; - guint signal_id; -}; - -struct _GtkHandler -{ - guint id; - guint blocked : 20; - guint object_signal : 1; - guint after : 1; - guint no_marshal : 1; - guint16 ref_count; - guint16 signal_id; - GtkSignalFunc func; - gpointer func_data; - GtkSignalDestroy destroy_func; - GtkHandler *prev; - GtkHandler *next; -}; - -struct _GtkEmission -{ - GtkObject *object; - guint signal_id; -}; - -union _GtkEmissionAllocator -{ - GtkEmissionAllocator *next; - GtkEmission emission; -}; - -struct _GtkDisconnectInfo -{ - GtkObject *object1; - guint disconnect_handler1; - guint signal_handler; - GtkObject *object2; - guint disconnect_handler2; -}; - - -static guint gtk_signal_hash (gconstpointer h); -static gint gtk_signal_compare (gconstpointer h1, - gconstpointer h2); -static GtkHandler* gtk_signal_handler_new (void); -static void gtk_signal_handler_ref (GtkHandler *handler); -static void gtk_signal_handler_unref (GtkHandler *handler, - GtkObject *object); -static void gtk_signal_handler_insert (GtkObject *object, - GtkHandler *handler); -static void gtk_signal_real_emit (GtkObject *object, - guint signal_id, - GtkArg *params); -static GtkHandler* gtk_signal_get_handlers (GtkObject *object, - guint signal_type); -static guint gtk_signal_connect_by_type (GtkObject *object, - guint signal_id, - GtkSignalFunc func, - gpointer func_data, - GtkSignalDestroy destroy_func, - gint object_signal, - gint after, - gint no_marshal); -static guint gtk_alive_disconnecter (GtkDisconnectInfo *info); -static GtkEmission* gtk_emission_new (void); -static void gtk_emission_add (GList **emissions, - GtkObject *object, - guint signal_type); -static void gtk_emission_remove (GList **emissions, - GtkObject *object, - guint signal_type); -static gint gtk_emission_check (GList *emissions, - GtkObject *object, - guint signal_type); -static gint gtk_handlers_run (GtkHandler *handlers, - GtkSignal *signal, - GtkObject *object, - GtkArg *params, - gint after); -static gboolean gtk_emission_hook_marshaller (GHook *hook, - gpointer data); -static gboolean gtk_signal_collect_params (GtkArg *params, - guint nparams, - GtkType *param_types, - GtkType return_type, - va_list var_args); - -#define LOOKUP_SIGNAL_ID(signal_id) ( \ - signal_id > 0 && signal_id < gtk_n_signals ? \ - (GtkSignal*) gtk_signals + signal_id : \ - (GtkSignal*) 0 \ -) - - -static GtkSignalMarshal global_marshaller = NULL; -static GtkSignalDestroy global_destroy_notify = NULL; - -static guint gtk_handler_id = 1; -static guint handler_quark = 0; -static GHashTable *gtk_signal_hash_table = NULL; -static GtkSignal *gtk_signals = NULL; -static guint gtk_n_signals = 0; -static GMemChunk *gtk_signal_hash_mem_chunk = NULL; -static GMemChunk *gtk_disconnect_info_mem_chunk = NULL; -static GtkHandler *gtk_handler_free_list = NULL; -static GtkEmissionAllocator *gtk_emission_free_list = NULL; - - - -static GList *current_emissions = NULL; -static GList *stop_emissions = NULL; -static GList *restart_emissions = NULL; - -static GtkSignal* -gtk_signal_next_and_invalidate (void) -{ - static guint gtk_n_free_signals = 0; - register GtkSignal *signal; - register guint new_signal_id; - - /* don't keep *any* GtkSignal pointers across invokation of this function!!! - */ - - if (gtk_n_free_signals == 0) - { - register guint i; - register guint size; - - /* nearest pow - */ - size = gtk_n_signals + SIGNAL_BLOCK_SIZE; - size *= sizeof (GtkSignal); - i = 1; - while (i < size) - i <<= 1; - size = i; - - gtk_signals = g_realloc (gtk_signals, size); - - gtk_n_free_signals = size / sizeof (GtkSignal) - gtk_n_signals; - - memset (gtk_signals + gtk_n_signals, 0, gtk_n_free_signals * sizeof (GtkSignal)); - } - - new_signal_id = gtk_n_signals++; - gtk_n_free_signals--; - - signal = LOOKUP_SIGNAL_ID (new_signal_id); - if (signal) - signal->signal_id = new_signal_id; - - return signal; -} +/* the real parameter limit is of course given by GSignal, bu we need + * an upper limit for the implementations. so this should be adjusted + * with any future changes on the GSignal side of things. + */ +#define SIGNAL_MAX_PARAMS 12 -void -gtk_signal_init (void) -{ - if (!handler_quark) - { - GtkSignal *zero; - - zero = gtk_signal_next_and_invalidate (); - g_assert (zero == NULL); - - handler_quark = g_quark_from_static_string ("gtk-signal-handlers"); - - gtk_signal_hash_mem_chunk = - g_mem_chunk_new ("GtkSignalHash mem chunk", - sizeof (GtkSignalHash), - sizeof (GtkSignalHash) * SIGNAL_BLOCK_SIZE, - G_ALLOC_ONLY); - gtk_disconnect_info_mem_chunk = - g_mem_chunk_new ("GtkDisconnectInfo mem chunk", - sizeof (GtkDisconnectInfo), - sizeof (GtkDisconnectInfo) * DISCONNECT_INFO_BLOCK_SIZE, - G_ALLOC_AND_FREE); - gtk_handler_free_list = NULL; - gtk_emission_free_list = NULL; - - gtk_signal_hash_table = g_hash_table_new (gtk_signal_hash, - gtk_signal_compare); - } -} +/* --- functions --- */ guint -gtk_signal_newv (const gchar *r_name, +gtk_signal_newv (const gchar *name, GtkSignalRunType signal_flags, - GtkType object_type, - guint function_offset, - GtkSignalMarshaller marshaller, - GtkType return_val, - guint nparams, - GtkType *params) + GType object_type, + guint function_offset, + GSignalCMarshaller marshaller, + GType return_val, + guint n_params, + GType *params) { - GtkSignal *signal; - GtkSignalHash *hash; - GQuark quark; - guint i; - gchar *name; - - g_return_val_if_fail (r_name != NULL, 0); - g_return_val_if_fail (nparams < MAX_SIGNAL_PARAMS, 0); - if (nparams) - g_return_val_if_fail (params != NULL, 0); - - if (!handler_quark) - gtk_signal_init (); - - - name = g_strdup (r_name); - g_strdelimit (name, NULL, '_'); - - quark = gtk_signal_lookup (name, object_type); - if (quark) - { - g_warning ("gtk_signal_newv(): signal \"%s\" already exists in the `%s' class ancestry\n", - r_name, - gtk_type_name (object_type)); - g_free (name); - return 0; - } - - if (return_val != GTK_TYPE_NONE && - (signal_flags & GTK_RUN_BOTH) == GTK_RUN_FIRST) - { - g_warning ("gtk_signal_newv(): signal \"%s\" - return value `%s' incompatible with GTK_RUN_FIRST", - name, gtk_type_name (return_val)); - g_free (name); - return 0; - } - - signal = gtk_signal_next_and_invalidate (); + GClosure *closure; - /* signal->signal_id already set */ + g_return_val_if_fail (n_params < SIGNAL_MAX_PARAMS, 0); - signal->object_type = object_type; - signal->name = name; - signal->function_offset = function_offset; - signal->marshaller = marshaller; - signal->return_val = return_val; - signal->signal_flags = signal_flags; - signal->nparams = nparams; - signal->hook_list = NULL; - - if (nparams > 0) - { - signal->params = g_new (GtkType, nparams); - - for (i = 0; i < nparams; i++) - signal->params[i] = params[i]; - } - else - signal->params = NULL; - - /* insert "signal_name" into hash table - */ - hash = g_chunk_new (GtkSignalHash, gtk_signal_hash_mem_chunk); - hash->object_type = object_type; - hash->quark = g_quark_from_string (signal->name); - hash->signal_id = signal->signal_id; - g_hash_table_insert (gtk_signal_hash_table, hash, GUINT_TO_POINTER (hash->signal_id)); - - /* insert "signal-name" into hash table - */ - g_strdelimit (signal->name, NULL, '-'); - quark = g_quark_from_static_string (signal->name); - if (quark != hash->quark) - { - hash = g_chunk_new (GtkSignalHash, gtk_signal_hash_mem_chunk); - hash->object_type = object_type; - hash->quark = quark; - hash->signal_id = signal->signal_id; - g_hash_table_insert (gtk_signal_hash_table, hash, GUINT_TO_POINTER (hash->signal_id)); - } + closure = function_offset ? g_signal_type_cclosure_new (object_type, function_offset) : NULL; - return signal->signal_id; + return g_signal_newv (name, object_type, (GSignalFlags)signal_flags, closure, + NULL, NULL, marshaller, return_val, n_params, params); } guint -gtk_signal_new (const gchar *name, +gtk_signal_new (const gchar *name, GtkSignalRunType signal_flags, - GtkType object_type, - guint function_offset, - GtkSignalMarshaller marshaller, - GtkType return_val, - guint nparams, + GType object_type, + guint function_offset, + GSignalCMarshaller marshaller, + GType return_val, + guint n_params, ...) { - GtkType *params; - guint i; - va_list args; + GType *params; guint signal_id; - g_return_val_if_fail (nparams < MAX_SIGNAL_PARAMS, 0); - - if (nparams > 0) + if (n_params) { - params = g_new (GtkType, nparams); - - va_start (args, nparams); - - for (i = 0; i < nparams; i++) - params[i] = va_arg (args, GtkType); + va_list args; + guint i; + params = g_new (GType, n_params); + va_start (args, n_params); + for (i = 0; i < n_params; i++) + params[i] = va_arg (args, GType); va_end (args); } else params = NULL; - signal_id = gtk_signal_newv (name, signal_flags, object_type, function_offset, marshaller, return_val, - nparams, + n_params, params); - g_free (params); return signal_id; } -guint -gtk_signal_lookup (const gchar *name, - GtkType object_type) -{ - GtkSignalHash hash; - - g_return_val_if_fail (name != NULL, 0); - g_return_val_if_fail (gtk_type_is_a (object_type, GTK_TYPE_OBJECT), 0); - - hash.quark = g_quark_try_string (name); - if (hash.quark) - { - while (object_type) - { - guint signal_id; - - hash.object_type = object_type; - - signal_id = GPOINTER_TO_UINT (g_hash_table_lookup (gtk_signal_hash_table, &hash)); - if (signal_id) - return signal_id; - - object_type = gtk_type_parent (object_type); - } - } - - return 0; -} - -GtkSignalQuery* -gtk_signal_query (guint signal_id) -{ - GtkSignalQuery *query; - GtkSignal *signal; - - g_return_val_if_fail (signal_id >= 1, NULL); - - signal = LOOKUP_SIGNAL_ID (signal_id); - if (signal) - { - query = g_new (GtkSignalQuery, 1); - - query->object_type = signal->object_type; - query->signal_id = signal_id; - query->signal_name = signal->name; - query->is_user_signal = signal->function_offset == 0; - query->signal_flags = signal->signal_flags; - query->return_val = signal->return_val; - query->nparams = signal->nparams; - query->params = signal->params; - } - else - query = NULL; - - return query; -} - -gchar* -gtk_signal_name (guint signal_id) +void +gtk_signal_emit_stop_by_name (GtkObject *object, + const gchar *name) { - GtkSignal *signal; - - g_return_val_if_fail (signal_id >= 1, NULL); - - signal = LOOKUP_SIGNAL_ID (signal_id); - if (signal) - return signal->name; + g_return_if_fail (GTK_IS_OBJECT (object)); - return NULL; + g_signal_stop_emission (object, g_signal_lookup (name, G_OBJECT_TYPE (object)), 0); } void -gtk_signal_emitv (GtkObject *object, - guint signal_id, - GtkArg *params) +gtk_signal_connect_object_while_alive (GtkObject *object, + const gchar *name, + GCallback func, + GtkObject *alive_object) { - GtkSignal *signal; - - g_return_if_fail (object != NULL); - g_return_if_fail (signal_id >= 1); + g_return_if_fail (GTK_IS_OBJECT (object)); - signal = LOOKUP_SIGNAL_ID (signal_id); - g_return_if_fail (signal != NULL); - g_return_if_fail (gtk_type_is_a (GTK_OBJECT_TYPE (object), signal->object_type)); - - if (signal->nparams > 0) - g_return_if_fail (params != NULL); - - gtk_signal_real_emit (object, signal_id, params); + g_signal_connect_closure_by_id (object, + g_signal_lookup (name, G_OBJECT_TYPE (object)), 0, + g_cclosure_new_object_swap (func, G_OBJECT (alive_object)), + FALSE); } void -gtk_signal_emit (GtkObject *object, - guint signal_id, - ...) +gtk_signal_connect_while_alive (GtkObject *object, + const gchar *name, + GCallback func, + gpointer func_data, + GtkObject *alive_object) { - GtkSignal *signal; - va_list args; - GtkArg params[MAX_SIGNAL_PARAMS + 1]; - gboolean abort; - - g_return_if_fail (object != NULL); - g_return_if_fail (signal_id >= 1); - - signal = LOOKUP_SIGNAL_ID (signal_id); - g_return_if_fail (signal != NULL); - g_return_if_fail (gtk_type_is_a (GTK_OBJECT_TYPE (object), signal->object_type)); + GClosure *closure; - va_start (args, signal_id); - abort = gtk_signal_collect_params (params, - signal->nparams, - signal->params, - signal->return_val, - args); - va_end (args); + g_return_if_fail (GTK_IS_OBJECT (object)); - if (!abort) - gtk_signal_real_emit (object, signal_id, params); + closure = g_cclosure_new (func, func_data, NULL); + g_object_watch_closure (G_OBJECT (alive_object), closure); + g_signal_connect_closure_by_id (object, + g_signal_lookup (name, G_OBJECT_TYPE (object)), 0, + closure, + FALSE); } -void -gtk_signal_emitv_by_name (GtkObject *object, - const gchar *name, - GtkArg *params) +gulong +gtk_signal_connect_full (GtkObject *object, + const gchar *name, + GCallback func, + GtkCallbackMarshal unsupported, + gpointer data, + GDestroyNotify destroy_func, + gint object_signal, + gint after) { - guint signal_id; - - g_return_if_fail (object != NULL); - g_return_if_fail (name != NULL); - g_return_if_fail (params != NULL); - - signal_id = gtk_signal_lookup (name, GTK_OBJECT_TYPE (object)); + g_return_val_if_fail (GTK_IS_OBJECT (object), 0); + g_return_val_if_fail (unsupported == NULL, 0); - if (signal_id >= 1) - { - GtkSignal *signal; - - signal = LOOKUP_SIGNAL_ID (signal_id); - g_return_if_fail (signal != NULL); - g_return_if_fail (gtk_type_is_a (GTK_OBJECT_TYPE (object), signal->object_type)); - - gtk_signal_real_emit (object, signal_id, params); - } - else - { - g_warning ("gtk_signal_emitv_by_name(): could not find signal \"%s\" in the `%s' class ancestry", - name, - gtk_type_name (GTK_OBJECT_TYPE (object))); - } + return g_signal_connect_closure_by_id (object, + g_signal_lookup (name, G_OBJECT_TYPE (object)), 0, + (object_signal + ? g_cclosure_new_swap + : g_cclosure_new) (func, + data, + (GClosureNotify) destroy_func), + after); } void -gtk_signal_emit_by_name (GtkObject *object, - const gchar *name, - ...) +gtk_signal_compat_matched (GtkObject *object, + GCallback func, + gpointer data, + GSignalMatchType match, + guint action) { - guint signal_id; - - g_return_if_fail (object != NULL); - g_return_if_fail (name != NULL); - - signal_id = gtk_signal_lookup (name, GTK_OBJECT_TYPE (object)); + guint n_handlers; - if (signal_id >= 1) - { - GtkSignal *signal; - GtkArg params[MAX_SIGNAL_PARAMS + 1]; - va_list args; - gboolean abort; - - signal = LOOKUP_SIGNAL_ID (signal_id); - g_return_if_fail (signal != NULL); - g_return_if_fail (gtk_type_is_a (GTK_OBJECT_TYPE (object), signal->object_type)); - - va_start (args, name); - abort = gtk_signal_collect_params (params, - signal->nparams, - signal->params, - signal->return_val, - args); - va_end (args); - - if (!abort) - gtk_signal_real_emit (object, signal_id, params); - } - else - { - g_warning ("gtk_signal_emit_by_name(): could not find signal \"%s\" in the `%s' class ancestry", - name, - gtk_type_name (GTK_OBJECT_TYPE (object))); - } -} + g_return_if_fail (GTK_IS_OBJECT (object)); -void -gtk_signal_emit_stop (GtkObject *object, - guint signal_id) -{ - g_return_if_fail (object != NULL); - g_return_if_fail (signal_id >= 1); - - if (gtk_emission_check (current_emissions, object, signal_id)) - { - if (!gtk_emission_check (stop_emissions, object, signal_id)) - gtk_emission_add (&stop_emissions, object, signal_id); - } - else - g_warning ("gtk_signal_emit_stop(): no current emission (%u) for object `%s'", - signal_id, - gtk_type_name (GTK_OBJECT_TYPE (object))); + switch (action) + { + case 0: n_handlers = g_signal_handlers_disconnect_matched (object, match, 0, 0, NULL, (gpointer) func, data); break; + case 1: n_handlers = g_signal_handlers_block_matched (object, match, 0, 0, NULL, (gpointer) func, data); break; + case 2: n_handlers = g_signal_handlers_unblock_matched (object, match, 0, 0, NULL, (gpointer) func, data); break; + default: n_handlers = 0; break; + } + + if (!n_handlers) + g_warning ("unable to find signal handler for object(%s:%p) with func(%p) and data(%p)", + G_OBJECT_TYPE_NAME (object), object, func, data); +} + +static inline gboolean +gtk_arg_to_value (GtkArg *arg, + GValue *value) +{ + switch (G_TYPE_FUNDAMENTAL (arg->type)) + { + case G_TYPE_CHAR: g_value_set_char (value, GTK_VALUE_CHAR (*arg)); break; + case G_TYPE_UCHAR: g_value_set_uchar (value, GTK_VALUE_UCHAR (*arg)); break; + case G_TYPE_BOOLEAN: g_value_set_boolean (value, GTK_VALUE_BOOL (*arg)); break; + case G_TYPE_INT: g_value_set_int (value, GTK_VALUE_INT (*arg)); break; + case G_TYPE_UINT: g_value_set_uint (value, GTK_VALUE_UINT (*arg)); break; + case G_TYPE_LONG: g_value_set_long (value, GTK_VALUE_LONG (*arg)); break; + case G_TYPE_ULONG: g_value_set_ulong (value, GTK_VALUE_ULONG (*arg)); break; + case G_TYPE_ENUM: g_value_set_enum (value, GTK_VALUE_ENUM (*arg)); break; + case G_TYPE_FLAGS: g_value_set_flags (value, GTK_VALUE_FLAGS (*arg)); break; + case G_TYPE_FLOAT: g_value_set_float (value, GTK_VALUE_FLOAT (*arg)); break; + case G_TYPE_DOUBLE: g_value_set_double (value, GTK_VALUE_DOUBLE (*arg)); break; + case G_TYPE_STRING: g_value_set_string (value, GTK_VALUE_STRING (*arg)); break; + case G_TYPE_BOXED: g_value_set_boxed (value, GTK_VALUE_BOXED (*arg)); break; + case G_TYPE_POINTER: g_value_set_pointer (value, GTK_VALUE_POINTER (*arg)); break; + case G_TYPE_OBJECT: g_value_set_object (value, GTK_VALUE_POINTER (*arg)); break; + default: + return FALSE; + } + return TRUE; +} + +static inline gboolean +gtk_arg_static_to_value (GtkArg *arg, + GValue *value) +{ + switch (G_TYPE_FUNDAMENTAL (arg->type)) + { + case G_TYPE_CHAR: g_value_set_char (value, GTK_VALUE_CHAR (*arg)); break; + case G_TYPE_UCHAR: g_value_set_uchar (value, GTK_VALUE_UCHAR (*arg)); break; + case G_TYPE_BOOLEAN: g_value_set_boolean (value, GTK_VALUE_BOOL (*arg)); break; + case G_TYPE_INT: g_value_set_int (value, GTK_VALUE_INT (*arg)); break; + case G_TYPE_UINT: g_value_set_uint (value, GTK_VALUE_UINT (*arg)); break; + case G_TYPE_LONG: g_value_set_long (value, GTK_VALUE_LONG (*arg)); break; + case G_TYPE_ULONG: g_value_set_ulong (value, GTK_VALUE_ULONG (*arg)); break; + case G_TYPE_ENUM: g_value_set_enum (value, GTK_VALUE_ENUM (*arg)); break; + case G_TYPE_FLAGS: g_value_set_flags (value, GTK_VALUE_FLAGS (*arg)); break; + case G_TYPE_FLOAT: g_value_set_float (value, GTK_VALUE_FLOAT (*arg)); break; + case G_TYPE_DOUBLE: g_value_set_double (value, GTK_VALUE_DOUBLE (*arg)); break; + case G_TYPE_STRING: g_value_set_static_string (value, GTK_VALUE_STRING (*arg)); break; + case G_TYPE_BOXED: g_value_set_static_boxed (value, GTK_VALUE_BOXED (*arg)); break; + case G_TYPE_POINTER: g_value_set_pointer (value, GTK_VALUE_POINTER (*arg)); break; + case G_TYPE_OBJECT: g_value_set_object (value, GTK_VALUE_POINTER (*arg)); break; + default: + return FALSE; + } + return TRUE; +} + +static inline gboolean +gtk_arg_set_from_value (GtkArg *arg, + GValue *value, + gboolean copy_string) +{ + switch (G_TYPE_FUNDAMENTAL (arg->type)) + { + case G_TYPE_CHAR: GTK_VALUE_CHAR (*arg) = g_value_get_char (value); break; + case G_TYPE_UCHAR: GTK_VALUE_UCHAR (*arg) = g_value_get_uchar (value); break; + case G_TYPE_BOOLEAN: GTK_VALUE_BOOL (*arg) = g_value_get_boolean (value); break; + case G_TYPE_INT: GTK_VALUE_INT (*arg) = g_value_get_int (value); break; + case G_TYPE_UINT: GTK_VALUE_UINT (*arg) = g_value_get_uint (value); break; + case G_TYPE_LONG: GTK_VALUE_LONG (*arg) = g_value_get_long (value); break; + case G_TYPE_ULONG: GTK_VALUE_ULONG (*arg) = g_value_get_ulong (value); break; + case G_TYPE_ENUM: GTK_VALUE_ENUM (*arg) = g_value_get_enum (value); break; + case G_TYPE_FLAGS: GTK_VALUE_FLAGS (*arg) = g_value_get_flags (value); break; + case G_TYPE_FLOAT: GTK_VALUE_FLOAT (*arg) = g_value_get_float (value); break; + case G_TYPE_DOUBLE: GTK_VALUE_DOUBLE (*arg) = g_value_get_double (value); break; + case G_TYPE_BOXED: GTK_VALUE_BOXED (*arg) = g_value_get_boxed (value); break; + case G_TYPE_POINTER: GTK_VALUE_POINTER (*arg) = g_value_get_pointer (value); break; + case G_TYPE_OBJECT: GTK_VALUE_POINTER (*arg) = g_value_get_object (value); break; + case G_TYPE_STRING: if (copy_string) + GTK_VALUE_STRING (*arg) = g_value_dup_string (value); + else + GTK_VALUE_STRING (*arg) = (char *) g_value_get_string (value); + break; + default: + return FALSE; + } + return TRUE; +} + +static inline gboolean +gtk_argloc_set_from_value (GtkArg *arg, + GValue *value, + gboolean copy_string) +{ + switch (G_TYPE_FUNDAMENTAL (arg->type)) + { + case G_TYPE_CHAR: *GTK_RETLOC_CHAR (*arg) = g_value_get_char (value); break; + case G_TYPE_UCHAR: *GTK_RETLOC_UCHAR (*arg) = g_value_get_uchar (value); break; + case G_TYPE_BOOLEAN: *GTK_RETLOC_BOOL (*arg) = g_value_get_boolean (value); break; + case G_TYPE_INT: *GTK_RETLOC_INT (*arg) = g_value_get_int (value); break; + case G_TYPE_UINT: *GTK_RETLOC_UINT (*arg) = g_value_get_uint (value); break; + case G_TYPE_LONG: *GTK_RETLOC_LONG (*arg) = g_value_get_long (value); break; + case G_TYPE_ULONG: *GTK_RETLOC_ULONG (*arg) = g_value_get_ulong (value); break; + case G_TYPE_ENUM: *GTK_RETLOC_ENUM (*arg) = g_value_get_enum (value); break; + case G_TYPE_FLAGS: *GTK_RETLOC_FLAGS (*arg) = g_value_get_flags (value); break; + case G_TYPE_FLOAT: *GTK_RETLOC_FLOAT (*arg) = g_value_get_float (value); break; + case G_TYPE_DOUBLE: *GTK_RETLOC_DOUBLE (*arg) = g_value_get_double (value); break; + case G_TYPE_BOXED: *GTK_RETLOC_BOXED (*arg) = g_value_get_boxed (value); break; + case G_TYPE_POINTER: *GTK_RETLOC_POINTER (*arg) = g_value_get_pointer (value); break; + case G_TYPE_OBJECT: *GTK_RETLOC_POINTER (*arg) = g_value_get_object (value); break; + case G_TYPE_STRING: if (copy_string) + *GTK_RETLOC_STRING (*arg) = g_value_dup_string (value); + else + *GTK_RETLOC_STRING (*arg) = (char *) g_value_get_string (value); + break; + default: + return FALSE; + } + return TRUE; } void -gtk_signal_emit_stop_by_name (GtkObject *object, - const gchar *name) +gtk_signal_emitv (GtkObject *object, + guint signal_id, + GtkArg *args) { - guint signal_id; - - g_return_if_fail (object != NULL); - g_return_if_fail (name != NULL); + GSignalQuery query; + GValue params[SIGNAL_MAX_PARAMS + 1] = { { 0, }, }; + GValue rvalue = { 0, }; + guint i; - signal_id = gtk_signal_lookup (name, GTK_OBJECT_TYPE (object)); - if (signal_id) - gtk_signal_emit_stop (object, signal_id); - else - g_warning ("gtk_signal_emit_stop_by_name(): could not find signal \"%s\" in the `%s' class ancestry", - name, - gtk_type_name (GTK_OBJECT_TYPE (object))); -} - -guint -gtk_signal_n_emissions (GtkObject *object, - guint signal_id) -{ - GList *list; - guint n; + g_return_if_fail (GTK_IS_OBJECT (object)); - g_return_val_if_fail (object != NULL, 0); - g_return_val_if_fail (GTK_IS_OBJECT (object), 0); + g_signal_query (signal_id, &query); + g_return_if_fail (query.signal_id != 0); + g_return_if_fail (g_type_is_a (GTK_OBJECT_TYPE (object), query.itype)); + g_return_if_fail (query.n_params < SIGNAL_MAX_PARAMS); + if (query.n_params > 0) + g_return_if_fail (args != NULL); - n = 0; - for (list = current_emissions; list; list = list->next) + g_value_init (params + 0, GTK_OBJECT_TYPE (object)); + g_value_set_object (params + 0, G_OBJECT (object)); + for (i = 0; i < query.n_params; i++) { - GtkEmission *emission; + GValue *value = params + 1 + i; + GtkArg *arg = args + i; - emission = list->data; - - if ((emission->object == object) && - (emission->signal_id == signal_id)) - n++; - } - - return n; -} - -guint -gtk_signal_n_emissions_by_name (GtkObject *object, - const gchar *name) -{ - guint signal_id; - guint n; - - g_return_val_if_fail (object != NULL, 0); - g_return_val_if_fail (GTK_IS_OBJECT (object), 0); - g_return_val_if_fail (name != NULL, 0); - - signal_id = gtk_signal_lookup (name, GTK_OBJECT_TYPE (object)); - if (signal_id) - n = gtk_signal_n_emissions (object, signal_id); - else - { - g_warning ("gtk_signal_n_emissions_by_name(): could not find signal \"%s\" in the `%s' class ancestry", - name, - gtk_type_name (GTK_OBJECT_TYPE (object))); - n = 0; - } - - return n; -} - -guint -gtk_signal_connect (GtkObject *object, - const gchar *name, - GtkSignalFunc func, - gpointer func_data) -{ - guint signal_id; - - g_return_val_if_fail (object != NULL, 0); - g_return_val_if_fail (GTK_IS_OBJECT (object), 0); - - signal_id = gtk_signal_lookup (name, GTK_OBJECT_TYPE (object)); - if (!signal_id) - { - g_warning ("gtk_signal_connect(): could not find signal \"%s\" in the `%s' class ancestry", - name, - gtk_type_name (GTK_OBJECT_TYPE (object))); - return 0; - } - - return gtk_signal_connect_by_type (object, signal_id, - func, func_data, NULL, - FALSE, FALSE, FALSE); -} - -guint -gtk_signal_connect_after (GtkObject *object, - const gchar *name, - GtkSignalFunc func, - gpointer func_data) -{ - guint signal_id; - - g_return_val_if_fail (object != NULL, 0); - - signal_id = gtk_signal_lookup (name, GTK_OBJECT_TYPE (object)); - if (!signal_id) - { - g_warning ("gtk_signal_connect_after(): could not find signal \"%s\" in the `%s' class ancestry", - name, - gtk_type_name (GTK_OBJECT_TYPE (object))); - return 0; - } - - return gtk_signal_connect_by_type (object, signal_id, - func, func_data, NULL, - FALSE, TRUE, FALSE); -} - -guint -gtk_signal_connect_full (GtkObject *object, - const gchar *name, - GtkSignalFunc func, - GtkCallbackMarshal marshal, - gpointer func_data, - GtkDestroyNotify destroy_func, - gint object_signal, - gint after) -{ - guint signal_id; - - g_return_val_if_fail (object != NULL, 0); - - signal_id = gtk_signal_lookup (name, GTK_OBJECT_TYPE (object)); - if (!signal_id) - { - g_warning ("gtk_signal_connect_full(): could not find signal \"%s\" in the `%s' class ancestry", - name, - gtk_type_name (GTK_OBJECT_TYPE (object))); - return 0; - } - - if (marshal) - return gtk_signal_connect_by_type (object, signal_id, (GtkSignalFunc) marshal, - func_data, destroy_func, - object_signal, after, TRUE); - else - return gtk_signal_connect_by_type (object, signal_id, func, - func_data, destroy_func, - object_signal, after, FALSE); -} - -guint -gtk_signal_connect_interp (GtkObject *object, - const gchar *name, - GtkCallbackMarshal func, - gpointer func_data, - GtkDestroyNotify destroy_func, - gint after) -{ - return gtk_signal_connect_full (object, name, NULL, func, - func_data, destroy_func, FALSE, after); -} - -guint -gtk_signal_connect_object (GtkObject *object, - const gchar *name, - GtkSignalFunc func, - GtkObject *slot_object) -{ - guint signal_id; - - g_return_val_if_fail (object != NULL, 0); - /* slot_object needs to be treated as ordinary pointer - */ - - signal_id = gtk_signal_lookup (name, GTK_OBJECT_TYPE (object)); - if (!signal_id) - { - g_warning ("gtk_signal_connect_object(): could not find signal \"%s\" in the `%s' class ancestry", - name, - gtk_type_name (GTK_OBJECT_TYPE (object))); - return 0; + g_value_init (value, arg->type & ~G_SIGNAL_TYPE_STATIC_SCOPE); + if (!gtk_arg_static_to_value (arg, value)) + { + g_warning ("%s: failed to convert arg type `%s' to value type `%s'", + G_STRLOC, g_type_name (arg->type & ~G_SIGNAL_TYPE_STATIC_SCOPE), + g_type_name (G_VALUE_TYPE (value))); + return; + } } + if (query.return_type != G_TYPE_NONE) + g_value_init (&rvalue, query.return_type); - return gtk_signal_connect_by_type (object, signal_id, - func, slot_object, NULL, - TRUE, FALSE, FALSE); -} - -guint -gtk_signal_connect_object_after (GtkObject *object, - const gchar *name, - GtkSignalFunc func, - GtkObject *slot_object) -{ - guint signal_id; - - g_return_val_if_fail (object != NULL, 0); + g_signal_emitv (params, signal_id, 0, &rvalue); - signal_id = gtk_signal_lookup (name, GTK_OBJECT_TYPE (object)); - if (!signal_id) + if (query.return_type != G_TYPE_NONE) { - g_warning ("gtk_signal_connect_object_after(): could not find signal \"%s\" in the `%s' class ancestry", - name, - gtk_type_name (GTK_OBJECT_TYPE (object))); - return 0; + gtk_argloc_set_from_value (args + query.n_params, &rvalue, TRUE); + g_value_unset (&rvalue); } - - return gtk_signal_connect_by_type (object, signal_id, - func, slot_object, NULL, - TRUE, TRUE, FALSE); + for (i = 0; i < query.n_params; i++) + g_value_unset (params + 1 + i); + g_value_unset (params + 0); } void -gtk_signal_connect_while_alive (GtkObject *object, - const gchar *signal, - GtkSignalFunc func, - gpointer func_data, - GtkObject *alive_object) +gtk_signal_emit (GtkObject *object, + guint signal_id, + ...) { - GtkDisconnectInfo *info; + va_list var_args; - g_return_if_fail (object != NULL); g_return_if_fail (GTK_IS_OBJECT (object)); - g_return_if_fail (signal != NULL); - g_return_if_fail (func != NULL); - g_return_if_fail (alive_object != NULL); - g_return_if_fail (GTK_IS_OBJECT (alive_object)); - - info = g_chunk_new (GtkDisconnectInfo, gtk_disconnect_info_mem_chunk); - info->object1 = object; - info->object2 = alive_object; - - info->signal_handler = gtk_signal_connect (object, signal, func, func_data); - info->disconnect_handler1 = - gtk_signal_connect_object (info->object1, - "destroy", - GTK_SIGNAL_FUNC (gtk_alive_disconnecter), - (GtkObject*) info); - info->disconnect_handler2 = - gtk_signal_connect_object (info->object2, - "destroy", - GTK_SIGNAL_FUNC (gtk_alive_disconnecter), - (GtkObject*) info); -} -void -gtk_signal_connect_object_while_alive (GtkObject *object, - const gchar *signal, - GtkSignalFunc func, - GtkObject *alive_object) -{ - GtkDisconnectInfo *info; - - g_return_if_fail (object != NULL); - g_return_if_fail (GTK_IS_OBJECT (object)); - g_return_if_fail (signal != NULL); - g_return_if_fail (func != NULL); - g_return_if_fail (alive_object != NULL); - g_return_if_fail (GTK_IS_OBJECT (alive_object)); - - info = g_chunk_new (GtkDisconnectInfo, gtk_disconnect_info_mem_chunk); - info->object1 = object; - info->object2 = alive_object; - - info->signal_handler = gtk_signal_connect_object (object, signal, func, alive_object); - info->disconnect_handler1 = - gtk_signal_connect_object (info->object1, - "destroy", - GTK_SIGNAL_FUNC (gtk_alive_disconnecter), - (GtkObject*) info); - info->disconnect_handler2 = - gtk_signal_connect_object (info->object2, - "destroy", - GTK_SIGNAL_FUNC (gtk_alive_disconnecter), - (GtkObject*) info); + va_start (var_args, signal_id); + g_signal_emit_valist (G_OBJECT (object), signal_id, 0, var_args); + va_end (var_args); } void -gtk_signal_disconnect (GtkObject *object, - guint handler_id) +gtk_signal_emit_by_name (GtkObject *object, + const gchar *name, + ...) { - GtkHandler *handler; + GSignalQuery query; + va_list var_args; - g_return_if_fail (object != NULL); - g_return_if_fail (handler_id > 0); - - handler = gtk_object_get_data_by_id (object, handler_quark); + g_return_if_fail (GTK_IS_OBJECT (object)); + g_return_if_fail (name != NULL); - while (handler) - { - if (handler->id == handler_id) - { - handler->id = 0; - handler->blocked += 1; - gtk_signal_handler_unref (handler, object); - return; - } - handler = handler->next; - } + g_signal_query (g_signal_lookup (name, GTK_OBJECT_TYPE (object)), &query); + g_return_if_fail (query.signal_id != 0); - g_warning ("gtk_signal_disconnect(): could not find handler (%u)", handler_id); + va_start (var_args, name); + g_signal_emit_valist (G_OBJECT (object), query.signal_id, 0, var_args); + va_end (var_args); } void -gtk_signal_disconnect_by_func (GtkObject *object, - GtkSignalFunc func, - gpointer data) +gtk_signal_emitv_by_name (GtkObject *object, + const gchar *name, + GtkArg *args) { - GtkHandler *handler; - gint found_one; - - g_return_if_fail (object != NULL); - g_return_if_fail (func != NULL); - - found_one = FALSE; - handler = gtk_object_get_data_by_id (object, handler_quark); - - while (handler) - { - GtkHandler *handler_next; - - handler_next = handler->next; - if ((handler->id > 0) && - (handler->func == func) && - (handler->func_data == data)) - { - found_one = TRUE; - handler->id = 0; - handler->blocked += 1; - gtk_signal_handler_unref (handler, object); - } - handler = handler_next; - } + g_return_if_fail (GTK_IS_OBJECT (object)); - if (!found_one) - g_warning ("gtk_signal_disconnect_by_func(): could not find handler (0x%0lX) containing data (0x%0lX)", (long) func, (long) data); + gtk_signal_emitv (object, g_signal_lookup (name, GTK_OBJECT_TYPE (object)), args); } -void -gtk_signal_disconnect_by_data (GtkObject *object, - gpointer data) -{ - GtkHandler *handler; - gint found_one; - - g_return_if_fail (object != NULL); - - found_one = FALSE; - handler = gtk_object_get_data_by_id (object, handler_quark); - - while (handler) - { - GtkHandler *handler_next; - - handler_next = handler->next; - if ((handler->id > 0) && - (handler->func_data == data)) - { - found_one = TRUE; - handler->id = 0; - handler->blocked += 1; - gtk_signal_handler_unref (handler, object); - } - handler = handler_next; - } - - if (!found_one) - g_warning ("gtk_signal_disconnect_by_data(): could not find handler containing data (0x%0lX)", (long) data); -} - -void -gtk_signal_handler_block (GtkObject *object, - guint handler_id) -{ - GtkHandler *handler; - - g_return_if_fail (object != NULL); - g_return_if_fail (handler_id > 0); - - handler = gtk_object_get_data_by_id (object, handler_quark); - - while (handler) - { - if (handler->id == handler_id) - { - handler->blocked += 1; - return; - } - handler = handler->next; - } - - g_warning ("gtk_signal_handler_block(): could not find handler (%u)", handler_id); -} - -void -gtk_signal_handler_block_by_func (GtkObject *object, - GtkSignalFunc func, - gpointer data) -{ - GtkHandler *handler; - gint found_one; - - g_return_if_fail (object != NULL); - g_return_if_fail (func != NULL); - - found_one = FALSE; - handler = gtk_object_get_data_by_id (object, handler_quark); - - while (handler) - { - if ((handler->id > 0) && - (handler->func == func) && - (handler->func_data == data)) - { - found_one = TRUE; - handler->blocked += 1; - } - handler = handler->next; - } - - if (!found_one) - g_warning ("gtk_signal_handler_block_by_func(): could not find handler (0x%0lX) containing data (0x%0lX)", (long) func, (long) data); -} - -void -gtk_signal_handler_block_by_data (GtkObject *object, - gpointer data) -{ - GtkHandler *handler; - gint found_one; - - g_return_if_fail (object != NULL); - - found_one = FALSE; - handler = gtk_object_get_data_by_id (object, handler_quark); - - while (handler) - { - if ((handler->id > 0) && - (handler->func_data == data)) - { - found_one = TRUE; - handler->blocked += 1; - } - handler = handler->next; - } - - if (!found_one) - g_warning ("gtk_signal_handler_block_by_data(): could not find handler containing data (0x%0lX)", (long) data); -} - -void -gtk_signal_handler_unblock (GtkObject *object, - guint handler_id) -{ - GtkHandler *handler; - - g_return_if_fail (object != NULL); - g_return_if_fail (handler_id > 0); - - handler = gtk_object_get_data_by_id (object, handler_quark); - - while (handler) - { - if (handler->id == handler_id) - { - if (handler->blocked > 0) - handler->blocked -= 1; - else - g_warning ("gtk_signal_handler_unblock(): handler (%u) is not blocked", handler_id); - return; - } - handler = handler->next; - } - - g_warning ("gtk_signal_handler_unblock(): could not find handler (%u)", handler_id); -} - -void -gtk_signal_handler_unblock_by_func (GtkObject *object, - GtkSignalFunc func, - gpointer data) -{ - GtkHandler *handler; - gint found_one; - - g_return_if_fail (object != NULL); - g_return_if_fail (func != NULL); - - found_one = FALSE; - handler = gtk_object_get_data_by_id (object, handler_quark); - - while (handler) - { - if ((handler->id > 0) && - (handler->func == func) && - (handler->func_data == data) && - (handler->blocked > 0)) - { - handler->blocked -= 1; - found_one = TRUE; - } - handler = handler->next; - } - - if (!found_one) - g_warning ("gtk_signal_handler_unblock_by_func(): could not find blocked handler (0x%0lX) containing data (0x%0lX)", (long) func, (long) data); -} - -void -gtk_signal_handler_unblock_by_data (GtkObject *object, - gpointer data) -{ - GtkHandler *handler; - gint found_one; - - g_return_if_fail (object != NULL); - - found_one = FALSE; - handler = gtk_object_get_data_by_id (object, handler_quark); - - while (handler) - { - if ((handler->id > 0) && - (handler->func_data == data) && - (handler->blocked > 0)) - { - handler->blocked -= 1; - found_one = TRUE; - } - handler = handler->next; - } - - if (!found_one) - g_warning ("gtk_signal_handler_unblock_by_data(): could not find blocked handler containing data (0x%0lX)", (long) data); -} - -void -gtk_signal_handlers_destroy (GtkObject *object) -{ - GtkHandler *handler; - - /* we make the "optimization" of destroying the first handler in the last - * place, since we don't want gtk_signal_handler_unref() to reset the objects - * handler_key data on each removal - */ - - handler = gtk_object_get_data_by_id (object, handler_quark); - if (handler) - { - handler = handler->next; - while (handler) - { - GtkHandler *next; - - next = handler->next; - if (handler->id > 0) - gtk_signal_handler_unref (handler, object); - handler = next; - } - handler = gtk_object_get_data_by_id (object, handler_quark); - if (handler->id > 0) - gtk_signal_handler_unref (handler, object); - } -} - -void -gtk_signal_set_funcs (GtkSignalMarshal marshal_func, - GtkSignalDestroy destroy_func) -{ - global_marshaller = marshal_func; - global_destroy_notify = destroy_func; -} - -static guint -gtk_signal_hash (gconstpointer h) -{ - register const GtkSignalHash *hash = h; - - return hash->object_type ^ hash->quark; -} - -static gint -gtk_signal_compare (gconstpointer h1, - gconstpointer h2) -{ - register const GtkSignalHash *hash1 = h1; - register const GtkSignalHash *hash2 = h2; - - return (hash1->quark == hash2->quark && - hash1->object_type == hash2->object_type); -} - -static guint -gtk_alive_disconnecter (GtkDisconnectInfo *info) -{ - g_return_val_if_fail (info != NULL, 0); - - gtk_signal_disconnect (info->object1, info->disconnect_handler1); - gtk_signal_disconnect (info->object1, info->signal_handler); - gtk_signal_disconnect (info->object2, info->disconnect_handler2); - - g_mem_chunk_free (gtk_disconnect_info_mem_chunk, info); - - return 0; -} - -static GtkHandler* -gtk_signal_handler_new (void) -{ - GtkHandler *handler; - - if (!gtk_handler_free_list) - { - GtkHandler *handler_block; - guint i; - - handler_block = g_new0 (GtkHandler, HANDLER_BLOCK_SIZE); - for (i = 1; i < HANDLER_BLOCK_SIZE; i++) - { - (handler_block + i)->next = gtk_handler_free_list; - gtk_handler_free_list = (handler_block + i); - } - - handler = handler_block; - } - else - { - handler = gtk_handler_free_list; - gtk_handler_free_list = handler->next; - } - - handler->id = 0; - handler->blocked = 0; - handler->signal_id = 0; - handler->object_signal = FALSE; - handler->after = FALSE; - handler->no_marshal = FALSE; - handler->ref_count = 1; - handler->func = NULL; - handler->func_data = NULL; - handler->destroy_func = NULL; - handler->prev = NULL; - handler->next = NULL; - - return handler; -} - -static void -gtk_signal_handler_ref (GtkHandler *handler) -{ - handler->ref_count += 1; -} - -static void -gtk_signal_handler_unref (GtkHandler *handler, - GtkObject *object) -{ - if (!handler->ref_count) - { - /* FIXME: i wanna get removed somewhen */ - g_warning ("gtk_signal_handler_unref(): handler with ref_count==0!"); - return; - } - - handler->ref_count -= 1; - - if (handler->ref_count == 0) - { - if (handler->destroy_func) - (* handler->destroy_func) (handler->func_data); - else if (!handler->func && global_destroy_notify) - (* global_destroy_notify) (handler->func_data); - - if (handler->prev) - handler->prev->next = handler->next; - else if (handler->next) - gtk_object_set_data_by_id (object, handler_quark, handler->next); - else - { - GTK_OBJECT_UNSET_FLAGS (object, GTK_CONNECTED); - gtk_object_set_data_by_id (object, handler_quark, NULL); - } - if (handler->next) - handler->next->prev = handler->prev; - - handler->next = gtk_handler_free_list; - gtk_handler_free_list = handler; - } -} - -static void -gtk_signal_handler_insert (GtkObject *object, - GtkHandler *handler) -{ - GtkHandler *tmp; - - /* FIXME: remove */ g_assert (handler->next == NULL); - /* FIXME: remove */ g_assert (handler->prev == NULL); - - tmp = gtk_object_get_data_by_id (object, handler_quark); - if (!tmp) - { - GTK_OBJECT_SET_FLAGS (object, GTK_CONNECTED); - gtk_object_set_data_by_id (object, handler_quark, handler); - } - else - while (tmp) - { - if (tmp->signal_id < handler->signal_id) - { - if (tmp->prev) - { - tmp->prev->next = handler; - handler->prev = tmp->prev; - } - else - gtk_object_set_data_by_id (object, handler_quark, handler); - tmp->prev = handler; - handler->next = tmp; - break; - } - - if (!tmp->next) - { - tmp->next = handler; - handler->prev = tmp; - break; - } - tmp = tmp->next; - } -} - - -#ifdef G_ENABLE_DEBUG -/* value typically set via gdb */ -static GtkObject *gtk_trace_signal_object = NULL; -#endif /* G_ENABLE_DEBUG */ - - -static void -gtk_signal_real_emit (GtkObject *object, - guint signal_id, - GtkArg *params) -{ - static guint emission_hooks_called = 0; - GtkSignal signal; - GtkHandler *handlers; - GtkSignalFunc signal_func; - - if (emission_hooks_called) - { - g_warning ("gtk_signal_real_emit() may not recurse from emission hooks"); - return; - } - - /* gtk_handlers_run() expects a reentrant GtkSignal*, so we allocate - * it locally on the stack. we save some lookups ourselves with this as well. - */ - signal = *LOOKUP_SIGNAL_ID (signal_id); - if (signal.function_offset) - signal_func = G_STRUCT_MEMBER (GtkSignalFunc, object->klass, signal.function_offset); - else - signal_func = NULL; - -#ifdef G_ENABLE_DEBUG - if (gtk_debug_flags & GTK_DEBUG_SIGNALS || - object == gtk_trace_signal_object) - g_message ("%s::%s emitted (object=%p class-method=%p)\n", - gtk_type_name (GTK_OBJECT_TYPE (object)), - signal.name, - object, - signal_func); -#endif /* G_ENABLE_DEBUG */ - - if (signal.signal_flags & GTK_RUN_NO_RECURSE && - gtk_emission_check (current_emissions, object, signal_id)) - { - if (!gtk_emission_check (restart_emissions, object, signal_id)) - gtk_emission_add (&restart_emissions, object, signal_id); - - return; - } - - gtk_object_ref (object); - - gtk_emission_add (¤t_emissions, object, signal_id); - - emission_restart: - - if (signal.signal_flags & GTK_RUN_FIRST && signal_func) - { - signal.marshaller (object, signal_func, NULL, params); - - if (stop_emissions && gtk_emission_check (stop_emissions, object, signal_id)) - { - gtk_emission_remove (&stop_emissions, object, signal_id); - goto emission_done; - } - else if (restart_emissions && - signal.signal_flags & GTK_RUN_NO_RECURSE && - gtk_emission_check (restart_emissions, object, signal_id)) - { - gtk_emission_remove (&restart_emissions, object, signal_id); - - goto emission_restart; - } - } - - if (GTK_OBJECT_CONNECTED (object)) - { - handlers = gtk_signal_get_handlers (object, signal_id); - if (handlers) - { - gint return_val; - - return_val = gtk_handlers_run (handlers, &signal, object, params, FALSE); - switch (return_val) - { - case EMISSION_CONTINUE: - break; - case EMISSION_RESTART: - goto emission_restart; - case EMISSION_DONE: - goto emission_done; - } - } - } - - if (signal.signal_flags & GTK_RUN_LAST && signal_func) - { - signal.marshaller (object, signal_func, NULL, params); - - if (stop_emissions && gtk_emission_check (stop_emissions, object, signal_id)) - { - gtk_emission_remove (&stop_emissions, object, signal_id); - goto emission_done; - } - else if (restart_emissions && - signal.signal_flags & GTK_RUN_NO_RECURSE && - gtk_emission_check (restart_emissions, object, signal_id)) - { - gtk_emission_remove (&restart_emissions, object, signal_id); - - goto emission_restart; - } - } - - if (GTK_OBJECT_CONNECTED (object)) - { - handlers = gtk_signal_get_handlers (object, signal_id); - if (handlers) - { - gint return_val; - - return_val = gtk_handlers_run (handlers, &signal, object, params, TRUE); - switch (return_val) - { - case EMISSION_CONTINUE: - break; - case EMISSION_RESTART: - goto emission_restart; - case EMISSION_DONE: - goto emission_done; - } - } - } - - emission_done: - if (restart_emissions && signal.signal_flags & GTK_RUN_NO_RECURSE) - gtk_emission_remove (&restart_emissions, object, signal_id); - - gtk_emission_remove (¤t_emissions, object, signal_id); - - /* the hook invokation portion may not be moved! - */ - if (signal.hook_list && !GTK_OBJECT_DESTROYED (object)) - { - gpointer data[2]; - - data[0] = &signal; - data[1] = object; - emission_hooks_called++; - g_hook_list_marshal_check (signal.hook_list, TRUE, gtk_emission_hook_marshaller, &data); - emission_hooks_called--; - } - - gtk_object_unref (object); -} - -static GtkHandler* -gtk_signal_get_handlers (GtkObject *object, - guint signal_id) -{ - GtkHandler *handlers; - - handlers = gtk_object_get_data_by_id (object, handler_quark); - - while (handlers) - { - if (handlers->signal_id == signal_id) - return handlers; - handlers = handlers->next; - } - - return NULL; -} - -guint -gtk_signal_handler_pending (GtkObject *object, - guint signal_id, - gboolean may_be_blocked) -{ - GtkHandler *handlers; - guint handler_id; - - g_return_val_if_fail (object != NULL, 0); - g_return_val_if_fail (signal_id >= 1, 0); - - if (GTK_OBJECT_CONNECTED (object)) - handlers = gtk_signal_get_handlers (object, signal_id); - else - return 0; - - handler_id = 0; - while (handlers && handlers->signal_id == signal_id) - { - if (handlers->id > 0 && - (may_be_blocked || handlers->blocked == FALSE)) - { - handler_id = handlers->id; - break; - } - - handlers = handlers->next; - } - - return handler_id; -} - -guint -gtk_signal_handler_pending_by_func (GtkObject *object, - guint signal_id, - gboolean may_be_blocked, - GtkSignalFunc func, - gpointer data) -{ - GtkHandler *handlers; - guint handler_id; - - g_return_val_if_fail (object != NULL, 0); - g_return_val_if_fail (func != NULL, 0); - g_return_val_if_fail (signal_id >= 1, 0); - - if (GTK_OBJECT_CONNECTED (object)) - handlers = gtk_signal_get_handlers (object, signal_id); - else - return 0; - - handler_id = 0; - while (handlers && handlers->signal_id == signal_id) - { - if (handlers->id > 0 && - handlers->func == func && - handlers->func_data == data && - (may_be_blocked || handlers->blocked == FALSE)) - { - handler_id = handlers->id; - break; - } - - handlers = handlers->next; - } - - return handler_id; -} - -guint -gtk_signal_add_emission_hook (guint signal_id, - GtkEmissionHook hook_func, - gpointer data) -{ - return gtk_signal_add_emission_hook_full (signal_id, hook_func, data, NULL); -} - -guint -gtk_signal_add_emission_hook_full (guint signal_id, - GtkEmissionHook hook_func, - gpointer data, - GDestroyNotify destroy) -{ - static guint seq_hook_id = 1; - GtkSignal *signal; - GHook *hook; - - g_return_val_if_fail (signal_id > 0, 0); - g_return_val_if_fail (hook_func != NULL, 0); - - signal = LOOKUP_SIGNAL_ID (signal_id); - g_return_val_if_fail (signal != NULL, 0); - if (signal->signal_flags & GTK_RUN_NO_HOOKS) - { - g_warning ("gtk_signal_add_emission_hook_full(): signal \"%s\" does not support emission hooks", - signal->name); - return 0; - } - - if (!signal->hook_list) - { - signal->hook_list = g_new (GHookList, 1); - g_hook_list_init (signal->hook_list, sizeof (GHook)); - } - - hook = g_hook_alloc (signal->hook_list); - hook->data = data; - hook->func = hook_func; - hook->destroy = destroy; - - signal->hook_list->seq_id = seq_hook_id; - g_hook_prepend (signal->hook_list, hook); - seq_hook_id = signal->hook_list->seq_id; - - return hook->hook_id; -} - -void -gtk_signal_remove_emission_hook (guint signal_id, - guint hook_id) -{ - GtkSignal *signal; - - g_return_if_fail (signal_id > 0); - g_return_if_fail (hook_id > 0); - - signal = LOOKUP_SIGNAL_ID (signal_id); - g_return_if_fail (signal != NULL); - - if (!signal->hook_list || !g_hook_destroy (signal->hook_list, hook_id)) - g_warning ("gtk_signal_remove_emission_hook(): could not find hook (%u)", hook_id); -} - -static gboolean -gtk_emission_hook_marshaller (GHook *hook, - gpointer data_p) -{ - gpointer *data = data_p; - GtkSignal *signal; - GtkEmissionHook func; - - signal = data[0]; - func = hook->func; - - if (!GTK_OBJECT_DESTROYED (data[1])) - return func (data[1], signal->signal_id, hook->data); - else - return TRUE; -} - -static guint -gtk_signal_connect_by_type (GtkObject *object, - guint signal_id, - GtkSignalFunc func, - gpointer func_data, - GtkSignalDestroy destroy_func, - gint object_signal, - gint after, - gint no_marshal) -{ - GtkObjectClass *class; - GtkHandler *handler; - gint found_it; - GtkSignal *signal; - - g_return_val_if_fail (object != NULL, 0); - g_return_val_if_fail (object->klass != NULL, 0); - - /* A signal without a default marshaller can only take no_marshal - handlers. */ - - signal = LOOKUP_SIGNAL_ID (signal_id); - g_return_val_if_fail (signal->marshaller || no_marshal, 0); - - /* Search through the signals for this object and make - * sure the one we are adding is valid. We need to perform - * the lookup on the objects parents as well. If it isn't - * valid then issue a warning and return. - * As of now (1998-05-27) this lookup shouldn't be neccessarry - * anymore since gtk_signal_lookup() has been reworked to only - * return correct signal ids per class-branch. - */ - found_it = FALSE; - class = object->klass; - while (class) - { - GtkType parent; - guint *object_signals; - guint nsignals; - guint i; - - object_signals = class->signals; - nsignals = class->nsignals; - - for (i = 0; i < nsignals; i++) - if (object_signals[i] == signal_id) - { - found_it = TRUE; - break; - } - - parent = gtk_type_parent (class->type); - if (parent) - class = gtk_type_class (parent); - else - class = NULL; - } - - if (!found_it) - { - g_warning ("gtk_signal_connect_by_type(): could not find signal id (%u) in the `%s' class ancestry", - signal_id, - gtk_type_name (object->klass->type)); - return 0; - } - - handler = gtk_signal_handler_new (); - handler->id = gtk_handler_id++; - handler->signal_id = signal_id; - handler->object_signal = object_signal; - handler->func = func; - handler->func_data = func_data; - handler->destroy_func = destroy_func; - handler->after = after != FALSE; - handler->no_marshal = no_marshal; - - gtk_signal_handler_insert (object, handler); - return handler->id; -} - -static GtkEmission* -gtk_emission_new (void) -{ - GtkEmission *emission; - - if (!gtk_emission_free_list) - { - GtkEmissionAllocator *emission_block; - guint i; - - emission_block = g_new0 (GtkEmissionAllocator, EMISSION_BLOCK_SIZE); - for (i = 1; i < EMISSION_BLOCK_SIZE; i++) - { - (emission_block + i)->next = gtk_emission_free_list; - gtk_emission_free_list = (emission_block + i); - } - - emission = &emission_block->emission; - } - else - { - emission = >k_emission_free_list->emission; - gtk_emission_free_list = gtk_emission_free_list->next; - } - - emission->object = NULL; - emission->signal_id = 0; - - return emission; -} - -static void -gtk_emission_add (GList **emissions, - GtkObject *object, - guint signal_id) -{ - GtkEmission *emission; - - g_return_if_fail (emissions != NULL); - g_return_if_fail (object != NULL); - - emission = gtk_emission_new (); - emission->object = object; - emission->signal_id = signal_id; - - *emissions = g_list_prepend (*emissions, emission); -} - -static void -gtk_emission_remove (GList **emissions, - GtkObject *object, - guint signal_id) -{ - GList *tmp; - - g_return_if_fail (emissions != NULL); - - tmp = *emissions; - while (tmp) - { - GtkEmissionAllocator *ea; - - ea = tmp->data; - - if ((ea->emission.object == object) && - (ea->emission.signal_id == signal_id)) - { - *emissions = g_list_remove_link (*emissions, tmp); - g_list_free (tmp); - - ea->next = gtk_emission_free_list; - gtk_emission_free_list = ea; - break; - } - - tmp = tmp->next; - } -} - -static gint -gtk_emission_check (GList *emissions, - GtkObject *object, - guint signal_id) -{ - GtkEmission *emission; - GList *tmp; - - tmp = emissions; - while (tmp) - { - emission = tmp->data; - tmp = tmp->next; - - if ((emission->object == object) && - (emission->signal_id == signal_id)) - return TRUE; - } - return FALSE; -} - -static gint -gtk_handlers_run (GtkHandler *handlers, - GtkSignal *signal, - GtkObject *object, - GtkArg *params, - gint after) -{ - /* *signal is a local copy on the stack of gtk_signal_real_emit(), - * so we don't need to look it up every time we invoked a function. - */ - while (handlers && handlers->signal_id == signal->signal_id) - { - GtkHandler *handlers_next; - - gtk_signal_handler_ref (handlers); - - if (!handlers->blocked && handlers->after == after) - { - if (handlers->func) - { - if (handlers->no_marshal) - (* (GtkCallbackMarshal) handlers->func) (object, - handlers->func_data, - signal->nparams, - params); - else if (handlers->object_signal) - /* don't cast with GTK_OBJECT () */ - (* signal->marshaller) ((GtkObject*) handlers->func_data, - handlers->func, - handlers->func_data, - params); - else - (* signal->marshaller) (object, - handlers->func, - handlers->func_data, - params); - } - else if (global_marshaller) - (* global_marshaller) (object, - handlers->func_data, - signal->nparams, - params, - signal->params, - signal->return_val); - - if (stop_emissions && gtk_emission_check (stop_emissions, - object, - signal->signal_id)) - { - gtk_emission_remove (&stop_emissions, object, signal->signal_id); - - gtk_signal_handler_unref (handlers, object); - - return EMISSION_DONE; - } - else if (restart_emissions && - signal->signal_flags & GTK_RUN_NO_RECURSE && - gtk_emission_check (restart_emissions, object, signal->signal_id)) - { - gtk_emission_remove (&restart_emissions, object, signal->signal_id); - - gtk_signal_handler_unref (handlers, object); - - return EMISSION_RESTART; - } - } - - handlers_next = handlers->next; - gtk_signal_handler_unref (handlers, object); - handlers = handlers_next; - } - - return EMISSION_CONTINUE; -} - -static gboolean -gtk_signal_collect_params (GtkArg *params, - guint n_params, - GtkType *param_types, - GtkType return_type, - va_list var_args) -{ - register GtkArg *last_param; - register gboolean failed = FALSE; - - for (last_param = params + n_params; params < last_param; params++) - { - register gchar *error; - - params->name = NULL; - params->type = *(param_types++); - GTK_ARG_COLLECT_VALUE (params, - var_args, - error); - if (error) - { - failed = TRUE; - g_warning ("gtk_signal_collect_params(): %s", error); - g_free (error); - } - } - - params->type = return_type; - params->name = NULL; - - return_type = GTK_FUNDAMENTAL_TYPE (return_type); - if (return_type != GTK_TYPE_NONE) - { - if ((return_type >= GTK_TYPE_FLAT_FIRST && - return_type <= GTK_TYPE_FLAT_LAST) || - (return_type == GTK_TYPE_OBJECT)) - { - GTK_VALUE_POINTER (*params) = va_arg (var_args, gpointer); - - if (GTK_VALUE_POINTER (*params) == NULL) - { - failed = TRUE; - g_warning ("gtk_signal_collect_params(): invalid NULL pointer for return argument type `%s'", - gtk_type_name (params->type)); - } - } - else - { - failed = TRUE; - g_warning ("gtk_signal_collect_params(): unsupported return argument type `%s'", - gtk_type_name (params->type)); - } - } - else - GTK_VALUE_POINTER (*params) = NULL; - - return failed; -} +#define __GTK_SIGNAL_C__ +#include "gtkaliasdef.c"