diff options
author | Tim Janik <timj@gtk.org> | 2000-10-25 22:34:14 +0000 |
---|---|---|
committer | Tim Janik <timj@src.gnome.org> | 2000-10-25 22:34:14 +0000 |
commit | d69496c06092c0b8943b7240761ae27401c65e9f (patch) | |
tree | 600e6c46af603a9c4f8ca22954cc815466aa04c2 /gtk/gtksignal.c | |
parent | 7ae3922d2cdc89cba86694f7e46393a629b12b61 (diff) | |
download | gdk-pixbuf-d69496c06092c0b8943b7240761ae27401c65e9f.tar.gz |
urg, removed implementation of gtk_marshal_VOID__INT_INT_INT_INT. if
Wed Oct 25 20:47:41 2000 Tim Janik <timj@gtk.org>
* gtk/gdk-pixbuf-loader.c (gdk_pixbuf_loader_class_init): urg, removed
implementation of gtk_marshal_VOID__INT_INT_INT_INT. if people do that,
couldn't they at least give it a non-standard name?
* gtk/gtktextlayout.c: arg! yet another implementation of
gtk_marshal_VOID__INT_INT_INT_INT(), is this a conspiracy?
* gtk/gtktextbuffer.c: gotcha! captured a vagabonding
gtk_marshal_VOID__INT_POINTER_INT() implementation, braught it back
home. now i know this _is_ a conspiracy.
* gtk/gtkwidget.c (gtk_widget_class_init): marshaller fixups for
::state-changed.
* gtk/gtkaccelgroup.c (gtk_accel_group_create_remove):
(gtk_accel_group_create_add): marshaller signature fixups.
* gtk/gtklistitem.c (gtk_list_item_class_init): signal creation fixups,
pass in GTK_TYPE_SCROLL_TYPE instead of GTK_TYPE_ENUM.
* gtk/gtkobject.[hc]: removed GTK_CONNECTED flag, it's not valid
anymore.
Tue Oct 24 23:59:21 2000 Tim Janik <timj@gtk.org>
* docs/reference/Makefile.am: disabled SUBDIRS for the moment, since
due to the signal system changes, it wouldn't build currently. to
be fixed soon.
* docs/Changes-2.0.txt: GtkSignal/GSignal updates.
* gtk/gtkwidget.c: ::direction_changed takes an enum as argument,
so it needs gtk_marshal_VOID__ENUM() instead of
gtk_marshal_NONE__UINT().
* gdk/gdk*.c: adapted type registration functions.
* gtk/gtkbindings.c:
* gtk/gtkaccelgroup.c: operate on GSignalQuery, GtkSignalQuery is
gone.
* gtk/gtkenums.h: define GtkSignalRunType in terms of GSignalType.
* gtk/gtkobject.c:
(gtk_object_destroy):
(gtk_object_shutdown): fixed recursion guards. basically we have to
catch the case where any of GObject.shutdown() or gtk_object_destroy()
is called during ::destroy, and avoid recursion there.
* gtk/gtktypeutils.c:
* gtk/maketypes.awk: awk-script hackup to provide gtk_type_init() with
boxed_copy/boxed_free. this needs a more general solution based on a
publically installed code-generator utility.
* gtk/gtktypeutils.[hc]: compat aliased GTK_TYPE_BOXED to G_TYPE_BOXED,
glib's gobject has support for that now.
define GtkSignalMarshaller in terms of GSignalCMarshaller.
Mon Oct 23 09:36:42 2000 Tim Janik <timj@gtk.org>
* gtk/gtksignal.[hc]:
* gtk/gtkmarshal.[hc]:
* gtk/Makefile.am: generate marshallers with glib-genmarshal and don't
compile gtkmarshal.c on its own anymore, just include it in gtksignal.c.
removed #include <gtkmarshal.h>s all over the place, gtksignal.h takes
care of that.
* *.c: marshaller name fixups.
* gtk/gtkmarshal.list: added a comment briefing the format.
Sun Oct 22 23:14:39 2000 Tim Janik <timj@gtk.org>
* gtk/gtksignal.[hc]: nuked old implementation. we mostly have
compatibility macros here now. more specifically, most of
the API is preserved (yes, _most_, nonwithstanding the
following exceptions listed, the API is stil lHUGE ;)
things that got removed completely:
GtkSignalQuery, gtk_signal_query(), gtk_signal_n_emissions(),
gtk_signal_n_emissions_by_name(), gtk_signal_handlers_destroy(),
gtk_signal_set_funcs(), gtk_signal_handler_pending_by_id(),
gtk_signal_add_emission_hook(), gtk_signal_add_emission_hook_full(),
gtk_signal_remove_emission_hook().
non-functional functions variants:
gtk_signal_add_emission_hook(), gtk_signal_remove_emission_hook().
the GtkCallbackMarshal argument to gtk_signal_connect_full() is
not supported anymore.
(gtk_signal_compat_matched): new internal function to aid
implementation of the compatibility macros, it provides
functionality to block/unblock/disconnect handlers based
on func/data.
* gtk/gtkenums.h: define GtkSignalRunType in terms of GSignalType,
* *.c: adaptions to new type registration API signatures.
Fri Oct 20 15:26:33 2000 Tim Janik <timj@gtk.org>
* gtk/gtktypeutils.[hc]: removed G_TYPE_GTK_POINTER cludge.
Diffstat (limited to 'gtk/gtksignal.c')
-rw-r--r-- | gtk/gtksignal.c | 2168 |
1 files changed, 296 insertions, 1872 deletions
diff --git a/gtk/gtksignal.c b/gtk/gtksignal.c index 5cfc38cfe..004b7293f 100644 --- a/gtk/gtksignal.c +++ b/gtk/gtksignal.c @@ -8,7 +8,7 @@ * * 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 + * 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 Lesser General Public @@ -17,2003 +17,427 @@ * Boston, MA 02111-1307, USA. */ -/* - * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS - * file for a list of people on the GTK+ Team. See the ChangeLog - * files for a list of changes. These files are distributed with - * GTK+ at ftp://ftp.gtk.org/pub/gtk/. - */ - -#include <stdarg.h> -#include <string.h> -#include <stdio.h> -#include "gtksignal.h" -#include "gtkargcollector.c" - - -#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) - -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 struct _GtkEmissionHookData GtkEmissionHookData; -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; - guint 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; - GtkHandler *next; - GtkHandler *prev; - 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; -}; - -struct _GtkEmission -{ - GtkObject *object; - guint16 signal_id; - guint in_hook : 1; - GtkEmission *next; -}; - -struct _GtkEmissionHookData -{ - GtkObject *object; - guint signal_id; - guint n_params; - GtkArg *params; -}; +#include "gtksignal.h" +#include "gtkargcollector.c" +#include "gtkmarshal.c" -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 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 (GtkEmission **emissions, - GtkObject *object, - guint signal_type); -static void gtk_emission_remove (GtkEmission **emissions, - GtkObject *object, - guint signal_type); -static gint gtk_emission_check (GtkEmission *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_private_n_signals ? \ - (GtkSignal*) _gtk_private_signals + signal_id : \ - (GtkSignal*) 0 \ -) - - -static GtkSignalMarshal global_marshaller = NULL; -static GtkSignalDestroy global_destroy_notify = NULL; - -static guint gtk_handler_id = 1; -static guint gtk_handler_quark = 0; -static GHashTable *gtk_signal_hash_table = NULL; -#ifdef G_OS_WIN32 -#define EXPORT __declspec(dllexport) -#else -#define EXPORT -#endif -EXPORT GtkSignal *_gtk_private_signals = NULL; -EXPORT guint _gtk_private_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 GtkEmission *gtk_free_emissions = NULL; - - - -static GtkEmission *current_emissions = NULL; -static GtkEmission *stop_emissions = NULL; -static GtkEmission *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_private_n_signals + SIGNAL_BLOCK_SIZE; - size *= sizeof (GtkSignal); - i = 1; - while (i < size) - i <<= 1; - size = i; - - _gtk_private_signals = g_realloc (_gtk_private_signals, size); - - gtk_n_free_signals = size / sizeof (GtkSignal) - _gtk_private_n_signals; - - memset (_gtk_private_signals + _gtk_private_n_signals, 0, gtk_n_free_signals * sizeof (GtkSignal)); - } - - new_signal_id = _gtk_private_n_signals++; - gtk_n_free_signals--; - g_assert (_gtk_private_n_signals < 65535); - - signal = LOOKUP_SIGNAL_ID (new_signal_id); - if (signal) - signal->signal_id = new_signal_id; - - return signal; -} - -static inline GtkHandler* -gtk_signal_get_handlers (GtkObject *object, - guint signal_id) -{ - GtkHandler *handlers; - - handlers = gtk_object_get_data_by_id (object, gtk_handler_quark); - - while (handlers) - { - if (handlers->signal_id == signal_id) - return handlers; - handlers = handlers->next; - } - - return NULL; -} +/* 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 (!gtk_handler_quark) - { - GtkSignal *zero; - - zero = gtk_signal_next_and_invalidate (); - g_assert (zero == NULL); - - gtk_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_free_emissions = 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, + GtkType object_type, + guint function_offset, GtkSignalMarshaller marshaller, - GtkType return_val, - guint nparams, - GtkType *params) + GtkType return_val, + guint n_params, + GtkType *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 (marshaller != NULL, 0); - g_return_val_if_fail (nparams < MAX_SIGNAL_PARAMS, 0); - if (nparams) - g_return_val_if_fail (params != NULL, 0); - - if (!gtk_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 (); - - /* signal->signal_id already set */ + GClosure *closure; - 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; + g_return_val_if_fail (n_params < SIGNAL_MAX_PARAMS, 0); - 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 = g_signal_type_closure_new (object_type, function_offset); - return signal->signal_id; + return g_signal_newv (name, object_type, signal_flags, closure, 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, + GtkType object_type, + guint function_offset, GtkSignalMarshaller marshaller, - GtkType return_val, - guint nparams, + GtkType return_val, + guint n_params, ...) { GtkType *params; - guint i; - va_list args; 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); + va_list args; + guint i; - for (i = 0; i < nparams; i++) + params = g_new (GtkType, n_params); + va_start (args, n_params); + for (i = 0; i < n_params; i++) params[i] = va_arg (args, GtkType); - 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; - GtkType lookup_type; - gpointer class = NULL; - - g_return_val_if_fail (name != NULL, 0); - g_return_val_if_fail (GTK_TYPE_IS_OBJECT (object_type), 0); - - relookup: - - lookup_type = object_type; - hash.quark = g_quark_try_string (name); - if (hash.quark) - { - while (lookup_type) - { - guint signal_id; - - hash.object_type = lookup_type; - - signal_id = GPOINTER_TO_UINT (g_hash_table_lookup (gtk_signal_hash_table, &hash)); - if (signal_id) - return signal_id; - - lookup_type = gtk_type_parent (lookup_type); - } - } - - if (!class) - { - class = gtk_type_class (object_type); - goto relookup; - } - - 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) -{ - GtkSignal *signal; - - g_return_val_if_fail (signal_id >= 1, NULL); - - signal = LOOKUP_SIGNAL_ID (signal_id); - if (signal) - return signal->name; - - return NULL; -} - void -gtk_signal_emitv (GtkObject *object, - guint signal_id, - GtkArg *params) +gtk_signal_emit_stop_by_name (GtkObject *object, + const gchar *name) { - GtkSignal *signal; - - 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)); - - if (signal->nparams > 0) - g_return_if_fail (params != NULL); - - gtk_signal_real_emit (object, signal_id, params); -} - -void -gtk_signal_emit (GtkObject *object, - guint signal_id, - ...) -{ - 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)); - - va_start (args, signal_id); - 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); -} - -void -gtk_signal_emitv_by_name (GtkObject *object, - const gchar *name, - GtkArg *params) -{ - 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_if_fail (GTK_IS_OBJECT (object)); - 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))); - } + g_signal_stop_emission (object, g_signal_lookup (name, G_OBJECT_TYPE (object))); } void -gtk_signal_emit_by_name (GtkObject *object, - const gchar *name, - ...) +gtk_signal_connect_object_while_alive (GtkObject *object, + const gchar *signal, + GtkSignalFunc func, + GtkObject *alive_object) { - 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)); - - 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))); - } -} - -void -gtk_signal_emit_stop (GtkObject *object, - guint signal_id) -{ - gint state; - - g_return_if_fail (object != NULL); - g_return_if_fail (signal_id >= 1); + g_return_if_fail (GTK_IS_OBJECT (object)); - state = gtk_emission_check (current_emissions, object, signal_id); - if (state > 1) - g_warning ("gtk_signal_emit_stop(): emission (%u) for object `%s' cannot be stopped from emission hook", - signal_id, - gtk_type_name (GTK_OBJECT_TYPE (object))); - else if (state) - { - 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))); + g_signal_connect_closure (object, + g_signal_lookup (signal, G_OBJECT_TYPE (object)), + g_cclosure_new_object_swap (func, alive_object), + FALSE); } void -gtk_signal_emit_stop_by_name (GtkObject *object, - const gchar *name) +gtk_signal_connect_while_alive (GtkObject *object, + const gchar *signal, + GtkSignalFunc func, + gpointer func_data, + GtkObject *alive_object) { - 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)); - 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))); -} + GClosure *closure; -guint -gtk_signal_n_emissions (GtkObject *object, - guint signal_id) -{ - GtkEmission *emission; - guint n; - - g_return_val_if_fail (object != NULL, 0); - g_return_val_if_fail (GTK_IS_OBJECT (object), 0); - - n = 0; - for (emission = current_emissions; emission; emission = emission->next) - { - if (emission->object == object && emission->signal_id == signal_id) - n++; - } - - return n; -} + g_return_if_fail (GTK_IS_OBJECT (object)); -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; + closure = g_cclosure_new (func, func_data, NULL); + g_object_watch_closure (G_OBJECT (alive_object), closure); + g_signal_connect_closure (object, + g_signal_lookup (signal, G_OBJECT_TYPE (object)), + closure, + FALSE); } 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, +gtk_signal_connect_full (GtkObject *object, + const gchar *name, + GtkSignalFunc func, + GtkCallbackMarshal unsupported, + gpointer data, GtkDestroyNotify destroy_func, - gint object_signal, - gint after) + 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_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; - } - - 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); - - signal_id = gtk_signal_lookup (name, GTK_OBJECT_TYPE (object)); - if (!signal_id) - { - 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; - } - - return gtk_signal_connect_by_type (object, signal_id, - func, slot_object, NULL, - TRUE, TRUE, FALSE); -} - -void -gtk_signal_connect_while_alive (GtkObject *object, - const gchar *signal, - GtkSignalFunc func, - gpointer func_data, - 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; + g_return_val_if_fail (GTK_IS_OBJECT (object), 0); + g_return_val_if_fail (unsupported == NULL, 0); - 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); + return g_signal_connect_closure (object, + g_signal_lookup (name, G_OBJECT_TYPE (object)), + (object_signal + ? g_cclosure_new_swap + : g_cclosure_new) (func, + data, + (GClosureNotify) destroy_func), + after); } void -gtk_signal_connect_object_while_alive (GtkObject *object, - const gchar *signal, - GtkSignalFunc func, - GtkObject *alive_object) +gtk_signal_compat_matched (GtkObject *object, + GtkSignalFunc func, + gpointer data, + GSignalMatchType match, + guint action) { - GtkDisconnectInfo *info; + guint id; - 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); -} - -void -gtk_signal_disconnect (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, gtk_handler_quark); + id = g_signal_handler_find (object, match, 0, NULL, func, data); - while (handler) - { - if (handler->id == handler_id) - { - handler->id = 0; - handler->blocked += 1; - gtk_signal_handler_unref (handler, object); - return; - } - handler = handler->next; - } - - g_warning ("gtk_signal_disconnect(): could not find handler (%u)", handler_id); + if (!id) + g_warning ("unable to find signal handler for object(%p) with func(%p) and data(%p)", + object, func, data); + else + switch (action) + { + case 0: g_signal_handler_disconnect (object, id); break; + case 1: g_signal_handler_block (object, id); break; + case 2: g_signal_handler_unblock (object, id); break; + } } -void -gtk_signal_disconnect_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, gtk_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; - } - - if (!found_one) - g_warning ("gtk_signal_disconnect_by_func(): could not find handler (0x%0lX) containing data (0x%0lX)", (long) func, (long) 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_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) = 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) = g_value_get_string (value); + break; + default: + return FALSE; + } + return TRUE; } void -gtk_signal_disconnect_by_data (GtkObject *object, - gpointer data) +gtk_signal_emitv (GtkObject *object, + guint signal_id, + GtkArg *args) { - GtkHandler *handler; - gint found_one; + GSignalQuery query; + GValue params[SIGNAL_MAX_PARAMS + 1] = { { 0, }, }; + GValue rvalue = { 0, }; + guint i; - g_return_if_fail (object != NULL); + g_return_if_fail (GTK_IS_OBJECT (object)); - found_one = FALSE; - handler = gtk_object_get_data_by_id (object, gtk_handler_quark); + g_signal_query (signal_id, &query); + g_return_if_fail (query.signal_id != 0); + g_return_if_fail (g_type_conforms_to (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); - while (handler) + 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++) { - GtkHandler *handler_next; + GValue *value = params + 1 + i; + GtkArg *arg = args + i; - handler_next = handler->next; - if ((handler->id > 0) && - (handler->func_data == data)) + g_value_init (value, arg->type); + if (!gtk_arg_to_value (arg, value)) { - 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, gtk_handler_quark); - - while (handler) - { - if (handler->id == handler_id) - { - handler->blocked += 1; + g_warning ("%s: failed to convert arg type `%s' to value type `%s'", + G_STRLOC, g_type_name (arg->type), g_type_name (G_VALUE_TYPE (value))); return; } - handler = handler->next; } + if (query.return_type != G_TYPE_NONE) + g_value_init (&rvalue, query.return_type); - 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, gtk_handler_quark); + g_signal_emitv (params, signal_id, &rvalue); - while (handler) + if (query.return_type != G_TYPE_NONE) { - if ((handler->id > 0) && - (handler->func == func) && - (handler->func_data == data)) - { - found_one = TRUE; - handler->blocked += 1; - } - handler = handler->next; + gtk_argloc_set_from_value (args + query.n_params, &rvalue, TRUE); + g_value_unset (&rvalue); } - - 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); + for (i = 0; i < query.n_params; i++) + g_value_unset (params + 1 + i); + g_value_unset (params + 0); } -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, gtk_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, gtk_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, gtk_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, gtk_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, gtk_handler_quark); - if (handler) - { - handler = handler->next; - while (handler) - { - GtkHandler *next; - - next = handler->next; - if (handler->id > 0) - { - handler->id = 0; - handler->blocked += 1; - gtk_signal_handler_unref (handler, object); - } - handler = next; - } - handler = gtk_object_get_data_by_id (object, gtk_handler_quark); - if (handler->id > 0) - { - handler->id = 0; - handler->blocked += 1; - 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, gtk_handler_quark, handler->next); - else - { - GTK_OBJECT_UNSET_FLAGS (object, GTK_CONNECTED); - gtk_object_set_data_by_id (object, gtk_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, gtk_handler_quark); - if (!tmp) - { - GTK_OBJECT_SET_FLAGS (object, GTK_CONNECTED); - gtk_object_set_data_by_id (object, gtk_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, gtk_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 gboolean +gtk_signal_collect_args (GtkArg *args, + guint n_args, + const GtkType *arg_types, + GtkType return_type, + va_list var_args) { - GtkSignal signal; - GtkHandler *handlers; - GtkSignalFunc signal_func; - GtkEmission *emission; - - /* 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, ((GTypeInstance*) object)->g_class, 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) - { - gint state; - - state = gtk_emission_check (current_emissions, object, signal_id); - if (state) - { - if (state > 1) - g_warning ("gtk_signal_real_emit(): emission (%u) for object `%s' cannot be restarted from emission hook", - signal_id, - gtk_type_name (GTK_OBJECT_TYPE (object))); - else 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 = current_emissions; - - emission_restart: + register GtkArg *last_arg; + register gboolean failed = FALSE; - if (signal.signal_flags & GTK_RUN_FIRST && signal_func) + for (last_arg = args + n_args; args < last_arg; args++) { - signal.marshaller (object, signal_func, NULL, params); + register gchar *error; - 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)) + args->name = NULL; + args->type = *(arg_types++); + GTK_ARG_COLLECT_VALUE (args, + var_args, + error); + if (error) { - gtk_emission_remove (&restart_emissions, object, signal_id); - - goto emission_restart; + failed = TRUE; + g_warning ("gtk_signal_collect_args(): %s", error); + g_free (error); } } - if (signal.hook_list && !GTK_OBJECT_DESTROYED (object)) - { - GtkEmissionHookData data; - - data.object = object; - data.n_params = signal.nparams; - data.params = params; - data.signal_id = signal_id; - emission->in_hook = 1; - g_hook_list_marshal_check (signal.hook_list, TRUE, gtk_emission_hook_marshaller, &data); - emission->in_hook = 0; - } - - 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; - } - } - } + args->type = return_type; + args->name = NULL; - 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)) + return_type = GTK_FUNDAMENTAL_TYPE (return_type); + if (return_type != G_TYPE_NONE) { - handlers = gtk_signal_get_handlers (object, signal_id); - if (handlers) + if (return_type != 0) /* FIXME: check for IS_ARG */ { - gint return_val; + GTK_VALUE_POINTER (*args) = va_arg (var_args, gpointer); - return_val = gtk_handlers_run (handlers, &signal, object, params, TRUE); - switch (return_val) + if (GTK_VALUE_POINTER (*args) == NULL) { - case EMISSION_CONTINUE: - break; - case EMISSION_RESTART: - goto emission_restart; - case EMISSION_DONE: - goto emission_done; + failed = TRUE; + g_warning ("gtk_signal_collect_args(): invalid NULL pointer for return argument type `%s'", + gtk_type_name (args->type)); } } - } - - 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); - - gtk_object_unref (object); -} - -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 == 0)) + else { - handler_id = handlers->id; - break; + failed = TRUE; + g_warning ("gtk_signal_collect_args(): unsupported return argument type `%s'", + gtk_type_name (args->type)); } - - handlers = handlers->next; } - - return handler_id; -} - -gint -gtk_signal_handler_pending_by_id (GtkObject *object, - guint handler_id, - gboolean may_be_blocked) -{ - GtkHandler *handlers; - - g_return_val_if_fail (object != NULL, FALSE); - g_return_val_if_fail (handler_id >= 1, FALSE); - - if (GTK_OBJECT_CONNECTED (object)) - handlers = gtk_object_get_data_by_id (object, gtk_handler_quark); else - return FALSE; + GTK_VALUE_POINTER (*args) = NULL; - while (handlers) - { - if (handlers->id == handler_id) - return may_be_blocked || handlers->blocked == 0; - - handlers = handlers->next; - } - - return FALSE; -} - -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; + return failed; } 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) -{ - GtkEmissionHookData *data = data_p; - GtkEmissionHook func; - - func = hook->func; - - if (!GTK_OBJECT_DESTROYED (data->object)) - return func (data->object, data->signal_id, - data->n_params, data->params, - 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) +gtk_signal_emit (GtkObject *object, + guint signal_id, + ...) { - GtkObjectClass *class; - GtkHandler *handler; - gint found_it; - GtkSignal *signal; - - g_return_val_if_fail (GTK_IS_OBJECT (object), 0); + GtkArg args[SIGNAL_MAX_PARAMS + 1]; + GSignalQuery query; + gboolean abort; + va_list var_args; - signal = LOOKUP_SIGNAL_ID (signal_id); - - /* 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 = GTK_OBJECT_GET_CLASS (object); - 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 = g_type_parent (GTK_CLASS_TYPE (class)); - if (GTK_TYPE_IS_OBJECT (parent)) - class = g_type_class_peek (parent); - else - class = NULL; - } + g_return_if_fail (GTK_IS_OBJECT (object)); - if (!found_it) - { - g_warning ("gtk_signal_connect_by_type(): could not find signal id (%u) in the `%s' class ancestry", - signal_id, - GTK_OBJECT_TYPE_NAME (object)); - return 0; - } + g_signal_query (signal_id, &query); + g_return_if_fail (query.signal_id != 0); + g_return_if_fail (query.n_params < SIGNAL_MAX_PARAMS); - handler = gtk_signal_handler_new (); - handler->id = gtk_handler_id++; - handler->signal_id = signal_id; - handler->object_signal = object_signal != FALSE; - handler->func = func; - handler->func_data = func_data; - handler->destroy_func = destroy_func; - handler->after = after != FALSE; - handler->no_marshal = no_marshal; + va_start (var_args, signal_id); + abort = gtk_signal_collect_args (args, + query.n_params, + query.param_types, + query.return_type, + var_args); + va_end (var_args); - gtk_signal_handler_insert (object, handler); - return handler->id; + if (!abort) + gtk_signal_emitv (object, signal_id, args); } -static GtkEmission* -gtk_emission_new (void) +void +gtk_signal_emit_by_name (GtkObject *object, + const gchar *name, + ...) { - GtkEmission *emission; + GtkArg args[SIGNAL_MAX_PARAMS + 1]; + GSignalQuery query; + gboolean abort; + va_list var_args; - if (!gtk_free_emissions) - { - GtkEmission *emission_block; - guint i; - - emission_block = g_new0 (GtkEmission, EMISSION_BLOCK_SIZE); - for (i = 1; i < EMISSION_BLOCK_SIZE; i++) - { - (emission_block + i)->next = gtk_free_emissions; - gtk_free_emissions = (emission_block + i); - } - - emission = emission_block; - } - else - { - emission = gtk_free_emissions; - gtk_free_emissions = emission->next; - } - - emission->object = NULL; - emission->signal_id = 0; - emission->in_hook = 0; - emission->next = NULL; + g_return_if_fail (GTK_IS_OBJECT (object)); + g_return_if_fail (name != NULL); - return emission; -} - -static void -gtk_emission_add (GtkEmission **emissions, - GtkObject *object, - guint signal_id) -{ - GtkEmission *emission; + g_signal_query (g_signal_lookup (name, GTK_OBJECT_TYPE (object)), &query); + g_return_if_fail (query.signal_id != 0); + g_return_if_fail (query.n_params < SIGNAL_MAX_PARAMS); - g_return_if_fail (emissions != NULL); - g_return_if_fail (object != NULL); + va_start (var_args, name); + abort = gtk_signal_collect_args (args, + query.n_params, + query.param_types, + query.return_type, + var_args); + va_end (var_args); - emission = gtk_emission_new (); - emission->object = object; - emission->signal_id = signal_id; - - emission->next = *emissions; - *emissions = emission; -} - -static void -gtk_emission_remove (GtkEmission **emissions, - GtkObject *object, - guint signal_id) -{ - GtkEmission *emission, *last; - - g_return_if_fail (emissions != NULL); - - last = NULL; - emission = *emissions; - while (emission) - { - if (emission->object == object && emission->signal_id == signal_id) - { - if (last) - last->next = emission->next; - else - *emissions = emission->next; - - emission->next = gtk_free_emissions; - gtk_free_emissions = emission; - break; - } - - last = emission; - emission = last->next; - } -} - -static gint -gtk_emission_check (GtkEmission *emission, - GtkObject *object, - guint signal_id) -{ - while (emission) - { - if (emission->object == object && emission->signal_id == signal_id) - return 1 + emission->in_hook; - emission = emission->next; - } - return FALSE; + if (!abort) + gtk_signal_emitv (object, query.signal_id, args); } -static gint -gtk_handlers_run (GtkHandler *handlers, - GtkSignal *signal, - GtkObject *object, - GtkArg *params, - gint after) +void +gtk_signal_emitv_by_name (GtkObject *object, + const gchar *name, + GtkArg *args) { - /* *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, - object, - 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; - } + g_return_if_fail (GTK_IS_OBJECT (object)); - 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 != 0) /* FIXME: check for IS_PARAM */ - { - 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; + gtk_signal_emitv (object, g_signal_lookup (name, GTK_OBJECT_TYPE (object)), args); } |