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 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 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-2000.  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 "config.h"
28 
29 #include <stdarg.h>
30 #include <string.h>
31 #include <stdio.h>
32 
33 #undef GTK_DISABLE_DEPRECATED
34 
35 #include "gtkobject.h"
36 #include "gtkintl.h"
37 #include "gtkmarshalers.h"
38 #include "gtkprivate.h"
39 
40 #include "gtkalias.h"
41 
42 
43 enum {
44   DESTROY,
45   LAST_SIGNAL
46 };
47 enum {
48   PROP_0,
49   PROP_USER_DATA
50 };
51 
52 
53 static void       gtk_object_base_class_init     (GtkObjectClass *class);
54 static void       gtk_object_base_class_finalize (GtkObjectClass *class);
55 static void       gtk_object_class_init          (GtkObjectClass *klass);
56 static void       gtk_object_init                (GtkObject      *object,
57 						  GtkObjectClass *klass);
58 static void	  gtk_object_set_property	 (GObject	 *object,
59 						  guint           property_id,
60 						  const GValue   *value,
61 						  GParamSpec     *pspec);
62 static void	  gtk_object_get_property	 (GObject	 *object,
63 						  guint           property_id,
64 						  GValue         *value,
65 						  GParamSpec     *pspec);
66 static void       gtk_object_dispose            (GObject        *object);
67 static void       gtk_object_real_destroy        (GtkObject      *object);
68 static void       gtk_object_finalize            (GObject        *object);
69 static void       gtk_object_notify_weaks        (GtkObject      *object);
70 
71 static gpointer    parent_class = NULL;
72 static guint       object_signals[LAST_SIGNAL] = { 0 };
73 static GQuark      quark_weakrefs = 0;
74 
75 
76 /****************************************************
77  * GtkObject type, class and instance initialization
78  *
79  ****************************************************/
80 
81 GType
gtk_object_get_type(void)82 gtk_object_get_type (void)
83 {
84   static GType object_type = 0;
85 
86   if (!object_type)
87     {
88       const GTypeInfo object_info =
89       {
90 	sizeof (GtkObjectClass),
91 	(GBaseInitFunc) gtk_object_base_class_init,
92 	(GBaseFinalizeFunc) gtk_object_base_class_finalize,
93 	(GClassInitFunc) gtk_object_class_init,
94 	NULL,		/* class_finalize */
95 	NULL,		/* class_data */
96 	sizeof (GtkObject),
97 	16,		/* n_preallocs */
98 	(GInstanceInitFunc) gtk_object_init,
99 	NULL,		/* value_table */
100       };
101 
102       object_type = g_type_register_static (G_TYPE_INITIALLY_UNOWNED, I_("GtkObject"),
103 					    &object_info, G_TYPE_FLAG_ABSTRACT);
104     }
105 
106   return object_type;
107 }
108 
109 static void
gtk_object_base_class_init(GtkObjectClass * class)110 gtk_object_base_class_init (GtkObjectClass *class)
111 {
112   /* reset instance specifc methods that don't get inherited */
113   class->get_arg = NULL;
114   class->set_arg = NULL;
115 }
116 
117 static void
gtk_object_base_class_finalize(GtkObjectClass * class)118 gtk_object_base_class_finalize (GtkObjectClass *class)
119 {
120 }
121 
122 static inline gboolean
gtk_arg_set_from_value(GtkArg * arg,const GValue * value,gboolean copy_string)123 gtk_arg_set_from_value (GtkArg       *arg,
124 			const GValue *value,
125 			gboolean      copy_string)
126 {
127   switch (G_TYPE_FUNDAMENTAL (arg->type))
128     {
129     case G_TYPE_CHAR:           GTK_VALUE_CHAR (*arg) = g_value_get_char (value);       break;
130     case G_TYPE_UCHAR:          GTK_VALUE_UCHAR (*arg) = g_value_get_uchar (value);     break;
131     case G_TYPE_BOOLEAN:        GTK_VALUE_BOOL (*arg) = g_value_get_boolean (value);    break;
132     case G_TYPE_INT:            GTK_VALUE_INT (*arg) = g_value_get_int (value);         break;
133     case G_TYPE_UINT:           GTK_VALUE_UINT (*arg) = g_value_get_uint (value);       break;
134     case G_TYPE_LONG:           GTK_VALUE_LONG (*arg) = g_value_get_long (value);       break;
135     case G_TYPE_ULONG:          GTK_VALUE_ULONG (*arg) = g_value_get_ulong (value);     break;
136     case G_TYPE_ENUM:           GTK_VALUE_ENUM (*arg) = g_value_get_enum (value);       break;
137     case G_TYPE_FLAGS:          GTK_VALUE_FLAGS (*arg) = g_value_get_flags (value);     break;
138     case G_TYPE_FLOAT:          GTK_VALUE_FLOAT (*arg) = g_value_get_float (value);     break;
139     case G_TYPE_DOUBLE:         GTK_VALUE_DOUBLE (*arg) = g_value_get_double (value);   break;
140     case G_TYPE_BOXED:          GTK_VALUE_BOXED (*arg) = g_value_get_boxed (value);     break;
141     case G_TYPE_POINTER:        GTK_VALUE_POINTER (*arg) = g_value_get_pointer (value); break;
142     case G_TYPE_OBJECT:         GTK_VALUE_POINTER (*arg) = g_value_get_object (value);  break;
143     case G_TYPE_STRING:         if (copy_string)
144       GTK_VALUE_STRING (*arg) = g_value_dup_string (value);
145     else
146       GTK_VALUE_STRING (*arg) = (char *) g_value_get_string (value);
147     break;
148     default:
149       return FALSE;
150     }
151   return TRUE;
152 }
153 
154 static inline gboolean
gtk_arg_to_value(GtkArg * arg,GValue * value)155 gtk_arg_to_value (GtkArg *arg,
156 		  GValue *value)
157 {
158   switch (G_TYPE_FUNDAMENTAL (arg->type))
159     {
160     case G_TYPE_CHAR:           g_value_set_char (value, GTK_VALUE_CHAR (*arg));        break;
161     case G_TYPE_UCHAR:          g_value_set_uchar (value, GTK_VALUE_UCHAR (*arg));      break;
162     case G_TYPE_BOOLEAN:        g_value_set_boolean (value, GTK_VALUE_BOOL (*arg));     break;
163     case G_TYPE_INT:            g_value_set_int (value, GTK_VALUE_INT (*arg));          break;
164     case G_TYPE_UINT:           g_value_set_uint (value, GTK_VALUE_UINT (*arg));        break;
165     case G_TYPE_LONG:           g_value_set_long (value, GTK_VALUE_LONG (*arg));        break;
166     case G_TYPE_ULONG:          g_value_set_ulong (value, GTK_VALUE_ULONG (*arg));      break;
167     case G_TYPE_ENUM:           g_value_set_enum (value, GTK_VALUE_ENUM (*arg));        break;
168     case G_TYPE_FLAGS:          g_value_set_flags (value, GTK_VALUE_FLAGS (*arg));      break;
169     case G_TYPE_FLOAT:          g_value_set_float (value, GTK_VALUE_FLOAT (*arg));      break;
170     case G_TYPE_DOUBLE:         g_value_set_double (value, GTK_VALUE_DOUBLE (*arg));    break;
171     case G_TYPE_STRING:         g_value_set_string (value, GTK_VALUE_STRING (*arg));    break;
172     case G_TYPE_BOXED:          g_value_set_boxed (value, GTK_VALUE_BOXED (*arg));      break;
173     case G_TYPE_POINTER:        g_value_set_pointer (value, GTK_VALUE_POINTER (*arg));  break;
174     case G_TYPE_OBJECT:         g_value_set_object (value, GTK_VALUE_POINTER (*arg));   break;
175     default:
176       return FALSE;
177     }
178   return TRUE;
179 }
180 
181 static void
gtk_arg_proxy_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)182 gtk_arg_proxy_set_property (GObject      *object,
183 			    guint         property_id,
184 			    const GValue *value,
185 			    GParamSpec   *pspec)
186 {
187   GtkObjectClass *class = g_type_class_peek (pspec->owner_type);
188   GtkArg arg;
189 
190   g_return_if_fail (class->set_arg != NULL);
191 
192   memset (&arg, 0, sizeof (arg));
193   arg.type = G_VALUE_TYPE (value);
194   gtk_arg_set_from_value (&arg, value, FALSE);
195   arg.name = pspec->name;
196   class->set_arg (GTK_OBJECT (object), &arg, property_id);
197 }
198 
199 static void
gtk_arg_proxy_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)200 gtk_arg_proxy_get_property (GObject     *object,
201 			    guint        property_id,
202 			    GValue      *value,
203 			    GParamSpec  *pspec)
204 {
205   GtkObjectClass *class = g_type_class_peek (pspec->owner_type);
206   GtkArg arg;
207 
208   g_return_if_fail (class->get_arg != NULL);
209 
210   memset (&arg, 0, sizeof (arg));
211   arg.type = G_VALUE_TYPE (value);
212   arg.name = pspec->name;
213   class->get_arg (GTK_OBJECT (object), &arg, property_id);
214   gtk_arg_to_value (&arg, value);
215 }
216 
217 void
gtk_object_add_arg_type(const gchar * arg_name,GType arg_type,guint arg_flags,guint arg_id)218 gtk_object_add_arg_type (const gchar *arg_name,
219 			 GType        arg_type,
220 			 guint        arg_flags,
221 			 guint        arg_id)
222 {
223   GObjectClass *oclass;
224   GParamSpec *pspec;
225   gchar *type_name, *pname;
226   GType type;
227 
228   g_return_if_fail (arg_name != NULL);
229   g_return_if_fail (arg_type > G_TYPE_NONE);
230   g_return_if_fail (arg_id > 0);
231   g_return_if_fail (arg_flags & G_PARAM_READWRITE);
232   if (arg_flags & G_PARAM_CONSTRUCT)
233     g_return_if_fail ((arg_flags & G_PARAM_CONSTRUCT_ONLY) == 0);
234   if (arg_flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY))
235     g_return_if_fail (arg_flags & G_PARAM_WRITABLE);
236   g_return_if_fail ((arg_flags & ~(G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME)) == 0);
237 
238   pname = strchr (arg_name, ':');
239   g_return_if_fail (pname && pname[1] == ':');
240 
241   type_name = g_strndup (arg_name, pname - arg_name);
242   pname += 2;
243   type = g_type_from_name (type_name);
244   g_free (type_name);
245   g_return_if_fail (G_TYPE_IS_OBJECT (type));
246 
247   oclass = gtk_type_class (type);
248   if (arg_flags & G_PARAM_READABLE)
249     {
250       if (oclass->get_property && oclass->get_property != gtk_arg_proxy_get_property)
251 	{
252 	  g_warning (G_STRLOC ": GtkArg compatibility code can't be mixed with customized %s.get_property() implementation",
253 		     g_type_name (type));
254 	  return;
255 	}
256       oclass->get_property = gtk_arg_proxy_get_property;
257     }
258   if (arg_flags & G_PARAM_WRITABLE)
259     {
260       if (oclass->set_property && oclass->set_property != gtk_arg_proxy_set_property)
261 	{
262 	  g_warning (G_STRLOC ": GtkArg compatibility code can't be mixed with customized %s.set_property() implementation",
263 		     g_type_name (type));
264 	  return;
265 	}
266       oclass->set_property = gtk_arg_proxy_set_property;
267     }
268   switch (G_TYPE_FUNDAMENTAL (arg_type))
269     {
270     case G_TYPE_ENUM:
271       pspec = g_param_spec_enum (pname, NULL, NULL, arg_type, 0, arg_flags);
272       break;
273     case G_TYPE_FLAGS:
274       pspec = g_param_spec_flags (pname, NULL, NULL, arg_type, 0, arg_flags);
275       break;
276     case G_TYPE_CHAR:
277       pspec = g_param_spec_char (pname, NULL, NULL, -128, 127, 0, arg_flags);
278       break;
279     case G_TYPE_UCHAR:
280       pspec = g_param_spec_uchar (pname, NULL, NULL, 0, 255, 0, arg_flags);
281       break;
282     case G_TYPE_BOOLEAN:
283       pspec = g_param_spec_boolean (pname, NULL, NULL, FALSE, arg_flags);
284       break;
285     case G_TYPE_INT:
286       pspec = g_param_spec_int (pname, NULL, NULL, G_MININT, G_MAXINT, 0, arg_flags);
287       break;
288     case G_TYPE_UINT:
289       pspec = g_param_spec_uint (pname, NULL, NULL, 0, G_MAXUINT, 0, arg_flags);
290       break;
291     case G_TYPE_FLOAT:
292       pspec = g_param_spec_float (pname, NULL, NULL, -G_MAXFLOAT, G_MAXFLOAT, 0, arg_flags);
293       break;
294     case G_TYPE_DOUBLE:
295       pspec = g_param_spec_double (pname, NULL, NULL, -G_MAXDOUBLE, G_MAXDOUBLE, 0, arg_flags);
296       break;
297     case G_TYPE_STRING:
298       pspec = g_param_spec_string (pname, NULL, NULL, NULL, arg_flags);
299       break;
300     case G_TYPE_POINTER:
301       pspec = g_param_spec_pointer (pname, NULL, NULL, arg_flags);
302       break;
303     case G_TYPE_OBJECT:
304       pspec = g_param_spec_object (pname, NULL, NULL, arg_type, arg_flags);
305       break;
306     case G_TYPE_BOXED:
307       if (!G_TYPE_IS_FUNDAMENTAL (arg_type))
308 	{
309 	  pspec = g_param_spec_boxed (pname, NULL, NULL, arg_type, arg_flags);
310 	  break;
311 	}
312     default:
313       g_warning (G_STRLOC ": Property type `%s' is not supported by the GtkArg compatibility code",
314 		 g_type_name (arg_type));
315       return;
316     }
317   g_object_class_install_property (oclass, arg_id, pspec);
318 }
319 
320 static guint (*gobject_floating_flag_handler) (GtkObject*,gint) = NULL;
321 
322 static guint
gtk_object_floating_flag_handler(GtkObject * object,gint job)323 gtk_object_floating_flag_handler (GtkObject *object,
324                                   gint       job)
325 {
326   /* FIXME: remove this whole thing once GTK+ breaks ABI */
327   if (!GTK_IS_OBJECT (object))
328     return gobject_floating_flag_handler (object, job);
329   switch (job)
330     {
331       guint32 oldvalue;
332     case +1:    /* force floating if possible */
333       do
334         oldvalue = g_atomic_int_get (&object->flags);
335       while (!g_atomic_int_compare_and_exchange ((gint *)&object->flags, oldvalue, oldvalue | GTK_FLOATING));
336       return oldvalue & GTK_FLOATING;
337     case -1:    /* sink if possible */
338       do
339         oldvalue = g_atomic_int_get (&object->flags);
340       while (!g_atomic_int_compare_and_exchange ((gint *)&object->flags, oldvalue, oldvalue & ~(guint32) GTK_FLOATING));
341       return oldvalue & GTK_FLOATING;
342     default:    /* check floating */
343       return 0 != (g_atomic_int_get (&object->flags) & GTK_FLOATING);
344     }
345 }
346 
347 static void
gtk_object_class_init(GtkObjectClass * class)348 gtk_object_class_init (GtkObjectClass *class)
349 {
350   GObjectClass *gobject_class = G_OBJECT_CLASS (class);
351   gboolean is_glib_2_10_1;
352 
353   parent_class = g_type_class_ref (G_TYPE_OBJECT);
354 
355   is_glib_2_10_1 = g_object_compat_control (3, &gobject_floating_flag_handler);
356   if (!is_glib_2_10_1)
357     g_error ("this version of Gtk+ requires GLib-2.10.1");
358   g_object_compat_control (2, gtk_object_floating_flag_handler);
359 
360   gobject_class->set_property = gtk_object_set_property;
361   gobject_class->get_property = gtk_object_get_property;
362   gobject_class->dispose = gtk_object_dispose;
363   gobject_class->finalize = gtk_object_finalize;
364 
365   class->destroy = gtk_object_real_destroy;
366 
367   g_object_class_install_property (gobject_class,
368 				   PROP_USER_DATA,
369 				   g_param_spec_pointer ("user-data",
370 							 P_("User Data"),
371 							 P_("Anonymous User Data Pointer"),
372 							 GTK_PARAM_READWRITE));
373   object_signals[DESTROY] =
374     g_signal_new (I_("destroy"),
375 		  G_TYPE_FROM_CLASS (gobject_class),
376 		  G_SIGNAL_RUN_CLEANUP | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
377 		  G_STRUCT_OFFSET (GtkObjectClass, destroy),
378 		  NULL, NULL,
379 		  _gtk_marshal_VOID__VOID,
380 		  G_TYPE_NONE, 0);
381 }
382 
383 static void
gtk_object_init(GtkObject * object,GtkObjectClass * klass)384 gtk_object_init (GtkObject      *object,
385 		 GtkObjectClass *klass)
386 {
387   gboolean was_floating;
388   /* sink the GInitiallyUnowned floating flag */
389   was_floating = gobject_floating_flag_handler (object, -1);
390   /* set GTK_FLOATING via gtk_object_floating_flag_handler */
391   if (was_floating)
392     g_object_force_floating (G_OBJECT (object));
393 }
394 
395 /********************************************
396  * Functions to end a GtkObject's life time
397  *
398  ********************************************/
399 void
gtk_object_destroy(GtkObject * object)400 gtk_object_destroy (GtkObject *object)
401 {
402   g_return_if_fail (object != NULL);
403   g_return_if_fail (GTK_IS_OBJECT (object));
404 
405   if (!(GTK_OBJECT_FLAGS (object) & GTK_IN_DESTRUCTION))
406     g_object_run_dispose (G_OBJECT (object));
407 }
408 
409 static void
gtk_object_dispose(GObject * gobject)410 gtk_object_dispose (GObject *gobject)
411 {
412   GtkObject *object = GTK_OBJECT (gobject);
413 
414   /* guard against reinvocations during
415    * destruction with the GTK_IN_DESTRUCTION flag.
416    */
417   if (!(GTK_OBJECT_FLAGS (object) & GTK_IN_DESTRUCTION))
418     {
419       GTK_OBJECT_SET_FLAGS (object, GTK_IN_DESTRUCTION);
420 
421       g_signal_emit (object, object_signals[DESTROY], 0);
422 
423       GTK_OBJECT_UNSET_FLAGS (object, GTK_IN_DESTRUCTION);
424     }
425 
426   G_OBJECT_CLASS (parent_class)->dispose (gobject);
427 }
428 
429 static void
gtk_object_real_destroy(GtkObject * object)430 gtk_object_real_destroy (GtkObject *object)
431 {
432   g_signal_handlers_destroy (object);
433 }
434 
435 static void
gtk_object_finalize(GObject * gobject)436 gtk_object_finalize (GObject *gobject)
437 {
438   GtkObject *object = GTK_OBJECT (gobject);
439 
440   if (g_object_is_floating (object))
441     {
442       g_warning ("A floating object was finalized. This means that someone\n"
443 		 "called g_object_unref() on an object that had only a floating\n"
444 		 "reference; the initial floating reference is not owned by anyone\n"
445 		 "and must be removed with g_object_ref_sink().");
446     }
447 
448   gtk_object_notify_weaks (object);
449 
450   G_OBJECT_CLASS (parent_class)->finalize (gobject);
451 }
452 
453 /*****************************************
454  * GtkObject argument handlers
455  *
456  *****************************************/
457 
458 static void
gtk_object_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)459 gtk_object_set_property (GObject      *object,
460 			 guint         property_id,
461 			 const GValue *value,
462 			 GParamSpec   *pspec)
463 {
464   switch (property_id)
465     {
466     case PROP_USER_DATA:
467       g_object_set_data (G_OBJECT (object), I_("user_data"), g_value_get_pointer (value));
468       break;
469     default:
470       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
471       break;
472     }
473 }
474 
475 static void
gtk_object_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)476 gtk_object_get_property (GObject     *object,
477 			 guint        property_id,
478 			 GValue      *value,
479 			 GParamSpec  *pspec)
480 {
481   switch (property_id)
482     {
483     case PROP_USER_DATA:
484       g_value_set_pointer (value, g_object_get_data (G_OBJECT (object), "user_data"));
485       break;
486     default:
487       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
488       break;
489     }
490 }
491 
492 void
gtk_object_sink(GtkObject * object)493 gtk_object_sink (GtkObject *object)
494 {
495   g_return_if_fail (GTK_IS_OBJECT (object));
496   g_object_ref_sink (object);
497   g_object_unref (object);
498 }
499 
500 /*****************************************
501  * Weak references.
502  *
503  * Weak refs are very similar to the old "destroy" signal.  They allow
504  * one to register a callback that is called when the weakly
505  * referenced object is finalized.
506  *
507  * They are not implemented as a signal because they really are
508  * special and need to be used with great care.  Unlike signals, which
509  * should be able to execute any code whatsoever.
510  *
511  * A weakref callback is not allowed to retain a reference to the
512  * object.  Object data keys may be retrieved in a weak reference
513  * callback.
514  *
515  * A weakref callback is called at most once.
516  *
517  *****************************************/
518 
519 typedef struct _GtkWeakRef	GtkWeakRef;
520 
521 struct _GtkWeakRef
522 {
523   GtkWeakRef	 *next;
524   GDestroyNotify  notify;
525   gpointer        data;
526 };
527 
528 void
gtk_object_weakref(GtkObject * object,GDestroyNotify notify,gpointer data)529 gtk_object_weakref (GtkObject      *object,
530 		    GDestroyNotify  notify,
531 		    gpointer        data)
532 {
533   GtkWeakRef *weak;
534 
535   g_return_if_fail (notify != NULL);
536   g_return_if_fail (GTK_IS_OBJECT (object));
537 
538   if (!quark_weakrefs)
539     quark_weakrefs = g_quark_from_static_string ("gtk-weakrefs");
540 
541   weak = g_new (GtkWeakRef, 1);
542   weak->next = g_object_get_qdata (G_OBJECT (object), quark_weakrefs);
543   weak->notify = notify;
544   weak->data = data;
545   g_object_set_qdata (G_OBJECT (object), quark_weakrefs, weak);
546 }
547 
548 void
gtk_object_weakunref(GtkObject * object,GDestroyNotify notify,gpointer data)549 gtk_object_weakunref (GtkObject      *object,
550 		      GDestroyNotify  notify,
551 		      gpointer        data)
552 {
553   GtkWeakRef *weaks, *w, **wp;
554 
555   g_return_if_fail (GTK_IS_OBJECT (object));
556 
557   if (!quark_weakrefs)
558     return;
559 
560   weaks = g_object_get_qdata (G_OBJECT (object), quark_weakrefs);
561   for (wp = &weaks; *wp; wp = &(*wp)->next)
562     {
563       w = *wp;
564       if (w->notify == notify && w->data == data)
565 	{
566 	  if (w == weaks)
567 	    g_object_set_qdata (G_OBJECT (object), quark_weakrefs, w->next);
568 	  else
569 	    *wp = w->next;
570 	  g_free (w);
571 	  return;
572 	}
573     }
574 }
575 
576 static void
gtk_object_notify_weaks(GtkObject * object)577 gtk_object_notify_weaks (GtkObject *object)
578 {
579   if (quark_weakrefs)
580     {
581       GtkWeakRef *w1, *w2;
582 
583       w1 = g_object_get_qdata (G_OBJECT (object), quark_weakrefs);
584 
585       while (w1)
586 	{
587 	  w1->notify (w1->data);
588 	  w2 = w1->next;
589 	  g_free (w1);
590 	  w1 = w2;
591 	}
592     }
593 }
594 
595 GtkObject*
gtk_object_new(GType object_type,const gchar * first_property_name,...)596 gtk_object_new (GType        object_type,
597 		const gchar *first_property_name,
598 		...)
599 {
600   GtkObject *object;
601   va_list var_args;
602 
603   g_return_val_if_fail (G_TYPE_IS_OBJECT (object_type), NULL);
604 
605   va_start (var_args, first_property_name);
606   object = (GtkObject *)g_object_new_valist (object_type, first_property_name, var_args);
607   va_end (var_args);
608 
609   return object;
610 }
611 
612 void
gtk_object_get(GtkObject * object,const gchar * first_property_name,...)613 gtk_object_get (GtkObject   *object,
614 		const gchar *first_property_name,
615 		...)
616 {
617   va_list var_args;
618 
619   g_return_if_fail (GTK_IS_OBJECT (object));
620 
621   va_start (var_args, first_property_name);
622   g_object_get_valist (G_OBJECT (object), first_property_name, var_args);
623   va_end (var_args);
624 }
625 
626 void
gtk_object_set(GtkObject * object,const gchar * first_property_name,...)627 gtk_object_set (GtkObject   *object,
628 		const gchar *first_property_name,
629 		...)
630 {
631   va_list var_args;
632 
633   g_return_if_fail (GTK_IS_OBJECT (object));
634 
635   va_start (var_args, first_property_name);
636   g_object_set_valist (G_OBJECT (object), first_property_name, var_args);
637   va_end (var_args);
638 }
639 
640 /*****************************************
641  * GtkObject object_data mechanism
642  *
643  *****************************************/
644 
645 void
gtk_object_set_data_by_id(GtkObject * object,GQuark data_id,gpointer data)646 gtk_object_set_data_by_id (GtkObject        *object,
647 			   GQuark	     data_id,
648 			   gpointer          data)
649 {
650   g_return_if_fail (GTK_IS_OBJECT (object));
651 
652   g_datalist_id_set_data (&G_OBJECT (object)->qdata, data_id, data);
653 }
654 
655 void
gtk_object_set_data(GtkObject * object,const gchar * key,gpointer data)656 gtk_object_set_data (GtkObject        *object,
657 		     const gchar      *key,
658 		     gpointer          data)
659 {
660   g_return_if_fail (GTK_IS_OBJECT (object));
661   g_return_if_fail (key != NULL);
662 
663   g_datalist_set_data (&G_OBJECT (object)->qdata, key, data);
664 }
665 
666 void
gtk_object_set_data_by_id_full(GtkObject * object,GQuark data_id,gpointer data,GDestroyNotify destroy)667 gtk_object_set_data_by_id_full (GtkObject      *object,
668 				GQuark		data_id,
669 				gpointer        data,
670 				GDestroyNotify  destroy)
671 {
672   g_return_if_fail (GTK_IS_OBJECT (object));
673 
674   g_datalist_id_set_data_full (&G_OBJECT (object)->qdata, data_id, data, destroy);
675 }
676 
677 void
gtk_object_set_data_full(GtkObject * object,const gchar * key,gpointer data,GDestroyNotify destroy)678 gtk_object_set_data_full (GtkObject      *object,
679 			  const gchar    *key,
680 			  gpointer        data,
681 			  GDestroyNotify  destroy)
682 {
683   g_return_if_fail (GTK_IS_OBJECT (object));
684   g_return_if_fail (key != NULL);
685 
686   g_datalist_set_data_full (&G_OBJECT (object)->qdata, key, data, destroy);
687 }
688 
689 gpointer
gtk_object_get_data_by_id(GtkObject * object,GQuark data_id)690 gtk_object_get_data_by_id (GtkObject   *object,
691 			   GQuark       data_id)
692 {
693   g_return_val_if_fail (GTK_IS_OBJECT (object), NULL);
694 
695   return g_datalist_id_get_data (&G_OBJECT (object)->qdata, data_id);
696 }
697 
698 gpointer
gtk_object_get_data(GtkObject * object,const gchar * key)699 gtk_object_get_data (GtkObject   *object,
700 		     const gchar *key)
701 {
702   g_return_val_if_fail (GTK_IS_OBJECT (object), NULL);
703   g_return_val_if_fail (key != NULL, NULL);
704 
705   return g_datalist_get_data (&G_OBJECT (object)->qdata, key);
706 }
707 
708 void
gtk_object_remove_data_by_id(GtkObject * object,GQuark data_id)709 gtk_object_remove_data_by_id (GtkObject   *object,
710 			      GQuark       data_id)
711 {
712   g_return_if_fail (GTK_IS_OBJECT (object));
713 
714   g_datalist_id_remove_data (&G_OBJECT (object)->qdata, data_id);
715 }
716 
717 void
gtk_object_remove_data(GtkObject * object,const gchar * key)718 gtk_object_remove_data (GtkObject   *object,
719 			const gchar *key)
720 {
721   g_return_if_fail (GTK_IS_OBJECT (object));
722   g_return_if_fail (key != NULL);
723 
724   g_datalist_remove_data (&G_OBJECT (object)->qdata, key);
725 }
726 
727 void
gtk_object_remove_no_notify_by_id(GtkObject * object,GQuark key_id)728 gtk_object_remove_no_notify_by_id (GtkObject      *object,
729 				   GQuark          key_id)
730 {
731   g_return_if_fail (GTK_IS_OBJECT (object));
732 
733   g_datalist_id_remove_no_notify (&G_OBJECT (object)->qdata, key_id);
734 }
735 
736 void
gtk_object_remove_no_notify(GtkObject * object,const gchar * key)737 gtk_object_remove_no_notify (GtkObject       *object,
738 			     const gchar     *key)
739 {
740   g_return_if_fail (GTK_IS_OBJECT (object));
741   g_return_if_fail (key != NULL);
742 
743   g_datalist_remove_no_notify (&G_OBJECT (object)->qdata, key);
744 }
745 
746 void
gtk_object_set_user_data(GtkObject * object,gpointer data)747 gtk_object_set_user_data (GtkObject *object,
748 			  gpointer   data)
749 {
750   g_return_if_fail (GTK_IS_OBJECT (object));
751 
752   g_object_set_data (G_OBJECT (object), "user_data", data);
753 }
754 
755 gpointer
gtk_object_get_user_data(GtkObject * object)756 gtk_object_get_user_data (GtkObject *object)
757 {
758   g_return_val_if_fail (GTK_IS_OBJECT (object), NULL);
759 
760   return g_object_get_data (G_OBJECT (object), "user_data");
761 }
762 
763 GtkObject*
gtk_object_ref(GtkObject * object)764 gtk_object_ref (GtkObject *object)
765 {
766   g_return_val_if_fail (GTK_IS_OBJECT (object), NULL);
767 
768   return (GtkObject*) g_object_ref ((GObject*) object);
769 }
770 
771 void
gtk_object_unref(GtkObject * object)772 gtk_object_unref (GtkObject *object)
773 {
774   g_return_if_fail (GTK_IS_OBJECT (object));
775 
776   g_object_unref ((GObject*) object);
777 }
778 
779 #define __GTK_OBJECT_C__
780 #include "gtkaliasdef.c"
781