gtkobject.c 21.2 KB
Newer Older
Elliot Lee's avatar
Elliot Lee committed
1 2 3 4
/* GTK - The GIMP Toolkit
 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
 *
 * This library is free software; you can redistribute it and/or
5
 * modify it under the terms of the GNU Lesser General Public
Elliot Lee's avatar
Elliot Lee committed
6 7 8 9 10 11
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
 * Lesser General Public License for more details.
Elliot Lee's avatar
Elliot Lee committed
13
 *
14
 * You should have received a copy of the GNU Lesser General Public
15 16 17
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
Elliot Lee's avatar
Elliot Lee committed
18
 */
19 20

/*
21
 * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
22 23 24 25 26
 * file for a list of people on the GTK+ Team.  See the ChangeLog
 * files for a list of changes.  These files are distributed with
 * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
 */

27
#include <config.h>
Elliot Lee's avatar
Elliot Lee committed
28 29
#include <stdarg.h>
#include <string.h>
30
#include <stdio.h>
Elliot Lee's avatar
Elliot Lee committed
31
#include "gtkobject.h"
32
#include "gtkmarshalers.h"
Elliot Lee's avatar
Elliot Lee committed
33 34 35 36 37 38 39
#include "gtksignal.h"


enum {
  DESTROY,
  LAST_SIGNAL
};
40
enum {
41
  PROP_0,
42
  PROP_USER_DATA
43
};
Elliot Lee's avatar
Elliot Lee committed
44 45


46 47 48 49 50
extern void	  gtk_object_init_type           (void);	/* for gtktypeutils.h */
static void       gtk_object_base_class_init     (GtkObjectClass *class);
static void       gtk_object_base_class_finalize (GtkObjectClass *class);
static void       gtk_object_class_init          (GtkObjectClass *klass);
static void       gtk_object_init                (GtkObject      *object,
51
						  GtkObjectClass *klass);
52 53 54
static void	  gtk_object_set_property	 (GObject	 *object,
						  guint           property_id,
						  const GValue   *value,
Tim Janik's avatar
Tim Janik committed
55
						  GParamSpec     *pspec);
56 57 58
static void	  gtk_object_get_property	 (GObject	 *object,
						  guint           property_id,
						  GValue         *value,
Tim Janik's avatar
Tim Janik committed
59
						  GParamSpec     *pspec);
Tim Janik's avatar
Tim Janik committed
60
static void       gtk_object_dispose            (GObject        *object);
61 62 63
static void       gtk_object_real_destroy        (GtkObject      *object);
static void       gtk_object_finalize            (GObject        *object);
static void       gtk_object_notify_weaks        (GtkObject      *object);
Elliot Lee's avatar
Elliot Lee committed
64

65 66 67
static gpointer    parent_class = NULL;
static guint       object_signals[LAST_SIGNAL] = { 0 };
static GQuark      quark_weakrefs = 0;
Elliot Lee's avatar
Elliot Lee committed
68

69

70 71
/****************************************************
 * GtkObject type, class and instance initialization
Elliot Lee's avatar
Elliot Lee committed
72
 *
73
 ****************************************************/
Elliot Lee's avatar
Elliot Lee committed
74

Manish Singh's avatar
Manish Singh committed
75
GType
76
gtk_object_get_type (void)
Elliot Lee's avatar
Elliot Lee committed
77
{
Manish Singh's avatar
Manish Singh committed
78
  static GType object_type = 0;
79 80 81 82 83 84 85 86 87 88 89 90

  if (!object_type)
    {
      static const GTypeInfo object_info =
      {
	sizeof (GtkObjectClass),
	(GBaseInitFunc) gtk_object_base_class_init,
	(GBaseFinalizeFunc) gtk_object_base_class_finalize,
	(GClassInitFunc) gtk_object_class_init,
	NULL,		/* class_finalize */
	NULL,		/* class_data */
	sizeof (GtkObject),
Manish Singh's avatar
Manish Singh committed
91
	16,		/* n_preallocs */
92
	(GInstanceInitFunc) gtk_object_init,
Manish Singh's avatar
Manish Singh committed
93
	NULL,		/* value_table */
94 95
      };
      
96 97
      object_type = g_type_register_static (G_TYPE_OBJECT, "GtkObject", 
					    &object_info, G_TYPE_FLAG_ABSTRACT);
98 99 100
    }

  return object_type;
Elliot Lee's avatar
Elliot Lee committed
101 102 103
}

static void
104
gtk_object_base_class_init (GtkObjectClass *class)
Elliot Lee's avatar
Elliot Lee committed
105
{
106 107 108 109 110
  /* reset instance specifc methods that don't get inherited */
  class->get_arg = NULL;
  class->set_arg = NULL;
}

111 112 113
static void
gtk_object_base_class_finalize (GtkObjectClass *class)
{
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
}

static inline gboolean
gtk_arg_set_from_value (GtkArg       *arg,
			const GValue *value,
			gboolean      copy_string)
{
  switch (G_TYPE_FUNDAMENTAL (arg->type))
    {
    case G_TYPE_CHAR:           GTK_VALUE_CHAR (*arg) = g_value_get_char (value);       break;
    case G_TYPE_UCHAR:          GTK_VALUE_UCHAR (*arg) = g_value_get_uchar (value);     break;
    case G_TYPE_BOOLEAN:        GTK_VALUE_BOOL (*arg) = g_value_get_boolean (value);    break;
    case G_TYPE_INT:            GTK_VALUE_INT (*arg) = g_value_get_int (value);         break;
    case G_TYPE_UINT:           GTK_VALUE_UINT (*arg) = g_value_get_uint (value);       break;
    case G_TYPE_LONG:           GTK_VALUE_LONG (*arg) = g_value_get_long (value);       break;
    case G_TYPE_ULONG:          GTK_VALUE_ULONG (*arg) = g_value_get_ulong (value);     break;
    case G_TYPE_ENUM:           GTK_VALUE_ENUM (*arg) = g_value_get_enum (value);       break;
    case G_TYPE_FLAGS:          GTK_VALUE_FLAGS (*arg) = g_value_get_flags (value);     break;
    case G_TYPE_FLOAT:          GTK_VALUE_FLOAT (*arg) = g_value_get_float (value);     break;
    case G_TYPE_DOUBLE:         GTK_VALUE_DOUBLE (*arg) = g_value_get_double (value);   break;
    case G_TYPE_BOXED:          GTK_VALUE_BOXED (*arg) = g_value_get_boxed (value);     break;
    case G_TYPE_POINTER:        GTK_VALUE_POINTER (*arg) = g_value_get_pointer (value); break;
    case G_TYPE_OBJECT:         GTK_VALUE_POINTER (*arg) = g_value_get_object (value);  break;
    case G_TYPE_STRING:         if (copy_string)
      GTK_VALUE_STRING (*arg) = g_value_dup_string (value);
    else
140
      GTK_VALUE_STRING (*arg) = (char *) g_value_get_string (value);
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
    break;
    default:
      return FALSE;
    }
  return TRUE;
}

static inline gboolean
gtk_arg_to_value (GtkArg *arg,
		  GValue *value)
{
  switch (G_TYPE_FUNDAMENTAL (arg->type))
    {
    case G_TYPE_CHAR:           g_value_set_char (value, GTK_VALUE_CHAR (*arg));        break;
    case G_TYPE_UCHAR:          g_value_set_uchar (value, GTK_VALUE_UCHAR (*arg));      break;
    case G_TYPE_BOOLEAN:        g_value_set_boolean (value, GTK_VALUE_BOOL (*arg));     break;
    case G_TYPE_INT:            g_value_set_int (value, GTK_VALUE_INT (*arg));          break;
    case G_TYPE_UINT:           g_value_set_uint (value, GTK_VALUE_UINT (*arg));        break;
    case G_TYPE_LONG:           g_value_set_long (value, GTK_VALUE_LONG (*arg));        break;
    case G_TYPE_ULONG:          g_value_set_ulong (value, GTK_VALUE_ULONG (*arg));      break;
    case G_TYPE_ENUM:           g_value_set_enum (value, GTK_VALUE_ENUM (*arg));        break;
    case G_TYPE_FLAGS:          g_value_set_flags (value, GTK_VALUE_FLAGS (*arg));      break;
    case G_TYPE_FLOAT:          g_value_set_float (value, GTK_VALUE_FLOAT (*arg));      break;
    case G_TYPE_DOUBLE:         g_value_set_double (value, GTK_VALUE_DOUBLE (*arg));    break;
    case G_TYPE_STRING:         g_value_set_string (value, GTK_VALUE_STRING (*arg));    break;
    case G_TYPE_BOXED:          g_value_set_boxed (value, GTK_VALUE_BOXED (*arg));      break;
    case G_TYPE_POINTER:        g_value_set_pointer (value, GTK_VALUE_POINTER (*arg));  break;
    case G_TYPE_OBJECT:         g_value_set_object (value, GTK_VALUE_POINTER (*arg));   break;
    default:
      return FALSE;
    }
  return TRUE;
}

static void
gtk_arg_proxy_set_property (GObject      *object,
			    guint         property_id,
			    const GValue *value,
Tim Janik's avatar
Tim Janik committed
179
			    GParamSpec   *pspec)
180 181
{
  GtkObjectClass *class = g_type_class_peek (pspec->owner_type);
182
  GtkArg arg;
183 184 185

  g_return_if_fail (class->set_arg != NULL);

186
  memset (&arg, 0, sizeof (arg));
187 188 189 190 191 192 193 194 195 196
  arg.type = G_VALUE_TYPE (value);
  gtk_arg_set_from_value (&arg, value, FALSE);
  arg.name = pspec->name;
  class->set_arg (GTK_OBJECT (object), &arg, property_id);
}

static void
gtk_arg_proxy_get_property (GObject     *object,
			    guint        property_id,
			    GValue      *value,
Tim Janik's avatar
Tim Janik committed
197
			    GParamSpec  *pspec)
198 199
{
  GtkObjectClass *class = g_type_class_peek (pspec->owner_type);
200
  GtkArg arg;
201 202 203

  g_return_if_fail (class->get_arg != NULL);

204
  memset (&arg, 0, sizeof (arg));
205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224
  arg.type = G_VALUE_TYPE (value);
  arg.name = pspec->name;
  class->get_arg (GTK_OBJECT (object), &arg, property_id);
  gtk_arg_to_value (&arg, value);
}

void
gtk_object_add_arg_type (const gchar *arg_name,
			 GtkType      arg_type,
			 guint        arg_flags,
			 guint        arg_id)
{
  GObjectClass *oclass;
  GParamSpec *pspec;
  gchar *type_name, *pname;
  GType type;
  
  g_return_if_fail (arg_name != NULL);
  g_return_if_fail (arg_type > G_TYPE_NONE);
  g_return_if_fail (arg_id > 0);
225
  g_return_if_fail (arg_flags & G_PARAM_READWRITE);
226 227 228 229
  if (arg_flags & G_PARAM_CONSTRUCT)
    g_return_if_fail ((arg_flags & G_PARAM_CONSTRUCT_ONLY) == 0);
  if (arg_flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY))
    g_return_if_fail (arg_flags & G_PARAM_WRITABLE);
230
  g_return_if_fail ((arg_flags & ~(G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY)) == 0);
231 232 233 234 235 236 237 238 239 240 241

  pname = strchr (arg_name, ':');
  g_return_if_fail (pname && pname[1] == ':');

  type_name = g_strndup (arg_name, pname - arg_name);
  pname += 2;
  type = g_type_from_name (type_name);
  g_free (type_name);
  g_return_if_fail (G_TYPE_IS_OBJECT (type));

  oclass = gtk_type_class (type);
242
  if (arg_flags & G_PARAM_READABLE)
243 244 245 246 247 248 249 250 251
    {
      if (oclass->get_property && oclass->get_property != gtk_arg_proxy_get_property)
	{
	  g_warning (G_STRLOC ": GtkArg compatibility code can't be mixed with customized %s.get_property() implementation",
		     g_type_name (type));
	  return;
	}
      oclass->get_property = gtk_arg_proxy_get_property;
    }
252
  if (arg_flags & G_PARAM_WRITABLE)
253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293
    {
      if (oclass->set_property && oclass->set_property != gtk_arg_proxy_set_property)
	{
	  g_warning (G_STRLOC ": GtkArg compatibility code can't be mixed with customized %s.set_property() implementation",
		     g_type_name (type));
	  return;
	}
      oclass->set_property = gtk_arg_proxy_set_property;
    }
  switch (G_TYPE_FUNDAMENTAL (arg_type))
    {
    case G_TYPE_ENUM:
      pspec = g_param_spec_enum (pname, NULL, NULL, arg_type, 0, arg_flags);
      break;
    case G_TYPE_FLAGS:
      pspec = g_param_spec_flags (pname, NULL, NULL, arg_type, 0, arg_flags);
      break;
    case G_TYPE_CHAR:
      pspec = g_param_spec_char (pname, NULL, NULL, -128, 127, 0, arg_flags);
      break;
    case G_TYPE_UCHAR:
      pspec = g_param_spec_uchar (pname, NULL, NULL, 0, 255, 0, arg_flags);
      break;
    case G_TYPE_BOOLEAN:
      pspec = g_param_spec_boolean (pname, NULL, NULL, FALSE, arg_flags);
      break;
    case G_TYPE_INT:
      pspec = g_param_spec_int (pname, NULL, NULL, -2147483647, 2147483647, 0, arg_flags);
      break;
    case G_TYPE_UINT:
      pspec = g_param_spec_uint (pname, NULL, NULL, 0, 4294967295U, 0, arg_flags);
      break;
    case G_TYPE_FLOAT:
      pspec = g_param_spec_float (pname, NULL, NULL, -1E+37, 1E+37, 0, arg_flags);
      break;
    case G_TYPE_DOUBLE:
      pspec = g_param_spec_double (pname, NULL, NULL, -1E+307, 1E+307, 0, arg_flags);
      break;
    case G_TYPE_STRING:
      pspec = g_param_spec_string (pname, NULL, NULL, NULL, arg_flags);
      break;
294 295 296
    case G_TYPE_POINTER:
      pspec = g_param_spec_pointer (pname, NULL, NULL, arg_flags);
      break;
297 298 299 300 301 302 303 304 305 306 307 308 309 310 311
    case G_TYPE_OBJECT:
      pspec = g_param_spec_object (pname, NULL, NULL, arg_type, arg_flags);
      break;
    case G_TYPE_BOXED:
      if (!G_TYPE_IS_FUNDAMENTAL (arg_type))
	{
	  pspec = g_param_spec_boxed (pname, NULL, NULL, arg_type, arg_flags);
	  break;
	}
    default:
      g_warning (G_STRLOC ": Property type `%s' is not supported by the GtkArg compatibility code",
		 g_type_name (arg_type));
      return;
    }
  g_object_class_install_property (oclass, arg_id, pspec);
312 313
}

314 315 316
static void
gtk_object_class_init (GtkObjectClass *class)
{
317 318 319 320
  GObjectClass *gobject_class = G_OBJECT_CLASS (class);

  parent_class = g_type_class_ref (G_TYPE_OBJECT);

321 322
  gobject_class->set_property = gtk_object_set_property;
  gobject_class->get_property = gtk_object_get_property;
Tim Janik's avatar
Tim Janik committed
323
  gobject_class->dispose = gtk_object_dispose;
324 325 326 327
  gobject_class->finalize = gtk_object_finalize;

  class->destroy = gtk_object_real_destroy;

328 329 330 331 332
  g_object_class_install_property (gobject_class,
				   PROP_USER_DATA,
				   g_param_spec_pointer ("user_data", "User Data",
							 "Anonymous User Data Pointer",
							 G_PARAM_READABLE | G_PARAM_WRITABLE));
Elliot Lee's avatar
Elliot Lee committed
333
  object_signals[DESTROY] =
334 335 336 337 338 339 340
    g_signal_new ("destroy",
		  G_TYPE_FROM_CLASS (gobject_class),
		  G_SIGNAL_RUN_CLEANUP | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
		  G_STRUCT_OFFSET (GtkObjectClass, destroy),
		  NULL, NULL,
		  _gtk_marshal_VOID__VOID,
		  G_TYPE_NONE, 0);
Elliot Lee's avatar
Elliot Lee committed
341 342 343
}

static void
344 345
gtk_object_init (GtkObject      *object,
		 GtkObjectClass *klass)
Elliot Lee's avatar
Elliot Lee committed
346
{
347
  GTK_OBJECT_FLAGS (object) = GTK_FLOATING;
Elliot Lee's avatar
Elliot Lee committed
348 349
}

350 351
/********************************************
 * Functions to end a GtkObject's life time
Elliot Lee's avatar
Elliot Lee committed
352
 *
353 354 355 356 357 358 359
 ********************************************/
void
gtk_object_destroy (GtkObject *object)
{
  g_return_if_fail (object != NULL);
  g_return_if_fail (GTK_IS_OBJECT (object));
  
360 361
  if (!(GTK_OBJECT_FLAGS (object) & GTK_IN_DESTRUCTION))
    g_object_run_dispose (G_OBJECT (object));
362 363 364
}

static void
Tim Janik's avatar
Tim Janik committed
365
gtk_object_dispose (GObject *gobject)
366
{
367 368
  GtkObject *object = GTK_OBJECT (gobject);

369
  /* guard against reinvocations during
Matthias Clasen's avatar
Matthias Clasen committed
370
   * destruction with the GTK_IN_DESTRUCTION flag.
371
   */
372
  if (!(GTK_OBJECT_FLAGS (object) & GTK_IN_DESTRUCTION))
373
    {
374
      GTK_OBJECT_SET_FLAGS (object, GTK_IN_DESTRUCTION);
375
      
376
      g_signal_emit (object, object_signals[DESTROY], 0);
377
      
378
      GTK_OBJECT_UNSET_FLAGS (object, GTK_IN_DESTRUCTION);
379
    }
380

Tim Janik's avatar
Tim Janik committed
381
  G_OBJECT_CLASS (parent_class)->dispose (gobject);
382 383 384 385 386
}

static void
gtk_object_real_destroy (GtkObject *object)
{
Manish Singh's avatar
Manish Singh committed
387
  g_signal_handlers_destroy (object);
388 389 390
}

static void
391
gtk_object_finalize (GObject *gobject)
392
{
393
  GtkObject *object = GTK_OBJECT (gobject);
394

395 396 397 398 399 400 401 402 403
  if (GTK_OBJECT_FLOATING (object))
    {
      g_warning ("A floating object was finalized. This means that someone\n"
		 "called g_object_unref() on an object that had only a floating\n"
		 "reference; the initial floating reference is not owned by anyone\n"
		 "and must be removed with gtk_object_sink() after a normal\n"
		 "reference is obtained with g_object_ref().");
    }
  
404
  gtk_object_notify_weaks (object);
405
  
406
  G_OBJECT_CLASS (parent_class)->finalize (gobject);
407 408 409 410
}

/*****************************************
 * GtkObject argument handlers
Elliot Lee's avatar
Elliot Lee committed
411 412 413 414
 *
 *****************************************/

static void
415 416 417
gtk_object_set_property (GObject      *object,
			 guint         property_id,
			 const GValue *value,
Tim Janik's avatar
Tim Janik committed
418
			 GParamSpec   *pspec)
Elliot Lee's avatar
Elliot Lee committed
419
{
420
  switch (property_id)
Elliot Lee's avatar
Elliot Lee committed
421
    {
422
    case PROP_USER_DATA:
423
      g_object_set_data (G_OBJECT (object), "user_data", g_value_get_pointer (value));
424
      break;
Tim Janik's avatar
Tim Janik committed
425
    default:
426
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
Tim Janik's avatar
Tim Janik committed
427
      break;
428 429 430 431
    }
}

static void
432 433 434
gtk_object_get_property (GObject     *object,
			 guint        property_id,
			 GValue      *value,
Tim Janik's avatar
Tim Janik committed
435
			 GParamSpec  *pspec)
436
{
437
  switch (property_id)
438
    {
439
    case PROP_USER_DATA:
440
      g_value_set_pointer (value, g_object_get_data (G_OBJECT (object), "user_data"));
441
      break;
442
    default:
443
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
444
      break;
Elliot Lee's avatar
Elliot Lee committed
445 446 447
    }
}

448 449 450 451 452 453 454 455 456 457 458
/*****************************************
 * gtk_object_sink:
 *
 *   arguments:
 *
 *   results:
 *****************************************/

void
gtk_object_sink (GtkObject *object)
{
459 460
  g_return_if_fail (GTK_IS_OBJECT (object));

461 462 463
  if (GTK_OBJECT_FLOATING (object))
    {
      GTK_OBJECT_UNSET_FLAGS (object, GTK_FLOATING);
464
      g_object_unref (object);
465 466 467 468 469 470 471 472
    }
}

/*****************************************
 * Weak references.
 *
 * Weak refs are very similar to the old "destroy" signal.  They allow
 * one to register a callback that is called when the weakly
Tim Janik's avatar
Tim Janik committed
473
 * referenced object is finalized.
474 475
 *  
 * They are not implemented as a signal because they really are
476
 * special and need to be used with great care.  Unlike signals, which
477 478 479
 * should be able to execute any code whatsoever.
 * 
 * A weakref callback is not allowed to retain a reference to the
480 481
 * object.  Object data keys may be retrieved in a weak reference
 * callback.
482
 * 
483
 * A weakref callback is called at most once.
484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505
 *
 *****************************************/

typedef struct _GtkWeakRef	GtkWeakRef;

struct _GtkWeakRef
{
  GtkWeakRef	   *next;
  GtkDestroyNotify  notify;
  gpointer          data;
};

void
gtk_object_weakref (GtkObject        *object,
		    GtkDestroyNotify  notify,
		    gpointer          data)
{
  GtkWeakRef *weak;

  g_return_if_fail (notify != NULL);
  g_return_if_fail (GTK_IS_OBJECT (object));

506 507
  if (!quark_weakrefs)
    quark_weakrefs = g_quark_from_static_string ("gtk-weakrefs");
508

509
  weak = g_new (GtkWeakRef, 1);
510
  weak->next = g_object_get_qdata (G_OBJECT (object), quark_weakrefs);
511 512
  weak->notify = notify;
  weak->data = data;
513
  g_object_set_qdata (G_OBJECT (object), quark_weakrefs, weak);
514 515 516 517 518 519 520 521 522 523 524
}

void
gtk_object_weakunref (GtkObject        *object,
		      GtkDestroyNotify  notify,
		      gpointer          data)
{
  GtkWeakRef *weaks, *w, **wp;

  g_return_if_fail (GTK_IS_OBJECT (object));

525
  if (!quark_weakrefs)
526 527
    return;

528
  weaks = g_object_get_qdata (G_OBJECT (object), quark_weakrefs);
529 530 531 532 533 534
  for (wp = &weaks; *wp; wp = &(*wp)->next)
    {
      w = *wp;
      if (w->notify == notify && w->data == data)
	{
	  if (w == weaks)
535
	    g_object_set_qdata (G_OBJECT (object), quark_weakrefs, w->next);
536 537 538 539 540 541 542 543 544
	  else
	    *wp = w->next;
	  g_free (w);
	  return;
	}
    }
}

static void
545
gtk_object_notify_weaks (GtkObject *object)
546
{
547
  if (quark_weakrefs)
548
    {
549 550
      GtkWeakRef *w1, *w2;
      
551
      w1 = g_object_get_qdata (G_OBJECT (object), quark_weakrefs);
552 553 554 555 556 557 558 559
      
      while (w1)
	{
	  w1->notify (w1->data);
	  w2 = w1->next;
	  g_free (w1);
	  w1 = w2;
	}
560
    }
Elliot Lee's avatar
Elliot Lee committed
561 562 563
}

GtkObject*
564
gtk_object_new (GtkType      object_type,
565
		const gchar *first_property_name,
Elliot Lee's avatar
Elliot Lee committed
566 567
		...)
{
568 569
  GtkObject *object;
  va_list var_args;
Elliot Lee's avatar
Elliot Lee committed
570

571
  g_return_val_if_fail (G_TYPE_IS_OBJECT (object_type), NULL);
Elliot Lee's avatar
Elliot Lee committed
572

573
  va_start (var_args, first_property_name);
Owen Taylor's avatar
Owen Taylor committed
574
  object = (GtkObject *)g_object_new_valist (object_type, first_property_name, var_args);
575
  va_end (var_args);
576

577 578
  return object;
}
Elliot Lee's avatar
Elliot Lee committed
579

580 581
void
gtk_object_get (GtkObject   *object,
582
		const gchar *first_property_name,
583 584 585 586 587 588
		...)
{
  va_list var_args;
  
  g_return_if_fail (GTK_IS_OBJECT (object));
  
589 590 591
  va_start (var_args, first_property_name);
  g_object_get_valist (G_OBJECT (object), first_property_name, var_args);
  va_end (var_args);
592 593
}

594
void
595 596
gtk_object_set (GtkObject   *object,
		const gchar *first_property_name,
597 598 599
		...)
{
  va_list var_args;
600
  
601 602
  g_return_if_fail (GTK_IS_OBJECT (object));
  
603 604
  va_start (var_args, first_property_name);
  g_object_set_valist (G_OBJECT (object), first_property_name, var_args);
605
  va_end (var_args);
Elliot Lee's avatar
Elliot Lee committed
606 607 608
}

/*****************************************
609
 * GtkObject object_data mechanism
Elliot Lee's avatar
Elliot Lee committed
610 611 612
 *
 *****************************************/

613 614
void
gtk_object_set_data_by_id (GtkObject        *object,
615
			   GQuark	     data_id,
616 617
			   gpointer          data)
{
618
  g_return_if_fail (GTK_IS_OBJECT (object));
619
  
620
  g_datalist_id_set_data (&G_OBJECT (object)->qdata, data_id, data);
621 622
}

Elliot Lee's avatar
Elliot Lee committed
623
void
624 625 626 627
gtk_object_set_data (GtkObject        *object,
		     const gchar      *key,
		     gpointer          data)
{
628
  g_return_if_fail (GTK_IS_OBJECT (object));
629 630
  g_return_if_fail (key != NULL);
  
631
  g_datalist_set_data (&G_OBJECT (object)->qdata, key, data);
632 633 634
}

void
635
gtk_object_set_data_by_id_full (GtkObject        *object,
636
				GQuark		  data_id,
637 638
				gpointer          data,
				GtkDestroyNotify  destroy)
Elliot Lee's avatar
Elliot Lee committed
639 640
{
  g_return_if_fail (GTK_IS_OBJECT (object));
641

642
  g_datalist_id_set_data_full (&G_OBJECT (object)->qdata, data_id, data, destroy);
Elliot Lee's avatar
Elliot Lee committed
643 644
}

645 646 647 648 649 650
void
gtk_object_set_data_full (GtkObject        *object,
			  const gchar      *key,
			  gpointer          data,
			  GtkDestroyNotify  destroy)
{
651
  g_return_if_fail (GTK_IS_OBJECT (object));
652 653
  g_return_if_fail (key != NULL);

654
  g_datalist_set_data_full (&G_OBJECT (object)->qdata, key, data, destroy);
655 656
}

Elliot Lee's avatar
Elliot Lee committed
657
gpointer
658
gtk_object_get_data_by_id (GtkObject   *object,
659
			   GQuark       data_id)
Elliot Lee's avatar
Elliot Lee committed
660 661 662
{
  g_return_val_if_fail (GTK_IS_OBJECT (object), NULL);

663
  return g_datalist_id_get_data (&G_OBJECT (object)->qdata, data_id);
664 665 666 667 668 669
}

gpointer
gtk_object_get_data (GtkObject   *object,
		     const gchar *key)
{
670
  g_return_val_if_fail (GTK_IS_OBJECT (object), NULL);
671 672
  g_return_val_if_fail (key != NULL, NULL);

673
  return g_datalist_get_data (&G_OBJECT (object)->qdata, key);
Elliot Lee's avatar
Elliot Lee committed
674 675
}

676 677
void
gtk_object_remove_data_by_id (GtkObject   *object,
678
			      GQuark       data_id)
679
{
680 681
  g_return_if_fail (GTK_IS_OBJECT (object));

682
  g_datalist_id_remove_data (&G_OBJECT (object)->qdata, data_id);
683
}
Elliot Lee's avatar
Elliot Lee committed
684 685 686 687 688

void
gtk_object_remove_data (GtkObject   *object,
			const gchar *key)
{
689 690
  g_return_if_fail (GTK_IS_OBJECT (object));
  g_return_if_fail (key != NULL);
691

692
  g_datalist_remove_data (&G_OBJECT (object)->qdata, key);
693 694 695
}

void
696 697
gtk_object_remove_no_notify_by_id (GtkObject      *object,
				   GQuark          key_id)
698 699 700
{
  g_return_if_fail (GTK_IS_OBJECT (object));

701
  g_datalist_id_remove_no_notify (&G_OBJECT (object)->qdata, key_id);
702 703 704
}

void
705
gtk_object_remove_no_notify (GtkObject       *object,
706
			     const gchar     *key)
707 708
{
  g_return_if_fail (GTK_IS_OBJECT (object));
Elliot Lee's avatar
Elliot Lee committed
709 710
  g_return_if_fail (key != NULL);

711
  g_datalist_remove_no_notify (&G_OBJECT (object)->qdata, key);
712 713
}

Elliot Lee's avatar
Elliot Lee committed
714 715 716 717
void
gtk_object_set_user_data (GtkObject *object,
			  gpointer   data)
{
718 719
  g_return_if_fail (GTK_IS_OBJECT (object));

720
  g_object_set_data (G_OBJECT (object), "user_data", data);
Elliot Lee's avatar
Elliot Lee committed
721 722 723 724 725
}

gpointer
gtk_object_get_user_data (GtkObject *object)
{
726
  g_return_val_if_fail (GTK_IS_OBJECT (object), NULL);
Elliot Lee's avatar
Elliot Lee committed
727

728
  return g_object_get_data (G_OBJECT (object), "user_data");
Elliot Lee's avatar
Elliot Lee committed
729 730
}

731
GtkObject*
732 733
gtk_object_ref (GtkObject *object)
{
734
  g_return_val_if_fail (GTK_IS_OBJECT (object), NULL);
735

736
  return (GtkObject*) g_object_ref ((GObject*) object);
737 738 739 740 741 742
}

void
gtk_object_unref (GtkObject *object)
{
  g_return_if_fail (GTK_IS_OBJECT (object));
Tim Janik's avatar
Tim Janik committed
743

744
  g_object_unref ((GObject*) object);
745
}