source: trunk/third/gtk/gtk/gtkobject.c @ 14482

Revision 14482, 29.4 KB checked in by ghudson, 24 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r14481, which included commits to RCS files with non-trunk default branches.
Line 
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
34enum {
35  DESTROY,
36  LAST_SIGNAL
37};
38enum {
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
48void                  gtk_object_init_type       (void);
49static void           gtk_object_base_class_init (GtkObjectClass *klass);
50static void           gtk_object_class_init      (GtkObjectClass *klass);
51static void           gtk_object_init            (GtkObject      *object,
52                                                  GtkObjectClass *klass);
53static void           gtk_object_set_arg         (GtkObject      *object,
54                                                  GtkArg         *arg,
55                                                  guint           arg_id);
56static void           gtk_object_get_arg         (GtkObject      *object,
57                                                  GtkArg         *arg,
58                                                  guint           arg_id);
59static void           gtk_object_shutdown        (GtkObject      *object);
60static void           gtk_object_real_destroy    (GtkObject      *object);
61static void           gtk_object_finalize        (GtkObject      *object);
62static void           gtk_object_notify_weaks    (GtkObject      *object);
63
64static guint object_signals[LAST_SIGNAL] = { 0 };
65
66static GHashTable *object_arg_info_ht = NULL;
67
68static GQuark quark_user_data = 0;
69static GQuark quark_weakrefs = 0;
70static GQuark quark_carg_history = 0;
71
72
73#ifdef G_ENABLE_DEBUG
74static guint obj_count = 0;
75static GHashTable *living_objs_ht = NULL;
76static void
77gtk_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}
89static void
90gtk_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
99void
100gtk_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
113void
114gtk_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
133GtkType
134gtk_object_get_type (void)
135{
136  return GTK_TYPE_OBJECT;
137}
138
139static void
140gtk_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
153static void
154gtk_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
196static void
197gtk_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 ********************************************/
232void
233gtk_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
251static void
252gtk_object_shutdown (GtkObject *object)
253{
254  GTK_OBJECT_SET_FLAGS (object, GTK_DESTROYED);
255  gtk_signal_emit (object, object_signals[DESTROY]);
256}
257
258static void
259gtk_object_real_destroy (GtkObject *object)
260{
261  if (GTK_OBJECT_CONNECTED (object))
262    gtk_signal_handlers_destroy (object);
263}
264
265static void
266gtk_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
280static void
281gtk_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
326static void
327gtk_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
352void
353gtk_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
367guint
368gtk_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
414guint
415gtk_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
453void
454gtk_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
485typedef struct _GtkWeakRef      GtkWeakRef;
486
487struct _GtkWeakRef
488{
489  GtkWeakRef       *next;
490  GtkDestroyNotify  notify;
491  gpointer          data;
492};
493
494void
495gtk_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
515void
516gtk_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
544static void
545gtk_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
568GtkObject*
569gtk_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
618GtkObject*
619gtk_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
641void
642gtk_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
657void
658gtk_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
673void
674gtk_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
716void
717gtk_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
759void
760gtk_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
823void
824gtk_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
865void
866gtk_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
918void
919gtk_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
930void
931gtk_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
974gchar*
975gtk_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
989gchar*
990gtk_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
1000GtkArg*
1001gtk_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
1017void
1018gtk_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
1028void
1029gtk_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
1040void
1041gtk_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
1052void
1053gtk_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
1065gpointer
1066gtk_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
1075gpointer
1076gtk_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
1086void
1087gtk_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
1096void
1097gtk_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
1107void
1108gtk_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
1117void
1118gtk_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
1128void
1129gtk_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
1141gpointer
1142gtk_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
1158void
1159gtk_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
1168void
1169gtk_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
1198static GtkObject *gtk_trace_object = NULL;
1199void
1200gtk_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}
Note: See TracBrowser for help on using the repository browser.