]> Pileus Git - ~andy/gtk/blob - gtk/gtkobject.c
Adapt cast macros to standard.
[~andy/gtk] / gtk / gtkobject.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library 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  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * 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  * Modified by the GTK+ Team and others 1997-1999.  See the AUTHORS
22  * file for a list of people on the GTK+ Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
25  */
26
27 #include <stdarg.h>
28 #include <string.h>
29 #include <stdio.h>
30 #include "gtkobject.h"
31 #include "gtksignal.h"
32
33
34 enum {
35   DESTROY,
36   LAST_SIGNAL
37 };
38 enum {
39   ARG_0,
40   ARG_USER_DATA,
41   ARG_SIGNAL,
42   ARG_SIGNAL_AFTER,
43   ARG_OBJECT_SIGNAL,
44   ARG_OBJECT_SIGNAL_AFTER
45 };
46
47
48 void                  gtk_object_init_type       (void);
49 static void           gtk_object_base_class_init (GtkObjectClass *klass);
50 static void           gtk_object_class_init      (GtkObjectClass *klass);
51 static void           gtk_object_init            (GtkObject      *object,
52                                                   GtkObjectClass *klass);
53 static void           gtk_object_set_arg         (GtkObject      *object,
54                                                   GtkArg         *arg,
55                                                   guint           arg_id);
56 static void           gtk_object_get_arg         (GtkObject      *object,
57                                                   GtkArg         *arg,
58                                                   guint           arg_id);
59 static void           gtk_object_shutdown        (GtkObject      *object);
60 static void           gtk_object_real_destroy    (GtkObject      *object);
61 static void           gtk_object_finalize        (GtkObject      *object);
62 static void           gtk_object_notify_weaks    (GtkObject      *object);
63
64 static guint object_signals[LAST_SIGNAL] = { 0 };
65
66 static GHashTable *object_arg_info_ht = NULL;
67
68 static GQuark quark_user_data = 0;
69 static GQuark quark_weakrefs = 0;
70 static GQuark quark_carg_history = 0;
71
72
73 #ifdef G_ENABLE_DEBUG
74 static guint obj_count = 0;
75 static GHashTable *living_objs_ht = NULL;
76 static void
77 gtk_object_debug_foreach (gpointer key, gpointer value, gpointer user_data)
78 {
79   GtkObject *object;
80   
81   object = (GtkObject*) value;
82   g_message ("[%p] %s\tref_count=%d%s%s",
83              object,
84              gtk_type_name (GTK_OBJECT_TYPE (object)),
85              object->ref_count,
86              GTK_OBJECT_FLOATING (object) ? " (floating)" : "",
87              GTK_OBJECT_DESTROYED (object) ? " (destroyed)" : "");
88 }
89 static void
90 gtk_object_debug (void)
91 {
92   if (living_objs_ht)
93     g_hash_table_foreach (living_objs_ht, gtk_object_debug_foreach, NULL);
94   
95   g_message ("living objects count = %d", obj_count);
96 }
97 #endif  /* G_ENABLE_DEBUG */
98
99 void
100 gtk_object_post_arg_parsing_init (void)
101 {
102 #ifdef G_ENABLE_DEBUG
103   if (gtk_debug_flags & GTK_DEBUG_OBJECTS)
104     g_atexit (gtk_object_debug);
105 #endif  /* G_ENABLE_DEBUG */
106 }
107
108 /****************************************************
109  * GtkObject type, class and instance initialization
110  *
111  ****************************************************/
112
113 void
114 gtk_object_init_type (void)
115 {
116   static const GtkTypeInfo object_info =
117   {
118     "GtkObject",
119     sizeof (GtkObject),
120     sizeof (GtkObjectClass),
121     (GtkClassInitFunc) gtk_object_class_init,
122     (GtkObjectInitFunc) gtk_object_init,
123     /* reserved_1 */ NULL,
124     /* reserved_2 */ NULL,
125     (GtkClassInitFunc) gtk_object_base_class_init,
126   };
127   GtkType object_type;
128
129   object_type = gtk_type_unique (0, &object_info);
130   g_assert (object_type == GTK_TYPE_OBJECT);
131 }
132
133 GtkType
134 gtk_object_get_type (void)
135 {
136   return GTK_TYPE_OBJECT;
137 }
138
139 static void
140 gtk_object_base_class_init (GtkObjectClass *class)
141 {
142   /* reset instance specific fields that don't get inherited */
143   class->signals = NULL;
144   class->nsignals = 0;
145   class->n_args = 0;
146   class->construct_args = NULL;
147
148   /* reset instance specifc methods that don't get inherited */
149   class->get_arg = NULL;
150   class->set_arg = NULL;
151 }
152
153 static void
154 gtk_object_class_init (GtkObjectClass *class)
155 {
156   quark_carg_history = g_quark_from_static_string ("gtk-construct-arg-history");
157
158   gtk_object_add_arg_type ("GtkObject::user_data",
159                            GTK_TYPE_POINTER,
160                            GTK_ARG_READWRITE,
161                            ARG_USER_DATA);
162   gtk_object_add_arg_type ("GtkObject::signal",
163                            GTK_TYPE_SIGNAL,
164                            GTK_ARG_WRITABLE,
165                            ARG_SIGNAL);
166   gtk_object_add_arg_type ("GtkObject::signal_after",
167                            GTK_TYPE_SIGNAL,
168                            GTK_ARG_WRITABLE,
169                            ARG_SIGNAL_AFTER);
170   gtk_object_add_arg_type ("GtkObject::object_signal",
171                            GTK_TYPE_SIGNAL,
172                            GTK_ARG_WRITABLE,
173                            ARG_OBJECT_SIGNAL);
174   gtk_object_add_arg_type ("GtkObject::object_signal_after",
175                            GTK_TYPE_SIGNAL,
176                            GTK_ARG_WRITABLE,
177                            ARG_OBJECT_SIGNAL_AFTER);
178
179   object_signals[DESTROY] =
180     gtk_signal_new ("destroy",
181                     GTK_RUN_LAST | GTK_RUN_NO_HOOKS,
182                     class->type,
183                     GTK_SIGNAL_OFFSET (GtkObjectClass, destroy),
184                     gtk_marshal_NONE__NONE,
185                     GTK_TYPE_NONE, 0);
186
187   gtk_object_class_add_signals (class, object_signals, LAST_SIGNAL);
188
189   class->get_arg = gtk_object_get_arg;
190   class->set_arg = gtk_object_set_arg;
191   class->shutdown = gtk_object_shutdown;
192   class->destroy = gtk_object_real_destroy;
193   class->finalize = gtk_object_finalize;
194 }
195
196 static void
197 gtk_object_init (GtkObject      *object,
198                  GtkObjectClass *klass)
199 {
200   gboolean needs_construction = FALSE;
201
202   GTK_OBJECT_FLAGS (object) = GTK_FLOATING;
203   do
204     {
205       needs_construction |= klass->construct_args != NULL;
206       klass = gtk_type_parent_class (klass->type);
207     }
208   while (klass && !needs_construction);
209   if (!needs_construction)
210     GTK_OBJECT_FLAGS (object) |= GTK_CONSTRUCTED;
211
212   object->ref_count = 1;
213   g_datalist_init (&object->object_data);
214
215 #ifdef G_ENABLE_DEBUG
216   if (gtk_debug_flags & GTK_DEBUG_OBJECTS)
217     {
218       obj_count++;
219       
220       if (!living_objs_ht)
221         living_objs_ht = g_hash_table_new (g_direct_hash, NULL);
222
223       g_hash_table_insert (living_objs_ht, object, object);
224     }
225 #endif /* G_ENABLE_DEBUG */
226 }
227
228 /********************************************
229  * Functions to end a GtkObject's life time
230  *
231  ********************************************/
232 void
233 gtk_object_destroy (GtkObject *object)
234 {
235   g_return_if_fail (object != NULL);
236   g_return_if_fail (GTK_IS_OBJECT (object));
237   g_return_if_fail (GTK_OBJECT_CONSTRUCTED (object));
238   
239   if (!GTK_OBJECT_DESTROYED (object))
240     {
241       /* we will hold a reference on the object in this place, so
242        * to ease all classes shutdown and destroy implementations.
243        * i.e. they don't have to bother about referencing at all.
244        */
245       gtk_object_ref (object);
246       object->klass->shutdown (object);
247       gtk_object_unref (object);
248     }
249 }
250
251 static void
252 gtk_object_shutdown (GtkObject *object)
253 {
254   GTK_OBJECT_SET_FLAGS (object, GTK_DESTROYED);
255   gtk_signal_emit (object, object_signals[DESTROY]);
256 }
257
258 static void
259 gtk_object_real_destroy (GtkObject *object)
260 {
261   if (GTK_OBJECT_CONNECTED (object))
262     gtk_signal_handlers_destroy (object);
263 }
264
265 static void
266 gtk_object_finalize (GtkObject *object)
267 {
268   gtk_object_notify_weaks (object);
269
270   g_datalist_clear (&object->object_data);
271   
272   gtk_type_free (GTK_OBJECT_TYPE (object), object);
273 }
274
275 /*****************************************
276  * GtkObject argument handlers
277  *
278  *****************************************/
279
280 static void
281 gtk_object_set_arg (GtkObject *object,
282                     GtkArg    *arg,
283                     guint      arg_id)
284 {
285   guint n = 0;
286
287   switch (arg_id)
288     {
289       gchar *arg_name;
290
291     case ARG_USER_DATA:
292       gtk_object_set_user_data (object, GTK_VALUE_POINTER (*arg));
293       break;
294     case ARG_OBJECT_SIGNAL_AFTER:
295       n += 6;
296     case ARG_OBJECT_SIGNAL:
297       n += 1;
298     case ARG_SIGNAL_AFTER:
299       n += 6;
300     case ARG_SIGNAL:
301       n += 6;
302       arg_name = gtk_arg_name_strip_type (arg->name);
303       if (arg_name &&
304           arg_name[n] == ':' &&
305           arg_name[n + 1] == ':' &&
306           arg_name[n + 2] != 0)
307         {
308           gtk_signal_connect_full (object,
309                                    arg_name + n + 2,
310                                    GTK_VALUE_SIGNAL (*arg).f, NULL,
311                                    GTK_VALUE_SIGNAL (*arg).d,
312                                    NULL,
313                                    (arg_id == ARG_OBJECT_SIGNAL ||
314                                     arg_id == ARG_OBJECT_SIGNAL_AFTER),
315                                    (arg_id == ARG_OBJECT_SIGNAL_AFTER ||
316                                     arg_id == ARG_SIGNAL_AFTER));
317         }
318       else
319         g_warning ("gtk_object_set_arg(): invalid signal argument: \"%s\"\n", arg->name);
320       break;
321     default:
322       break;
323     }
324 }
325
326 static void
327 gtk_object_get_arg (GtkObject *object,
328                     GtkArg    *arg,
329                     guint      arg_id)
330 {
331   switch (arg_id)
332     {
333     case ARG_USER_DATA:
334       GTK_VALUE_POINTER (*arg) = gtk_object_get_user_data (object);
335       break;
336     case ARG_SIGNAL:
337     case ARG_OBJECT_SIGNAL:
338     default:
339       arg->type = GTK_TYPE_INVALID;
340       break;
341     }
342 }
343
344 /*****************************************
345  * gtk_object_class_add_signals:
346  *
347  *   arguments:
348  *
349  *   results:
350  *****************************************/
351
352 void
353 gtk_object_class_add_signals (GtkObjectClass *class,
354                               guint          *signals,
355                               guint           nsignals)
356 {
357   g_return_if_fail (GTK_IS_OBJECT_CLASS (class));
358   if (!nsignals)
359     return;
360   g_return_if_fail (signals != NULL);
361   
362   class->signals = g_renew (guint, class->signals, class->nsignals + nsignals);
363   memcpy (class->signals + class->nsignals, signals, nsignals * sizeof (guint));
364   class->nsignals += nsignals;
365 }
366
367 guint
368 gtk_object_class_user_signal_new (GtkObjectClass     *class,
369                                   const gchar        *name,
370                                   GtkSignalRunType    signal_flags,
371                                   GtkSignalMarshaller marshaller,
372                                   GtkType             return_val,
373                                   guint               nparams,
374                                   ...)
375 {
376   GtkType *params;
377   guint i;
378   va_list args;
379   guint signal_id;
380
381   g_return_val_if_fail (class != NULL, 0);
382
383   if (nparams > 0)
384     {
385       params = g_new (GtkType, nparams);
386
387       va_start (args, nparams);
388
389       for (i = 0; i < nparams; i++)
390         params[i] = va_arg (args, GtkType);
391
392       va_end (args);
393     }
394   else
395     params = NULL;
396
397   signal_id = gtk_signal_newv (name,
398                                signal_flags,
399                                class->type,
400                                0,
401                                marshaller,
402                                return_val,
403                                nparams,
404                                params);
405
406   g_free (params);
407
408   if (signal_id)
409     gtk_object_class_add_signals (class, &signal_id, 1);
410
411   return signal_id;
412 }
413
414 guint
415 gtk_object_class_user_signal_newv (GtkObjectClass     *class,
416                                    const gchar        *name,
417                                    GtkSignalRunType    signal_flags,
418                                    GtkSignalMarshaller marshaller,
419                                    GtkType             return_val,
420                                    guint               nparams,
421                                    GtkType            *params)
422 {
423   guint signal_id;
424
425   g_return_val_if_fail (class != NULL, 0);
426
427   if (nparams > 0)
428     g_return_val_if_fail (params != NULL, 0);
429
430   signal_id = gtk_signal_newv (name,
431                                signal_flags,
432                                class->type,
433                                0,
434                                marshaller,
435                                return_val,
436                                nparams,
437                                params);
438
439   if (signal_id)
440     gtk_object_class_add_signals (class, &signal_id, 1);
441
442   return signal_id;
443 }
444
445 /*****************************************
446  * gtk_object_sink:
447  *
448  *   arguments:
449  *
450  *   results:
451  *****************************************/
452
453 void
454 gtk_object_sink (GtkObject *object)
455 {
456   g_return_if_fail (object != NULL);
457   g_return_if_fail (GTK_IS_OBJECT (object));
458
459   if (GTK_OBJECT_FLOATING (object))
460     {
461       GTK_OBJECT_UNSET_FLAGS (object, GTK_FLOATING);
462       gtk_object_unref (object);
463     }
464 }
465
466 /*****************************************
467  * Weak references.
468  *
469  * Weak refs are very similar to the old "destroy" signal.  They allow
470  * one to register a callback that is called when the weakly
471  * referenced object is finalized.
472  *  
473  * They are not implemented as a signal because they really are
474  * special and need to be used with great care.  Unlike signals, which
475  * should be able to execute any code whatsoever.
476  * 
477  * A weakref callback is not allowed to retain a reference to the
478  * object.  Object data keys may be retrieved in a weak reference
479  * callback.
480  * 
481  * A weakref callback is called at most once.
482  *
483  *****************************************/
484
485 typedef struct _GtkWeakRef      GtkWeakRef;
486
487 struct _GtkWeakRef
488 {
489   GtkWeakRef       *next;
490   GtkDestroyNotify  notify;
491   gpointer          data;
492 };
493
494 void
495 gtk_object_weakref (GtkObject        *object,
496                     GtkDestroyNotify  notify,
497                     gpointer          data)
498 {
499   GtkWeakRef *weak;
500
501   g_return_if_fail (object != NULL);
502   g_return_if_fail (notify != NULL);
503   g_return_if_fail (GTK_IS_OBJECT (object));
504
505   if (!quark_weakrefs)
506     quark_weakrefs = g_quark_from_static_string ("gtk-weakrefs");
507
508   weak = g_new (GtkWeakRef, 1);
509   weak->next = gtk_object_get_data_by_id (object, quark_weakrefs);
510   weak->notify = notify;
511   weak->data = data;
512   gtk_object_set_data_by_id (object, quark_weakrefs, weak);
513 }
514
515 void
516 gtk_object_weakunref (GtkObject        *object,
517                       GtkDestroyNotify  notify,
518                       gpointer          data)
519 {
520   GtkWeakRef *weaks, *w, **wp;
521
522   g_return_if_fail (object != NULL);
523   g_return_if_fail (GTK_IS_OBJECT (object));
524
525   if (!quark_weakrefs)
526     return;
527
528   weaks = gtk_object_get_data_by_id (object, quark_weakrefs);
529   for (wp = &weaks; *wp; wp = &(*wp)->next)
530     {
531       w = *wp;
532       if (w->notify == notify && w->data == data)
533         {
534           if (w == weaks)
535             gtk_object_set_data_by_id (object, quark_weakrefs, w->next);
536           else
537             *wp = w->next;
538           g_free (w);
539           return;
540         }
541     }
542 }
543
544 static void
545 gtk_object_notify_weaks (GtkObject *object)
546 {
547   if (quark_weakrefs)
548     {
549       GtkWeakRef *w1, *w2;
550       
551       w1 = gtk_object_get_data_by_id (object, quark_weakrefs);
552       
553       while (w1)
554         {
555           w1->notify (w1->data);
556           w2 = w1->next;
557           g_free (w1);
558           w1 = w2;
559         }
560     }
561 }
562
563 /****************************************************
564  * GtkObject argument mechanism and object creation
565  *
566  ****************************************************/
567
568 GtkObject*
569 gtk_object_new (GtkType      object_type,
570                 const gchar *first_arg_name,
571                 ...)
572 {
573   GtkObject *object;
574   va_list var_args;
575   GSList *arg_list = NULL;
576   GSList *info_list = NULL;
577   gchar *error;
578
579   g_return_val_if_fail (GTK_FUNDAMENTAL_TYPE (object_type) == GTK_TYPE_OBJECT, NULL);
580
581   object = gtk_type_new (object_type);
582
583   va_start (var_args, first_arg_name);
584   error = gtk_object_args_collect (GTK_OBJECT_TYPE (object),
585                                    &arg_list,
586                                    &info_list,
587                                    first_arg_name,
588                                    var_args);
589   va_end (var_args);
590   
591   if (error)
592     {
593       g_warning ("gtk_object_new(): %s", error);
594       g_free (error);
595     }
596   else
597     {
598       GSList *slist_arg;
599       GSList *slist_info;
600       
601       slist_arg = arg_list;
602       slist_info = info_list;
603       while (slist_arg)
604         {
605           gtk_object_arg_set (object, slist_arg->data, slist_info->data);
606           slist_arg = slist_arg->next;
607           slist_info = slist_info->next;
608         }
609       gtk_args_collect_cleanup (arg_list, info_list);
610     }
611
612   if (!GTK_OBJECT_CONSTRUCTED (object))
613     gtk_object_default_construct (object);
614
615   return object;
616 }
617
618 GtkObject*
619 gtk_object_newv (GtkType  object_type,
620                  guint    n_args,
621                  GtkArg  *args)
622 {
623   GtkObject *object;
624   GtkArg *max_args;
625   
626   g_return_val_if_fail (GTK_FUNDAMENTAL_TYPE (object_type) == GTK_TYPE_OBJECT, NULL);
627   if (n_args)
628     g_return_val_if_fail (args != NULL, NULL);
629   
630   object = gtk_type_new (object_type);
631   
632   for (max_args = args + n_args; args < max_args; args++)
633     gtk_object_arg_set (object, args, NULL);
634   
635   if (!GTK_OBJECT_CONSTRUCTED (object))
636     gtk_object_default_construct (object);
637
638   return object;
639 }
640
641 void
642 gtk_object_setv (GtkObject *object,
643                  guint      n_args,
644                  GtkArg    *args)
645 {
646   GtkArg *max_args;
647   
648   g_return_if_fail (object != NULL);
649   g_return_if_fail (GTK_IS_OBJECT (object));
650   if (n_args)
651     g_return_if_fail (args != NULL);
652
653   for (max_args = args + n_args; args < max_args; args++)
654     gtk_object_arg_set (object, args, NULL);
655 }
656
657 void
658 gtk_object_getv (GtkObject           *object,
659                  guint                n_args,
660                  GtkArg              *args)
661 {
662   GtkArg *max_args;
663   
664   g_return_if_fail (object != NULL);
665   g_return_if_fail (GTK_IS_OBJECT (object));
666   if (n_args)
667     g_return_if_fail (args != NULL);
668   
669   for (max_args = args + n_args; args < max_args; args++)
670     gtk_object_arg_get (object, args, NULL);
671 }
672
673 void
674 gtk_object_get (GtkObject   *object,
675                 const gchar *first_arg_name,
676                 ...)
677 {
678   va_list var_args;
679   gchar *name;
680   
681   g_return_if_fail (GTK_IS_OBJECT (object));
682   
683   va_start (var_args, first_arg_name);
684
685   name = (gchar*) first_arg_name;
686   while (name)
687     {
688       gpointer value_pointer = va_arg (var_args, gpointer);
689
690       if (value_pointer)
691         {
692           GtkArgInfo *info;
693           gchar *error;
694           GtkArg arg;
695           
696           error = gtk_arg_get_info (GTK_OBJECT_TYPE (object),
697                                     object_arg_info_ht,
698                                     name,
699                                     &info);
700           if (error)
701             {
702               g_warning ("gtk_object_get(): %s", error);
703               g_free (error);
704               return;
705             }
706           
707           arg.name = name;
708           gtk_object_arg_get (object, &arg, info);
709           gtk_arg_to_valueloc (&arg, value_pointer);
710         }
711
712       name = va_arg (var_args, gchar*);
713     }
714 }
715
716 void
717 gtk_object_set (GtkObject *object,
718                 const gchar    *first_arg_name,
719                 ...)
720 {
721   va_list var_args;
722   GSList *arg_list = NULL;
723   GSList *info_list = NULL;
724   gchar *error;
725   
726   g_return_if_fail (object != NULL);
727   g_return_if_fail (GTK_IS_OBJECT (object));
728   
729   va_start (var_args, first_arg_name);
730   error = gtk_object_args_collect (GTK_OBJECT_TYPE (object),
731                                    &arg_list,
732                                    &info_list,
733                                    first_arg_name,
734                                    var_args);
735   va_end (var_args);
736   
737   if (error)
738     {
739       g_warning ("gtk_object_set(): %s", error);
740       g_free (error);
741     }
742   else
743     {
744       GSList *slist_arg;
745       GSList *slist_info;
746       
747       slist_arg = arg_list;
748       slist_info = info_list;
749       while (slist_arg)
750         {
751           gtk_object_arg_set (object, slist_arg->data, slist_info->data);
752           slist_arg = slist_arg->next;
753           slist_info = slist_info->next;
754         }
755       gtk_args_collect_cleanup (arg_list, info_list);
756     }
757 }
758
759 void
760 gtk_object_arg_set (GtkObject  *object,
761                     GtkArg     *arg,
762                     GtkArgInfo *info)
763 {
764   GtkObjectClass *oclass;
765
766   g_return_if_fail (object != NULL);
767   g_return_if_fail (GTK_IS_OBJECT (object));
768   g_return_if_fail (arg != NULL);
769
770   if (!info)
771     {
772       gchar *error;
773
774       error = gtk_arg_get_info (GTK_OBJECT_TYPE (object),
775                                 object_arg_info_ht,
776                                 arg->name,
777                                 &info);
778       if (error)
779         {
780           g_warning ("gtk_object_arg_set(): %s", error);
781           g_free (error);
782           return;
783         }
784     }
785
786   if (info->arg_flags & GTK_ARG_CONSTRUCT_ONLY &&
787       GTK_OBJECT_CONSTRUCTED (object))
788     {
789       g_warning ("gtk_object_arg_set(): cannot set argument \"%s\" for constructed object",
790                  info->full_name);
791       return;
792     }
793   if (!(info->arg_flags & GTK_ARG_WRITABLE))
794     {
795       g_warning ("gtk_object_arg_set(): argument \"%s\" is not writable",
796                  info->full_name);
797       return;
798     }
799   if (info->type != arg->type)
800     {
801       g_warning ("gtk_object_arg_set(): argument \"%s\" has invalid type `%s'",
802                  info->full_name,
803                  gtk_type_name (arg->type));
804       return;
805     }
806   
807   oclass = gtk_type_class (info->class_type);
808   g_assert (oclass->set_arg != NULL);
809   oclass->set_arg (object, arg, info->arg_id);
810   if (!GTK_OBJECT_CONSTRUCTED (object) &&
811       (info->arg_flags & GTK_ARG_CONSTRUCT_ONLY ||
812        info->arg_flags & GTK_ARG_CONSTRUCT))
813     {
814       GSList *slist;
815
816       slist = gtk_object_get_data_by_id (object, quark_carg_history);
817       gtk_object_set_data_by_id (object,
818                                  quark_carg_history,
819                                  g_slist_prepend (slist, info));
820     }
821 }
822
823 void
824 gtk_object_arg_get (GtkObject  *object,
825                     GtkArg     *arg,
826                     GtkArgInfo *info)
827 {
828   GtkObjectClass *oclass;
829   
830   g_return_if_fail (object != NULL);
831   g_return_if_fail (GTK_IS_OBJECT (object));
832   g_return_if_fail (arg != NULL);
833
834   if (!info)
835     {
836       gchar *error;
837
838       error = gtk_arg_get_info (GTK_OBJECT_TYPE (object),
839                                 object_arg_info_ht,
840                                 arg->name,
841                                 &info);
842       if (error)
843         {
844           g_warning ("gtk_object_arg_get(): %s", error);
845           g_free (error);
846           arg->type = GTK_TYPE_INVALID;
847           return;
848         }
849     }
850   
851   if (! (info->arg_flags & GTK_ARG_READABLE))
852     {
853       g_warning ("gtk_object_arg_get(): argument \"%s\" is not readable",
854                  info->full_name);
855       arg->type = GTK_TYPE_INVALID;
856       return;
857     }
858   
859   oclass = gtk_type_class (info->class_type);
860   g_assert (oclass->get_arg != NULL);
861   arg->type = info->type;
862   oclass->get_arg (object, arg, info->arg_id);
863 }
864
865 void
866 gtk_object_default_construct (GtkObject *object)
867 {
868   GSList *slist;
869
870   g_return_if_fail (object != NULL);
871   g_return_if_fail (GTK_IS_OBJECT (object));
872
873   if (!GTK_OBJECT_CONSTRUCTED (object))
874     {
875       for (slist = object->klass->construct_args;
876            slist && !GTK_OBJECT_CONSTRUCTED (object);
877            slist = slist->next)
878         {
879           GSList *history;
880           GtkArgInfo *info;
881           
882           info = slist->data;
883           history = gtk_object_get_data_by_id (object, quark_carg_history);
884           if (!g_slist_find (history, info))
885             {
886               GtkArg arg;
887               
888               /* default application */
889               arg.type = info->type;
890               arg.name = info->name;
891               switch (gtk_type_get_varargs_type (arg.type))
892                 {
893                 case GTK_TYPE_FLOAT:
894                   GTK_VALUE_FLOAT (arg) = 0.0;
895                   break;
896                 case GTK_TYPE_DOUBLE:
897                   GTK_VALUE_DOUBLE (arg) = 0.0;
898                   break;
899                 case GTK_TYPE_BOXED:
900                 case GTK_TYPE_STRING:
901                 case GTK_TYPE_POINTER:
902                 case GTK_TYPE_OBJECT:
903                   GTK_VALUE_POINTER (arg) = NULL;
904                   break;
905                 default:
906                   memset (&arg.d, 0, sizeof (arg.d));
907                   break;
908                 }
909               gtk_object_arg_set (object, &arg, info);
910             }
911         }
912
913       if (!GTK_OBJECT_CONSTRUCTED (object))
914         gtk_object_constructed (object);
915     }
916 }
917
918 void
919 gtk_object_constructed (GtkObject *object)
920 {
921   g_return_if_fail (object != NULL);
922   g_return_if_fail (GTK_IS_OBJECT (object));
923   g_return_if_fail (GTK_OBJECT_CONSTRUCTED (object) == FALSE);
924   
925   g_slist_free (gtk_object_get_data_by_id (object, quark_carg_history));
926   gtk_object_set_data_by_id (object, quark_carg_history, NULL);
927   GTK_OBJECT_FLAGS (object) |= GTK_CONSTRUCTED;
928 }
929
930 void
931 gtk_object_add_arg_type (const char *arg_name,
932                          GtkType     arg_type,
933                          guint       arg_flags,
934                          guint       arg_id)
935 {
936   GtkArgInfo *info;
937
938   g_return_if_fail (arg_name != NULL);
939   g_return_if_fail (arg_type > GTK_TYPE_NONE);
940   g_return_if_fail (arg_id > 0);
941   g_return_if_fail ((arg_flags & GTK_ARG_CHILD_ARG) == 0);
942   if (arg_flags & GTK_ARG_CONSTRUCT)
943     g_return_if_fail ((arg_flags & GTK_ARG_READWRITE) == GTK_ARG_READWRITE);
944   else
945     g_return_if_fail ((arg_flags & GTK_ARG_READWRITE) != 0);
946   if (arg_flags & GTK_ARG_CONSTRUCT_ONLY)
947     g_return_if_fail ((arg_flags & GTK_ARG_WRITABLE) == GTK_ARG_WRITABLE);
948     
949   if (!object_arg_info_ht)
950     object_arg_info_ht = g_hash_table_new (gtk_arg_info_hash,
951                                            gtk_arg_info_equal);
952
953   info = gtk_arg_type_new_static (GTK_TYPE_OBJECT,
954                                   arg_name,
955                                   GTK_STRUCT_OFFSET (GtkObjectClass, n_args),
956                                   object_arg_info_ht,
957                                   arg_type,
958                                   arg_flags,
959                                   arg_id);
960   if (info &&
961       (info->arg_flags & GTK_ARG_CONSTRUCT ||
962        info->arg_flags & GTK_ARG_CONSTRUCT_ONLY))
963     {
964       GtkObjectClass *class;
965
966       class = gtk_type_class (info->class_type);
967       if (info->arg_flags & GTK_ARG_CONSTRUCT_ONLY)
968         class->construct_args = g_slist_prepend (class->construct_args, info);
969       else
970         class->construct_args = g_slist_append (class->construct_args, info);
971     }
972 }
973
974 gchar*
975 gtk_object_args_collect (GtkType      object_type,
976                          GSList      **arg_list_p,
977                          GSList      **info_list_p,
978                          const gchar  *first_arg_name,
979                          va_list       var_args)
980 {
981   return gtk_args_collect (object_type,
982                            object_arg_info_ht,
983                            arg_list_p,
984                            info_list_p,
985                            first_arg_name,
986                            var_args);
987 }
988
989 gchar*
990 gtk_object_arg_get_info (GtkType      object_type,
991                          const gchar *arg_name,
992                          GtkArgInfo **info_p)
993 {
994   return gtk_arg_get_info (object_type,
995                            object_arg_info_ht,
996                            arg_name,
997                            info_p);
998 }
999
1000 GtkArg*
1001 gtk_object_query_args (GtkType        class_type,
1002                        guint32      **arg_flags,
1003                        guint         *n_args)
1004 {
1005   g_return_val_if_fail (n_args != NULL, NULL);
1006   *n_args = 0;
1007   g_return_val_if_fail (GTK_FUNDAMENTAL_TYPE (class_type) == GTK_TYPE_OBJECT, NULL);
1008
1009   return gtk_args_query (class_type, object_arg_info_ht, arg_flags, n_args);
1010 }
1011
1012 /*****************************************
1013  * GtkObject object_data mechanism
1014  *
1015  *****************************************/
1016
1017 void
1018 gtk_object_set_data_by_id (GtkObject        *object,
1019                            GQuark            data_id,
1020                            gpointer          data)
1021 {
1022   g_return_if_fail (object != NULL);
1023   g_return_if_fail (GTK_IS_OBJECT (object));
1024   
1025   g_datalist_id_set_data (&object->object_data, data_id, data);
1026 }
1027
1028 void
1029 gtk_object_set_data (GtkObject        *object,
1030                      const gchar      *key,
1031                      gpointer          data)
1032 {
1033   g_return_if_fail (object != NULL);
1034   g_return_if_fail (GTK_IS_OBJECT (object));
1035   g_return_if_fail (key != NULL);
1036   
1037   g_datalist_set_data (&object->object_data, key, data);
1038 }
1039
1040 void
1041 gtk_object_set_data_by_id_full (GtkObject        *object,
1042                                 GQuark            data_id,
1043                                 gpointer          data,
1044                                 GtkDestroyNotify  destroy)
1045 {
1046   g_return_if_fail (object != NULL);
1047   g_return_if_fail (GTK_IS_OBJECT (object));
1048
1049   g_datalist_id_set_data_full (&object->object_data, data_id, data, destroy);
1050 }
1051
1052 void
1053 gtk_object_set_data_full (GtkObject        *object,
1054                           const gchar      *key,
1055                           gpointer          data,
1056                           GtkDestroyNotify  destroy)
1057 {
1058   g_return_if_fail (object != NULL);
1059   g_return_if_fail (GTK_IS_OBJECT (object));
1060   g_return_if_fail (key != NULL);
1061
1062   g_datalist_set_data_full (&object->object_data, key, data, destroy);
1063 }
1064
1065 gpointer
1066 gtk_object_get_data_by_id (GtkObject   *object,
1067                            GQuark       data_id)
1068 {
1069   g_return_val_if_fail (object != NULL, NULL);
1070   g_return_val_if_fail (GTK_IS_OBJECT (object), NULL);
1071
1072   return g_datalist_id_get_data (&object->object_data, data_id);
1073 }
1074
1075 gpointer
1076 gtk_object_get_data (GtkObject   *object,
1077                      const gchar *key)
1078 {
1079   g_return_val_if_fail (object != NULL, NULL);
1080   g_return_val_if_fail (GTK_IS_OBJECT (object), NULL);
1081   g_return_val_if_fail (key != NULL, NULL);
1082
1083   return g_datalist_get_data (&object->object_data, key);
1084 }
1085
1086 void
1087 gtk_object_remove_data_by_id (GtkObject   *object,
1088                               GQuark       data_id)
1089 {
1090   g_return_if_fail (object != NULL);
1091   g_return_if_fail (GTK_IS_OBJECT (object));
1092
1093   g_datalist_id_remove_data (&object->object_data, data_id);
1094 }
1095
1096 void
1097 gtk_object_remove_data (GtkObject   *object,
1098                         const gchar *key)
1099 {
1100   g_return_if_fail (object != NULL);
1101   g_return_if_fail (GTK_IS_OBJECT (object));
1102   g_return_if_fail (key != NULL);
1103
1104   g_datalist_remove_data (&object->object_data, key);
1105 }
1106
1107 void
1108 gtk_object_remove_no_notify_by_id (GtkObject      *object,
1109                                    GQuark          key_id)
1110 {
1111   g_return_if_fail (object != NULL);
1112   g_return_if_fail (GTK_IS_OBJECT (object));
1113
1114   g_datalist_id_remove_no_notify (&object->object_data, key_id);
1115 }
1116
1117 void
1118 gtk_object_remove_no_notify (GtkObject       *object,
1119                              const gchar     *key)
1120 {
1121   g_return_if_fail (object != NULL);
1122   g_return_if_fail (GTK_IS_OBJECT (object));
1123   g_return_if_fail (key != NULL);
1124
1125   g_datalist_remove_no_notify (&object->object_data, key);
1126 }
1127
1128 void
1129 gtk_object_set_user_data (GtkObject *object,
1130                           gpointer   data)
1131 {
1132   g_return_if_fail (object != NULL);
1133   g_return_if_fail (GTK_IS_OBJECT (object));
1134
1135   if (!quark_user_data)
1136     quark_user_data = g_quark_from_static_string ("user_data");
1137
1138   g_datalist_id_set_data (&object->object_data, quark_user_data, data);
1139 }
1140
1141 gpointer
1142 gtk_object_get_user_data (GtkObject *object)
1143 {
1144   g_return_val_if_fail (object != NULL, NULL);
1145   g_return_val_if_fail (GTK_IS_OBJECT (object), NULL);
1146
1147   return g_datalist_id_get_data (&object->object_data, quark_user_data);
1148 }
1149
1150 /*******************************************
1151  * GtkObject referencing and unreferencing
1152  *
1153  *******************************************/
1154
1155 #undef  gtk_object_ref
1156 #undef  gtk_object_unref
1157
1158 void
1159 gtk_object_ref (GtkObject *object)
1160 {
1161   g_return_if_fail (object != NULL);
1162   g_return_if_fail (GTK_IS_OBJECT (object));
1163   g_return_if_fail (object->ref_count > 0);
1164
1165   object->ref_count += 1;
1166 }
1167
1168 void
1169 gtk_object_unref (GtkObject *object)
1170 {
1171   g_return_if_fail (object != NULL);
1172   g_return_if_fail (GTK_IS_OBJECT (object));
1173   g_return_if_fail (object->ref_count > 0);
1174   
1175   if (object->ref_count == 1)
1176     {
1177       gtk_object_destroy (object);
1178   
1179       g_return_if_fail (object->ref_count > 0);
1180     }
1181
1182   object->ref_count -= 1;
1183
1184   if (object->ref_count == 0)
1185     {
1186 #ifdef G_ENABLE_DEBUG
1187       if (gtk_debug_flags & GTK_DEBUG_OBJECTS)
1188         {
1189           g_assert (g_hash_table_lookup (living_objs_ht, object) == object);
1190           g_hash_table_remove (living_objs_ht, object);
1191           obj_count--;
1192         }
1193 #endif /* G_ENABLE_DEBUG */      
1194       object->klass->finalize (object);
1195     }
1196 }
1197
1198 static GtkObject *gtk_trace_object = NULL;
1199 void
1200 gtk_trace_referencing (GtkObject   *object,
1201                        const gchar *func,
1202                        guint       dummy,
1203                        guint       line,
1204                        gboolean    do_ref)
1205 {
1206   if (gtk_debug_flags & GTK_DEBUG_OBJECTS)
1207     {
1208       gboolean exists = TRUE;
1209
1210       g_return_if_fail (object != NULL);
1211       g_return_if_fail (GTK_IS_OBJECT (object));
1212
1213 #ifdef  G_ENABLE_DEBUG
1214       exists = g_hash_table_lookup (living_objs_ht, object) != NULL;
1215 #endif  /* G_ENABLE_DEBUG */
1216       
1217       if (exists &&
1218           (object == gtk_trace_object ||
1219            gtk_trace_object == (void*)42))
1220         fprintf (stdout, "trace: object_%s: (%s:%p)->ref_count=%d %s (%s:%d)\n",
1221                  do_ref ? "ref" : "unref",
1222                  gtk_type_name (GTK_OBJECT_TYPE (object)),
1223                  object,
1224                  object->ref_count,
1225                  do_ref ? "+ 1" : "- 1",
1226                  func,
1227                  line);
1228       else if (!exists)
1229         fprintf (stdout, "trace: object_%s(%p): no such object! (%s:%d)\n",
1230                  do_ref ? "ref" : "unref",
1231                  object,
1232                  func,
1233                  line);
1234     }
1235   
1236   if (do_ref)
1237     gtk_object_ref (object);
1238   else
1239     gtk_object_unref (object);
1240 }