moved includes back to the top of the files (before gtk-doc SECTION
[platform/upstream/glib.git] / gobject / gparam.c
1 /* GObject - GLib Type, Object, Parameter and Signal Library
2  * Copyright (C) 1997-1999, 2000-2001 Tim Janik and Red Hat, Inc.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General
15  * Public License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * MT safe
22  */
23
24 #include "config.h"
25
26 #include <string.h>
27
28 #include "gparam.h"
29 #include "gparamspecs.h"
30 #include "gvaluecollector.h"
31 #include "gobjectalias.h"
32
33
34 /**
35  * SECTION:gparamspec
36  * @Short_description: Metadata for parameter specifications
37  * @See_also:g_object_class_install_property(), g_object_set(), g_object_get(),
38  * g_object_set_property(), g_object_get_property(), g_value_register_transform_func()
39  * @Title: GParamSpec
40  *
41  * #GParamSpec is an object structure that encapsulates the metadata
42  * required to specify parameters, such as e.g. #GObject properties.
43  *
44  * <para id="canonical-parameter-name">
45  * Parameter names need to start with a letter (a-z or A-Z). Subsequent
46  * characters can be letters, numbers or a '-'.
47  * All other characters are replaced by a '-' during construction.
48  * The result of this replacement is called the canonical name of the
49  * parameter.
50  * </para>
51  */
52
53
54 /* --- defines --- */
55 #define PARAM_FLOATING_FLAG                     0x2
56 #define G_PARAM_USER_MASK                       (~0 << G_PARAM_USER_SHIFT)
57 #define PSPEC_APPLIES_TO_VALUE(pspec, value)    (G_TYPE_CHECK_VALUE_TYPE ((value), G_PARAM_SPEC_VALUE_TYPE (pspec)))
58 #define G_SLOCK(mutex)                          g_static_mutex_lock (mutex)
59 #define G_SUNLOCK(mutex)                        g_static_mutex_unlock (mutex)
60
61
62 /* --- prototypes --- */
63 static void     g_param_spec_class_base_init     (GParamSpecClass       *class);
64 static void     g_param_spec_class_base_finalize (GParamSpecClass       *class);
65 static void     g_param_spec_class_init          (GParamSpecClass       *class,
66                                                   gpointer               class_data);
67 static void     g_param_spec_init                (GParamSpec            *pspec,
68                                                   GParamSpecClass       *class);
69 static void     g_param_spec_finalize            (GParamSpec            *pspec);
70 static void     value_param_init                (GValue         *value);
71 static void     value_param_free_value          (GValue         *value);
72 static void     value_param_copy_value          (const GValue   *src_value,
73                                                  GValue         *dest_value);
74 static void     value_param_transform_value     (const GValue   *src_value,
75                                                  GValue         *dest_value);
76 static gpointer value_param_peek_pointer        (const GValue   *value);
77 static gchar*   value_param_collect_value       (GValue         *value,
78                                                  guint           n_collect_values,
79                                                  GTypeCValue    *collect_values,
80                                                  guint           collect_flags);
81 static gchar*   value_param_lcopy_value         (const GValue   *value,
82                                                  guint           n_collect_values,
83                                                  GTypeCValue    *collect_values,
84                                                  guint           collect_flags);
85
86
87 /* --- functions --- */
88 void
89 g_param_type_init (void)
90 {
91   static const GTypeFundamentalInfo finfo = {
92     (G_TYPE_FLAG_CLASSED |
93      G_TYPE_FLAG_INSTANTIATABLE |
94      G_TYPE_FLAG_DERIVABLE |
95      G_TYPE_FLAG_DEEP_DERIVABLE),
96   };
97   static const GTypeValueTable param_value_table = {
98     value_param_init,           /* value_init */
99     value_param_free_value,     /* value_free */
100     value_param_copy_value,     /* value_copy */
101     value_param_peek_pointer,   /* value_peek_pointer */
102     "p",                        /* collect_format */
103     value_param_collect_value,  /* collect_value */
104     "p",                        /* lcopy_format */
105     value_param_lcopy_value,    /* lcopy_value */
106   };
107   static const GTypeInfo param_spec_info = {
108     sizeof (GParamSpecClass),
109
110     (GBaseInitFunc) g_param_spec_class_base_init,
111     (GBaseFinalizeFunc) g_param_spec_class_base_finalize,
112     (GClassInitFunc) g_param_spec_class_init,
113     (GClassFinalizeFunc) NULL,
114     NULL,       /* class_data */
115
116     sizeof (GParamSpec),
117     0,          /* n_preallocs */
118     (GInstanceInitFunc) g_param_spec_init,
119
120     &param_value_table,
121   };
122   GType type;
123
124   type = g_type_register_fundamental (G_TYPE_PARAM, g_intern_static_string ("GParam"), &param_spec_info, &finfo, G_TYPE_FLAG_ABSTRACT);
125   g_assert (type == G_TYPE_PARAM);
126   g_value_register_transform_func (G_TYPE_PARAM, G_TYPE_PARAM, value_param_transform_value);
127 }
128
129 static void
130 g_param_spec_class_base_init (GParamSpecClass *class)
131 {
132 }
133
134 static void
135 g_param_spec_class_base_finalize (GParamSpecClass *class)
136 {
137 }
138
139 static void
140 g_param_spec_class_init (GParamSpecClass *class,
141                          gpointer         class_data)
142 {
143   class->value_type = G_TYPE_NONE;
144   class->finalize = g_param_spec_finalize;
145   class->value_set_default = NULL;
146   class->value_validate = NULL;
147   class->values_cmp = NULL;
148 }
149
150 static void
151 g_param_spec_init (GParamSpec      *pspec,
152                    GParamSpecClass *class)
153 {
154   pspec->name = NULL;
155   pspec->_nick = NULL;
156   pspec->_blurb = NULL;
157   pspec->flags = 0;
158   pspec->value_type = class->value_type;
159   pspec->owner_type = 0;
160   pspec->qdata = NULL;
161   g_datalist_init (&pspec->qdata);
162   g_datalist_set_flags (&pspec->qdata, PARAM_FLOATING_FLAG);
163   pspec->ref_count = 1;
164   pspec->param_id = 0;
165 }
166
167 static void
168 g_param_spec_finalize (GParamSpec *pspec)
169 {
170   g_datalist_clear (&pspec->qdata);
171
172   if (!(pspec->flags & G_PARAM_STATIC_NAME))
173     g_free (pspec->name);
174   
175   if (!(pspec->flags & G_PARAM_STATIC_NICK))
176     g_free (pspec->_nick);
177
178   if (!(pspec->flags & G_PARAM_STATIC_BLURB))
179     g_free (pspec->_blurb);
180
181   g_type_free_instance ((GTypeInstance*) pspec);
182 }
183
184 /**
185  * g_param_spec_ref:
186  * @pspec: a valid #GParamSpec
187  * 
188  * Increments the reference count of @pspec.
189  * 
190  * Returns: the #GParamSpec that was passed into this function
191  */
192 GParamSpec*
193 g_param_spec_ref (GParamSpec *pspec)
194 {
195   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
196   g_return_val_if_fail (pspec->ref_count > 0, NULL);
197
198   g_atomic_int_inc (&pspec->ref_count);
199
200   return pspec;
201 }
202
203 /**
204  * g_param_spec_unref:
205  * @pspec: a valid #GParamSpec
206  * 
207  * Decrements the reference count of a @pspec.
208  */
209 void
210 g_param_spec_unref (GParamSpec *pspec)
211 {
212   gboolean is_zero;
213
214   g_return_if_fail (G_IS_PARAM_SPEC (pspec));
215   g_return_if_fail (pspec->ref_count > 0);
216
217   is_zero = g_atomic_int_dec_and_test (&pspec->ref_count);
218
219   if (G_UNLIKELY (is_zero))
220     {
221       G_PARAM_SPEC_GET_CLASS (pspec)->finalize (pspec);
222     }
223 }
224
225 /**
226  * g_param_spec_sink:
227  * @pspec: a valid #GParamSpec
228  * 
229  * The initial reference count of a newly created #GParamSpec is 1, even 
230  * though no one has explicitly called g_param_spec_ref() on it yet. So the 
231  * initial reference count is flagged as "floating", until someone calls 
232  * <literal>g_param_spec_ref (pspec); g_param_spec_sink (pspec);</literal>
233  * in sequence on it, taking over the initial reference count (thus
234  * ending up with a @pspec that has a reference count of 1 still, but is
235  * not flagged "floating" anymore).
236  */
237 void
238 g_param_spec_sink (GParamSpec *pspec)
239 {
240   gpointer oldvalue;
241   g_return_if_fail (G_IS_PARAM_SPEC (pspec));
242   g_return_if_fail (pspec->ref_count > 0);
243
244   do
245     oldvalue = g_atomic_pointer_get (&pspec->qdata);
246   while (!g_atomic_pointer_compare_and_exchange ((void**) &pspec->qdata, oldvalue,
247                                                  (gpointer) ((gsize) oldvalue & ~(gsize) PARAM_FLOATING_FLAG)));
248   if ((gsize) oldvalue & PARAM_FLOATING_FLAG)
249     g_param_spec_unref (pspec);
250 }
251
252 /**
253  * g_param_spec_ref_sink:
254  * @pspec: a valid #GParamSpec
255  * 
256  * Convenience function to ref and sink a #GParamSpec.
257  * 
258  * Since: 2.10
259  * Returns: the #GParamSpec that was passed into this function
260  */
261 GParamSpec*
262 g_param_spec_ref_sink (GParamSpec *pspec)
263 {
264   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
265   g_return_val_if_fail (pspec->ref_count > 0, NULL);
266
267   g_param_spec_ref (pspec);
268   g_param_spec_sink (pspec);
269   return pspec;
270 }
271
272 /**
273  * g_param_spec_get_name:
274  * @pspec: a valid #GParamSpec
275  * 
276  * Get the name of a #GParamSpec.
277  * 
278  * Returns: the name of @pspec.
279  */
280 G_CONST_RETURN gchar*
281 g_param_spec_get_name (GParamSpec *pspec)
282 {
283   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
284
285   return pspec->name;
286 }
287
288 /**
289  * g_param_spec_get_nick:
290  * @pspec: a valid #GParamSpec
291  * 
292  * Get the nickname of a #GParamSpec.
293  * 
294  * Returns: the nickname of @pspec.
295  */
296 G_CONST_RETURN gchar*
297 g_param_spec_get_nick (GParamSpec *pspec)
298 {
299   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
300
301   if (pspec->_nick)
302     return pspec->_nick;
303   else
304     {
305       GParamSpec *redirect_target;
306
307       redirect_target = g_param_spec_get_redirect_target (pspec);
308       if (redirect_target && redirect_target->_nick)
309         return redirect_target->_nick;
310     }
311
312   return pspec->name;
313 }
314
315 /**
316  * g_param_spec_get_blurb:
317  * @pspec: a valid #GParamSpec
318  * 
319  * Get the short description of a #GParamSpec.
320  * 
321  * Returns: the short description of @pspec.
322  */
323 G_CONST_RETURN gchar*
324 g_param_spec_get_blurb (GParamSpec *pspec)
325 {
326   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
327
328   if (pspec->_blurb)
329     return pspec->_blurb;
330   else
331     {
332       GParamSpec *redirect_target;
333
334       redirect_target = g_param_spec_get_redirect_target (pspec);
335       if (redirect_target && redirect_target->_blurb)
336         return redirect_target->_blurb;
337     }
338
339   return NULL;
340 }
341
342 static void
343 canonicalize_key (gchar *key)
344 {
345   gchar *p;
346   
347   for (p = key; *p != 0; p++)
348     {
349       gchar c = *p;
350       
351       if (c != '-' &&
352           (c < '0' || c > '9') &&
353           (c < 'A' || c > 'Z') &&
354           (c < 'a' || c > 'z'))
355         *p = '-';
356     }
357 }
358
359 static gboolean
360 is_canonical (const gchar *key)
361 {
362   const gchar *p;
363
364   for (p = key; *p != 0; p++)
365     {
366       gchar c = *p;
367       
368       if (c != '-' &&
369           (c < '0' || c > '9') &&
370           (c < 'A' || c > 'Z') &&
371           (c < 'a' || c > 'z'))
372         return FALSE;
373     }
374
375   return TRUE;
376 }
377
378 /**
379  * g_param_spec_internal:
380  * @param_type: the #GType for the property; must be derived from #G_TYPE_PARAM
381  * @name: the canonical name of the property
382  * @nick: the nickname of the property
383  * @blurb: a short description of the property
384  * @flags: a combination of #GParamFlags
385  * 
386  * Creates a new #GParamSpec instance.
387  * 
388  * A property name consists of segments consisting of ASCII letters and
389  * digits, separated by either the '-' or '_' character. The first
390  * character of a property name must be a letter. Names which violate these
391  * rules lead to undefined behaviour. 
392  * 
393  * When creating and looking up a #GParamSpec, either separator can be used, 
394  * but they cannot be mixed. Using '-' is considerably more efficient and in 
395  * fact required when using property names as detail strings for signals.
396  * 
397  * Beyond the name, #GParamSpec<!-- -->s have two more descriptive strings 
398  * associated with them, the @nick, which should be suitable for use as 
399  * a label for the property in a property editor, and the @blurb, which should
400  * be a somewhat longer description, suitable for e.g. a tooltip. The @nick
401  * and @blurb should ideally be localized.
402  * 
403  * Returns: a newly allocated #GParamSpec instance
404  */
405 gpointer
406 g_param_spec_internal (GType        param_type,
407                        const gchar *name,
408                        const gchar *nick,
409                        const gchar *blurb,
410                        GParamFlags  flags)
411 {
412   GParamSpec *pspec;
413   
414   g_return_val_if_fail (G_TYPE_IS_PARAM (param_type) && param_type != G_TYPE_PARAM, NULL);
415   g_return_val_if_fail (name != NULL, NULL);
416   g_return_val_if_fail ((name[0] >= 'A' && name[0] <= 'Z') || (name[0] >= 'a' && name[0] <= 'z'), NULL);
417   g_return_val_if_fail (!(flags & G_PARAM_STATIC_NAME) || is_canonical (name), NULL);
418   
419   pspec = (gpointer) g_type_create_instance (param_type);
420
421   if (flags & G_PARAM_STATIC_NAME)
422     {
423       pspec->name = g_intern_static_string (name);
424       if (!is_canonical (pspec->name))
425         g_warning ("G_PARAM_STATIC_NAME used with non-canonical pspec name: %s", pspec->name);
426     }
427   else
428     {
429       pspec->name = g_strdup (name);
430       canonicalize_key (pspec->name);
431       g_intern_string (pspec->name);
432     }
433
434   if (flags & G_PARAM_STATIC_NICK)
435     pspec->_nick = (gchar*) nick;
436   else
437     pspec->_nick = g_strdup (nick);
438
439   if (flags & G_PARAM_STATIC_BLURB)
440     pspec->_blurb = (gchar*) blurb;
441   else
442     pspec->_blurb = g_strdup (blurb);
443
444   pspec->flags = (flags & G_PARAM_USER_MASK) | (flags & G_PARAM_MASK);
445   
446   return pspec;
447 }
448
449 /**
450  * g_param_spec_get_qdata:
451  * @pspec: a valid #GParamSpec
452  * @quark: a #GQuark, naming the user data pointer
453  * 
454  * Gets back user data pointers stored via g_param_spec_set_qdata().
455  * 
456  * Returns: the user data pointer set, or %NULL
457  */
458 gpointer
459 g_param_spec_get_qdata (GParamSpec *pspec,
460                         GQuark      quark)
461 {
462   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
463   
464   return quark ? g_datalist_id_get_data (&pspec->qdata, quark) : NULL;
465 }
466
467 /**
468  * g_param_spec_set_qdata:
469  * @pspec: the #GParamSpec to set store a user data pointer
470  * @quark: a #GQuark, naming the user data pointer
471  * @data: an opaque user data pointer
472  * 
473  * Sets an opaque, named pointer on a #GParamSpec. The name is specified 
474  * through a #GQuark (retrieved e.g. via g_quark_from_static_string()), and 
475  * the pointer can be gotten back from the @pspec with g_param_spec_get_qdata().
476  * Setting a previously set user data pointer, overrides (frees)
477  * the old pointer set, using %NULL as pointer essentially
478  * removes the data stored.
479  */
480 void
481 g_param_spec_set_qdata (GParamSpec *pspec,
482                         GQuark      quark,
483                         gpointer    data)
484 {
485   g_return_if_fail (G_IS_PARAM_SPEC (pspec));
486   g_return_if_fail (quark > 0);
487
488   g_datalist_id_set_data (&pspec->qdata, quark, data);
489 }
490
491 /**
492  * g_param_spec_set_qdata_full:
493  * @pspec: the #GParamSpec to set store a user data pointer
494  * @quark: a #GQuark, naming the user data pointer
495  * @data: an opaque user data pointer
496  * @destroy: function to invoke with @data as argument, when @data needs to
497  *  be freed
498  * 
499  * This function works like g_param_spec_set_qdata(), but in addition, 
500  * a <literal>void (*destroy) (gpointer)</literal> function may be 
501  * specified which is called with @data as argument when the @pspec is 
502  * finalized, or the data is being overwritten by a call to 
503  * g_param_spec_set_qdata() with the same @quark.
504  */
505 void
506 g_param_spec_set_qdata_full (GParamSpec    *pspec,
507                              GQuark         quark,
508                              gpointer       data,
509                              GDestroyNotify destroy)
510 {
511   g_return_if_fail (G_IS_PARAM_SPEC (pspec));
512   g_return_if_fail (quark > 0);
513
514   g_datalist_id_set_data_full (&pspec->qdata, quark, data, data ? destroy : (GDestroyNotify) NULL);
515 }
516
517 /**
518  * g_param_spec_steal_qdata:
519  * @pspec: the #GParamSpec to get a stored user data pointer from
520  * @quark: a #GQuark, naming the user data pointer
521  * 
522  * Gets back user data pointers stored via g_param_spec_set_qdata() and 
523  * removes the @data from @pspec without invoking it's destroy() function 
524  * (if any was set).
525  * Usually, calling this function is only required to update
526  * user data pointers with a destroy notifier.
527  * 
528  * Returns: the user data pointer set, or %NULL
529  */
530 gpointer
531 g_param_spec_steal_qdata (GParamSpec *pspec,
532                           GQuark      quark)
533 {
534   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
535   g_return_val_if_fail (quark > 0, NULL);
536   
537   return g_datalist_id_remove_no_notify (&pspec->qdata, quark);
538 }
539
540 /**
541  * g_param_spec_get_redirect_target:
542  * @pspec: a #GParamSpec
543  * 
544  * If the paramspec redirects operations to another paramspec,
545  * returns that paramspec. Redirect is used typically for
546  * providing a new implementation of a property in a derived
547  * type while preserving all the properties from the parent
548  * type. Redirection is established by creating a property
549  * of type #GParamSpecOverride. See g_object_class_override_property()
550  * for an example of the use of this capability.
551  * 
552  * Since: 2.4
553  * Returns: paramspec to which requests on this paramspec should
554  *  be redirected, or %NULL if none.
555  */
556 GParamSpec*
557 g_param_spec_get_redirect_target (GParamSpec *pspec)
558 {
559   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
560
561   if (G_IS_PARAM_SPEC_OVERRIDE (pspec))
562     {
563       GParamSpecOverride *ospec = G_PARAM_SPEC_OVERRIDE (pspec);
564
565       return ospec->overridden;
566     }
567   else
568     return NULL;
569 }
570
571 /**
572  * g_param_value_set_default:
573  * @pspec: a valid #GParamSpec
574  * @value: a #GValue of correct type for @pspec
575  * 
576  * Sets @value to its default value as specified in @pspec.
577  */
578 void
579 g_param_value_set_default (GParamSpec *pspec,
580                            GValue     *value)
581 {
582   g_return_if_fail (G_IS_PARAM_SPEC (pspec));
583   g_return_if_fail (G_IS_VALUE (value));
584   g_return_if_fail (PSPEC_APPLIES_TO_VALUE (pspec, value));
585
586   g_value_reset (value);
587   G_PARAM_SPEC_GET_CLASS (pspec)->value_set_default (pspec, value);
588 }
589
590 /**
591  * g_param_value_defaults:
592  * @pspec: a valid #GParamSpec
593  * @value: a #GValue of correct type for @pspec
594  * 
595  * Checks whether @value contains the default value as specified in @pspec.
596  * 
597  * Returns: whether @value contains the canonical default for this @pspec
598  */
599 gboolean
600 g_param_value_defaults (GParamSpec *pspec,
601                         GValue     *value)
602 {
603   GValue dflt_value = { 0, };
604   gboolean defaults;
605
606   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), FALSE);
607   g_return_val_if_fail (G_IS_VALUE (value), FALSE);
608   g_return_val_if_fail (PSPEC_APPLIES_TO_VALUE (pspec, value), FALSE);
609
610   g_value_init (&dflt_value, G_PARAM_SPEC_VALUE_TYPE (pspec));
611   G_PARAM_SPEC_GET_CLASS (pspec)->value_set_default (pspec, &dflt_value);
612   defaults = G_PARAM_SPEC_GET_CLASS (pspec)->values_cmp (pspec, value, &dflt_value) == 0;
613   g_value_unset (&dflt_value);
614
615   return defaults;
616 }
617
618 /**
619  * g_param_value_validate:
620  * @pspec: a valid #GParamSpec
621  * @value: a #GValue of correct type for @pspec
622  * 
623  * Ensures that the contents of @value comply with the specifications
624  * set out by @pspec. For example, a #GParamSpecInt might require
625  * that integers stored in @value may not be smaller than -42 and not be
626  * greater than +42. If @value contains an integer outside of this range,
627  * it is modified accordingly, so the resulting value will fit into the
628  * range -42 .. +42.
629  * 
630  * Returns: whether modifying @value was necessary to ensure validity
631  */
632 gboolean
633 g_param_value_validate (GParamSpec *pspec,
634                         GValue     *value)
635 {
636   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), FALSE);
637   g_return_val_if_fail (G_IS_VALUE (value), FALSE);
638   g_return_val_if_fail (PSPEC_APPLIES_TO_VALUE (pspec, value), FALSE);
639
640   if (G_PARAM_SPEC_GET_CLASS (pspec)->value_validate)
641     {
642       GValue oval = *value;
643
644       if (G_PARAM_SPEC_GET_CLASS (pspec)->value_validate (pspec, value) ||
645           memcmp (&oval.data, &value->data, sizeof (oval.data)))
646         return TRUE;
647     }
648
649   return FALSE;
650 }
651
652 /**
653  * g_param_value_convert:
654  * @pspec: a valid #GParamSpec
655  * @src_value: souce #GValue
656  * @dest_value: destination #GValue of correct type for @pspec
657  * @strict_validation: %TRUE requires @dest_value to conform to @pspec without modifications
658  * 
659  * Transforms @src_value into @dest_value if possible, and then validates 
660  * @dest_value, in order for it to conform to @pspec.
661  * If @strict_validation is %TRUE this function will only succeed if
662  * the transformed @dest_value complied to @pspec without modifications.
663  * 
664  * See also g_value_type_transformable(), g_value_transform() and
665  * g_param_value_validate().
666  * 
667  * Returns: %TRUE if transformation and validation were successful,
668  *  %FALSE otherwise and @dest_value is left untouched.
669  */
670 gboolean
671 g_param_value_convert (GParamSpec   *pspec,
672                        const GValue *src_value,
673                        GValue       *dest_value,
674                        gboolean      strict_validation)
675 {
676   GValue tmp_value = { 0, };
677
678   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), FALSE);
679   g_return_val_if_fail (G_IS_VALUE (src_value), FALSE);
680   g_return_val_if_fail (G_IS_VALUE (dest_value), FALSE);
681   g_return_val_if_fail (PSPEC_APPLIES_TO_VALUE (pspec, dest_value), FALSE);
682
683   /* better leave dest_value untouched when returning FALSE */
684
685   g_value_init (&tmp_value, G_VALUE_TYPE (dest_value));
686   if (g_value_transform (src_value, &tmp_value) &&
687       (!g_param_value_validate (pspec, &tmp_value) || !strict_validation))
688     {
689       g_value_unset (dest_value);
690       
691       /* values are relocatable */
692       memcpy (dest_value, &tmp_value, sizeof (tmp_value));
693       
694       return TRUE;
695     }
696   else
697     {
698       g_value_unset (&tmp_value);
699       
700       return FALSE;
701     }
702 }
703
704 /**
705  * g_param_values_cmp:
706  * @pspec: a valid #GParamSpec
707  * @value1: a #GValue of correct type for @pspec
708  * @value2: a #GValue of correct type for @pspec
709  * 
710  * Compares @value1 with @value2 according to @pspec, and return -1, 0 or +1,
711  * if @value1 is found to be less than, equal to or greater than @value2, 
712  * respectively.
713  * 
714  * Returns: -1, 0 or +1, for a less than, equal to or greater than result
715  */
716 gint
717 g_param_values_cmp (GParamSpec   *pspec,
718                     const GValue *value1,
719                     const GValue *value2)
720 {
721   gint cmp;
722
723   /* param_values_cmp() effectively does: value1 - value2
724    * so the return values are:
725    * -1)  value1 < value2
726    *  0)  value1 == value2
727    *  1)  value1 > value2
728    */
729   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), 0);
730   g_return_val_if_fail (G_IS_VALUE (value1), 0);
731   g_return_val_if_fail (G_IS_VALUE (value2), 0);
732   g_return_val_if_fail (PSPEC_APPLIES_TO_VALUE (pspec, value1), 0);
733   g_return_val_if_fail (PSPEC_APPLIES_TO_VALUE (pspec, value2), 0);
734
735   cmp = G_PARAM_SPEC_GET_CLASS (pspec)->values_cmp (pspec, value1, value2);
736
737   return CLAMP (cmp, -1, 1);
738 }
739
740 static void
741 value_param_init (GValue *value)
742 {
743   value->data[0].v_pointer = NULL;
744 }
745
746 static void
747 value_param_free_value (GValue *value)
748 {
749   if (value->data[0].v_pointer)
750     g_param_spec_unref (value->data[0].v_pointer);
751 }
752
753 static void
754 value_param_copy_value (const GValue *src_value,
755                         GValue       *dest_value)
756 {
757   if (src_value->data[0].v_pointer)
758     dest_value->data[0].v_pointer = g_param_spec_ref (src_value->data[0].v_pointer);
759   else
760     dest_value->data[0].v_pointer = NULL;
761 }
762
763 static void
764 value_param_transform_value (const GValue *src_value,
765                              GValue       *dest_value)
766 {
767   if (src_value->data[0].v_pointer &&
768       g_type_is_a (G_PARAM_SPEC_TYPE (dest_value->data[0].v_pointer), G_VALUE_TYPE (dest_value)))
769     dest_value->data[0].v_pointer = g_param_spec_ref (src_value->data[0].v_pointer);
770   else
771     dest_value->data[0].v_pointer = NULL;
772 }
773
774 static gpointer
775 value_param_peek_pointer (const GValue *value)
776 {
777   return value->data[0].v_pointer;
778 }
779
780 static gchar*
781 value_param_collect_value (GValue      *value,
782                            guint        n_collect_values,
783                            GTypeCValue *collect_values,
784                            guint        collect_flags)
785 {
786   if (collect_values[0].v_pointer)
787     {
788       GParamSpec *param = collect_values[0].v_pointer;
789
790       if (param->g_type_instance.g_class == NULL)
791         return g_strconcat ("invalid unclassed param spec pointer for value type `",
792                             G_VALUE_TYPE_NAME (value),
793                             "'",
794                             NULL);
795       else if (!g_value_type_compatible (G_PARAM_SPEC_TYPE (param), G_VALUE_TYPE (value)))
796         return g_strconcat ("invalid param spec type `",
797                             G_PARAM_SPEC_TYPE_NAME (param),
798                             "' for value type `",
799                             G_VALUE_TYPE_NAME (value),
800                             "'",
801                             NULL);
802       value->data[0].v_pointer = g_param_spec_ref (param);
803     }
804   else
805     value->data[0].v_pointer = NULL;
806
807   return NULL;
808 }
809
810 static gchar*
811 value_param_lcopy_value (const GValue *value,
812                          guint         n_collect_values,
813                          GTypeCValue  *collect_values,
814                          guint         collect_flags)
815 {
816   GParamSpec **param_p = collect_values[0].v_pointer;
817
818   if (!param_p)
819     return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value));
820
821   if (!value->data[0].v_pointer)
822     *param_p = NULL;
823   else if (collect_flags & G_VALUE_NOCOPY_CONTENTS)
824     *param_p = value->data[0].v_pointer;
825   else
826     *param_p = g_param_spec_ref (value->data[0].v_pointer);
827
828   return NULL;
829 }
830
831
832 /* --- param spec pool --- */
833 /**
834  * GParamSpecPool:
835  * 
836  * A #GParamSpecPool maintains a collection of #GParamSpec<!-- -->s which can be
837  * quickly accessed by owner and name. The implementation of the #GObject property
838  * system uses such a pool to store the #GParamSpecs of the properties all object
839  * types. 
840  */
841 struct _GParamSpecPool
842 {
843   GStaticMutex smutex;
844   gboolean     type_prefixing;
845   GHashTable  *hash_table;
846 };
847
848 static guint
849 param_spec_pool_hash (gconstpointer key_spec)
850 {
851   const GParamSpec *key = key_spec;
852   const gchar *p;
853   guint h = key->owner_type;
854
855   for (p = key->name; *p; p++)
856     h = (h << 5) - h + *p;
857
858   return h;
859 }
860
861 static gboolean
862 param_spec_pool_equals (gconstpointer key_spec_1,
863                         gconstpointer key_spec_2)
864 {
865   const GParamSpec *key1 = key_spec_1;
866   const GParamSpec *key2 = key_spec_2;
867
868   return (key1->owner_type == key2->owner_type &&
869           strcmp (key1->name, key2->name) == 0);
870 }
871
872 /**
873  * g_param_spec_pool_new:
874  * @type_prefixing: Whether the pool will support type-prefixed property names.
875  * 
876  * Creates a new #GParamSpecPool.
877  * 
878  * If @type_prefixing is %TRUE, lookups in the newly created pool will
879  * allow to specify the owner as a colon-separated prefix of the property name, 
880  * like "GtkContainer:border-width". This feature is deprecated, so you should 
881  * always set @type_prefixing to %FALSE.
882  * 
883  * Returns: a newly allocated #GParamSpecPool.
884  */
885 GParamSpecPool*
886 g_param_spec_pool_new (gboolean type_prefixing)
887 {
888   static GStaticMutex init_smutex = G_STATIC_MUTEX_INIT;
889   GParamSpecPool *pool = g_new (GParamSpecPool, 1);
890
891   memcpy (&pool->smutex, &init_smutex, sizeof (init_smutex));
892   pool->type_prefixing = type_prefixing != FALSE;
893   pool->hash_table = g_hash_table_new (param_spec_pool_hash, param_spec_pool_equals);
894
895   return pool;
896 }
897
898 /**
899  * g_param_spec_pool_insert:
900  * @pool: a #GParamSpecPool.
901  * @pspec: the #GParamSpec to insert
902  * @owner_type: a #GType identifying the owner of @pspec
903  * 
904  * Inserts a #GParamSpec in the pool.
905  */void
906 g_param_spec_pool_insert (GParamSpecPool *pool,
907                           GParamSpec     *pspec,
908                           GType           owner_type)
909 {
910   gchar *p;
911   
912   if (pool && pspec && owner_type > 0 && pspec->owner_type == 0)
913     {
914       G_SLOCK (&pool->smutex);
915       for (p = pspec->name; *p; p++)
916         {
917           if (!strchr (G_CSET_A_2_Z G_CSET_a_2_z G_CSET_DIGITS "-_", *p))
918             {
919               g_warning (G_STRLOC ": pspec name \"%s\" contains invalid characters", pspec->name);
920               G_SUNLOCK (&pool->smutex);
921               return;
922             }
923         }
924       
925       pspec->owner_type = owner_type;
926       g_param_spec_ref (pspec);
927       g_hash_table_insert (pool->hash_table, pspec, pspec);
928       G_SUNLOCK (&pool->smutex);
929     }
930   else
931     {
932       g_return_if_fail (pool != NULL);
933       g_return_if_fail (pspec);
934       g_return_if_fail (owner_type > 0);
935       g_return_if_fail (pspec->owner_type == 0);
936     }
937 }
938
939 /**
940  * g_param_spec_pool_remove:
941  * @pool: a #GParamSpecPool
942  * @pspec: the #GParamSpec to remove
943  * 
944  * Removes a #GParamSpec from the pool.
945  */
946 void
947 g_param_spec_pool_remove (GParamSpecPool *pool,
948                           GParamSpec     *pspec)
949 {
950   if (pool && pspec)
951     {
952       G_SLOCK (&pool->smutex);
953       if (g_hash_table_remove (pool->hash_table, pspec))
954         g_param_spec_unref (pspec);
955       else
956         g_warning (G_STRLOC ": attempt to remove unknown pspec `%s' from pool", pspec->name);
957       G_SUNLOCK (&pool->smutex);
958     }
959   else
960     {
961       g_return_if_fail (pool != NULL);
962       g_return_if_fail (pspec);
963     }
964 }
965
966 static inline GParamSpec*
967 param_spec_ht_lookup (GHashTable  *hash_table,
968                       const gchar *param_name,
969                       GType        owner_type,
970                       gboolean     walk_ancestors)
971 {
972   GParamSpec key, *pspec;
973
974   key.owner_type = owner_type;
975   key.name = (gchar*) param_name;
976   if (walk_ancestors)
977     do
978       {
979         pspec = g_hash_table_lookup (hash_table, &key);
980         if (pspec)
981           return pspec;
982         key.owner_type = g_type_parent (key.owner_type);
983       }
984     while (key.owner_type);
985   else
986     pspec = g_hash_table_lookup (hash_table, &key);
987
988   if (!pspec && !is_canonical (param_name))
989     {
990       /* try canonicalized form */
991       key.name = g_strdup (param_name);
992       key.owner_type = owner_type;
993       
994       canonicalize_key (key.name);
995       if (walk_ancestors)
996         do
997           {
998             pspec = g_hash_table_lookup (hash_table, &key);
999             if (pspec)
1000               {
1001                 g_free (key.name);
1002                 return pspec;
1003               }
1004             key.owner_type = g_type_parent (key.owner_type);
1005           }
1006         while (key.owner_type);
1007       else
1008         pspec = g_hash_table_lookup (hash_table, &key);
1009       g_free (key.name);
1010     }
1011
1012   return pspec;
1013 }
1014
1015 /**
1016  * g_param_spec_pool_lookup:
1017  * @pool: a #GParamSpecPool
1018  * @param_name: the name to look for
1019  * @owner_type: the owner to look for
1020  * @walk_ancestors: If %TRUE, also try to find a #GParamSpec with @param_name 
1021  *  owned by an ancestor of @owner_type.
1022  * 
1023  * Looks up a #GParamSpec in the pool.
1024  * 
1025  * Returns: The found #GParamSpec, or %NULL if no matching #GParamSpec was found.
1026  */
1027 GParamSpec*
1028 g_param_spec_pool_lookup (GParamSpecPool *pool,
1029                           const gchar    *param_name,
1030                           GType           owner_type,
1031                           gboolean        walk_ancestors)
1032 {
1033   GParamSpec *pspec;
1034   gchar *delim;
1035
1036   if (!pool || !param_name)
1037     {
1038       g_return_val_if_fail (pool != NULL, NULL);
1039       g_return_val_if_fail (param_name != NULL, NULL);
1040     }
1041
1042   G_SLOCK (&pool->smutex);
1043
1044   delim = pool->type_prefixing ? strchr (param_name, ':') : NULL;
1045
1046   /* try quick and away, i.e. without prefix */
1047   if (!delim)
1048     {
1049       pspec = param_spec_ht_lookup (pool->hash_table, param_name, owner_type, walk_ancestors);
1050       G_SUNLOCK (&pool->smutex);
1051
1052       return pspec;
1053     }
1054
1055   /* strip type prefix */
1056   if (pool->type_prefixing && delim[1] == ':')
1057     {
1058       guint l = delim - param_name;
1059       gchar stack_buffer[32], *buffer = l < 32 ? stack_buffer : g_new (gchar, l + 1);
1060       GType type;
1061       
1062       strncpy (buffer, param_name, delim - param_name);
1063       buffer[l] = 0;
1064       type = g_type_from_name (buffer);
1065       if (l >= 32)
1066         g_free (buffer);
1067       if (type)         /* type==0 isn't a valid type pefix */
1068         {
1069           /* sanity check, these cases don't make a whole lot of sense */
1070           if ((!walk_ancestors && type != owner_type) || !g_type_is_a (owner_type, type))
1071             {
1072               G_SUNLOCK (&pool->smutex);
1073
1074               return NULL;
1075             }
1076           owner_type = type;
1077           param_name += l + 2;
1078           pspec = param_spec_ht_lookup (pool->hash_table, param_name, owner_type, walk_ancestors);
1079           G_SUNLOCK (&pool->smutex);
1080
1081           return pspec;
1082         }
1083     }
1084   /* malformed param_name */
1085
1086   G_SUNLOCK (&pool->smutex);
1087
1088   return NULL;
1089 }
1090
1091 static void
1092 pool_list (gpointer key,
1093            gpointer value,
1094            gpointer user_data)
1095 {
1096   GParamSpec *pspec = value;
1097   gpointer *data = user_data;
1098   GType owner_type = (GType) data[1];
1099
1100   if (owner_type == pspec->owner_type)
1101     data[0] = g_list_prepend (data[0], pspec);
1102 }
1103
1104 /**
1105  * g_param_spec_pool_list_owned:
1106  * @pool: a #GParamSpecPool
1107  * @owner_type: the owner to look for
1108  * 
1109  * Gets an #GList of all #GParamSpec<!-- -->s owned by @owner_type in the pool. 
1110  * 
1111  * Returns: a #GList of all #GParamSpec<!-- -->s owned by @owner_type in 
1112  *  the pool#GParamSpec<!-- -->s.
1113  */
1114 GList*
1115 g_param_spec_pool_list_owned (GParamSpecPool *pool,
1116                               GType           owner_type)
1117 {
1118   gpointer data[2];
1119
1120   g_return_val_if_fail (pool != NULL, NULL);
1121   g_return_val_if_fail (owner_type > 0, NULL);
1122   
1123   G_SLOCK (&pool->smutex);
1124   data[0] = NULL;
1125   data[1] = (gpointer) owner_type;
1126   g_hash_table_foreach (pool->hash_table, pool_list, &data);
1127   G_SUNLOCK (&pool->smutex);
1128
1129   return data[0];
1130 }
1131
1132 static gint
1133 pspec_compare_id (gconstpointer a,
1134                   gconstpointer b)
1135 {
1136   const GParamSpec *pspec1 = a, *pspec2 = b;
1137
1138   return pspec1->param_id < pspec2->param_id ? -1 : pspec1->param_id > pspec2->param_id;
1139 }
1140
1141 static inline GSList*
1142 pspec_list_remove_overridden_and_redirected (GSList     *plist,
1143                                              GHashTable *ht,
1144                                              GType       owner_type,
1145                                              guint      *n_p)
1146 {
1147   GSList *rlist = NULL;
1148
1149   while (plist)
1150     {
1151       GSList *tmp = plist->next;
1152       GParamSpec *pspec = plist->data;
1153       GParamSpec *found;
1154       gboolean remove = FALSE;
1155
1156       /* Remove paramspecs that are redirected, and also paramspecs
1157        * that have are overridden by non-redirected properties.
1158        * The idea is to get the single paramspec for each name that
1159        * best corresponds to what the application sees.
1160        */
1161       if (g_param_spec_get_redirect_target (pspec))
1162         remove = TRUE;
1163       else
1164         {
1165           found = param_spec_ht_lookup (ht, pspec->name, owner_type, TRUE);
1166           if (found != pspec)
1167             {
1168               GParamSpec *redirect = g_param_spec_get_redirect_target (found);
1169               if (redirect != pspec)
1170                 remove = TRUE;
1171             }
1172         }
1173
1174       if (remove)
1175         {
1176           g_slist_free_1 (plist);
1177         }
1178       else
1179         {
1180           plist->next = rlist;
1181           rlist = plist;
1182           *n_p += 1;
1183         }
1184       plist = tmp;
1185     }
1186   return rlist;
1187 }
1188
1189 static void
1190 pool_depth_list (gpointer key,
1191                  gpointer value,
1192                  gpointer user_data)
1193 {
1194   GParamSpec *pspec = value;
1195   gpointer *data = user_data;
1196   GSList **slists = data[0];
1197   GType owner_type = (GType) data[1];
1198
1199   if (g_type_is_a (owner_type, pspec->owner_type))
1200     {
1201       if (G_TYPE_IS_INTERFACE (pspec->owner_type))
1202         {
1203           slists[0] = g_slist_prepend (slists[0], pspec);
1204         }
1205       else
1206         {
1207           guint d = g_type_depth (pspec->owner_type);
1208
1209           slists[d - 1] = g_slist_prepend (slists[d - 1], pspec);
1210         }
1211     }
1212 }
1213
1214 /* We handle interfaces specially since we don't want to
1215  * count interface prerequisites like normal inheritance;
1216  * the property comes from the direct inheritance from
1217  * the prerequisite class, not from the interface that
1218  * prerequires it.
1219  * 
1220  * also 'depth' isn't a meaningful concept for interface
1221  * prerequites.
1222  */
1223 static void
1224 pool_depth_list_for_interface (gpointer key,
1225                                gpointer value,
1226                                gpointer user_data)
1227 {
1228   GParamSpec *pspec = value;
1229   gpointer *data = user_data;
1230   GSList **slists = data[0];
1231   GType owner_type = (GType) data[1];
1232
1233   if (pspec->owner_type == owner_type)
1234     slists[0] = g_slist_prepend (slists[0], pspec);
1235 }
1236
1237 /**
1238  * g_param_spec_pool_list:
1239  * @pool: a #GParamSpecPool
1240  * @owner_type: the owner to look for
1241  * @n_pspecs_p: return location for the length of the returned array
1242  * 
1243  * Gets an array of all #GParamSpec<!-- -->s owned by @owner_type in the pool. 
1244  * 
1245  * Returns: a newly allocated array containing pointers to all 
1246  *  #GParamSpec<!-- -->s owned by @owner_type in the pool
1247  */
1248 GParamSpec**
1249 g_param_spec_pool_list (GParamSpecPool *pool,
1250                         GType           owner_type,
1251                         guint          *n_pspecs_p)
1252 {
1253   GParamSpec **pspecs, **p;
1254   GSList **slists, *node;
1255   gpointer data[2];
1256   guint d, i;
1257
1258   g_return_val_if_fail (pool != NULL, NULL);
1259   g_return_val_if_fail (owner_type > 0, NULL);
1260   g_return_val_if_fail (n_pspecs_p != NULL, NULL);
1261   
1262   G_SLOCK (&pool->smutex);
1263   *n_pspecs_p = 0;
1264   d = g_type_depth (owner_type);
1265   slists = g_new0 (GSList*, d);
1266   data[0] = slists;
1267   data[1] = (gpointer) owner_type;
1268
1269   g_hash_table_foreach (pool->hash_table,
1270                         G_TYPE_IS_INTERFACE (owner_type) ?
1271                            pool_depth_list_for_interface :
1272                            pool_depth_list,
1273                         &data);
1274   
1275   for (i = 0; i < d; i++)
1276     slists[i] = pspec_list_remove_overridden_and_redirected (slists[i], pool->hash_table, owner_type, n_pspecs_p);
1277   pspecs = g_new (GParamSpec*, *n_pspecs_p + 1);
1278   p = pspecs;
1279   for (i = 0; i < d; i++)
1280     {
1281       slists[i] = g_slist_sort (slists[i], pspec_compare_id);
1282       for (node = slists[i]; node; node = node->next)
1283         *p++ = node->data;
1284       g_slist_free (slists[i]);
1285     }
1286   *p++ = NULL;
1287   g_free (slists);
1288   G_SUNLOCK (&pool->smutex);
1289
1290   return pspecs;
1291 }
1292
1293
1294 /* --- auxillary functions --- */
1295 typedef struct
1296 {
1297   /* class portion */
1298   GType           value_type;
1299   void          (*finalize)             (GParamSpec   *pspec);
1300   void          (*value_set_default)    (GParamSpec   *pspec,
1301                                          GValue       *value);
1302   gboolean      (*value_validate)       (GParamSpec   *pspec,
1303                                          GValue       *value);
1304   gint          (*values_cmp)           (GParamSpec   *pspec,
1305                                          const GValue *value1,
1306                                          const GValue *value2);
1307 } ParamSpecClassInfo;
1308
1309 static void
1310 param_spec_generic_class_init (gpointer g_class,
1311                                gpointer class_data)
1312 {
1313   GParamSpecClass *class = g_class;
1314   ParamSpecClassInfo *info = class_data;
1315
1316   class->value_type = info->value_type;
1317   if (info->finalize)
1318     class->finalize = info->finalize;                   /* optional */
1319   class->value_set_default = info->value_set_default;
1320   if (info->value_validate)
1321     class->value_validate = info->value_validate;       /* optional */
1322   class->values_cmp = info->values_cmp;
1323   g_free (class_data);
1324 }
1325
1326 static void
1327 default_value_set_default (GParamSpec *pspec,
1328                            GValue     *value)
1329 {
1330   /* value is already zero initialized */
1331 }
1332
1333 static gint
1334 default_values_cmp (GParamSpec   *pspec,
1335                     const GValue *value1,
1336                     const GValue *value2)
1337 {
1338   return memcmp (&value1->data, &value2->data, sizeof (value1->data));
1339 }
1340
1341 /**
1342  * g_param_type_register_static:
1343  * @name: 0-terminated string used as the name of the new #GParamSpec type.
1344  * @pspec_info: The #GParamSpecTypeInfo for this #GParamSpec type.
1345  * 
1346  * Registers @name as the name of a new static type derived from
1347  * #G_TYPE_PARAM. The type system uses the information contained in the
1348  * #GParamSpecTypeInfo structure pointed to by @info to manage the #GParamSpec 
1349  * type and its instances. 
1350  * 
1351  * Returns: The new type identifier.
1352  */
1353 GType
1354 g_param_type_register_static (const gchar              *name,
1355                               const GParamSpecTypeInfo *pspec_info)
1356 {
1357   GTypeInfo info = {
1358     sizeof (GParamSpecClass),      /* class_size */
1359     NULL,                          /* base_init */
1360     NULL,                          /* base_destroy */
1361     param_spec_generic_class_init, /* class_init */
1362     NULL,                          /* class_destroy */
1363     NULL,                          /* class_data */
1364     0,                             /* instance_size */
1365     16,                            /* n_preallocs */
1366     NULL,                          /* instance_init */
1367   };
1368   ParamSpecClassInfo *cinfo;
1369
1370   g_return_val_if_fail (name != NULL, 0);
1371   g_return_val_if_fail (pspec_info != NULL, 0);
1372   g_return_val_if_fail (g_type_from_name (name) == 0, 0);
1373   g_return_val_if_fail (pspec_info->instance_size >= sizeof (GParamSpec), 0);
1374   g_return_val_if_fail (g_type_name (pspec_info->value_type) != NULL, 0);
1375   /* default: g_return_val_if_fail (pspec_info->value_set_default != NULL, 0); */
1376   /* optional: g_return_val_if_fail (pspec_info->value_validate != NULL, 0); */
1377   /* default: g_return_val_if_fail (pspec_info->values_cmp != NULL, 0); */
1378
1379   info.instance_size = pspec_info->instance_size;
1380   info.n_preallocs = pspec_info->n_preallocs;
1381   info.instance_init = (GInstanceInitFunc) pspec_info->instance_init;
1382   cinfo = g_new (ParamSpecClassInfo, 1);
1383   cinfo->value_type = pspec_info->value_type;
1384   cinfo->finalize = pspec_info->finalize;
1385   cinfo->value_set_default = pspec_info->value_set_default ? pspec_info->value_set_default : default_value_set_default;
1386   cinfo->value_validate = pspec_info->value_validate;
1387   cinfo->values_cmp = pspec_info->values_cmp ? pspec_info->values_cmp : default_values_cmp;
1388   info.class_data = cinfo;
1389
1390   return g_type_register_static (G_TYPE_PARAM, name, &info, 0);
1391 }
1392
1393 /**
1394  * g_value_set_param:
1395  * @value: a valid #GValue of type %G_TYPE_PARAM
1396  * @param: the #GParamSpec to be set
1397  * 
1398  * Set the contents of a %G_TYPE_PARAM #GValue to @param.
1399  */
1400 void
1401 g_value_set_param (GValue     *value,
1402                    GParamSpec *param)
1403 {
1404   g_return_if_fail (G_VALUE_HOLDS_PARAM (value));
1405   if (param)
1406     g_return_if_fail (G_IS_PARAM_SPEC (param));
1407
1408   if (value->data[0].v_pointer)
1409     g_param_spec_unref (value->data[0].v_pointer);
1410   value->data[0].v_pointer = param;
1411   if (value->data[0].v_pointer)
1412     g_param_spec_ref (value->data[0].v_pointer);
1413 }
1414
1415 /**
1416  * g_value_set_param_take_ownership:
1417  * @value: a valid #GValue of type %G_TYPE_PARAM
1418  * @param: the #GParamSpec to be set
1419  * 
1420  * This is an internal function introduced mainly for C marshallers.
1421  * 
1422  * Deprecated: 2.4: Use g_value_take_param() instead.
1423  */
1424 void
1425 g_value_set_param_take_ownership (GValue     *value,
1426                                   GParamSpec *param)
1427 {
1428   g_value_take_param (value, param);
1429 }
1430
1431 /**
1432  * g_value_take_param:
1433  * @value: a valid #GValue of type %G_TYPE_PARAM
1434  * @param: the #GParamSpec to be set
1435  * 
1436  * Sets the contents of a %G_TYPE_PARAM #GValue to @param and
1437  * takes over the ownership of the callers reference to @param; 
1438  * the caller doesn't have to unref it any more.
1439  * 
1440  * Since: 2.4
1441  */
1442 void
1443 g_value_take_param (GValue     *value,
1444                     GParamSpec *param)
1445 {
1446   g_return_if_fail (G_VALUE_HOLDS_PARAM (value));
1447   if (param)
1448     g_return_if_fail (G_IS_PARAM_SPEC (param));
1449
1450   if (value->data[0].v_pointer)
1451     g_param_spec_unref (value->data[0].v_pointer);
1452   value->data[0].v_pointer = param; /* we take over the reference count */
1453 }
1454
1455 /**
1456  * g_value_get_param:
1457  * @value: a valid #GValue whose type is derived from %G_TYPE_PARAM
1458  * 
1459  * Get the contents of a %G_TYPE_PARAM #GValue.
1460  * 
1461  * Returns: #GParamSpec content of @value
1462  */
1463 GParamSpec*
1464 g_value_get_param (const GValue *value)
1465 {
1466   g_return_val_if_fail (G_VALUE_HOLDS_PARAM (value), NULL);
1467
1468   return value->data[0].v_pointer;
1469 }
1470
1471 /**
1472  * g_value_dup_param:
1473  * @value: a valid #GValue whose type is derived from %G_TYPE_PARAM
1474  * 
1475  * Get the contents of a %G_TYPE_PARAM #GValue, increasing its reference count.
1476  * 
1477  * Returns: #GParamSpec content of @value, should be unreferenced when no longer needed.
1478  */
1479 GParamSpec*
1480 g_value_dup_param (const GValue *value)
1481 {
1482   g_return_val_if_fail (G_VALUE_HOLDS_PARAM (value), NULL);
1483
1484   return value->data[0].v_pointer ? g_param_spec_ref (value->data[0].v_pointer) : NULL;
1485 }
1486
1487 #define __G_PARAM_C__
1488 #include "gobjectaliasdef.c"