use g_signal_newc
[platform/upstream/glib.git] / gobject / gsignal.c
1 /* GObject - GLib Type, Object, Parameter and Signal Library
2  * Copyright (C) 2000 Red Hat, Inc.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General
15  * Public License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
17  * Boston, MA 02111-1307, USA.
18  *
19  * this code is based on the original GtkSignal implementation
20  * for the Gtk+ library by Peter Mattis <petm@xcf.berkeley.edu>
21  */
22 #include <string.h> 
23
24 #include        "gsignal.h"
25 #include        "gbsearcharray.h"
26 #include        "gvaluecollector.h"
27
28
29 /* pre allocation configurations
30  */
31 #define MAX_STACK_VALUES        (16)
32 #define BSA_PRE_ALLOC           (20)
33 #define HANDLER_PRE_ALLOC       (48)
34 #define EMISSION_PRE_ALLOC      (16)
35
36 #define TIGHT_MEMORY    (1)
37
38 #define REPORT_BUG      "please report occourance circumstances to gtk-devel-list@gnome.org"
39
40
41 /* --- generic allocation --- */
42 /* we can special case allocations generically by replacing
43  * these functions with more speed/memory aware variants
44  */
45 static inline gpointer
46 g_generic_node_alloc (GTrashStack **trash_stack_p,
47                       guint         sizeof_node,
48                       guint         nodes_pre_alloc)
49 {
50   gpointer node = g_trash_stack_pop (trash_stack_p);
51   
52   if (!node)
53     {
54       guint8 *block;
55       
56       nodes_pre_alloc = MAX (nodes_pre_alloc, 1);
57       block = g_malloc (sizeof_node * nodes_pre_alloc);
58       while (--nodes_pre_alloc)
59         {
60           g_trash_stack_push (trash_stack_p, block);
61           block += sizeof_node;
62         }
63       node = block;
64     }
65   
66   return node;
67 }
68 static inline void
69 g_generic_node_free (GTrashStack **trash_stack_p,
70                      gpointer      node)
71 {
72   g_trash_stack_push (trash_stack_p, node);
73 }
74
75
76 /* --- typedefs --- */
77 typedef struct _SignalNode   SignalNode;
78 typedef struct _SignalKey    SignalKey;
79 typedef struct _Emission     Emission;
80 typedef struct _Handler      Handler;
81 typedef struct _HandlerList  HandlerList;
82 typedef struct _HandlerMatch HandlerMatch;
83 typedef enum
84 {
85   EMISSION_STOP,
86   EMISSION_RUN,
87   EMISSION_HOOK,
88   EMISSION_RESTART
89 } EmissionState;
90
91
92 /* --- prototypes --- */
93 static inline guint             signal_id_lookup        (GQuark           quark,
94                                                          GType            itype);
95 static        void              signal_destroy_R        (SignalNode      *signal_node);
96 static inline HandlerList*      handler_list_ensure     (guint            signal_id,
97                                                          gpointer         instance);
98 static inline HandlerList*      handler_list_lookup     (guint            signal_id,
99                                                          gpointer         instance);
100 static inline Handler*          handler_new             (gboolean         after);
101 static        void              handler_insert          (guint            signal_id,
102                                                          gpointer         instance,
103                                                          Handler         *handler);
104 static        Handler*          handler_lookup          (gpointer         instance,
105                                                          guint            handler_id,
106                                                          guint           *signal_id_p);
107 static inline HandlerMatch*     handler_match_prepend   (HandlerMatch    *list,
108                                                          Handler         *handler,
109                                                          guint            signal_id);
110 static inline HandlerMatch*     handler_match_free1_R   (HandlerMatch    *node,
111                                                          gpointer         instance);
112 static        HandlerMatch*     handlers_find           (gpointer         instance,
113                                                          GSignalMatchType mask,
114                                                          guint            signal_id,
115                                                          GQuark           detail,
116                                                          GClosure        *closure,
117                                                          gpointer         func,
118                                                          gpointer         data,
119                                                          gboolean         one_and_only);
120 static inline void              handler_ref             (Handler         *handler);
121 static inline void              handler_unref_R         (guint            signal_id,
122                                                          gpointer         instance,
123                                                          Handler         *handler);
124 static inline void              emission_push           (Emission       **emission_list_p,
125                                                          guint            signal_id,
126                                                          GQuark           detail,
127                                                          gpointer         instance,
128                                                          EmissionState   *state_p);
129 static inline void              emission_pop            (Emission       **emission_list_p,
130                                                          EmissionState   *state_p);
131 static inline Emission*         emission_find           (Emission        *emission_list,
132                                                          guint            signal_id,
133                                                          GQuark           detail,
134                                                          gpointer         instance);
135 static        gboolean          signal_emit_R           (SignalNode      *node,
136                                                          GQuark           detail,
137                                                          gpointer         instance,
138                                                          GValue          *return_value,
139                                                          const GValue    *instance_and_params);
140
141
142 /* --- structures --- */
143 struct _SignalNode
144 {
145   /* permanent portion */
146   guint              signal_id;
147   GType              itype;
148   gchar             *name;
149   guint              destroyed : 1;
150   
151   /* reinitializable portion */
152   guint              flags : 8;
153   guint              n_params : 8;
154   GType             *param_types;
155   GType              return_type;
156   GClosure          *class_closure;
157   GSignalAccumulator accumulator;
158   GSignalCMarshaller c_marshaller;
159   GHookList         *emission_hooks;
160 };
161
162 struct _SignalKey
163 {
164   GType  itype;
165   GQuark quark;
166   guint  signal_id;
167 };
168
169 struct _Emission
170 {
171   Emission      *next;
172   guint          signal_id;
173   GQuark         detail;
174   gpointer       instance;
175   EmissionState *state_p;
176 };
177
178 struct _HandlerList
179 {
180   guint    signal_id;
181   Handler *handlers;
182 };
183 struct _Handler
184 {
185   guint         id;
186   Handler      *next;
187   Handler      *prev;
188   GQuark        detail;
189   guint         ref_count : 16;
190 #define HANDLER_MAX_REF_COUNT   (1 << 16)
191   guint         block_count : 12;
192 #define HANDLER_MAX_BLOCK_COUNT (1 << 12)
193   guint         after : 1;
194   GClosure     *closure;
195 };
196 struct _HandlerMatch
197 {
198   Handler      *handler;
199   HandlerMatch *next;
200   union {
201     guint       signal_id;
202     gpointer    dummy;
203   } d;
204 };
205
206
207 /* --- variables --- */
208 static GBSearchArray  g_signal_key_bsa = { NULL, 0, 0, 0, NULL };
209 static GHashTable    *g_handler_list_bsa_ht = NULL;
210 static Emission      *g_recursive_emissions = NULL;
211 static Emission      *g_restart_emissions = NULL;
212 static GTrashStack   *g_bsa_ts = NULL;
213 static GTrashStack   *g_handler_ts = NULL;
214 static GTrashStack   *g_emission_ts = NULL;
215 G_LOCK_DEFINE_STATIC (g_signal_mutex);
216
217
218 /* --- signal nodes --- */
219 static guint          g_n_signal_nodes = 0;
220 static SignalNode   **g_signal_nodes = NULL;
221
222 static inline SignalNode*
223 LOOKUP_SIGNAL_NODE (register guint signal_id)
224 {
225   if (signal_id < g_n_signal_nodes)
226     return g_signal_nodes[signal_id];
227   else
228     return NULL;
229 }
230
231
232 /* --- functions --- */
233 static inline guint
234 signal_id_lookup (GQuark quark,
235                   GType  itype)
236 {
237   GType *ifaces, type = itype;
238   SignalKey key;
239   guint n_ifaces;
240
241   key.quark = quark;
242
243   /* try looking up signals for this type and its anchestors */
244   do
245     {
246       SignalKey *signal_key;
247       
248       key.itype = type;
249       signal_key = g_bsearch_array_lookup (&g_signal_key_bsa, &key);
250       
251       if (signal_key)
252         return signal_key->signal_id;
253       
254       type = g_type_parent (type);
255     }
256   while (type);
257
258   /* no luck, try interfaces it exports */
259   ifaces = g_type_interfaces (itype, &n_ifaces);
260   while (n_ifaces--)
261     {
262       SignalKey *signal_key;
263
264       key.itype = ifaces[n_ifaces];
265       signal_key = g_bsearch_array_lookup (&g_signal_key_bsa, &key);
266
267       if (signal_key)
268         {
269           g_free (ifaces);
270           return signal_key->signal_id;
271         }
272     }
273   g_free (ifaces);
274   
275   return 0;
276 }
277
278 static gint
279 handler_lists_cmp (gconstpointer node1,
280                    gconstpointer node2)
281 {
282   const HandlerList *hlist1 = node1, *hlist2 = node2;
283   
284   return G_BSEARCH_ARRAY_CMP (hlist1->signal_id, hlist2->signal_id);
285 }
286
287 static inline HandlerList*
288 handler_list_ensure (guint    signal_id,
289                      gpointer instance)
290 {
291   GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
292   HandlerList key;
293   
294   if (!hlbsa)
295     {
296       hlbsa = g_generic_node_alloc (&g_bsa_ts,
297                                     sizeof (GBSearchArray),
298                                     BSA_PRE_ALLOC);
299       hlbsa->cmp_func = handler_lists_cmp;
300       hlbsa->sizeof_node = sizeof (HandlerList);
301       hlbsa->flags = G_BSEARCH_DEFER_SHRINK;
302       hlbsa->n_nodes = 0;
303       hlbsa->nodes = NULL;
304       g_hash_table_insert (g_handler_list_bsa_ht, instance, hlbsa);
305     }
306   key.signal_id = signal_id;
307   key.handlers = NULL;
308   
309   return g_bsearch_array_insert (hlbsa, &key, FALSE);
310 }
311
312 static inline HandlerList*
313 handler_list_lookup (guint    signal_id,
314                      gpointer instance)
315 {
316   GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
317   HandlerList key;
318   
319   key.signal_id = signal_id;
320   
321   return hlbsa ? g_bsearch_array_lookup (hlbsa, &key) : NULL;
322 }
323
324 static Handler*
325 handler_lookup (gpointer instance,
326                 guint    handler_id,
327                 guint   *signal_id_p)
328 {
329   GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
330   
331   if (hlbsa)
332     {
333       guint i;
334       
335       for (i = 0; i < hlbsa->n_nodes; i++)
336         {
337           HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, i);
338           Handler *handler;
339           
340           for (handler = hlist->handlers; handler; handler = handler->next)
341             if (handler->id == handler_id)
342               {
343                 if (signal_id_p)
344                   *signal_id_p = hlist->signal_id;
345                 
346                 return handler;
347               }
348         }
349     }
350   
351   return NULL;
352 }
353
354 static inline HandlerMatch*
355 handler_match_prepend (HandlerMatch *list,
356                        Handler      *handler,
357                        guint         signal_id)
358 {
359   HandlerMatch *node;
360   
361   /* yeah, we could use our own memchunk here, introducing yet more
362    * rarely used cached nodes and extra allocation overhead.
363    * instead, we use GList* nodes, since they are exactly the size
364    * we need and are already cached. g_signal_init() asserts this.
365    */
366   node = (HandlerMatch*) g_list_alloc ();
367   node->handler = handler;
368   node->next = list;
369   node->d.signal_id = signal_id;
370   handler_ref (handler);
371   
372   return node;
373 }
374 static inline HandlerMatch*
375 handler_match_free1_R (HandlerMatch *node,
376                        gpointer      instance)
377 {
378   HandlerMatch *next = node->next;
379   
380   handler_unref_R (node->d.signal_id, instance, node->handler);
381   g_list_free_1 ((GList*) node);
382   
383   return next;
384 }
385
386 static HandlerMatch*
387 handlers_find (gpointer         instance,
388                GSignalMatchType mask,
389                guint            signal_id,
390                GQuark           detail,
391                GClosure        *closure,
392                gpointer         func,
393                gpointer         data,
394                gboolean         one_and_only)
395 {
396   HandlerMatch *mlist = NULL;
397   
398   if (mask & G_SIGNAL_MATCH_ID)
399     {
400       HandlerList *hlist = handler_list_lookup (signal_id, instance);
401       Handler *handler;
402       SignalNode *node = NULL;
403       
404       if (mask & G_SIGNAL_MATCH_FUNC)
405         {
406           node = LOOKUP_SIGNAL_NODE (signal_id);
407           if (!node || !node->c_marshaller)
408             return NULL;
409         }
410       
411       mask = ~mask;
412       for (handler = hlist ? hlist->handlers : NULL; handler; handler = handler->next)
413         if (handler->id &&
414             ((mask & G_SIGNAL_MATCH_DETAIL) || handler->detail == detail) &&
415             ((mask & G_SIGNAL_MATCH_CLOSURE) || handler->closure == closure) &&
416             ((mask & G_SIGNAL_MATCH_DATA) || handler->closure->data == data) &&
417             ((mask & G_SIGNAL_MATCH_UNBLOCKED) || handler->block_count == 0) &&
418             ((mask & G_SIGNAL_MATCH_FUNC) || (handler->closure->marshal == node->c_marshaller &&
419                                               handler->closure->meta_marshal == 0 &&
420                                               ((GCClosure*) handler->closure)->callback == func)))
421           {
422             mlist = handler_match_prepend (mlist, handler, signal_id);
423             if (one_and_only)
424               return mlist;
425           }
426     }
427   else
428     {
429       GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
430       
431       mask = ~mask;
432       if (hlbsa)
433         {
434           guint i;
435           
436           for (i = 0; i < hlbsa->n_nodes; i++)
437             {
438               HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, i);
439               SignalNode *node = NULL;
440               Handler *handler;
441               
442               if (!(mask & G_SIGNAL_MATCH_FUNC))
443                 {
444                   node = LOOKUP_SIGNAL_NODE (hlist->signal_id);
445                   if (!node->c_marshaller)
446                     continue;
447                 }
448               
449               for (handler = hlist->handlers; handler; handler = handler->next)
450                 if (handler->id &&
451                     ((mask & G_SIGNAL_MATCH_DETAIL) || handler->detail == detail) &&
452                     ((mask & G_SIGNAL_MATCH_CLOSURE) || handler->closure == closure) &&
453                     ((mask & G_SIGNAL_MATCH_DATA) || handler->closure->data == data) &&
454                     ((mask & G_SIGNAL_MATCH_UNBLOCKED) || handler->block_count == 0) &&
455                     ((mask & G_SIGNAL_MATCH_FUNC) || (handler->closure->marshal == node->c_marshaller &&
456                                                       handler->closure->meta_marshal == 0 &&
457                                                       ((GCClosure*) handler->closure)->callback == func)))
458                   {
459                     mlist = handler_match_prepend (mlist, handler, hlist->signal_id);
460                     if (one_and_only)
461                       return mlist;
462                   }
463             }
464         }
465     }
466   
467   return mlist;
468 }
469
470 static inline Handler*
471 handler_new (gboolean after)
472 {
473   static guint handler_id = 1;
474   Handler *handler = g_generic_node_alloc (&g_handler_ts,
475                                            sizeof (Handler),
476                                            HANDLER_PRE_ALLOC);
477 #ifndef G_DISABLE_CHECKS
478   if (handler_id == 0)
479     g_error (G_STRLOC ": handler id overflow, %s", REPORT_BUG);
480 #endif
481   
482   handler->id = handler_id++;
483   handler->prev = NULL;
484   handler->next = NULL;
485   handler->detail = 0;
486   handler->ref_count = 1;
487   handler->block_count = 0;
488   handler->after = after != FALSE;
489   handler->closure = NULL;
490   
491   return handler;
492 }
493
494 static inline void
495 handler_ref (Handler *handler)
496 {
497   g_return_if_fail (handler->ref_count > 0);
498   
499 #ifndef G_DISABLE_CHECKS
500   if (handler->ref_count >= HANDLER_MAX_REF_COUNT - 1)
501     g_error (G_STRLOC ": handler ref_count overflow, %s", REPORT_BUG);
502 #endif
503   
504   handler->ref_count += 1;
505 }
506
507 static inline void
508 handler_unref_R (guint    signal_id,
509                  gpointer instance,
510                  Handler *handler)
511 {
512   g_return_if_fail (handler->ref_count > 0);
513   
514   handler->ref_count -= 1;
515   if (!handler->ref_count)
516     {
517       if (handler->next)
518         handler->next->prev = handler->prev;
519       if (handler->prev)        /* watch out for g_signal_handlers_destroy()! */
520         handler->prev->next = handler->next;
521       else
522         {
523           HandlerList *hlist = handler_list_lookup (signal_id, instance);
524           
525           hlist->handlers = handler->next;
526         }
527       G_UNLOCK (g_signal_mutex);
528       g_closure_unref (handler->closure);
529       G_LOCK (g_signal_mutex);
530       g_generic_node_free (&g_handler_ts, handler);
531     }
532 }
533
534 static void
535 handler_insert (guint    signal_id,
536                 gpointer instance,
537                 Handler  *handler)
538 {
539   HandlerList *hlist;
540   
541   g_assert (handler->prev == NULL && handler->next == NULL); /* paranoid */
542   
543   hlist = handler_list_ensure (signal_id, instance);
544   if (!hlist->handlers)
545     hlist->handlers = handler;
546   else if (hlist->handlers->after && !handler->after)
547     {
548       handler->next = hlist->handlers;
549       hlist->handlers->prev = handler;
550       hlist->handlers = handler;
551     }
552   else
553     {
554       Handler *tmp = hlist->handlers;
555       
556       if (handler->after)
557         while (tmp->next)
558           tmp = tmp->next;
559       else
560         while (tmp->next && !tmp->next->after)
561           tmp = tmp->next;
562       if (tmp->next)
563         tmp->next->prev = handler;
564       handler->next = tmp->next;
565       handler->prev = tmp;
566       tmp->next = handler;
567     }
568 }
569
570 static inline void
571 emission_push (Emission     **emission_list_p,
572                guint          signal_id,
573                GQuark         detail,
574                gpointer       instance,
575                EmissionState *state_p)
576 {
577   Emission *emission = g_generic_node_alloc (&g_emission_ts,
578                                              sizeof (Emission),
579                                              EMISSION_PRE_ALLOC);
580   emission->next = *emission_list_p;
581   emission->signal_id = signal_id;
582   emission->detail = detail;
583   emission->instance = instance;
584   emission->state_p = state_p;
585   *emission_list_p = emission;
586 }
587
588 static inline void
589 emission_pop (Emission     **emission_list_p,
590               EmissionState *state_p)
591 {
592   Emission **loc = emission_list_p, *emission = *loc;
593   
594   while (emission->state_p != state_p)
595     {
596       loc = &emission->next;
597       emission = *loc;
598     }
599   *loc = emission->next;
600   g_generic_node_free (&g_emission_ts, emission);
601 }
602
603 static inline Emission*
604 emission_find (Emission *emission_list,
605                guint     signal_id,
606                GQuark    detail,
607                gpointer  instance)
608 {
609   Emission *emission;
610   
611   for (emission = emission_list; emission; emission = emission->next)
612     if (emission->instance == instance &&
613         emission->signal_id == signal_id &&
614         emission->detail == detail)
615       return emission;
616   return NULL;
617 }
618
619 static gint
620 signal_key_cmp (gconstpointer node1,
621                 gconstpointer node2)
622 {
623   const SignalKey *key1 = node1, *key2 = node2;
624   
625   if (key1->itype == key2->itype)
626     return G_BSEARCH_ARRAY_CMP (key1->quark, key2->quark);
627   else
628     return G_BSEARCH_ARRAY_CMP (key1->itype, key2->itype);
629 }
630
631 void
632 g_signal_init (void) /* sync with gtype.c */
633 {
634   G_LOCK (g_signal_mutex);
635   if (!g_n_signal_nodes)
636     {
637       /* handler_id_node_prepend() requires this */
638       g_assert (sizeof (GList) == sizeof (HandlerMatch));
639       
640       /* setup signal key array */
641       g_signal_key_bsa.cmp_func = signal_key_cmp;
642       g_signal_key_bsa.sizeof_node = sizeof (SignalKey);
643       g_signal_key_bsa.flags = 0; /* alloc-only */
644       
645       /* setup handler list binary searchable array hash table (in german, that'd be one word ;) */
646       g_handler_list_bsa_ht = g_hash_table_new (g_direct_hash, NULL);
647       
648       /* invalid (0) signal_id */
649       g_n_signal_nodes = 1;
650       g_signal_nodes = g_renew (SignalNode*, g_signal_nodes, g_n_signal_nodes);
651       g_signal_nodes[0] = NULL;
652     }
653   G_UNLOCK (g_signal_mutex);
654 }
655
656 void
657 _g_signals_destroy (GType itype)
658 {
659   guint i;
660   
661   G_LOCK (g_signal_mutex);
662   for (i = 1; i < g_n_signal_nodes; i++)
663     {
664       SignalNode *node = g_signal_nodes[i];
665       
666       if (node->itype == itype)
667         {
668           if (node->destroyed)
669             g_warning (G_STRLOC ": signal \"%s\" of type `%s' already destroyed",
670                        node->name,
671                        g_type_name (node->itype));
672           else
673             signal_destroy_R (node);
674         }
675     }
676   G_UNLOCK (g_signal_mutex);
677 }
678
679 void
680 g_signal_stop_emission (gpointer instance,
681                         guint    signal_id,
682                         GQuark   detail)
683 {
684   SignalNode *node;
685   
686   g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
687   g_return_if_fail (signal_id > 0);
688   
689   G_LOCK (g_signal_mutex);
690   node = LOOKUP_SIGNAL_NODE (signal_id);
691   if (node && detail && !(node->flags & G_SIGNAL_DETAILED))
692     {
693       g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
694       G_UNLOCK (g_signal_mutex);
695       return;
696     }
697   if (node && g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype))
698     {
699       Emission *emission_list = node->flags & G_SIGNAL_NO_RECURSE ? g_restart_emissions : g_recursive_emissions;
700       Emission *emission = emission_find (emission_list, signal_id, detail, instance);
701       
702       if (emission)
703         {
704           if (*emission->state_p == EMISSION_HOOK)
705             g_warning (G_STRLOC ": emission of signal \"%s\" for instance `%p' cannot be stopped from emission hook",
706                        node->name, instance);
707           else if (*emission->state_p == EMISSION_RUN)
708             *emission->state_p = EMISSION_STOP;
709         }
710       else
711         g_warning (G_STRLOC ": no emission of signal \"%s\" to stop for instance `%p'",
712                    node->name, instance);
713     }
714   else
715     g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
716   G_UNLOCK (g_signal_mutex);
717 }
718
719 static inline guint
720 signal_parse_name (const gchar *name,
721                    GType        itype,
722                    GQuark      *detail_p,
723                    gboolean     force_quark)
724 {
725   const gchar *colon = strchr (name, ':');
726   guint signal_id;
727   
728   if (!colon)
729     {
730       signal_id = signal_id_lookup (g_quark_try_string (name), itype);
731       if (signal_id && detail_p)
732         *detail_p = 0;
733     }
734   else if (colon[1] == ':')
735     {
736       gchar buffer[32];
737       guint l = colon - name;
738       
739       if (l < 32)
740         {
741           memcpy (buffer, name, l);
742           buffer[l] = 0;
743           signal_id = signal_id_lookup (g_quark_try_string (buffer), itype);
744         }
745       else
746         {
747           gchar *signal = g_new (gchar, l + 1);
748           
749           memcpy (signal, name, l);
750           signal[l] = 0;
751           signal_id = signal_id_lookup (g_quark_try_string (signal), itype);
752           g_free (signal);
753         }
754       
755       if (signal_id && detail_p)
756         *detail_p = colon[2] ? (force_quark ? g_quark_from_string : g_quark_try_string) (colon + 2) : 0;
757     }
758   else
759     signal_id = 0;
760   return signal_id;
761 }
762
763 gboolean
764 g_signal_parse_name (const gchar *detailed_signal,
765                      GType        itype,
766                      guint       *signal_id_p,
767                      GQuark      *detail_p,
768                      gboolean     force_detail_quark)
769 {
770   GQuark detail = 0;
771   guint signal_id;
772   
773   g_return_val_if_fail (detailed_signal != NULL, FALSE);
774   g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), FALSE);
775   
776   G_LOCK (g_signal_mutex);
777   signal_id = signal_parse_name (detailed_signal, itype, &detail, force_detail_quark);
778   G_UNLOCK (g_signal_mutex);
779   
780   if (signal_id)
781     {
782       if (signal_id_p)
783         *signal_id_p = signal_id;
784       if (detail_p)
785         *detail_p = detail;
786       
787       return TRUE;
788     }
789   else
790     return FALSE;
791 }
792
793 guint
794 g_signal_lookup (const gchar *name,
795                  GType        itype)
796 {
797   guint signal_id;
798   
799   g_return_val_if_fail (name != NULL, 0);
800   g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), 0);
801   
802   G_LOCK (g_signal_mutex);
803   signal_id = signal_id_lookup (g_quark_try_string (name), itype);
804   G_UNLOCK (g_signal_mutex);
805   
806   return signal_id;
807 }
808
809 gchar*
810 g_signal_name (guint signal_id)
811 {
812   SignalNode *node;
813   gchar *name;
814   
815   G_LOCK (g_signal_mutex);
816   node = LOOKUP_SIGNAL_NODE (signal_id);
817   name = node ? node->name : NULL;
818   G_UNLOCK (g_signal_mutex);
819   
820   return name;
821 }
822
823 void
824 g_signal_query (guint         signal_id,
825                 GSignalQuery *query)
826 {
827   SignalNode *node;
828   
829   g_return_if_fail (query != NULL);
830   
831   G_LOCK (g_signal_mutex);
832   node = LOOKUP_SIGNAL_NODE (signal_id);
833   if (!node || node->destroyed)
834     query->signal_id = 0;
835   else
836     {
837       query->signal_id = node->signal_id;
838       query->signal_name = node->name;
839       query->itype = node->itype;
840       query->signal_flags = node->flags;
841       query->return_type = node->return_type;
842       query->n_params = node->n_params;
843       query->param_types = node->param_types;
844     }
845   G_UNLOCK (g_signal_mutex);
846 }
847
848 guint*
849 g_signal_list_ids (GType  itype,
850                    guint *n_ids)
851 {
852   SignalKey *keys;
853   GArray *result;
854   guint n_nodes;
855   guint i;
856   
857   g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), NULL);
858   g_return_val_if_fail (n_ids != NULL, NULL);
859   
860   G_LOCK (g_signal_mutex);
861   
862   keys = g_signal_key_bsa.nodes;
863   n_nodes  = g_signal_key_bsa.n_nodes;
864   result = g_array_new (FALSE, FALSE, sizeof (guint));
865   
866   for (i = 0; i < n_nodes; i++)
867     if (keys[i].itype == itype)
868       {
869         gchar *name = g_quark_to_string (keys[i].quark);
870         
871         /* Signal names with "_" in them are aliases to the same
872          * name with "-" instead of "_".
873          */
874         if (!strchr (name, '_'))
875           g_array_append_val (result, keys[i].signal_id);
876       }
877   
878   *n_ids = result->len;
879   
880   G_UNLOCK (g_signal_mutex);
881   
882   return (guint *) g_array_free (result, FALSE);
883 }
884
885 guint
886 g_signal_new_valist (const gchar       *signal_name,
887                      GType              itype,
888                      GSignalFlags       signal_flags,
889                      GClosure          *class_closure,
890                      GSignalAccumulator accumulator,
891                      GSignalCMarshaller c_marshaller,
892                      GType              return_type,
893                      guint              n_params,
894                      va_list            args)
895 {
896   GType *param_types;
897   guint i;
898   guint signal_id;
899
900   if (n_params > 0)
901     {
902       param_types = g_new (GType, n_params);
903
904       for (i = 0; i < n_params; i++)
905         param_types[i] = va_arg (args, GType);
906     }
907   else
908     param_types = NULL;
909
910   signal_id = g_signal_newv (signal_name, itype, signal_flags,
911                              class_closure, accumulator, c_marshaller,
912                              return_type, n_params, param_types);
913   g_free (param_types);
914
915   return signal_id;
916 }
917
918 guint
919 g_signal_newc (const gchar       *signal_name,
920                GType              itype,
921                GSignalFlags       signal_flags,
922                guint              class_offset,
923                GSignalAccumulator accumulator,
924                GSignalCMarshaller c_marshaller,
925                GType              return_type,
926                guint              n_params,
927                ...)
928 {
929   va_list args;
930   guint signal_id;
931
932   g_return_val_if_fail (signal_name != NULL, 0);
933   
934   va_start (args, n_params);
935
936   signal_id = g_signal_new_valist (signal_name, itype, signal_flags,
937                                    g_signal_type_cclosure_new (itype,
938                                                                class_offset),
939                                    accumulator, c_marshaller,
940                                    return_type, n_params, args);
941
942   va_end (args);
943  
944   return signal_id;
945 }
946
947 guint
948 g_signal_newv (const gchar       *signal_name,
949                GType              itype,
950                GSignalFlags       signal_flags,
951                GClosure          *class_closure,
952                GSignalAccumulator accumulator,
953                GSignalCMarshaller c_marshaller,
954                GType              return_type,
955                guint              n_params,
956                GType             *param_types)
957 {
958   gchar *name;
959   guint signal_id, i;
960   SignalNode *node;
961   
962   g_return_val_if_fail (signal_name != NULL, 0);
963   g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), 0);
964   if (n_params)
965     g_return_val_if_fail (param_types != NULL, 0);
966   if (return_type != G_TYPE_NONE)
967     g_return_val_if_fail (accumulator == NULL, 0);
968   
969   name = g_strdup (signal_name);
970   g_strdelimit (name, G_STR_DELIMITERS ":^", '_');  // FIXME do character checks like for types
971   
972   G_LOCK (g_signal_mutex);
973   
974   signal_id = signal_id_lookup (g_quark_try_string (name), itype);
975   node = LOOKUP_SIGNAL_NODE (signal_id);
976   if (node && !node->destroyed)
977     {
978       g_warning (G_STRLOC ": signal \"%s\" already exists in the `%s' %s",
979                  name,
980                  g_type_name (node->itype),
981                  G_TYPE_IS_INTERFACE (node->itype) ? "interface" : "class ancestry");
982       g_free (name);
983       G_UNLOCK (g_signal_mutex);
984       return 0;
985     }
986   if (node && node->itype != itype)
987     {
988       g_warning (G_STRLOC ": signal \"%s\" for type `%s' was previously created for type `%s'",
989                  name,
990                  g_type_name (itype),
991                  g_type_name (node->itype));
992       g_free (name);
993       G_UNLOCK (g_signal_mutex);
994       return 0;
995     }
996   for (i = 0; i < n_params; i++)
997     if (!G_TYPE_IS_VALUE (param_types[i]) ||
998         param_types[i] == G_TYPE_ENUM || param_types[i] == G_TYPE_FLAGS) /* FIXME: kludge */
999       {
1000         g_warning (G_STRLOC ": parameter %d of type `%s' for signal \"%s::%s\" is not a value type",
1001                    i + 1, g_type_name (param_types[i]), g_type_name (itype), name);
1002         g_free (name);
1003         G_UNLOCK (g_signal_mutex);
1004         return 0;
1005       }
1006   if (return_type != G_TYPE_NONE && !G_TYPE_IS_VALUE (return_type))
1007     {
1008       g_warning (G_STRLOC ": return value of type `%s' for signal \"%s::%s\" is not a value type",
1009                  g_type_name (param_types[i]), g_type_name (itype), name);
1010       g_free (name);
1011       G_UNLOCK (g_signal_mutex);
1012       return 0;
1013     }
1014   
1015   /* setup permanent portion of signal node */
1016   if (!node)
1017     {
1018       SignalKey key;
1019       
1020       signal_id = g_n_signal_nodes++;
1021       node = g_new (SignalNode, 1);
1022       node->signal_id = signal_id;
1023       g_signal_nodes = g_renew (SignalNode*, g_signal_nodes, g_n_signal_nodes);
1024       g_signal_nodes[signal_id] = node;
1025       node->itype = itype;
1026       node->name = name;
1027       key.itype = itype;
1028       key.quark = g_quark_from_string (node->name);
1029       key.signal_id = signal_id;
1030       g_bsearch_array_insert (&g_signal_key_bsa, &key, FALSE);
1031       g_strdelimit (node->name, "_", '-');
1032       key.quark = g_quark_from_static_string (node->name);
1033       g_bsearch_array_insert (&g_signal_key_bsa, &key, FALSE);
1034     }
1035   node->destroyed = FALSE;
1036   
1037   /* setup reinitializable portion */
1038   node->flags = signal_flags & G_SIGNAL_FLAGS_MASK;
1039   node->n_params = n_params;
1040   node->param_types = g_memdup (param_types, sizeof (GType) * n_params);
1041   node->return_type = return_type;
1042   node->class_closure = class_closure ? g_closure_ref (class_closure) : NULL;
1043   node->accumulator = accumulator;
1044   node->c_marshaller = c_marshaller;
1045   node->emission_hooks = NULL;
1046   if (node->c_marshaller && class_closure && G_CLOSURE_NEEDS_MARSHAL (class_closure))
1047     g_closure_set_marshal (class_closure, node->c_marshaller);
1048   
1049   G_UNLOCK (g_signal_mutex);
1050   return signal_id;
1051 }
1052
1053 static void
1054 signal_destroy_R (SignalNode *signal_node)
1055 {
1056   SignalNode node = *signal_node;
1057   
1058   signal_node->destroyed = TRUE;
1059   
1060   /* reentrancy caution, zero out real contents first */
1061   signal_node->n_params = 0;
1062   signal_node->param_types = NULL;
1063   signal_node->return_type = 0;
1064   signal_node->class_closure = NULL;
1065   signal_node->accumulator = NULL;
1066   signal_node->c_marshaller = NULL;
1067   signal_node->emission_hooks = NULL;
1068   
1069 #ifndef G_DISABLE_CHECKS
1070   /* check current emissions */
1071   {
1072     Emission *emission;
1073     
1074     for (emission = (node.flags & G_SIGNAL_NO_RECURSE) ? g_restart_emissions : g_recursive_emissions;
1075          emission; emission = emission->next)
1076       if (emission->signal_id == node.signal_id)
1077         g_critical (G_STRLOC ": signal \"%s\" being destroyed is currently in emission (instance `%p')",
1078                     node.name, emission->instance);
1079   }
1080 #endif
1081   
1082   /* free contents that need to
1083    */
1084   G_UNLOCK (g_signal_mutex);
1085   g_free (node.param_types);
1086   g_closure_unref (node.class_closure);
1087   if (node.emission_hooks)
1088     {
1089       g_hook_list_clear (node.emission_hooks);
1090       g_free (node.emission_hooks);
1091     }
1092   G_LOCK (g_signal_mutex);
1093 }
1094
1095 guint
1096 g_signal_connect_closure_by_id (gpointer  instance,
1097                                 guint     signal_id,
1098                                 GQuark    detail,
1099                                 GClosure *closure,
1100                                 gboolean  after)
1101 {
1102   SignalNode *node;
1103   guint handler_id = 0;
1104   
1105   g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
1106   g_return_val_if_fail (signal_id > 0, 0);
1107   g_return_val_if_fail (closure != NULL, 0);
1108   
1109   G_LOCK (g_signal_mutex);
1110   node = LOOKUP_SIGNAL_NODE (signal_id);
1111   if (node)
1112     {
1113       if (detail && !(node->flags & G_SIGNAL_DETAILED))
1114         g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
1115       else if (!g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype))
1116         g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
1117       else
1118         {
1119           Handler *handler = handler_new (after);
1120           
1121           handler_id = handler->id;
1122           handler->detail = detail;
1123           handler->closure = g_closure_ref (closure);
1124           handler_insert (signal_id, instance, handler);
1125           if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (closure))
1126             g_closure_set_marshal (closure, node->c_marshaller);
1127         }
1128     }
1129   else
1130     g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
1131   G_UNLOCK (g_signal_mutex);
1132   
1133   return handler_id;
1134 }
1135
1136 guint
1137 g_signal_connect_closure (gpointer     instance,
1138                           const gchar *detailed_signal,
1139                           GClosure    *closure,
1140                           gboolean     after)
1141 {
1142   guint signal_id, handler_id = 0;
1143   GQuark detail = 0;
1144   GType itype;
1145
1146   g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
1147   g_return_val_if_fail (detailed_signal != NULL, 0);
1148   g_return_val_if_fail (closure != NULL, 0);
1149
1150   G_LOCK (g_signal_mutex);
1151   itype = G_TYPE_FROM_INSTANCE (instance);
1152   signal_id = signal_parse_name (detailed_signal, itype, &detail, TRUE);
1153   if (signal_id)
1154     {
1155       SignalNode *node = LOOKUP_SIGNAL_NODE (signal_id);
1156
1157       if (detail && !(node->flags & G_SIGNAL_DETAILED))
1158         g_warning ("%s: signal `%s' does not support details", G_STRLOC, detailed_signal);
1159       else if (!g_type_is_a (itype, node->itype))
1160         g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance);
1161       else
1162         {
1163           Handler *handler = handler_new (after);
1164
1165           handler_id = handler->id;
1166           handler->detail = detail;
1167           handler->closure = g_closure_ref (closure);
1168           handler_insert (signal_id, instance, handler);
1169           if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (handler->closure))
1170             g_closure_set_marshal (handler->closure, node->c_marshaller);
1171         }
1172     }
1173   else
1174     g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance);
1175   G_UNLOCK (g_signal_mutex);
1176
1177   return handler_id;
1178 }
1179
1180 guint
1181 g_signal_connect_data (gpointer       instance,
1182                        const gchar   *detailed_signal,
1183                        GCallback      c_handler,
1184                        gpointer       data,
1185                        GClosureNotify destroy_data,
1186                        gboolean       swapped,
1187                        gboolean       after)
1188 {
1189   guint signal_id, handler_id = 0;
1190   GQuark detail = 0;
1191   GType itype;
1192
1193   g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
1194   g_return_val_if_fail (detailed_signal != NULL, 0);
1195   g_return_val_if_fail (c_handler != NULL, 0);
1196
1197   G_LOCK (g_signal_mutex);
1198   itype = G_TYPE_FROM_INSTANCE (instance);
1199   signal_id = signal_parse_name (detailed_signal, itype, &detail, TRUE);
1200   if (signal_id)
1201     {
1202       SignalNode *node = LOOKUP_SIGNAL_NODE (signal_id);
1203
1204       if (detail && !(node->flags & G_SIGNAL_DETAILED))
1205         g_warning ("%s: signal `%s' does not support details", G_STRLOC, detailed_signal);
1206       else if (!g_type_is_a (itype, node->itype))
1207         g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance);
1208       else
1209         {
1210           Handler *handler = handler_new (after);
1211
1212           handler_id = handler->id;
1213           handler->detail = detail;
1214           handler->closure = g_closure_ref ((swapped ? g_cclosure_new_swap : g_cclosure_new) (c_handler, data, destroy_data));
1215           handler_insert (signal_id, instance, handler);
1216           if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (handler->closure))
1217             g_closure_set_marshal (handler->closure, node->c_marshaller);
1218         }
1219     }
1220   else
1221     g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance);
1222   G_UNLOCK (g_signal_mutex);
1223
1224   return handler_id;
1225 }
1226
1227 void
1228 g_signal_handler_block (gpointer instance,
1229                         guint    handler_id)
1230 {
1231   Handler *handler;
1232   
1233   g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1234   g_return_if_fail (handler_id > 0);
1235   
1236   G_LOCK (g_signal_mutex);
1237   handler = handler_lookup (instance, handler_id, NULL);
1238   if (handler)
1239     {
1240 #ifndef G_DISABLE_CHECKS
1241       if (handler->block_count >= HANDLER_MAX_BLOCK_COUNT - 1)
1242         g_error (G_STRLOC ": handler block_count overflow, %s", REPORT_BUG);
1243 #endif
1244       
1245       handler->block_count += 1;
1246     }
1247   else
1248     g_warning ("%s: instance `%p' has no handler with id `%u'", G_STRLOC, instance, handler_id);
1249   G_UNLOCK (g_signal_mutex);
1250 }
1251
1252 void
1253 g_signal_handler_unblock (gpointer instance,
1254                           guint    handler_id)
1255 {
1256   Handler *handler;
1257   
1258   g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1259   g_return_if_fail (handler_id > 0);
1260   
1261   G_LOCK (g_signal_mutex);
1262   handler = handler_lookup (instance, handler_id, NULL);
1263   if (handler)
1264     {
1265       if (handler->block_count)
1266         handler->block_count -= 1;
1267       else
1268         g_warning (G_STRLOC ": handler `%u' of instance `%p' is not blocked", handler_id, instance);
1269     }
1270   else
1271     g_warning ("%s: instance `%p' has no handler with id `%u'", G_STRLOC, instance, handler_id);
1272   G_UNLOCK (g_signal_mutex);
1273 }
1274
1275 void
1276 g_signal_handler_disconnect (gpointer instance,
1277                              guint    handler_id)
1278 {
1279   Handler *handler;
1280   guint signal_id;
1281   
1282   g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1283   g_return_if_fail (handler_id > 0);
1284   
1285   G_LOCK (g_signal_mutex);
1286   handler = handler_lookup (instance, handler_id, &signal_id);
1287   if (handler)
1288     {
1289       handler->id = 0;
1290       handler->block_count = 1;
1291       handler_unref_R (signal_id, instance, handler);
1292     }
1293   else
1294     g_warning ("%s: instance `%p' has no handler with id `%u'", G_STRLOC, instance, handler_id);
1295   G_UNLOCK (g_signal_mutex);
1296 }
1297
1298 void
1299 g_signal_handlers_destroy (gpointer instance)
1300 {
1301   GBSearchArray *hlbsa;
1302   
1303   g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1304   
1305   G_LOCK (g_signal_mutex);
1306   hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
1307   if (hlbsa)
1308     {
1309       guint i;
1310       
1311       /* reentrancy caution, delete instance trace first */
1312       g_hash_table_remove (g_handler_list_bsa_ht, instance);
1313       
1314       for (i = 0; i < hlbsa->n_nodes; i++)
1315         {
1316           HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, i);
1317           Handler *handler = hlist->handlers;
1318           
1319           while (handler)
1320             {
1321               Handler *tmp = handler;
1322               
1323               handler = tmp->next;
1324               tmp->block_count = 1;
1325               /* cruel unlink, this works because _all_ handlers vanish */
1326               tmp->next = NULL;
1327               tmp->prev = tmp;
1328               if (tmp->id)
1329                 {
1330                   tmp->id = 0;
1331                   handler_unref_R (0, NULL, tmp);
1332                 }
1333             }
1334         }
1335       g_free (hlbsa->nodes);
1336       g_generic_node_free (&g_bsa_ts, hlbsa);
1337     }
1338   G_UNLOCK (g_signal_mutex);
1339 }
1340
1341 guint
1342 g_signal_handler_find (gpointer         instance,
1343                        GSignalMatchType mask,
1344                        guint            signal_id,
1345                        GQuark           detail,
1346                        GClosure        *closure,
1347                        gpointer         func,
1348                        gpointer         data)
1349 {
1350   guint handler_id = 0;
1351   
1352   g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
1353   g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, 0);
1354   
1355   if (mask & G_SIGNAL_MATCH_MASK)
1356     {
1357       HandlerMatch *mlist;
1358       
1359       G_LOCK (g_signal_mutex);
1360       mlist = handlers_find (instance, mask, signal_id, detail, closure, func, data, TRUE);
1361       if (mlist)
1362         {
1363           handler_id = mlist->handler->id;
1364           handler_match_free1_R (mlist, instance);
1365         }
1366       G_UNLOCK (g_signal_mutex);
1367     }
1368   
1369   return handler_id;
1370 }
1371
1372 static guint
1373 signal_handlers_foreach_matched_R (gpointer         instance,
1374                                    GSignalMatchType mask,
1375                                    guint            signal_id,
1376                                    GQuark           detail,
1377                                    GClosure        *closure,
1378                                    gpointer         func,
1379                                    gpointer         data,
1380                                    void           (*callback) (gpointer instance,
1381                                                                guint    handler_id))
1382 {
1383   HandlerMatch *mlist;
1384   guint n_handlers = 0;
1385   
1386   mlist = handlers_find (instance, mask, signal_id, detail, closure, func, data, FALSE);
1387   while (mlist)
1388     {
1389       n_handlers++;
1390       G_UNLOCK (g_signal_mutex);
1391       callback (instance, mlist->handler->id);
1392       G_LOCK (g_signal_mutex);
1393       mlist = handler_match_free1_R (mlist, instance);
1394     }
1395   
1396   return n_handlers;
1397 }
1398
1399 guint
1400 g_signal_handlers_block_matched (gpointer         instance,
1401                                  GSignalMatchType mask,
1402                                  guint            signal_id,
1403                                  GQuark           detail,
1404                                  GClosure        *closure,
1405                                  gpointer         func,
1406                                  gpointer         data)
1407 {
1408   guint n_handlers = 0;
1409   
1410   g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE);
1411   g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, FALSE);
1412   
1413   if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA))
1414     {
1415       G_LOCK (g_signal_mutex);
1416       n_handlers = signal_handlers_foreach_matched_R (instance, mask, signal_id, detail,
1417                                                       closure, func, data,
1418                                                       g_signal_handler_block);
1419       G_UNLOCK (g_signal_mutex);
1420     }
1421   
1422   return n_handlers;
1423 }
1424
1425 guint
1426 g_signal_handlers_unblock_matched (gpointer         instance,
1427                                    GSignalMatchType mask,
1428                                    guint            signal_id,
1429                                    GQuark           detail,
1430                                    GClosure        *closure,
1431                                    gpointer         func,
1432                                    gpointer         data)
1433 {
1434   guint n_handlers = 0;
1435   
1436   g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE);
1437   g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, FALSE);
1438   
1439   if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA))
1440     {
1441       G_LOCK (g_signal_mutex);
1442       n_handlers = signal_handlers_foreach_matched_R (instance, mask, signal_id, detail,
1443                                                       closure, func, data,
1444                                                       g_signal_handler_unblock);
1445       G_UNLOCK (g_signal_mutex);
1446     }
1447   
1448   return n_handlers;
1449 }
1450
1451 guint
1452 g_signal_handlers_disconnect_matched (gpointer         instance,
1453                                       GSignalMatchType mask,
1454                                       guint            signal_id,
1455                                       GQuark           detail,
1456                                       GClosure        *closure,
1457                                       gpointer         func,
1458                                       gpointer         data)
1459 {
1460   guint n_handlers = 0;
1461   
1462   g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE);
1463   g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, FALSE);
1464   
1465   if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA))
1466     {
1467       G_LOCK (g_signal_mutex);
1468       n_handlers = signal_handlers_foreach_matched_R (instance, mask, signal_id, detail,
1469                                                       closure, func, data,
1470                                                       g_signal_handler_disconnect);
1471       G_UNLOCK (g_signal_mutex);
1472     }
1473   
1474   return n_handlers;
1475 }
1476
1477 gboolean
1478 g_signal_has_handler_pending (gpointer instance,
1479                               guint    signal_id,
1480                               GQuark   detail,
1481                               gboolean may_be_blocked)
1482 {
1483   HandlerMatch *mlist;
1484   gboolean has_pending;
1485   
1486   g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE);
1487   g_return_val_if_fail (signal_id > 0, FALSE);
1488   
1489   G_LOCK (g_signal_mutex);
1490   if (detail)
1491     {
1492       SignalNode *node = LOOKUP_SIGNAL_NODE (signal_id);
1493       
1494       if (!(node->flags & G_SIGNAL_DETAILED))
1495         {
1496           g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
1497           G_UNLOCK (g_signal_mutex);
1498           return FALSE;
1499         }
1500     }
1501   mlist = handlers_find (instance,
1502                          (G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DETAIL | (may_be_blocked ? 0 : G_SIGNAL_MATCH_UNBLOCKED)),
1503                          signal_id, detail, NULL, NULL, NULL, TRUE);
1504   if (mlist)
1505     {
1506       has_pending = TRUE;
1507       handler_match_free1_R (mlist, instance);
1508     }
1509   else
1510     has_pending = FALSE;
1511   G_UNLOCK (g_signal_mutex);
1512   
1513   return has_pending;
1514 }
1515
1516 void
1517 g_signal_emitv (const GValue *instance_and_params,
1518                 guint         signal_id,
1519                 GQuark        detail,
1520                 GValue       *return_value)
1521 {
1522   const GValue *param_values;
1523   gpointer instance;
1524   SignalNode *node;
1525   guint i;
1526   
1527   g_return_if_fail (instance_and_params != NULL);
1528   instance = g_value_get_as_pointer (instance_and_params);
1529   g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1530   g_return_if_fail (signal_id > 0);
1531
1532   param_values = instance_and_params + 1;
1533   
1534   G_LOCK (g_signal_mutex);
1535   node = LOOKUP_SIGNAL_NODE (signal_id);
1536   if (!node || !g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype))
1537     {
1538       g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
1539       G_UNLOCK (g_signal_mutex);
1540       return;
1541     }
1542 #ifndef G_DISABLE_CHECKS
1543   if (detail && !(node->flags & G_SIGNAL_DETAILED))
1544     {
1545       g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
1546       G_UNLOCK (g_signal_mutex);
1547       return;
1548     }
1549   for (i = 0; i < node->n_params; i++)
1550     if (!G_VALUE_HOLDS (param_values + i, node->param_types[i]))
1551       {
1552         g_critical ("%s: value for `%s' parameter %u for signal \"%s\" is of type `%s'",
1553                     G_STRLOC,
1554                     g_type_name (node->param_types[i]),
1555                     i,
1556                     node->name,
1557                     G_VALUE_TYPE_NAME (param_values + i));
1558         G_UNLOCK (g_signal_mutex);
1559         return;
1560       }
1561   if (node->return_type != G_TYPE_NONE)
1562     {
1563       if (!return_value)
1564         {
1565           g_critical ("%s: return value `%s' for signal \"%s\" is (NULL)",
1566                       G_STRLOC,
1567                       g_type_name (node->return_type),
1568                       node->name);
1569           G_UNLOCK (g_signal_mutex);
1570           return;
1571         }
1572       else if (!node->accumulator && !G_VALUE_HOLDS (return_value, node->return_type))
1573         {
1574           g_critical ("%s: return value `%s' for signal \"%s\" is of type `%s'",
1575                       G_STRLOC,
1576                       g_type_name (node->return_type),
1577                       node->name,
1578                       G_VALUE_TYPE_NAME (return_value));
1579           G_UNLOCK (g_signal_mutex);
1580           return;
1581         }
1582     }
1583   else
1584     return_value = NULL;
1585 #endif  /* !G_DISABLE_CHECKS */
1586
1587   signal_emit_R (node, detail, instance, return_value, instance_and_params);
1588   G_UNLOCK (g_signal_mutex);
1589 }
1590
1591 void
1592 g_signal_emit_valist (gpointer instance,
1593                       guint    signal_id,
1594                       GQuark   detail,
1595                       va_list  var_args)
1596 {
1597   GValue *instance_and_params, stack_values[MAX_STACK_VALUES], *free_me = NULL;
1598   GValue *param_values;
1599   SignalNode *node;
1600   guint i;
1601
1602   g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1603   g_return_if_fail (signal_id > 0);
1604
1605   G_LOCK (g_signal_mutex);
1606   node = LOOKUP_SIGNAL_NODE (signal_id);
1607   if (!node || !g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype))
1608     {
1609       g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
1610       G_UNLOCK (g_signal_mutex);
1611       return;
1612     }
1613 #ifndef G_DISABLE_CHECKS
1614   if (detail && !(node->flags & G_SIGNAL_DETAILED))
1615     {
1616       g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
1617       G_UNLOCK (g_signal_mutex);
1618       return;
1619     }
1620 #endif  /* !G_DISABLE_CHECKS */
1621
1622   if (node->n_params < MAX_STACK_VALUES)
1623     instance_and_params = stack_values;
1624   else
1625     {
1626       free_me = g_new (GValue, node->n_params + 1);
1627       instance_and_params = free_me;
1628     }
1629   param_values = instance_and_params + 1;
1630   for (i = 0; i < node->n_params; i++)
1631     {
1632       gchar *error;
1633
1634       param_values[i].g_type = 0;
1635       g_value_init (param_values + i, node->param_types[i]);
1636       G_VALUE_COLLECT (param_values + i, var_args, &error);
1637       if (error)
1638         {
1639           g_warning ("%s: %s", G_STRLOC, error);
1640           g_free (error);
1641
1642           /* we purposely leak the value here, it might not be
1643            * in a sane state if an error condition occoured
1644            */
1645           while (i--)
1646             g_value_unset (param_values + i);
1647
1648           G_UNLOCK (g_signal_mutex);
1649           g_free (free_me);
1650           return;
1651         }
1652     }
1653   instance_and_params->g_type = 0;
1654   g_value_init (instance_and_params, node->itype);
1655   g_value_set_instance (instance_and_params, instance);
1656   if (node->return_type == G_TYPE_NONE)
1657     signal_emit_R (node, detail, instance, NULL, instance_and_params);
1658   else
1659     {
1660       GValue return_value = { 0, };
1661       gchar *error = NULL;
1662
1663       g_value_init (&return_value, node->return_type);
1664       if (signal_emit_R (node, detail, instance, &return_value, instance_and_params))
1665         G_VALUE_LCOPY (&return_value, var_args, &error);
1666       if (!error)
1667         g_value_unset (&return_value);
1668       else
1669         {
1670           g_warning ("%s: %s", G_STRLOC, error);
1671           g_free (error);
1672
1673           /* we purposely leak the value here, it might not be
1674            * in a sane state if an error condition occoured
1675            */
1676         }
1677     }
1678   for (i = 0; i < node->n_params; i++)
1679     g_value_unset (param_values + i);
1680   g_value_unset (instance_and_params);
1681   if (free_me)
1682     g_free (free_me);
1683   G_UNLOCK (g_signal_mutex);
1684 }
1685
1686 void
1687 g_signal_emit (gpointer instance,
1688                guint    signal_id,
1689                GQuark   detail,
1690                ...)
1691 {
1692   va_list var_args;
1693
1694   va_start (var_args, detail);
1695   g_signal_emit_valist (instance, signal_id, detail, var_args);
1696   va_end (var_args);
1697 }
1698
1699 void
1700 g_signal_emit_by_name (gpointer     instance,
1701                        const gchar *detailed_signal,
1702                        ...)
1703 {
1704   GQuark detail = 0;
1705   guint signal_id;
1706
1707   g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1708   g_return_if_fail (detailed_signal != NULL);
1709
1710   G_LOCK (g_signal_mutex);
1711   signal_id = signal_parse_name (detailed_signal, G_TYPE_FROM_INSTANCE (instance), &detail, TRUE);
1712   G_UNLOCK (g_signal_mutex);
1713
1714   if (signal_id)
1715     {
1716       va_list var_args;
1717
1718       va_start (var_args, detailed_signal);
1719       g_signal_emit_valist (instance, signal_id, detail, var_args);
1720       va_end (var_args);
1721     }
1722   else
1723     g_warning ("%s: signal name `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance);
1724 }
1725
1726 static gboolean
1727 signal_emit_R (SignalNode   *node,
1728                GQuark        detail,
1729                gpointer      instance,
1730                GValue       *return_value,
1731                const GValue *instance_and_params)
1732 {
1733   EmissionState emission_state = 0;
1734   GSignalAccumulator accumulator;
1735   GSignalInvocationHint ihint;
1736   GClosure *class_closure;
1737   HandlerList *hlist;
1738   Handler *handler_list = NULL;
1739   GValue accu = { 0, };
1740   gboolean accu_used = FALSE;
1741   guint signal_id = node->signal_id;
1742   gboolean return_value_altered = FALSE;
1743   
1744   if (node->flags & G_SIGNAL_NO_RECURSE)
1745     {
1746       Emission *emission = emission_find (g_restart_emissions, signal_id, detail, instance);
1747       
1748       if (emission)
1749         {
1750           *emission->state_p = EMISSION_RESTART;
1751           return return_value_altered;
1752         }
1753     }
1754   ihint.signal_id = node->signal_id;
1755   ihint.detail = detail;
1756   accumulator = node->accumulator;
1757   if (accumulator)
1758     g_value_init (&accu, node->return_type);
1759   emission_push ((node->flags & G_SIGNAL_NO_RECURSE) ? &g_restart_emissions : &g_recursive_emissions,
1760                  signal_id, detail, instance, &emission_state);
1761   class_closure = node->class_closure;
1762   
1763  EMIT_RESTART:
1764   
1765   if (handler_list)
1766     handler_unref_R (signal_id, instance, handler_list);
1767   hlist = handler_list_lookup (signal_id, instance);
1768   handler_list = hlist ? hlist->handlers : NULL;
1769   if (handler_list)
1770     handler_ref (handler_list);
1771   
1772   ihint.run_type = G_SIGNAL_RUN_FIRST;
1773   
1774   if ((node->flags & G_SIGNAL_RUN_FIRST) && class_closure)
1775     {
1776       emission_state = EMISSION_RUN;
1777       
1778       G_UNLOCK (g_signal_mutex);
1779       if (accumulator)
1780         {
1781           if (accu_used)
1782             g_value_reset (&accu);
1783           g_closure_invoke (class_closure,
1784                             &accu,
1785                             node->n_params + 1,
1786                             instance_and_params,
1787                             &ihint);
1788           if (!accumulator (&ihint, return_value, &accu) &&
1789               emission_state == EMISSION_RUN)
1790             emission_state = EMISSION_STOP;
1791           accu_used = TRUE;
1792         }
1793       else
1794         g_closure_invoke (class_closure,
1795                           return_value,
1796                           node->n_params + 1,
1797                           instance_and_params,
1798                           &ihint);
1799       G_LOCK (g_signal_mutex);
1800       return_value_altered = TRUE;
1801       
1802       if (emission_state == EMISSION_STOP)
1803         goto EMIT_CLEANUP;
1804       else if (emission_state == EMISSION_RESTART)
1805         goto EMIT_RESTART;
1806     }
1807   
1808   if (node->emission_hooks)
1809     {
1810       emission_state = EMISSION_HOOK;
1811       
1812       G_UNLOCK (g_signal_mutex);
1813       g_print ("emission_hooks()\n");
1814       G_LOCK (g_signal_mutex);
1815       
1816       if (emission_state == EMISSION_RESTART)
1817         goto EMIT_RESTART;
1818     }
1819   
1820   if (handler_list)
1821     {
1822       Handler *handler = handler_list;
1823       
1824       emission_state = EMISSION_RUN;
1825       handler_ref (handler);
1826       do
1827         {
1828           Handler *tmp;
1829           
1830           if (handler->after)
1831             {
1832               handler_unref_R (signal_id, instance, handler_list);
1833               handler_list = handler;
1834               break;
1835             }
1836           else if (!handler->block_count && (!handler->detail || handler->detail == detail))
1837             {
1838               G_UNLOCK (g_signal_mutex);
1839               if (accumulator)
1840                 {
1841                   if (accu_used)
1842                     g_value_reset (&accu);
1843                   g_closure_invoke (handler->closure,
1844                                     &accu,
1845                                     node->n_params + 1,
1846                                     instance_and_params,
1847                                     &ihint);
1848                   if (!accumulator (&ihint, return_value, &accu) &&
1849                       emission_state == EMISSION_RUN)
1850                     emission_state = EMISSION_STOP;
1851                   accu_used = TRUE;
1852                 }
1853               else
1854                 g_closure_invoke (handler->closure,
1855                                   return_value,
1856                                   node->n_params + 1,
1857                                   instance_and_params,
1858                                   &ihint);
1859               G_LOCK (g_signal_mutex);
1860               return_value_altered = TRUE;
1861               
1862               tmp = emission_state == EMISSION_RUN ? handler->next : NULL;
1863             }
1864           else
1865             tmp = handler->next;
1866           
1867           if (tmp)
1868             handler_ref (tmp);
1869           handler_unref_R (signal_id, instance, handler_list);
1870           handler_list = handler;
1871           handler = tmp;
1872         }
1873       while (handler);
1874       
1875       if (emission_state == EMISSION_STOP)
1876         goto EMIT_CLEANUP;
1877       else if (emission_state == EMISSION_RESTART)
1878         goto EMIT_RESTART;
1879     }
1880   
1881   ihint.run_type = G_SIGNAL_RUN_LAST;
1882   
1883   if ((node->flags & G_SIGNAL_RUN_LAST) && class_closure)
1884     {
1885       emission_state = EMISSION_RUN;
1886       
1887       G_UNLOCK (g_signal_mutex);
1888       if (accumulator)
1889         {
1890           if (accu_used)
1891             g_value_reset (&accu);
1892           g_closure_invoke (class_closure,
1893                             &accu,
1894                             node->n_params + 1,
1895                             instance_and_params,
1896                             &ihint);
1897           if (!accumulator (&ihint, return_value, &accu) &&
1898               emission_state == EMISSION_RUN)
1899             emission_state = EMISSION_STOP;
1900           accu_used = TRUE;
1901         }
1902       else
1903         g_closure_invoke (class_closure,
1904                           return_value,
1905                           node->n_params + 1,
1906                           instance_and_params,
1907                           &ihint);
1908       G_LOCK (g_signal_mutex);
1909       return_value_altered = TRUE;
1910       
1911       if (emission_state == EMISSION_STOP)
1912         goto EMIT_CLEANUP;
1913       else if (emission_state == EMISSION_RESTART)
1914         goto EMIT_RESTART;
1915     }
1916   
1917   if (handler_list)
1918     {
1919       Handler *handler = handler_list;
1920       
1921       emission_state = EMISSION_RUN;
1922       handler_ref (handler);
1923       do
1924         {
1925           Handler *tmp;
1926           
1927           if (handler->after && !handler->block_count && (!handler->detail || handler->detail == detail))
1928             {
1929               G_UNLOCK (g_signal_mutex);
1930               if (accumulator)
1931                 {
1932                   if (accu_used)
1933                     g_value_reset (&accu);
1934                   g_closure_invoke (handler->closure,
1935                                     &accu,
1936                                     node->n_params + 1,
1937                                     instance_and_params,
1938                                     &ihint);
1939                   if (!accumulator (&ihint, return_value, &accu) &&
1940                       emission_state == EMISSION_RUN)
1941                     emission_state = EMISSION_STOP;
1942                   accu_used = TRUE;
1943                 }
1944               else
1945                 g_closure_invoke (handler->closure,
1946                                   return_value,
1947                                   node->n_params + 1,
1948                                   instance_and_params,
1949                                   &ihint);
1950               G_LOCK (g_signal_mutex);
1951               return_value_altered = TRUE;
1952               
1953               tmp = emission_state == EMISSION_RUN ? handler->next : NULL;
1954             }
1955           else
1956             tmp = handler->next;
1957           
1958           if (tmp)
1959             handler_ref (tmp);
1960           handler_unref_R (signal_id, instance, handler);
1961           handler = tmp;
1962         }
1963       while (handler);
1964       
1965       if (emission_state == EMISSION_STOP)
1966         goto EMIT_CLEANUP;
1967       else if (emission_state == EMISSION_RESTART)
1968         goto EMIT_RESTART;
1969     }
1970   
1971  EMIT_CLEANUP:
1972   
1973   ihint.run_type = G_SIGNAL_RUN_CLEANUP;
1974   
1975   if ((node->flags & G_SIGNAL_RUN_CLEANUP) && class_closure)
1976     {
1977       gboolean need_unset = FALSE;
1978       
1979       emission_state = EMISSION_STOP;
1980       
1981       G_UNLOCK (g_signal_mutex);
1982       if (node->return_type != G_TYPE_NONE)
1983         {
1984           if (!accumulator)
1985             {
1986               g_value_init (&accu, node->return_type);
1987               need_unset = TRUE;
1988             }
1989           else if (accu_used)
1990             g_value_reset (&accu);
1991         }
1992       g_closure_invoke (class_closure,
1993                         node->return_type != G_TYPE_NONE ? &accu : NULL,
1994                         node->n_params + 1,
1995                         instance_and_params,
1996                         &ihint);
1997       if (need_unset)
1998         g_value_unset (&accu);
1999       G_LOCK (g_signal_mutex);
2000       
2001       if (emission_state == EMISSION_RESTART)
2002         goto EMIT_RESTART;
2003     }
2004   
2005   if (handler_list)
2006     handler_unref_R (signal_id, instance, handler_list);
2007   
2008   emission_pop ((node->flags & G_SIGNAL_NO_RECURSE) ? &g_restart_emissions : &g_recursive_emissions, &emission_state);
2009   if (accumulator)
2010     g_value_unset (&accu);
2011
2012   return return_value_altered;
2013 }
2014
2015
2016 /* compile standard marshallers */
2017 #include        "gvaluetypes.h"
2018 #include        "gmarshal.c"