removed archaic gpointer derived_data; relict and added a GData member
[platform/upstream/glib.git] / gobject / gobject.c
1 /* GObject - GLib Type, Object, Parameter and Signal Library
2  * Copyright (C) 1998-1999, 2000-2001 Tim Janik and 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
20 /*
21  * MT safe
22  */
23
24 #include        "gobject.h"
25
26
27 #include        "gvaluecollector.h"
28 #include        "gsignal.h"
29 #include        "gparamspecs.h"
30 #include        "gvaluetypes.h"
31 #include        <string.h>
32
33
34 #define PREALLOC_CPARAMS        (8)
35
36
37 /* --- macros --- */
38 #define PARAM_SPEC_PARAM_ID(pspec)      (GPOINTER_TO_UINT (g_param_spec_get_qdata ((pspec), quark_property_id)))
39
40
41 /* --- signals --- */
42 enum {
43   PROPERTIES_CHANGED,
44   NOTIFY,
45   LAST_SIGNAL
46 };
47
48
49 /* --- properties --- */
50 enum {
51   PROP_NONE
52 };
53
54
55 /* --- typedefs --- */
56 typedef struct _NotifyQueue NotifyQueue;
57
58
59 /* --- prototypes --- */
60 static void     g_object_base_class_init                (GObjectClass   *class);
61 static void     g_object_base_class_finalize            (GObjectClass   *class);
62 static void     g_object_do_class_init                  (GObjectClass   *class);
63 static void     g_object_init                           (GObject        *object);
64 static GObject* g_object_constructor                    (GType                  type,
65                                                          guint                  n_construct_properties,
66                                                          GObjectConstructParam *construct_params);
67 static void     g_object_last_unref                     (GObject        *object);
68 static void     g_object_shutdown                       (GObject        *object);
69 static void     g_object_finalize                       (GObject        *object);
70 static void     g_object_do_set_property                (GObject        *object,
71                                                          guint           property_id,
72                                                          const GValue   *value,
73                                                          GParamSpec     *pspec);
74 static void     g_object_do_get_property                (GObject        *object,
75                                                          guint           property_id,
76                                                          GValue         *value,
77                                                          GParamSpec     *pspec);
78 static void     g_value_object_init                     (GValue         *value);
79 static void     g_value_object_free_value               (GValue         *value);
80 static void     g_value_object_copy_value               (const GValue   *src_value,
81                                                          GValue         *dest_value);
82 static void     g_value_object_transform_value          (const GValue   *src_value,
83                                                          GValue         *dest_value);
84 static gpointer g_value_object_peek_pointer             (const GValue   *value);
85 static gchar*   g_value_object_collect_value            (GValue         *value,
86                                                          guint           n_collect_values,
87                                                          GTypeCValue    *collect_values,
88                                                          guint           collect_flags);
89 static gchar*   g_value_object_lcopy_value              (const GValue   *value,
90                                                          guint           n_collect_values,
91                                                          GTypeCValue    *collect_values,
92                                                          guint           collect_flags);
93 static void     g_object_dispatch_properties_changed    (GObject        *object,
94                                                          guint           n_pspecs,
95                                                          GParamSpec    **pspecs);
96 static void     g_object_properties_changed             (GObject        *object,
97                                                          guint           n_pspecs,
98                                                          GParamSpec    **pspecs);
99 static void     g_object_notify_property_changed        (GObject        *object,
100                                                          GParamSpec     *pspec);
101 static inline NotifyQueue* object_freeze_notifies       (GObject        *object);
102 static inline void         object_queue_property        (GObject        *object,
103                                                          GParamSpec     *pspec,
104                                                          NotifyQueue    *nqueue);
105 static inline void         object_thaw_notifies         (GObject        *object,
106                                                          NotifyQueue    *nqueue);
107 static inline void         object_get_property          (GObject        *object,
108                                                          GParamSpec     *pspec,
109                                                          GValue         *value);
110 static inline void         object_set_property          (GObject        *object,
111                                                          GParamSpec     *pspec,
112                                                          const GValue   *value,
113                                                          NotifyQueue    *nqueue);
114
115
116 /* --- structures --- */
117 struct _NotifyQueue
118 {
119   GSList *pspecs;
120   guint   n_pspecs;
121   guint   freeze_count;
122 };
123
124
125 /* --- variables --- */
126 static GQuark            quark_notify_queue = 0;
127 static GQuark            quark_property_id = 0;
128 static GQuark            quark_closure_array = 0;
129 static GParamSpecPool   *pspec_pool = NULL;
130 static gulong            gobject_signals[LAST_SIGNAL] = { 0, };
131
132
133 /* --- functions --- */
134 #ifdef  G_ENABLE_DEBUG
135 #define IF_DEBUG(debug_type)    if (_g_type_debug_flags & G_TYPE_DEBUG_ ## debug_type)
136 G_LOCK_DEFINE_STATIC     (debug_objects);
137 static volatile GObject *g_trap_object_ref = NULL;
138 static guint             debug_objects_count = 0;
139 static GHashTable       *debug_objects_ht = NULL;
140 static void
141 debug_objects_foreach (gpointer key,
142                        gpointer value,
143                        gpointer user_data)
144 {
145   GObject *object = value;
146
147   g_message ("[%p] stale %s\tref_count=%u",
148              object,
149              G_OBJECT_TYPE_NAME (object),
150              object->ref_count);
151 }
152 static void
153 debug_objects_atexit (void)
154 {
155   IF_DEBUG (OBJECTS)
156     {
157       G_LOCK (debug_objects);
158       if (debug_objects_ht)
159         {
160           g_message ("stale GObjects: %u", debug_objects_count);
161           g_hash_table_foreach (debug_objects_ht, debug_objects_foreach, NULL);
162         }
163       G_UNLOCK (debug_objects);
164     }
165 }
166 #endif  /* G_ENABLE_DEBUG */
167
168 void
169 g_object_type_init (void)       /* sync with gtype.c */
170 {
171   static gboolean initialized = FALSE;
172   static const GTypeFundamentalInfo finfo = {
173     G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE,
174   };
175   static GTypeInfo info = {
176     sizeof (GObjectClass),
177     (GBaseInitFunc) g_object_base_class_init,
178     (GBaseFinalizeFunc) g_object_base_class_finalize,
179     (GClassInitFunc) g_object_do_class_init,
180     NULL        /* class_destroy */,
181     NULL        /* class_data */,
182     sizeof (GObject),
183     0           /* n_preallocs */,
184     (GInstanceInitFunc) g_object_init,
185     NULL,       /* value_table */
186   };
187   static const GTypeValueTable value_table = {
188     g_value_object_init,          /* value_init */
189     g_value_object_free_value,    /* value_free */
190     g_value_object_copy_value,    /* value_copy */
191     g_value_object_peek_pointer,  /* value_peek_pointer */
192     "p",                          /* collect_format */
193     g_value_object_collect_value, /* collect_value */
194     "p",                          /* lcopy_format */
195     g_value_object_lcopy_value,   /* lcopy_value */
196   };
197   GType type;
198   
199   g_return_if_fail (initialized == FALSE);
200   initialized = TRUE;
201   
202   /* G_TYPE_OBJECT
203    */
204   info.value_table = &value_table;
205   type = g_type_register_fundamental (G_TYPE_OBJECT, "GObject", &info, &finfo, 0);
206   g_assert (type == G_TYPE_OBJECT);
207   g_value_register_transform_func (G_TYPE_OBJECT, G_TYPE_OBJECT, g_value_object_transform_value);
208   
209 #ifdef  G_ENABLE_DEBUG
210   IF_DEBUG (OBJECTS)
211     g_atexit (debug_objects_atexit);
212 #endif  /* G_ENABLE_DEBUG */
213 }
214
215 static void
216 g_object_base_class_init (GObjectClass *class)
217 {
218   GObjectClass *pclass = g_type_class_peek_parent (class);
219
220   /* reset instance specific fields and methods that don't get inherited */
221   class->n_property_specs = 0;
222   class->property_specs = NULL;
223   class->construct_properties = pclass ? g_slist_copy (pclass->construct_properties) : NULL;
224   class->get_property = NULL;
225   class->set_property = NULL;
226 }
227
228 static void
229 g_object_base_class_finalize (GObjectClass *class)
230 {
231   guint i;
232   
233   g_message ("finallizing base class of %s", G_OBJECT_CLASS_NAME (class));
234
235   _g_signals_destroy (G_OBJECT_CLASS_TYPE (class));
236
237   g_slist_free (class->construct_properties);
238   class->construct_properties = NULL;
239   for (i = 0; i < class->n_property_specs; i++)
240     {
241       GParamSpec *pspec = class->property_specs[i];
242       
243       g_param_spec_pool_remove (pspec_pool, pspec);
244       g_param_spec_set_qdata (pspec, quark_property_id, NULL);
245       g_param_spec_unref (pspec);
246     }
247   class->n_property_specs = 0;
248   g_free (class->property_specs);
249   class->property_specs = NULL;
250 }
251
252 static void
253 g_object_do_class_init (GObjectClass *class)
254 {
255   quark_notify_queue = g_quark_from_static_string ("GObject-notify-queue");
256   quark_property_id = g_quark_from_static_string ("GObject-property-id");
257   quark_closure_array = g_quark_from_static_string ("GObject-closure-array");
258   pspec_pool = g_param_spec_pool_new (TRUE);
259   
260   class->constructor = g_object_constructor;
261   class->set_property = g_object_do_set_property;
262   class->get_property = g_object_do_get_property;
263   class->shutdown = g_object_shutdown;
264   class->finalize = g_object_finalize;
265   class->dispatch_properties_changed = g_object_dispatch_properties_changed;
266   class->properties_changed = g_object_properties_changed;
267   class->notify = g_object_notify_property_changed;
268
269   gobject_signals[PROPERTIES_CHANGED] =
270     g_signal_newc ("properties_changed",
271                    G_TYPE_FROM_CLASS (class),
272                    G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE,
273                    G_STRUCT_OFFSET (GObjectClass, properties_changed),
274                    NULL, NULL,
275                    g_cclosure_marshal_VOID__UINT_POINTER,
276                    G_TYPE_NONE,
277                    2, G_TYPE_UINT, G_TYPE_POINTER);
278   gobject_signals[NOTIFY] =
279     g_signal_newc ("notify",
280                    G_TYPE_FROM_CLASS (class),
281                    G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE | G_SIGNAL_DETAILED | G_SIGNAL_NO_HOOKS,
282                    G_STRUCT_OFFSET (GObjectClass, notify),
283                    NULL, NULL,
284                    g_cclosure_marshal_VOID__PARAM,
285                    G_TYPE_NONE,
286                    1, G_TYPE_PARAM);
287 }
288
289 void
290 g_object_class_install_property (GObjectClass *class,
291                                  guint         property_id,
292                                  GParamSpec   *pspec)
293 {
294   guint i;
295   
296   g_return_if_fail (G_IS_OBJECT_CLASS (class));
297   g_return_if_fail (G_IS_PARAM_SPEC (pspec));
298   if (pspec->flags & G_PARAM_WRITABLE)
299     g_return_if_fail (class->set_property != NULL);
300   if (pspec->flags & G_PARAM_READABLE)
301     g_return_if_fail (class->get_property != NULL);
302   g_return_if_fail (property_id > 0);
303   g_return_if_fail (PARAM_SPEC_PARAM_ID (pspec) == 0);  /* paranoid */
304   if (pspec->flags & G_PARAM_CONSTRUCT)
305     g_return_if_fail ((pspec->flags & G_PARAM_CONSTRUCT_ONLY) == 0);
306   if (pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY))
307     g_return_if_fail (pspec->flags & G_PARAM_WRITABLE);
308
309   /* expensive paranoia checks ;( */
310   for (i = 0; i < class->n_property_specs; i++)
311     if (PARAM_SPEC_PARAM_ID (class->property_specs[i]) == property_id)
312       {
313         g_warning (G_STRLOC ": class `%s' already contains a property `%s' with id %u, "
314                    "cannot install property `%s'",
315                    G_OBJECT_CLASS_NAME (class),
316                    class->property_specs[i]->name,
317                    property_id,
318                    pspec->name);
319         return;
320       }
321   if (g_param_spec_pool_lookup (pspec_pool, pspec->name, G_OBJECT_CLASS_TYPE (class), FALSE))
322     {
323       g_warning (G_STRLOC ": class `%s' already contains a property named `%s'",
324                  G_OBJECT_CLASS_NAME (class),
325                  pspec->name);
326       return;
327     }
328
329   g_param_spec_ref (pspec);
330   g_param_spec_sink (pspec);
331   g_param_spec_set_qdata (pspec, quark_property_id, GUINT_TO_POINTER (property_id));
332   g_param_spec_pool_insert (pspec_pool, pspec, G_OBJECT_CLASS_TYPE (class));
333   i = class->n_property_specs++;
334   class->property_specs = g_renew (GParamSpec*, class->property_specs, class->n_property_specs);
335   class->property_specs[i] = pspec;
336   if (pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY))
337     class->construct_properties = g_slist_prepend (class->construct_properties, pspec);
338
339   /* for property overrides of construct poperties, we have to get rid
340    * of the overidden inherited construct property
341    */
342   pspec = g_param_spec_pool_lookup (pspec_pool, pspec->name, g_type_parent (G_OBJECT_CLASS_TYPE (class)), TRUE);
343   if (pspec && pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY))
344     class->construct_properties = g_slist_remove (class->construct_properties, pspec);
345 }
346
347 GParamSpec*
348 g_object_class_find_property (GObjectClass *class,
349                               const gchar  *property_name)
350 {
351   g_return_val_if_fail (G_IS_OBJECT_CLASS (class), NULL);
352   g_return_val_if_fail (property_name != NULL, NULL);
353   
354   return g_param_spec_pool_lookup (pspec_pool,
355                                    property_name,
356                                    G_OBJECT_CLASS_TYPE (class),
357                                    TRUE);
358 }
359
360 static void
361 free_notify_queue (gpointer data)
362 {
363   NotifyQueue *nqueue = data;
364   
365   g_slist_free (nqueue->pspecs);
366   g_free (nqueue);
367 }
368
369 static inline NotifyQueue*
370 object_freeze_notifies (GObject *object)
371 {
372   NotifyQueue *nqueue;
373
374   nqueue = g_object_get_qdata (object, quark_notify_queue);
375   if (!nqueue)
376     {
377       nqueue = g_new0 (NotifyQueue, 1);
378       g_object_set_qdata_full (object, quark_notify_queue, nqueue, free_notify_queue);
379     }
380   nqueue->freeze_count++;
381
382   return nqueue;
383 }
384
385 static inline void
386 object_queue_property (GObject     *object,
387                        GParamSpec  *pspec,
388                        NotifyQueue *nqueue)
389 {
390   /* we will dedup later */
391   nqueue->pspecs = g_slist_prepend (nqueue->pspecs, pspec);
392   nqueue->n_pspecs++;
393 }
394
395 static void
396 g_object_init (GObject *object)
397 {
398   object->ref_count = 1;
399   g_datalist_init (&object->qdata);
400   
401   /* freeze object's notification queue, g_object_new_valist() takes care of that */
402   object_freeze_notifies (object);
403   
404 #ifdef  G_ENABLE_DEBUG
405   IF_DEBUG (OBJECTS)
406     {
407       G_LOCK (debug_objects);
408       if (!debug_objects_ht)
409         debug_objects_ht = g_hash_table_new (g_direct_hash, NULL);
410       debug_objects_count++;
411       g_hash_table_insert (debug_objects_ht, object, object);
412       G_UNLOCK (debug_objects);
413     }
414 #endif  /* G_ENABLE_DEBUG */
415 }
416
417 static void
418 g_object_do_set_property (GObject      *object,
419                           guint         property_id,
420                           const GValue *value,
421                           GParamSpec   *pspec)
422 {
423   switch (property_id)
424     {
425     default:
426       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
427       break;
428     }
429 }
430
431 static void
432 g_object_do_get_property (GObject     *object,
433                           guint        property_id,
434                           GValue      *value,
435                           GParamSpec  *pspec)
436 {
437   switch (property_id)
438     {
439     default:
440       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
441       break;
442     }
443 }
444
445 static void
446 g_object_last_unref (GObject *object)
447 {
448   g_return_if_fail (object->ref_count > 0);
449   
450   if (object->ref_count == 1)   /* may have been re-referenced meanwhile */
451     G_OBJECT_GET_CLASS (object)->shutdown (object);
452   
453 #ifdef  G_ENABLE_DEBUG
454   if (g_trap_object_ref == object)
455     G_BREAKPOINT ();
456 #endif  /* G_ENABLE_DEBUG */
457
458   object->ref_count -= 1;
459   
460   if (object->ref_count == 0)   /* may have been re-referenced meanwhile */
461     {
462       g_signal_handlers_destroy (object);
463       g_object_set_qdata (object, quark_closure_array, NULL);
464       G_OBJECT_GET_CLASS (object)->finalize (object);
465 #ifdef  G_ENABLE_DEBUG
466       IF_DEBUG (OBJECTS)
467         {
468           G_LOCK (debug_objects);
469           if (debug_objects_ht)
470             g_assert (g_hash_table_lookup (debug_objects_ht, object) == NULL);
471           G_UNLOCK (debug_objects);
472         }
473 #endif  /* G_ENABLE_DEBUG */
474       g_type_free_instance ((GTypeInstance*) object);
475     }
476 }
477
478 static void
479 g_object_shutdown (GObject *object)
480 {
481   /* this function needs to be always present for unconditional
482    * chaining, we also might add some code here later.
483    * beware though, subclasses may invoke shutdown() arbitrarily.
484    */
485 }
486
487 static void
488 g_object_finalize (GObject *object)
489 {
490   g_signal_handlers_destroy (object);
491   g_datalist_clear (&object->qdata);
492   
493 #ifdef  G_ENABLE_DEBUG
494   IF_DEBUG (OBJECTS)
495     {
496       G_LOCK (debug_objects);
497       g_assert (g_hash_table_lookup (debug_objects_ht, object) == object);
498       g_hash_table_remove (debug_objects_ht, object);
499       debug_objects_count--;
500       G_UNLOCK (debug_objects);
501     }
502 #endif  /* G_ENABLE_DEBUG */
503 }
504
505 static inline void
506 object_thaw_notifies (GObject     *object,
507                       NotifyQueue *nqueue)
508 {
509   GParamSpec **pspecs;
510   GSList *slist;
511   guint n_pspecs = 0;
512   
513   nqueue->freeze_count--;
514   if (nqueue->freeze_count)
515     return;
516   g_return_if_fail (object->ref_count > 0);
517   
518   pspecs = g_new (GParamSpec*, nqueue->n_pspecs);
519   for (slist = nqueue->pspecs; slist; slist = slist->next)
520     {
521       GParamSpec *pspec = slist->data;
522       gint i = 0;
523       
524       /* dedup, make pspecs in the list unique */
525     redo_dedup_check:
526       if (pspecs[i] == pspec)
527         continue;
528       if (++i < n_pspecs)
529         goto redo_dedup_check;
530       
531       pspecs[n_pspecs++] = pspec;
532     }
533   g_object_set_qdata (object, quark_notify_queue, NULL);
534   
535   if (n_pspecs)
536     G_OBJECT_GET_CLASS (object)->dispatch_properties_changed (object, n_pspecs, pspecs);
537   
538   g_free (pspecs);
539 }
540
541 static void
542 g_object_dispatch_properties_changed (GObject     *object,
543                                       guint        n_pspecs,
544                                       GParamSpec **pspecs)
545 {
546   g_signal_emit (object, gobject_signals[PROPERTIES_CHANGED], 0, n_pspecs, pspecs);
547 }
548
549 static void
550 g_object_properties_changed (GObject     *object,
551                              guint        n_pspecs,
552                              GParamSpec **pspecs)
553 {
554   guint i;
555
556   for (i = 0; i < n_pspecs; i++)
557     g_signal_emit (object, gobject_signals[NOTIFY], g_quark_from_string (pspecs[i]->name), pspecs[i]);
558 }
559
560 static void
561 g_object_notify_property_changed (GObject    *object,
562                                   GParamSpec *pspec)
563 {
564   if (0) /* FIXME */
565     g_message ("NOTIFICATION: property `%s' changed on object `%s'",
566                pspec->name,
567                G_OBJECT_TYPE_NAME (object));
568 }
569
570 void
571 g_object_freeze_notify (GObject *object)
572 {
573   g_return_if_fail (G_IS_OBJECT (object));
574   if (!object->ref_count)
575     return;
576
577   g_object_ref (object);
578   object_freeze_notifies (object);
579   g_object_unref (object);
580 }
581
582 void
583 g_object_notify (GObject     *object,
584                  const gchar *property_name)
585 {
586   GParamSpec *pspec;
587   
588   g_return_if_fail (G_IS_OBJECT (object));
589   g_return_if_fail (property_name != NULL);
590   if (!object->ref_count)
591     return;
592   
593   g_object_ref (object);
594   pspec = g_param_spec_pool_lookup (pspec_pool,
595                                     property_name,
596                                     G_OBJECT_TYPE (object),
597                                     TRUE);
598   if (!pspec)
599     g_warning ("%s: object class `%s' has no property named `%s'",
600                G_STRLOC,
601                G_OBJECT_TYPE_NAME (object),
602                property_name);
603   else
604     {
605       NotifyQueue *nqueue = object_freeze_notifies (object);
606
607       object_queue_property (object, pspec, nqueue);
608       object_thaw_notifies (object, nqueue);
609     }
610   g_object_unref (object);
611 }
612
613 void
614 g_object_thaw_notify (GObject *object)
615 {
616   NotifyQueue *nqueue;
617   
618   g_return_if_fail (G_IS_OBJECT (object));
619   if (!object->ref_count)
620     return;
621   
622   g_object_ref (object);
623   nqueue = g_object_get_qdata (object, quark_notify_queue);
624   if (!nqueue || !nqueue->freeze_count)
625     g_warning (G_STRLOC ": property-changed notification for %s(%p) is not frozen",
626                G_OBJECT_TYPE_NAME (object), object);
627   else
628     object_thaw_notifies (object, nqueue);
629   g_object_unref (object);
630 }
631
632 static inline void
633 object_get_property (GObject     *object,
634                      GParamSpec  *pspec,
635                      GValue      *value)
636 {
637   GObjectClass *class;
638   
639   class = g_type_class_peek (pspec->owner_type);
640   
641   class->get_property (object, PARAM_SPEC_PARAM_ID (pspec), value, pspec);
642 }
643
644 static inline void
645 object_set_property (GObject      *object,
646                      GParamSpec   *pspec,
647                      const GValue *value,
648                      NotifyQueue  *nqueue)
649 {
650   GValue tmp_value = { 0, };
651   GObjectClass *class = g_type_class_peek (pspec->owner_type);
652
653   /* provide a copy to work from, convert (if necessary) and validate */
654   g_value_init (&tmp_value, G_PARAM_SPEC_VALUE_TYPE (pspec));
655   if (!g_value_transform (value, &tmp_value))
656     g_warning ("unable to set property `%s' of type `%s' from value of type `%s'",
657                pspec->name,
658                g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)),
659                G_VALUE_TYPE_NAME (value));
660   else if (g_param_value_validate (pspec, &tmp_value) && !(pspec->flags & G_PARAM_LAX_VALIDATION))
661     {
662       gchar *contents = g_strdup_value_contents (value);
663
664       g_warning ("value \"%s\" of type `%s' is invalid for property `%s' of type `%s'",
665                  contents,
666                  G_VALUE_TYPE_NAME (value),
667                  pspec->name,
668                  g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)));
669       g_free (contents);
670     }
671   else
672     {
673       class->set_property (object, PARAM_SPEC_PARAM_ID (pspec), &tmp_value, pspec);
674       object_queue_property (object, pspec, nqueue);
675     }
676   g_value_unset (&tmp_value);
677 }
678
679 gpointer
680 g_object_new (GType        object_type,
681               const gchar *first_property_name,
682               ...)
683 {
684   GObject *object;
685   va_list var_args;
686   
687   g_return_val_if_fail (G_TYPE_IS_OBJECT (object_type), NULL);
688   
689   va_start (var_args, first_property_name);
690   object = g_object_new_valist (object_type, first_property_name, var_args);
691   va_end (var_args);
692   
693   return object;
694 }
695
696 gpointer
697 g_object_new_valist (GType        object_type,
698                      const gchar *first_property_name,
699                      va_list      var_args)
700 {
701   NotifyQueue *nqueue;
702   GObject *object;
703   GObjectClass *class;
704   const gchar *name;
705   GObjectConstructParam *cparams = NULL, *nparams = NULL;
706   guint n_cparams = 0, n_nparams = 0;
707   GSList *clist;
708   
709   g_return_val_if_fail (G_TYPE_IS_OBJECT (object_type), NULL);
710
711   class = g_type_class_ref (object_type);
712   clist = g_slist_copy (class->construct_properties);
713
714   /* collect parameters, sort into construction and normal ones */
715   name = first_property_name;
716   while (name)
717     {
718       GValue *value;
719       GParamSpec *pspec;
720       gchar *error = NULL;
721       
722       pspec = g_param_spec_pool_lookup (pspec_pool,
723                                         name,
724                                         object_type,
725                                         TRUE);
726       if (!pspec)
727         {
728           g_warning ("%s: object class `%s' has no property named `%s'",
729                      G_STRLOC,
730                      g_type_name (object_type),
731                      name);
732           break;
733         }
734       if (!(pspec->flags & G_PARAM_WRITABLE))
735         {
736           g_warning ("%s: property `%s' of object class `%s' is not writable",
737                      G_STRLOC,
738                      pspec->name,
739                      g_type_name (object_type));
740           break;
741         }
742
743       value = g_new (GValue, 1);
744       value->g_type = 0;
745       g_value_init (value, G_PARAM_SPEC_VALUE_TYPE (pspec));
746       G_VALUE_COLLECT (value, var_args, 0, &error);
747       if (error)
748         {
749           g_warning ("%s: %s", G_STRLOC, error);
750           g_free (error);
751
752           /* we purposely leak the value here, it might not be
753            * in a sane state if an error condition occoured
754            */
755           break;
756         }
757       if (pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY))
758         {
759           guint i;
760
761           if (!n_cparams || n_cparams >= PREALLOC_CPARAMS)
762             cparams = g_renew (GObjectConstructParam, cparams, MAX (n_cparams + 1, PREALLOC_CPARAMS));
763           cparams[n_cparams].pspec = pspec;
764           cparams[n_cparams].value = value;
765           for (i = 0; i < n_cparams; i++)       /* picky, aren't we? ;) */
766             if (cparams[i].pspec == pspec)
767               g_warning (G_STRLOC ": construct property \"%s\" for object `%s' is being set twice",
768                          pspec->name, g_type_name (object_type));
769           n_cparams++;
770           clist = g_slist_remove (clist, pspec);   /* FIXME: unique */
771         }
772       else
773         {
774           if (!n_nparams || n_nparams >= PREALLOC_CPARAMS)
775             nparams = g_renew (GObjectConstructParam, nparams, MAX (n_nparams + 1, PREALLOC_CPARAMS));
776           nparams[n_nparams].pspec = pspec;
777           nparams[n_nparams].value = value;
778           n_nparams++;
779         }
780
781       name = va_arg (var_args, gchar*);
782     }
783
784   /* construct object from construction parameters */
785   while (clist)
786     {
787       GSList *tmp = clist->next;
788       GParamSpec *pspec = clist->data;
789       GValue *value = g_new (GValue, 1);
790
791       value->g_type = 0;
792       g_value_init (value, G_PARAM_SPEC_VALUE_TYPE (pspec));
793       g_param_value_set_default (pspec, value);
794
795       if (!n_cparams || n_cparams >= PREALLOC_CPARAMS)
796         cparams = g_renew (GObjectConstructParam, cparams, MAX (n_cparams + 1, PREALLOC_CPARAMS));
797       cparams[n_cparams].pspec = pspec;
798       cparams[n_cparams].value = value;
799       n_cparams++;
800
801       g_slist_free_1 (clist);
802       clist = tmp;
803     }
804   object = class->constructor (object_type, n_cparams, cparams);
805
806   /* free construction values */
807   while (n_cparams--)
808     {
809       g_value_unset (cparams[n_cparams].value);
810       g_free (cparams[n_cparams].value);
811     }
812   g_free (cparams);
813   
814   /* release g_object_init() notification queue freeze_count */
815   nqueue = object_freeze_notifies (object);
816   nqueue->freeze_count--;
817   
818   /* set remaining properties */
819   cparams = nparams;
820   while (n_nparams--)
821     {
822       GValue *value = nparams->value;
823       GParamSpec *pspec = nparams->pspec;
824
825       nparams++;
826       object_set_property (object, pspec, value, nqueue);
827       g_value_unset (value);
828       g_free (value);
829     }
830   g_free (cparams);
831
832   g_type_class_unref (class);
833
834   /* release our own freeze count and handle notifications */
835   object_thaw_notifies (object, nqueue);
836   
837   return object;
838 }
839
840 static GObject*
841 g_object_constructor (GType                  type,
842                       guint                  n_construct_properties,
843                       GObjectConstructParam *construct_params)
844 {
845   GObject *object;
846
847   /* create object */
848   object = (GObject*) g_type_create_instance (type);
849
850   /* set construction parameters */
851   if (n_construct_properties)
852     {
853       NotifyQueue *nqueue = object_freeze_notifies (object);
854       
855       /* set construct properties */
856       while (n_construct_properties--)
857         {
858           GValue *value = construct_params->value;
859           GParamSpec *pspec = construct_params->pspec;
860
861           construct_params++;
862           object_set_property (object, pspec, value, nqueue);
863         }
864       nqueue->freeze_count--;
865       /* the notification queue is still frozen from g_object_init(), so
866        * we don't need to handle it here, g_object_new_valist() takes
867        * care of that
868        */
869     }
870
871   return object;
872 }
873
874 void
875 g_object_set_valist (GObject     *object,
876                      const gchar *first_property_name,
877                      va_list      var_args)
878 {
879   NotifyQueue *nqueue;
880   const gchar *name;
881   
882   g_return_if_fail (G_IS_OBJECT (object));
883   
884   g_object_ref (object);
885   nqueue = object_freeze_notifies (object);
886   
887   name = first_property_name;
888   while (name)
889     {
890       GValue value = { 0, };
891       GParamSpec *pspec;
892       gchar *error = NULL;
893       
894       pspec = g_param_spec_pool_lookup (pspec_pool,
895                                         name,
896                                         G_OBJECT_TYPE (object),
897                                         TRUE);
898       if (!pspec)
899         {
900           g_warning ("%s: object class `%s' has no property named `%s'",
901                      G_STRLOC,
902                      G_OBJECT_TYPE_NAME (object),
903                      name);
904           break;
905         }
906       if (!(pspec->flags & G_PARAM_WRITABLE))
907         {
908           g_warning ("%s: property `%s' of object class `%s' is not writable",
909                      G_STRLOC,
910                      pspec->name,
911                      G_OBJECT_TYPE_NAME (object));
912           break;
913         }
914       
915       g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
916       
917       G_VALUE_COLLECT (&value, var_args, 0, &error);
918       if (error)
919         {
920           g_warning ("%s: %s", G_STRLOC, error);
921           g_free (error);
922           
923           /* we purposely leak the value here, it might not be
924            * in a sane state if an error condition occoured
925            */
926           break;
927         }
928       
929       object_set_property (object, pspec, &value, nqueue);
930       g_value_unset (&value);
931       
932       name = va_arg (var_args, gchar*);
933     }
934
935   object_thaw_notifies (object, nqueue);
936   g_object_unref (object);
937 }
938
939 void
940 g_object_get_valist (GObject     *object,
941                      const gchar *first_property_name,
942                      va_list      var_args)
943 {
944   const gchar *name;
945   
946   g_return_if_fail (G_IS_OBJECT (object));
947   
948   g_object_ref (object);
949   
950   name = first_property_name;
951   
952   while (name)
953     {
954       GValue value = { 0, };
955       GParamSpec *pspec;
956       gchar *error;
957       
958       pspec = g_param_spec_pool_lookup (pspec_pool,
959                                         name,
960                                         G_OBJECT_TYPE (object),
961                                         TRUE);
962       if (!pspec)
963         {
964           g_warning ("%s: object class `%s' has no property named `%s'",
965                      G_STRLOC,
966                      G_OBJECT_TYPE_NAME (object),
967                      name);
968           break;
969         }
970       if (!(pspec->flags & G_PARAM_READABLE))
971         {
972           g_warning ("%s: property `%s' of object class `%s' is not readable",
973                      G_STRLOC,
974                      pspec->name,
975                      G_OBJECT_TYPE_NAME (object));
976           break;
977         }
978       
979       g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
980       
981       object_get_property (object, pspec, &value);
982       
983       G_VALUE_LCOPY (&value, var_args, G_VALUE_NOCOPY_CONTENTS, &error);
984       if (error)
985         {
986           g_warning ("%s: %s", G_STRLOC, error);
987           g_free (error);
988           g_value_unset (&value);
989           break;
990         }
991       
992       g_value_unset (&value);
993       
994       name = va_arg (var_args, gchar*);
995     }
996   
997   g_object_unref (object);
998 }
999
1000 gpointer
1001 g_object_set (gpointer     _object,
1002               const gchar *first_property_name,
1003               ...)
1004 {
1005   GObject *object = _object;
1006   va_list var_args;
1007   
1008   g_return_val_if_fail (G_IS_OBJECT (object), NULL);
1009   
1010   va_start (var_args, first_property_name);
1011   g_object_set_valist (object, first_property_name, var_args);
1012   va_end (var_args);
1013
1014   return object;
1015 }
1016
1017 void
1018 g_object_get (gpointer     _object,
1019               const gchar *first_property_name,
1020               ...)
1021 {
1022   GObject *object = _object;
1023   va_list var_args;
1024   
1025   g_return_if_fail (G_IS_OBJECT (object));
1026   
1027   va_start (var_args, first_property_name);
1028   g_object_get_valist (object, first_property_name, var_args);
1029   va_end (var_args);
1030 }
1031
1032 void
1033 g_object_set_property (GObject      *object,
1034                        const gchar  *property_name,
1035                        const GValue *value)
1036 {
1037   NotifyQueue *nqueue;
1038   GParamSpec *pspec;
1039   
1040   g_return_if_fail (G_IS_OBJECT (object));
1041   g_return_if_fail (property_name != NULL);
1042   g_return_if_fail (G_IS_VALUE (value));
1043   
1044   g_object_ref (object);
1045   nqueue = object_freeze_notifies (object);
1046   
1047   pspec = g_param_spec_pool_lookup (pspec_pool,
1048                                     property_name,
1049                                     G_OBJECT_TYPE (object),
1050                                     TRUE);
1051   if (!pspec)
1052     g_warning ("%s: object class `%s' has no property named `%s'",
1053                G_STRLOC,
1054                G_OBJECT_TYPE_NAME (object),
1055                property_name);
1056   else
1057     object_set_property (object, pspec, value, nqueue);
1058   
1059   object_thaw_notifies (object, nqueue);
1060   g_object_unref (object);
1061 }
1062
1063 void
1064 g_object_get_property (GObject     *object,
1065                        const gchar *property_name,
1066                        GValue      *value)
1067 {
1068   GParamSpec *pspec;
1069   
1070   g_return_if_fail (G_IS_OBJECT (object));
1071   g_return_if_fail (property_name != NULL);
1072   g_return_if_fail (G_IS_VALUE (value));
1073   
1074   g_object_ref (object);
1075   
1076   pspec = g_param_spec_pool_lookup (pspec_pool,
1077                                     property_name,
1078                                     G_OBJECT_TYPE (object),
1079                                     TRUE);
1080   if (!pspec)
1081     g_warning ("%s: object class `%s' has no property named `%s'",
1082                G_STRLOC,
1083                G_OBJECT_TYPE_NAME (object),
1084                property_name);
1085   else
1086     {
1087       GValue *prop_value, tmp_value = { 0, };
1088       
1089       /* auto-conversion of the callers value type
1090        */
1091       if (G_VALUE_TYPE (value) == G_PARAM_SPEC_VALUE_TYPE (pspec))
1092         {
1093           g_value_reset (value);
1094           prop_value = value;
1095         }
1096       else if (!g_value_type_transformable (G_PARAM_SPEC_VALUE_TYPE (pspec), G_VALUE_TYPE (value)))
1097         {
1098           g_warning ("can't retrive property `%s' of type `%s' as value of type `%s'",
1099                      pspec->name,
1100                      g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)),
1101                      G_VALUE_TYPE_NAME (value));
1102           g_object_unref (object);
1103           return;
1104         }
1105       else
1106         {
1107           g_value_init (&tmp_value, G_PARAM_SPEC_VALUE_TYPE (pspec));
1108           prop_value = &tmp_value;
1109         }
1110       object_get_property (object, pspec, prop_value);
1111       if (prop_value != value)
1112         {
1113           g_value_transform (prop_value, value);
1114           g_value_unset (&tmp_value);
1115         }
1116     }
1117   
1118   g_object_unref (object);
1119 }
1120
1121 gpointer
1122 g_object_connect (gpointer     _object,
1123                   const gchar *signal_spec,
1124                   ...)
1125 {
1126   GObject *object = _object;
1127   va_list var_args;
1128
1129   g_return_val_if_fail (G_IS_OBJECT (object), NULL);
1130   g_return_val_if_fail (object->ref_count > 0, object);
1131
1132   va_start (var_args, signal_spec);
1133   while (signal_spec)
1134     {
1135       gpointer callback = va_arg (var_args, gpointer);
1136       gpointer data = va_arg (var_args, gpointer);
1137       guint sid;
1138
1139       if (strncmp (signal_spec, "signal::", 8) == 0)
1140         sid = g_signal_connect_data (object, signal_spec + 8,
1141                                      callback, data, NULL,
1142                                      FALSE, FALSE);
1143       else if (strncmp (signal_spec, "swapped_signal::", 16) == 0)
1144         sid = g_signal_connect_data (object, signal_spec + 16,
1145                                      callback, data, NULL,
1146                                      TRUE, FALSE);
1147       else if (strncmp (signal_spec, "signal_after::", 14) == 0)
1148         sid = g_signal_connect_data (object, signal_spec + 14,
1149                                      callback, data, NULL,
1150                                      FALSE, TRUE);
1151       else if (strncmp (signal_spec, "swapped_signal_after::", 22) == 0)
1152         sid = g_signal_connect_data (object, signal_spec + 22,
1153                                      callback, data, NULL,
1154                                      TRUE, TRUE);
1155       else
1156         {
1157           g_warning ("%s: invalid signal spec \"%s\"", G_STRLOC, signal_spec);
1158           break;
1159         }
1160       signal_spec = va_arg (var_args, gchar*);
1161     }
1162   va_end (var_args);
1163
1164   return object;
1165 }
1166
1167 gpointer
1168 g_object_disconnect (gpointer     _object,
1169                      const gchar *signal_spec,
1170                      ...)
1171 {
1172   GObject *object = _object;
1173   va_list var_args;
1174
1175   g_return_val_if_fail (G_IS_OBJECT (object), NULL);
1176   g_return_val_if_fail (object->ref_count > 0, object);
1177
1178   va_start (var_args, signal_spec);
1179   while (signal_spec)
1180     {
1181       gpointer callback = va_arg (var_args, gpointer);
1182       gpointer data = va_arg (var_args, gpointer);
1183       guint sid = 0, detail = 0, mask = 0;
1184
1185       if (strncmp (signal_spec, "any_signal::", 12) == 0)
1186         {
1187           signal_spec += 12;
1188           mask = G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA;
1189         }
1190       else if (strcmp (signal_spec, "any_signal") == 0)
1191         {
1192           signal_spec += 10;
1193           mask = G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA;
1194         }
1195       else
1196         {
1197           g_warning ("%s: invalid signal spec \"%s\"", G_STRLOC, signal_spec);
1198           break;
1199         }
1200
1201       if ((mask & G_SIGNAL_MATCH_ID) &&
1202           !g_signal_parse_name (signal_spec, G_OBJECT_TYPE (object), &sid, &detail, FALSE))
1203         g_warning ("%s: invalid signal name \"%s\"", G_STRLOC, signal_spec);
1204       else if (!g_signal_handlers_disconnect_matched (object, mask | (detail ? G_SIGNAL_MATCH_DETAIL : 0),
1205                                                       sid, detail,
1206                                                       NULL, callback, data))
1207         g_warning (G_STRLOC ": signal handler %p(%p) is not connected", callback, data);
1208       signal_spec = va_arg (var_args, gchar*);
1209     }
1210   va_end (var_args);
1211
1212   return object;
1213 }
1214
1215 gpointer
1216 g_object_ref (gpointer _object)
1217 {
1218   GObject *object = _object;
1219
1220   g_return_val_if_fail (G_IS_OBJECT (object), NULL);
1221   g_return_val_if_fail (object->ref_count > 0, NULL);
1222   
1223 #ifdef  G_ENABLE_DEBUG
1224   if (g_trap_object_ref == object)
1225     G_BREAKPOINT ();
1226 #endif  /* G_ENABLE_DEBUG */
1227
1228   object->ref_count += 1;
1229   
1230   return object;
1231 }
1232
1233 void
1234 g_object_unref (gpointer _object)
1235 {
1236   GObject *object = _object;
1237
1238   g_return_if_fail (G_IS_OBJECT (object));
1239   g_return_if_fail (object->ref_count > 0);
1240   
1241 #ifdef  G_ENABLE_DEBUG
1242   if (g_trap_object_ref == object)
1243     G_BREAKPOINT ();
1244 #endif  /* G_ENABLE_DEBUG */
1245
1246   if (object->ref_count > 1)
1247     object->ref_count -= 1;
1248   else
1249     g_object_last_unref (object);
1250 }
1251
1252 gpointer
1253 g_object_get_qdata (GObject *object,
1254                     GQuark   quark)
1255 {
1256   g_return_val_if_fail (G_IS_OBJECT (object), NULL);
1257   
1258   return quark ? g_datalist_id_get_data (&object->qdata, quark) : NULL;
1259 }
1260
1261 void
1262 g_object_set_qdata (GObject *object,
1263                     GQuark   quark,
1264                     gpointer data)
1265 {
1266   g_return_if_fail (G_IS_OBJECT (object));
1267   g_return_if_fail (quark > 0);
1268   
1269   g_datalist_id_set_data (&object->qdata, quark, data);
1270 }
1271
1272 void
1273 g_object_set_qdata_full (GObject       *object,
1274                          GQuark         quark,
1275                          gpointer       data,
1276                          GDestroyNotify destroy)
1277 {
1278   g_return_if_fail (G_IS_OBJECT (object));
1279   g_return_if_fail (quark > 0);
1280   
1281   g_datalist_id_set_data_full (&object->qdata, quark, data, data ? destroy : NULL);
1282 }
1283
1284 gpointer
1285 g_object_steal_qdata (GObject *object,
1286                       GQuark   quark)
1287 {
1288   g_return_val_if_fail (G_IS_OBJECT (object), NULL);
1289   g_return_val_if_fail (quark > 0, NULL);
1290   
1291   return g_datalist_id_remove_no_notify (&object->qdata, quark);
1292 }
1293
1294 gpointer
1295 g_object_get_data (GObject     *object,
1296                    const gchar *key)
1297 {
1298   GQuark quark;
1299
1300   g_return_val_if_fail (G_IS_OBJECT (object), NULL);
1301   g_return_val_if_fail (key != NULL, NULL);
1302
1303   quark = g_quark_try_string (key);
1304
1305   return quark ? g_datalist_id_get_data (&object->qdata, quark) : NULL;
1306 }
1307
1308 void
1309 g_object_set_data (GObject     *object,
1310                    const gchar *key,
1311                    gpointer     data)
1312 {
1313   g_return_if_fail (G_IS_OBJECT (object));
1314   g_return_if_fail (key != NULL);
1315
1316   g_datalist_id_set_data (&object->qdata, g_quark_from_string (key), data);
1317 }
1318
1319 void
1320 g_object_set_data_full (GObject       *object,
1321                         const gchar   *key,
1322                         gpointer       data,
1323                         GDestroyNotify destroy)
1324 {
1325   g_return_if_fail (G_IS_OBJECT (object));
1326   g_return_if_fail (key != NULL);
1327
1328   g_datalist_id_set_data_full (&object->qdata, g_quark_from_string (key), data, data ? destroy : NULL);
1329 }
1330
1331 gpointer
1332 g_object_steal_data (GObject     *object,
1333                      const gchar *key)
1334 {
1335   GQuark quark;
1336
1337   g_return_val_if_fail (G_IS_OBJECT (object), NULL);
1338   g_return_val_if_fail (key != NULL, NULL);
1339
1340   quark = g_quark_try_string (key);
1341
1342   return quark ? g_datalist_id_remove_no_notify (&object->qdata, quark) : NULL;
1343 }
1344
1345 static void
1346 g_value_object_init (GValue *value)
1347 {
1348   value->data[0].v_pointer = NULL;
1349 }
1350
1351 static void
1352 g_value_object_free_value (GValue *value)
1353 {
1354   if (value->data[0].v_pointer)
1355     g_object_unref (value->data[0].v_pointer);
1356 }
1357
1358 static void
1359 g_value_object_copy_value (const GValue *src_value,
1360                            GValue       *dest_value)
1361 {
1362   if (src_value->data[0].v_pointer)
1363     dest_value->data[0].v_pointer = g_object_ref (src_value->data[0].v_pointer);
1364   else
1365     dest_value->data[0].v_pointer = NULL;
1366 }
1367
1368 static void
1369 g_value_object_transform_value (const GValue *src_value,
1370                                 GValue       *dest_value)
1371 {
1372   if (src_value->data[0].v_pointer && g_type_is_a (G_OBJECT_TYPE (src_value->data[0].v_pointer), G_VALUE_TYPE (dest_value)))
1373     dest_value->data[0].v_pointer = g_object_ref (src_value->data[0].v_pointer);
1374   else
1375     dest_value->data[0].v_pointer = NULL;
1376 }
1377
1378 static gpointer
1379 g_value_object_peek_pointer (const GValue *value)
1380 {
1381   return value->data[0].v_pointer;
1382 }
1383
1384 static gchar*
1385 g_value_object_collect_value (GValue      *value,
1386                               guint        n_collect_values,
1387                               GTypeCValue *collect_values,
1388                               guint        collect_flags)
1389 {
1390   if (collect_values[0].v_pointer)
1391     {
1392       GObject *object = collect_values[0].v_pointer;
1393       
1394       if (object->g_type_instance.g_class == NULL)
1395         return g_strconcat ("invalid unclassed object pointer for value type `",
1396                             G_VALUE_TYPE_NAME (value),
1397                             "'",
1398                             NULL);
1399       else if (!g_value_type_compatible (G_OBJECT_TYPE (object), G_VALUE_TYPE (value)))
1400         return g_strconcat ("invalid object type `",
1401                             G_OBJECT_TYPE_NAME (object),
1402                             "' for value type `",
1403                             G_VALUE_TYPE_NAME (value),
1404                             "'",
1405                             NULL);
1406       /* never honour G_VALUE_NOCOPY_CONTENTS for ref-counted types */
1407       value->data[0].v_pointer = g_object_ref (object);
1408     }
1409   else
1410     value->data[0].v_pointer = NULL;
1411   
1412   return NULL;
1413 }
1414
1415 static gchar*
1416 g_value_object_lcopy_value (const GValue *value,
1417                             guint        n_collect_values,
1418                             GTypeCValue *collect_values,
1419                             guint        collect_flags)
1420 {
1421   GObject **object_p = collect_values[0].v_pointer;
1422   
1423   if (!object_p)
1424     return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value));
1425
1426   if (!value->data[0].v_pointer)
1427     *object_p = NULL;
1428   else if (collect_flags & G_VALUE_NOCOPY_CONTENTS)
1429     *object_p = value->data[0].v_pointer;
1430   else
1431     *object_p = g_object_ref (value->data[0].v_pointer);
1432   
1433   return NULL;
1434 }
1435
1436 void
1437 g_value_set_object (GValue  *value,
1438                     GObject *v_object)
1439 {
1440   g_return_if_fail (G_VALUE_HOLDS_OBJECT (value));
1441   
1442   if (value->data[0].v_pointer)
1443     {
1444       g_object_unref (value->data[0].v_pointer);
1445       value->data[0].v_pointer = NULL;
1446     }
1447
1448   if (v_object)
1449     {
1450       g_return_if_fail (G_IS_OBJECT (v_object));
1451       g_return_if_fail (g_value_type_compatible (G_OBJECT_TYPE (v_object), G_VALUE_TYPE (value)));
1452
1453       value->data[0].v_pointer = v_object;
1454       g_object_ref (value->data[0].v_pointer);
1455     }
1456 }
1457
1458 gpointer
1459 g_value_get_object (const GValue *value)
1460 {
1461   g_return_val_if_fail (G_VALUE_HOLDS_OBJECT (value), NULL);
1462   
1463   return value->data[0].v_pointer;
1464 }
1465
1466 GObject*
1467 g_value_dup_object (const GValue *value)
1468 {
1469   g_return_val_if_fail (G_VALUE_HOLDS_OBJECT (value), NULL);
1470   
1471   return value->data[0].v_pointer ? g_object_ref (value->data[0].v_pointer) : NULL;
1472 }
1473
1474 guint
1475 g_signal_connect_object (gpointer     instance,
1476                          const gchar *detailed_signal,
1477                          GCallback    c_handler,
1478                          gpointer     gobject,
1479                          gboolean     swapped,
1480                          gboolean     after)
1481 {
1482   g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
1483   g_return_val_if_fail (detailed_signal != NULL, 0);
1484   g_return_val_if_fail (c_handler != NULL, 0);
1485
1486   if (gobject)
1487     {
1488       GClosure *closure;
1489
1490       g_return_val_if_fail (G_IS_OBJECT (gobject), 0);
1491
1492       closure = (swapped ? g_cclosure_new_object_swap : g_cclosure_new_object) (c_handler, gobject);
1493
1494       return g_signal_connect_closure (instance, detailed_signal, closure, after);
1495     }
1496   else
1497     return g_signal_connect_data (instance, detailed_signal, c_handler, NULL, NULL, swapped, after);
1498 }
1499
1500 typedef struct {
1501   GObject  *object;
1502   guint     n_closures;
1503   GClosure *closures[1]; /* flexible array */
1504 } CArray;
1505
1506 static void
1507 object_remove_closure (gpointer  data,
1508                        GClosure *closure)
1509 {
1510   GObject *object = data;
1511   CArray *carray = g_object_get_qdata (object, quark_closure_array);
1512   guint i;
1513   
1514   for (i = 0; i < carray->n_closures; i++)
1515     if (carray->closures[i] == closure)
1516       {
1517         carray->n_closures--;
1518         if (i < carray->n_closures)
1519           carray->closures[i] = carray->closures[carray->n_closures];
1520         return;
1521       }
1522   g_assert_not_reached ();
1523 }
1524
1525 static void
1526 destroy_closure_array (gpointer data)
1527 {
1528   CArray *carray = data;
1529   GObject *object = carray->object;
1530   guint i, n = carray->n_closures;
1531   
1532   for (i = 0; i < n; i++)
1533     {
1534       GClosure *closure = carray->closures[i];
1535       
1536       /* removing object_remove_closure() upfront is probably faster than
1537        * letting it fiddle with quark_closure_array which is empty anyways
1538        */
1539       g_closure_remove_invalidate_notifier (closure, object, object_remove_closure);
1540       g_closure_invalidate (closure);
1541     }
1542   g_free (carray);
1543 }
1544
1545 void
1546 g_object_watch_closure (GObject  *object,
1547                         GClosure *closure)
1548 {
1549   CArray *carray;
1550   
1551   g_return_if_fail (G_IS_OBJECT (object));
1552   g_return_if_fail (closure != NULL);
1553   g_return_if_fail (closure->is_invalid == FALSE);
1554   g_return_if_fail (closure->in_marshal == FALSE);
1555   g_return_if_fail (object->ref_count > 0);     /* this doesn't work on finalizing objects */
1556   
1557   g_closure_add_invalidate_notifier (closure, object, object_remove_closure);
1558   g_closure_add_marshal_guards (closure,
1559                                 object, (GClosureNotify) g_object_ref,
1560                                 object, (GClosureNotify) g_object_unref);
1561   carray = g_object_steal_qdata (object, quark_closure_array);
1562   if (!carray)
1563     {
1564       carray = g_renew (CArray, NULL, 1);
1565       carray->object = object;
1566       carray->n_closures = 1;
1567       carray->closures[0] = closure;
1568       g_object_set_qdata_full (object, quark_closure_array, carray, destroy_closure_array);
1569     }
1570   else
1571     {
1572       guint i = carray->n_closures++;
1573       
1574       carray = g_realloc (carray, sizeof (*carray) + sizeof (carray->closures[0]) * i);
1575       carray->closures[i] = closure;
1576       g_object_set_qdata_full (object, quark_closure_array, carray, destroy_closure_array);
1577     }
1578 }
1579
1580 GClosure*
1581 g_closure_new_object (guint    sizeof_closure,
1582                       GObject *object)
1583 {
1584   GClosure *closure;
1585
1586   g_return_val_if_fail (G_IS_OBJECT (object), NULL);
1587   g_return_val_if_fail (object->ref_count > 0, NULL);     /* this doesn't work on finalizing objects */
1588
1589   closure = g_closure_new_simple (sizeof_closure, object);
1590   g_object_watch_closure (object, closure);
1591
1592   return closure;
1593 }
1594
1595 GClosure*
1596 g_cclosure_new_object (GCallback callback_func,
1597                        gpointer  _object)
1598 {
1599   GObject *object = _object;
1600   GClosure *closure;
1601
1602   g_return_val_if_fail (G_IS_OBJECT (object), NULL);
1603   g_return_val_if_fail (object->ref_count > 0, NULL);     /* this doesn't work on finalizing objects */
1604   g_return_val_if_fail (callback_func != NULL, NULL);
1605
1606   closure = g_cclosure_new (callback_func, object, NULL);
1607   g_object_watch_closure (object, closure);
1608
1609   return closure;
1610 }
1611
1612 GClosure*
1613 g_cclosure_new_object_swap (GCallback callback_func,
1614                             gpointer  _object)
1615 {
1616   GObject *object = _object;
1617   GClosure *closure;
1618
1619   g_return_val_if_fail (G_IS_OBJECT (object), NULL);
1620   g_return_val_if_fail (object->ref_count > 0, NULL);     /* this doesn't work on finalizing objects */
1621   g_return_val_if_fail (callback_func != NULL, NULL);
1622
1623   closure = g_cclosure_new_swap (callback_func, object, NULL);
1624   g_object_watch_closure (object, closure);
1625
1626   return closure;
1627 }