gparamspecs.c revision 617332234d4426ed0941ec1e2cb9f0736bd796c3
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	"gparamspecs.h"
25
26#include	"gvaluecollector.h"
27#include	"gvaluearray.h"
28#include	<string.h>
29#include	"../config.h"	/* for SIZEOF_LONG */
30
31#define	G_FLOAT_EPSILON		(1e-30)
32#define	G_DOUBLE_EPSILON	(1e-90)
33
34
35/* --- param spec functions --- */
36static void
37param_char_init (GParamSpec *pspec)
38{
39  GParamSpecChar *cspec = G_PARAM_SPEC_CHAR (pspec);
40
41  cspec->minimum = 0x7f;
42  cspec->maximum = 0x80;
43  cspec->default_value = 0;
44}
45
46static void
47param_char_set_default (GParamSpec *pspec,
48			GValue	   *value)
49{
50  value->data[0].v_int = G_PARAM_SPEC_CHAR (pspec)->default_value;
51}
52
53static gboolean
54param_char_validate (GParamSpec *pspec,
55		     GValue     *value)
56{
57  GParamSpecChar *cspec = G_PARAM_SPEC_CHAR (pspec);
58  gint oval = value->data[0].v_int;
59
60  value->data[0].v_int = CLAMP (value->data[0].v_int, cspec->minimum, cspec->maximum);
61
62  return value->data[0].v_int != oval;
63}
64
65static void
66param_uchar_init (GParamSpec *pspec)
67{
68  GParamSpecUChar *uspec = G_PARAM_SPEC_UCHAR (pspec);
69
70  uspec->minimum = 0;
71  uspec->maximum = 0xff;
72  uspec->default_value = 0;
73}
74
75static void
76param_uchar_set_default (GParamSpec *pspec,
77			 GValue	    *value)
78{
79  value->data[0].v_uint = G_PARAM_SPEC_UCHAR (pspec)->default_value;
80}
81
82static gboolean
83param_uchar_validate (GParamSpec *pspec,
84		      GValue     *value)
85{
86  GParamSpecUChar *uspec = G_PARAM_SPEC_UCHAR (pspec);
87  guint oval = value->data[0].v_uint;
88
89  value->data[0].v_uint = CLAMP (value->data[0].v_uint, uspec->minimum, uspec->maximum);
90
91  return value->data[0].v_uint != oval;
92}
93
94static void
95param_boolean_set_default (GParamSpec *pspec,
96			   GValue     *value)
97{
98  value->data[0].v_int = G_PARAM_SPEC_BOOLEAN (pspec)->default_value;
99}
100
101static gboolean
102param_boolean_validate (GParamSpec *pspec,
103			GValue     *value)
104{
105  gint oval = value->data[0].v_int;
106
107  value->data[0].v_int = value->data[0].v_int != FALSE;
108
109  return value->data[0].v_int != oval;
110}
111
112static void
113param_int_init (GParamSpec *pspec)
114{
115  GParamSpecInt *ispec = G_PARAM_SPEC_INT (pspec);
116
117  ispec->minimum = 0x7fffffff;
118  ispec->maximum = 0x80000000;
119  ispec->default_value = 0;
120}
121
122static void
123param_int_set_default (GParamSpec *pspec,
124		       GValue     *value)
125{
126  value->data[0].v_int = G_PARAM_SPEC_INT (pspec)->default_value;
127}
128
129static gboolean
130param_int_validate (GParamSpec *pspec,
131		    GValue     *value)
132{
133  GParamSpecInt *ispec = G_PARAM_SPEC_INT (pspec);
134  gint oval = value->data[0].v_int;
135
136  value->data[0].v_int = CLAMP (value->data[0].v_int, ispec->minimum, ispec->maximum);
137
138  return value->data[0].v_int != oval;
139}
140
141static gint
142param_int_values_cmp (GParamSpec   *pspec,
143		      const GValue *value1,
144		      const GValue *value2)
145{
146  if (value1->data[0].v_int < value2->data[0].v_int)
147    return -1;
148  else
149    return value1->data[0].v_int > value2->data[0].v_int;
150}
151
152static void
153param_uint_init (GParamSpec *pspec)
154{
155  GParamSpecUInt *uspec = G_PARAM_SPEC_UINT (pspec);
156
157  uspec->minimum = 0;
158  uspec->maximum = 0xffffffff;
159  uspec->default_value = 0;
160}
161
162static void
163param_uint_set_default (GParamSpec *pspec,
164			GValue     *value)
165{
166  value->data[0].v_uint = G_PARAM_SPEC_UINT (pspec)->default_value;
167}
168
169static gboolean
170param_uint_validate (GParamSpec *pspec,
171		     GValue     *value)
172{
173  GParamSpecUInt *uspec = G_PARAM_SPEC_UINT (pspec);
174  guint oval = value->data[0].v_uint;
175
176  value->data[0].v_uint = CLAMP (value->data[0].v_uint, uspec->minimum, uspec->maximum);
177
178  return value->data[0].v_uint != oval;
179}
180
181static gint
182param_uint_values_cmp (GParamSpec   *pspec,
183		       const GValue *value1,
184		       const GValue *value2)
185{
186  if (value1->data[0].v_uint < value2->data[0].v_uint)
187    return -1;
188  else
189    return value1->data[0].v_uint > value2->data[0].v_uint;
190}
191
192static void
193param_long_init (GParamSpec *pspec)
194{
195  GParamSpecLong *lspec = G_PARAM_SPEC_LONG (pspec);
196
197#if SIZEOF_LONG == 4
198  lspec->minimum = 0x7fffffff;
199  lspec->maximum = 0x80000000;
200#else /* SIZEOF_LONG != 4 (8) */
201  lspec->minimum = 0x7fffffffffffffff;
202  lspec->maximum = 0x8000000000000000;
203#endif
204  lspec->default_value = 0;
205}
206
207static void
208param_long_set_default (GParamSpec *pspec,
209			GValue     *value)
210{
211  value->data[0].v_long = G_PARAM_SPEC_LONG (pspec)->default_value;
212}
213
214static gboolean
215param_long_validate (GParamSpec *pspec,
216		     GValue     *value)
217{
218  GParamSpecLong *lspec = G_PARAM_SPEC_LONG (pspec);
219  glong oval = value->data[0].v_long;
220
221  value->data[0].v_long = CLAMP (value->data[0].v_long, lspec->minimum, lspec->maximum);
222
223  return value->data[0].v_long != oval;
224}
225
226static gint
227param_long_values_cmp (GParamSpec   *pspec,
228		       const GValue *value1,
229		       const GValue *value2)
230{
231  if (value1->data[0].v_long < value2->data[0].v_long)
232    return -1;
233  else
234    return value1->data[0].v_long > value2->data[0].v_long;
235}
236
237static void
238param_ulong_init (GParamSpec *pspec)
239{
240  GParamSpecULong *uspec = G_PARAM_SPEC_ULONG (pspec);
241
242  uspec->minimum = 0;
243#if SIZEOF_LONG == 4
244  uspec->maximum = 0xffffffff;
245#else /* SIZEOF_LONG != 4 (8) */
246  uspec->maximum = 0xffffffffffffffff;
247#endif
248  uspec->default_value = 0;
249}
250
251static void
252param_ulong_set_default (GParamSpec *pspec,
253			 GValue     *value)
254{
255  value->data[0].v_ulong = G_PARAM_SPEC_ULONG (pspec)->default_value;
256}
257
258static gboolean
259param_ulong_validate (GParamSpec *pspec,
260		      GValue     *value)
261{
262  GParamSpecULong *uspec = G_PARAM_SPEC_ULONG (pspec);
263  gulong oval = value->data[0].v_ulong;
264
265  value->data[0].v_ulong = CLAMP (value->data[0].v_ulong, uspec->minimum, uspec->maximum);
266
267  return value->data[0].v_ulong != oval;
268}
269
270static gint
271param_ulong_values_cmp (GParamSpec   *pspec,
272			const GValue *value1,
273			const GValue *value2)
274{
275  if (value1->data[0].v_ulong < value2->data[0].v_ulong)
276    return -1;
277  else
278    return value1->data[0].v_ulong > value2->data[0].v_ulong;
279}
280
281static void
282param_enum_init (GParamSpec *pspec)
283{
284  GParamSpecEnum *espec = G_PARAM_SPEC_ENUM (pspec);
285
286  espec->enum_class = NULL;
287  espec->default_value = 0;
288}
289
290static void
291param_enum_finalize (GParamSpec *pspec)
292{
293  GParamSpecEnum *espec = G_PARAM_SPEC_ENUM (pspec);
294  GParamSpecClass *parent_class = g_type_class_peek (g_type_parent (G_TYPE_PARAM_ENUM));
295
296  if (espec->enum_class)
297    {
298      g_type_class_unref (espec->enum_class);
299      espec->enum_class = NULL;
300    }
301
302  parent_class->finalize (pspec);
303}
304
305static void
306param_enum_set_default (GParamSpec *pspec,
307			GValue     *value)
308{
309  value->data[0].v_long = G_PARAM_SPEC_ENUM (pspec)->default_value;
310}
311
312static gboolean
313param_enum_validate (GParamSpec *pspec,
314		     GValue     *value)
315{
316  GParamSpecEnum *espec = G_PARAM_SPEC_ENUM (pspec);
317  glong oval = value->data[0].v_long;
318
319  if (!espec->enum_class ||
320      !g_enum_get_value (espec->enum_class, value->data[0].v_long))
321    value->data[0].v_long = espec->default_value;
322
323  return value->data[0].v_long != oval;
324}
325
326static void
327param_flags_init (GParamSpec *pspec)
328{
329  GParamSpecFlags *fspec = G_PARAM_SPEC_FLAGS (pspec);
330
331  fspec->flags_class = NULL;
332  fspec->default_value = 0;
333}
334
335static void
336param_flags_finalize (GParamSpec *pspec)
337{
338  GParamSpecFlags *fspec = G_PARAM_SPEC_FLAGS (pspec);
339  GParamSpecClass *parent_class = g_type_class_peek (g_type_parent (G_TYPE_PARAM_FLAGS));
340
341  if (fspec->flags_class)
342    {
343      g_type_class_unref (fspec->flags_class);
344      fspec->flags_class = NULL;
345    }
346
347  parent_class->finalize (pspec);
348}
349
350static void
351param_flags_set_default (GParamSpec *pspec,
352			 GValue     *value)
353{
354  value->data[0].v_ulong = G_PARAM_SPEC_FLAGS (pspec)->default_value;
355}
356
357static gboolean
358param_flags_validate (GParamSpec *pspec,
359		      GValue     *value)
360{
361  GParamSpecFlags *fspec = G_PARAM_SPEC_FLAGS (pspec);
362  gulong oval = value->data[0].v_ulong;
363
364  if (fspec->flags_class)
365    value->data[0].v_ulong &= fspec->flags_class->mask;
366  else
367    value->data[0].v_ulong = fspec->default_value;
368
369  return value->data[0].v_ulong != oval;
370}
371
372static void
373param_float_init (GParamSpec *pspec)
374{
375  GParamSpecFloat *fspec = G_PARAM_SPEC_FLOAT (pspec);
376
377  fspec->minimum = G_MINFLOAT;
378  fspec->maximum = G_MAXFLOAT;
379  fspec->default_value = 0;
380  fspec->epsilon = G_FLOAT_EPSILON;
381}
382
383static void
384param_float_set_default (GParamSpec *pspec,
385			 GValue     *value)
386{
387  value->data[0].v_float = G_PARAM_SPEC_FLOAT (pspec)->default_value;
388}
389
390static gboolean
391param_float_validate (GParamSpec *pspec,
392		      GValue     *value)
393{
394  GParamSpecFloat *fspec = G_PARAM_SPEC_FLOAT (pspec);
395  gfloat oval = value->data[0].v_float;
396
397  value->data[0].v_float = CLAMP (value->data[0].v_float, fspec->minimum, fspec->maximum);
398
399  return value->data[0].v_float != oval;
400}
401
402static gint
403param_float_values_cmp (GParamSpec   *pspec,
404			const GValue *value1,
405			const GValue *value2)
406{
407  gfloat epsilon = G_PARAM_SPEC_FLOAT (pspec)->epsilon;
408
409  if (value1->data[0].v_float < value2->data[0].v_float)
410    return - (value2->data[0].v_float - value1->data[0].v_float > epsilon);
411  else
412    return value1->data[0].v_float - value2->data[0].v_float > epsilon;
413}
414
415static void
416param_double_init (GParamSpec *pspec)
417{
418  GParamSpecDouble *dspec = G_PARAM_SPEC_DOUBLE (pspec);
419
420  dspec->minimum = G_MINDOUBLE;
421  dspec->maximum = G_MAXDOUBLE;
422  dspec->default_value = 0;
423  dspec->epsilon = G_DOUBLE_EPSILON;
424}
425
426static void
427param_double_set_default (GParamSpec *pspec,
428			  GValue     *value)
429{
430  value->data[0].v_double = G_PARAM_SPEC_DOUBLE (pspec)->default_value;
431}
432
433static gboolean
434param_double_validate (GParamSpec *pspec,
435		       GValue     *value)
436{
437  GParamSpecDouble *dspec = G_PARAM_SPEC_DOUBLE (pspec);
438  gdouble oval = value->data[0].v_double;
439
440  value->data[0].v_double = CLAMP (value->data[0].v_double, dspec->minimum, dspec->maximum);
441
442  return value->data[0].v_double != oval;
443}
444
445static gint
446param_double_values_cmp (GParamSpec   *pspec,
447			 const GValue *value1,
448			 const GValue *value2)
449{
450  gdouble epsilon = G_PARAM_SPEC_DOUBLE (pspec)->epsilon;
451
452  if (value1->data[0].v_double < value2->data[0].v_double)
453    return - (value2->data[0].v_double - value1->data[0].v_double > epsilon);
454  else
455    return value1->data[0].v_double - value2->data[0].v_double > epsilon;
456}
457
458static void
459param_string_init (GParamSpec *pspec)
460{
461  GParamSpecString *sspec = G_PARAM_SPEC_STRING (pspec);
462
463  sspec->default_value = NULL;
464  sspec->cset_first = NULL;
465  sspec->cset_nth = NULL;
466  sspec->substitutor = '_';
467  sspec->null_fold_if_empty = FALSE;
468  sspec->ensure_non_null = FALSE;
469}
470
471static void
472param_string_finalize (GParamSpec *pspec)
473{
474  GParamSpecString *sspec = G_PARAM_SPEC_STRING (pspec);
475  GParamSpecClass *parent_class = g_type_class_peek (g_type_parent (G_TYPE_PARAM_STRING));
476
477  g_free (sspec->default_value);
478  g_free (sspec->cset_first);
479  g_free (sspec->cset_nth);
480  sspec->default_value = NULL;
481  sspec->cset_first = NULL;
482  sspec->cset_nth = NULL;
483
484  parent_class->finalize (pspec);
485}
486
487static void
488param_string_set_default (GParamSpec *pspec,
489			  GValue     *value)
490{
491  value->data[0].v_pointer = g_strdup (G_PARAM_SPEC_STRING (pspec)->default_value);
492}
493
494static gboolean
495param_string_validate (GParamSpec *pspec,
496		       GValue     *value)
497{
498  GParamSpecString *sspec = G_PARAM_SPEC_STRING (pspec);
499  gchar *string = value->data[0].v_pointer;
500  guint changed = 0;
501
502  if (string && string[0])
503    {
504      gchar *s;
505
506      if (sspec->cset_first && !strchr (sspec->cset_first, string[0]))
507	{
508	  string[0] = sspec->substitutor;
509	  changed++;
510	}
511      if (sspec->cset_nth)
512	for (s = string + 1; *s; s++)
513	  if (!strchr (sspec->cset_nth, *s))
514	    {
515	      *s = sspec->substitutor;
516	      changed++;
517	    }
518    }
519  if (sspec->null_fold_if_empty && string && string[0] == 0)
520    {
521      g_free (value->data[0].v_pointer);
522      value->data[0].v_pointer = NULL;
523      changed++;
524      string = value->data[0].v_pointer;
525    }
526  if (sspec->ensure_non_null && !string)
527    {
528      value->data[0].v_pointer = g_strdup ("");
529      changed++;
530      string = value->data[0].v_pointer;
531    }
532
533  return changed;
534}
535
536static gint
537param_string_values_cmp (GParamSpec   *pspec,
538			 const GValue *value1,
539			 const GValue *value2)
540{
541  if (!value1->data[0].v_pointer)
542    return value2->data[0].v_pointer != NULL ? -1 : 0;
543  else if (!value2->data[0].v_pointer)
544    return value1->data[0].v_pointer != NULL;
545  else
546    return strcmp (value1->data[0].v_pointer, value2->data[0].v_pointer);
547}
548
549static void
550param_param_init (GParamSpec *pspec)
551{
552  /* GParamSpecParam *spec = G_PARAM_SPEC_PARAM (pspec); */
553}
554
555static void
556param_param_set_default (GParamSpec *pspec,
557			 GValue     *value)
558{
559  value->data[0].v_pointer = NULL;
560}
561
562static gboolean
563param_param_validate (GParamSpec *pspec,
564		      GValue     *value)
565{
566  /* GParamSpecParam *spec = G_PARAM_SPEC_PARAM (pspec); */
567  GParamSpec *param = value->data[0].v_pointer;
568  guint changed = 0;
569
570  if (param && !g_value_type_compatible (G_PARAM_SPEC_TYPE (param), G_PARAM_SPEC_VALUE_TYPE (pspec)))
571    {
572      g_param_spec_unref (param);
573      value->data[0].v_pointer = NULL;
574      changed++;
575    }
576
577  return changed;
578}
579
580static void
581param_boxed_init (GParamSpec *pspec)
582{
583  /* GParamSpecBoxed *bspec = G_PARAM_SPEC_BOXED (pspec); */
584}
585
586static void
587param_boxed_set_default (GParamSpec *pspec,
588			 GValue     *value)
589{
590  value->data[0].v_pointer = NULL;
591}
592
593static gboolean
594param_boxed_validate (GParamSpec *pspec,
595		      GValue     *value)
596{
597  /* GParamSpecBoxed *bspec = G_PARAM_SPEC_BOXED (pspec); */
598  guint changed = 0;
599
600  /* can't do a whole lot here since we haven't even G_BOXED_TYPE() */
601
602  return changed;
603}
604
605static gint
606param_boxed_values_cmp (GParamSpec    *pspec,
607			 const GValue *value1,
608			 const GValue *value2)
609{
610  guint8 *p1 = value1->data[0].v_pointer;
611  guint8 *p2 = value2->data[0].v_pointer;
612
613  /* not much to compare here, try to at least provide stable lesser/greater result */
614
615  return p1 < p2 ? -1 : p1 > p2;
616}
617
618static void
619param_pointer_init (GParamSpec *pspec)
620{
621  /* GParamSpecPointer *spec = G_PARAM_SPEC_POINTER (pspec); */
622}
623
624static void
625param_pointer_set_default (GParamSpec *pspec,
626			   GValue     *value)
627{
628  value->data[0].v_pointer = NULL;
629}
630
631static gboolean
632param_pointer_validate (GParamSpec *pspec,
633			GValue     *value)
634{
635  /* GParamSpecPointer *spec = G_PARAM_SPEC_POINTER (pspec); */
636  guint changed = 0;
637
638  return changed;
639}
640
641static gint
642param_pointer_values_cmp (GParamSpec   *pspec,
643			  const GValue *value1,
644			  const GValue *value2)
645{
646  guint8 *p1 = value1->data[0].v_pointer;
647  guint8 *p2 = value2->data[0].v_pointer;
648
649  /* not much to compare here, try to at least provide stable lesser/greater result */
650
651  return p1 < p2 ? -1 : p1 > p2;
652}
653
654static void
655param_closure_init (GParamSpec *pspec)
656{
657  /* GParamSpecClosure *cspec = G_PARAM_SPEC_CLOSURE (pspec); */
658}
659
660static void
661param_closure_set_default (GParamSpec *pspec,
662			   GValue     *value)
663{
664  value->data[0].v_pointer = NULL;
665}
666
667static gboolean
668param_closure_validate (GParamSpec *pspec,
669			GValue     *value)
670{
671  /* GParamSpecClosure *cspec = G_PARAM_SPEC_CLOSURE (pspec); */
672  /* GClosure *closure = value->data[0].v_pointer; */
673  guint changed = 0;
674
675  /* we don't actually have necessary means to ensure closure validity */
676
677  return changed;
678}
679
680static gint
681param_closure_values_cmp (GParamSpec   *pspec,
682			  const GValue *value1,
683			  const GValue *value2)
684{
685  guint8 *p1 = value1->data[0].v_pointer;
686  guint8 *p2 = value2->data[0].v_pointer;
687
688  /* not much to compare here, try to at least provide stable lesser/greater result */
689
690  return p1 < p2 ? -1 : p1 > p2;
691}
692
693static void
694param_value_array_init (GParamSpec *pspec)
695{
696  GParamSpecValueArray *aspec = G_PARAM_SPEC_VALUE_ARRAY (pspec);
697
698  aspec->element_spec = NULL;
699  aspec->fixed_n_elements = 0; /* disable */
700}
701
702static inline guint
703value_array_ensure_size (GValueArray *value_array,
704			 guint        fixed_n_elements)
705{
706  guint changed = 0;
707
708  if (fixed_n_elements)
709    {
710      while (value_array->n_values < fixed_n_elements)
711	{
712	  g_value_array_append (value_array, NULL);
713	  changed++;
714	}
715      while (value_array->n_values > fixed_n_elements)
716	{
717	  g_value_array_remove (value_array, value_array->n_values - 1);
718	  changed++;
719	}
720    }
721  return changed;
722}
723
724static void
725param_value_array_finalize (GParamSpec *pspec)
726{
727  GParamSpecValueArray *aspec = G_PARAM_SPEC_VALUE_ARRAY (pspec);
728  GParamSpecClass *parent_class = g_type_class_peek (g_type_parent (G_TYPE_PARAM_VALUE_ARRAY));
729
730  if (aspec->element_spec)
731    {
732      g_param_spec_unref (aspec->element_spec);
733      aspec->element_spec = NULL;
734    }
735
736  parent_class->finalize (pspec);
737}
738
739static void
740param_value_array_set_default (GParamSpec *pspec,
741			       GValue     *value)
742{
743  GParamSpecValueArray *aspec = G_PARAM_SPEC_VALUE_ARRAY (pspec);
744
745  g_return_if_fail (value->data[0].v_pointer != NULL);	/* paranoid */
746
747  /* g_value_reset (value);  already done */
748  value_array_ensure_size (value->data[0].v_pointer, aspec->fixed_n_elements);
749}
750
751static gboolean
752param_value_array_validate (GParamSpec *pspec,
753			    GValue     *value)
754{
755  GParamSpecValueArray *aspec = G_PARAM_SPEC_VALUE_ARRAY (pspec);
756  GValueArray *value_array = value->data[0].v_pointer;
757  guint changed = 0;
758
759  g_return_val_if_fail (value->data[0].v_pointer != NULL, FALSE);	/* paranoid */
760
761  /* ensure array size validity */
762  changed += value_array_ensure_size (value_array, aspec->fixed_n_elements);
763
764  /* ensure array values validity against a present element spec */
765  if (aspec->element_spec)
766    {
767      GParamSpec *element_spec = aspec->element_spec;
768      guint i;
769
770      for (i = 0; i < value_array->n_values; i++)
771	{
772	  GValue *element = value_array->values + i;
773
774	  /* need to fixup value type, or ensure that the array value is initialized at all */
775	  if (!g_value_type_compatible (G_VALUE_TYPE (element), G_PARAM_SPEC_VALUE_TYPE (element_spec)))
776	    {
777	      if (G_VALUE_TYPE (element) != 0)
778		g_value_unset (element);
779	      g_value_init (element, G_PARAM_SPEC_VALUE_TYPE (element_spec));
780	      g_param_value_set_default (element_spec, element);
781	      changed++;
782	    }
783	  /* validate array value against element_spec */
784	  changed += g_param_value_validate (element_spec, element);
785	}
786    }
787
788  return changed;
789}
790
791static gint
792param_value_array_values_cmp (GParamSpec   *pspec,
793			      const GValue *value1,
794			      const GValue *value2)
795{
796  GParamSpecValueArray *aspec = G_PARAM_SPEC_VALUE_ARRAY (pspec);
797  GValueArray *value_array1 = value1->data[0].v_pointer;
798  GValueArray *value_array2 = value2->data[0].v_pointer;
799
800  g_return_val_if_fail (value1->data[0].v_pointer != NULL, -1);	/* paranoid */
801  g_return_val_if_fail (value2->data[0].v_pointer != NULL, 1);	/* paranoid */
802
803  if (value_array1->n_values != value_array2->n_values)
804    return value_array1->n_values < value_array2->n_values ? -1 : 1;
805  else if (!aspec->element_spec)
806    {
807      /* we need an element specification for comparisons, so there's not much
808       * to compare here, try to at least provide stable lesser/greater result
809       */
810      return value_array1->n_values < value_array2->n_values ? -1 : value_array1->n_values > value_array2->n_values;
811    }
812  else /* value_array1->n_values == value_array2->n_values */
813    {
814      guint i;
815
816      for (i = 0; i < value_array1->n_values; i++)
817	{
818	  GValue *element1 = value_array1->values + i;
819	  GValue *element2 = value_array2->values + i;
820	  gint cmp;
821
822	  /* need corresponding element types, provide stable result otherwise */
823	  if (G_VALUE_TYPE (element1) != G_VALUE_TYPE (element2))
824	    return G_VALUE_TYPE (element1) < G_VALUE_TYPE (element2) ? -1 : 1;
825	  cmp = g_param_values_cmp (aspec->element_spec, element1, element2);
826	  if (cmp)
827	    return cmp;
828	}
829      return 0;
830    }
831}
832
833static void
834param_object_init (GParamSpec *pspec)
835{
836  /* GParamSpecObject *ospec = G_PARAM_SPEC_OBJECT (pspec); */
837}
838
839static void
840param_object_set_default (GParamSpec *pspec,
841			  GValue     *value)
842{
843  value->data[0].v_pointer = NULL;
844}
845
846static gboolean
847param_object_validate (GParamSpec *pspec,
848		       GValue     *value)
849{
850  GParamSpecObject *ospec = G_PARAM_SPEC_OBJECT (pspec);
851  GObject *object = value->data[0].v_pointer;
852  guint changed = 0;
853
854  if (object && !g_value_type_compatible (G_OBJECT_TYPE (object), G_PARAM_SPEC_VALUE_TYPE (ospec)))
855    {
856      g_object_unref (object);
857      value->data[0].v_pointer = NULL;
858      changed++;
859    }
860
861  return changed;
862}
863
864static gint
865param_object_values_cmp (GParamSpec   *pspec,
866			 const GValue *value1,
867			 const GValue *value2)
868{
869  guint8 *p1 = value1->data[0].v_pointer;
870  guint8 *p2 = value2->data[0].v_pointer;
871
872  /* not much to compare here, try to at least provide stable lesser/greater result */
873
874  return p1 < p2 ? -1 : p1 > p2;
875}
876
877
878/* --- type initialization --- */
879void
880g_param_spec_types_init (void)	/* sync with gtype.c */
881{
882  GType type;
883
884  /* G_TYPE_PARAM_CHAR
885   */
886  {
887    static const GParamSpecTypeInfo pspec_info = {
888      sizeof (GParamSpecChar),	/* instance_size */
889      16,			/* n_preallocs */
890      param_char_init,		/* instance_init */
891      G_TYPE_CHAR,		/* value_type */
892      NULL,			/* finalize */
893      param_char_set_default,	/* value_set_default */
894      param_char_validate,	/* value_validate */
895      param_int_values_cmp,	/* values_cmp */
896    };
897    type = g_param_type_register_static ("GParamChar", &pspec_info);
898    g_assert (type == G_TYPE_PARAM_CHAR);
899  }
900
901  /* G_TYPE_PARAM_UCHAR
902   */
903  {
904    static const GParamSpecTypeInfo pspec_info = {
905      sizeof (GParamSpecUChar), /* instance_size */
906      16,                       /* n_preallocs */
907      param_uchar_init,         /* instance_init */
908      G_TYPE_UCHAR,		/* value_type */
909      NULL,			/* finalize */
910      param_uchar_set_default,	/* value_set_default */
911      param_uchar_validate,	/* value_validate */
912      param_uint_values_cmp,	/* values_cmp */
913    };
914    type = g_param_type_register_static ("GParamUChar", &pspec_info);
915    g_assert (type == G_TYPE_PARAM_UCHAR);
916  }
917
918  /* G_TYPE_PARAM_BOOLEAN
919   */
920  {
921    static const GParamSpecTypeInfo pspec_info = {
922      sizeof (GParamSpecBoolean), /* instance_size */
923      16,                         /* n_preallocs */
924      NULL,			  /* instance_init */
925      G_TYPE_BOOLEAN,             /* value_type */
926      NULL,                       /* finalize */
927      param_boolean_set_default,  /* value_set_default */
928      param_boolean_validate,     /* value_validate */
929      param_int_values_cmp,       /* values_cmp */
930    };
931    type = g_param_type_register_static ("GParamBoolean", &pspec_info);
932    g_assert (type == G_TYPE_PARAM_BOOLEAN);
933  }
934
935  /* G_TYPE_PARAM_INT
936   */
937  {
938    static const GParamSpecTypeInfo pspec_info = {
939      sizeof (GParamSpecInt),   /* instance_size */
940      16,                       /* n_preallocs */
941      param_int_init,           /* instance_init */
942      G_TYPE_INT,		/* value_type */
943      NULL,			/* finalize */
944      param_int_set_default,	/* value_set_default */
945      param_int_validate,	/* value_validate */
946      param_int_values_cmp,	/* values_cmp */
947    };
948    type = g_param_type_register_static ("GParamInt", &pspec_info);
949    g_assert (type == G_TYPE_PARAM_INT);
950  }
951
952  /* G_TYPE_PARAM_UINT
953   */
954  {
955    static const GParamSpecTypeInfo pspec_info = {
956      sizeof (GParamSpecUInt),  /* instance_size */
957      16,                       /* n_preallocs */
958      param_uint_init,          /* instance_init */
959      G_TYPE_UINT,		/* value_type */
960      NULL,			/* finalize */
961      param_uint_set_default,	/* value_set_default */
962      param_uint_validate,	/* value_validate */
963      param_uint_values_cmp,	/* values_cmp */
964    };
965    type = g_param_type_register_static ("GParamUInt", &pspec_info);
966    g_assert (type == G_TYPE_PARAM_UINT);
967  }
968
969  /* G_TYPE_PARAM_LONG
970   */
971  {
972    static const GParamSpecTypeInfo pspec_info = {
973      sizeof (GParamSpecLong),  /* instance_size */
974      16,                       /* n_preallocs */
975      param_long_init,          /* instance_init */
976      G_TYPE_LONG,		/* value_type */
977      NULL,			/* finalize */
978      param_long_set_default,	/* value_set_default */
979      param_long_validate,	/* value_validate */
980      param_long_values_cmp,	/* values_cmp */
981    };
982    type = g_param_type_register_static ("GParamLong", &pspec_info);
983    g_assert (type == G_TYPE_PARAM_LONG);
984  }
985
986  /* G_TYPE_PARAM_ULONG
987   */
988  {
989    static const GParamSpecTypeInfo pspec_info = {
990      sizeof (GParamSpecULong), /* instance_size */
991      16,                       /* n_preallocs */
992      param_ulong_init,         /* instance_init */
993      G_TYPE_ULONG,		/* value_type */
994      NULL,			/* finalize */
995      param_ulong_set_default,	/* value_set_default */
996      param_ulong_validate,	/* value_validate */
997      param_ulong_values_cmp,	/* values_cmp */
998    };
999    type = g_param_type_register_static ("GParamULong", &pspec_info);
1000    g_assert (type == G_TYPE_PARAM_ULONG);
1001  }
1002
1003  /* G_TYPE_PARAM_ENUM
1004   */
1005  {
1006    static const GParamSpecTypeInfo pspec_info = {
1007      sizeof (GParamSpecEnum),  /* instance_size */
1008      16,                       /* n_preallocs */
1009      param_enum_init,          /* instance_init */
1010      G_TYPE_ENUM,		/* value_type */
1011      param_enum_finalize,	/* finalize */
1012      param_enum_set_default,	/* value_set_default */
1013      param_enum_validate,	/* value_validate */
1014      param_long_values_cmp,	/* values_cmp */
1015    };
1016    type = g_param_type_register_static ("GParamEnum", &pspec_info);
1017    g_assert (type == G_TYPE_PARAM_ENUM);
1018  }
1019
1020  /* G_TYPE_PARAM_FLAGS
1021   */
1022  {
1023    static const GParamSpecTypeInfo pspec_info = {
1024      sizeof (GParamSpecFlags),	/* instance_size */
1025      16,			/* n_preallocs */
1026      param_flags_init,		/* instance_init */
1027      G_TYPE_FLAGS,		/* value_type */
1028      param_flags_finalize,	/* finalize */
1029      param_flags_set_default,	/* value_set_default */
1030      param_flags_validate,	/* value_validate */
1031      param_ulong_values_cmp,	/* values_cmp */
1032    };
1033    type = g_param_type_register_static ("GParamFlags", &pspec_info);
1034    g_assert (type == G_TYPE_PARAM_FLAGS);
1035  }
1036
1037  /* G_TYPE_PARAM_FLOAT
1038   */
1039  {
1040    static const GParamSpecTypeInfo pspec_info = {
1041      sizeof (GParamSpecFloat), /* instance_size */
1042      16,                       /* n_preallocs */
1043      param_float_init,         /* instance_init */
1044      G_TYPE_FLOAT,		/* value_type */
1045      NULL,			/* finalize */
1046      param_float_set_default,	/* value_set_default */
1047      param_float_validate,	/* value_validate */
1048      param_float_values_cmp,	/* values_cmp */
1049    };
1050    type = g_param_type_register_static ("GParamFloat", &pspec_info);
1051    g_assert (type == G_TYPE_PARAM_FLOAT);
1052  }
1053
1054  /* G_TYPE_PARAM_DOUBLE
1055   */
1056  {
1057    static const GParamSpecTypeInfo pspec_info = {
1058      sizeof (GParamSpecDouble),	/* instance_size */
1059      16,				/* n_preallocs */
1060      param_double_init,		/* instance_init */
1061      G_TYPE_DOUBLE,			/* value_type */
1062      NULL,				/* finalize */
1063      param_double_set_default,		/* value_set_default */
1064      param_double_validate,		/* value_validate */
1065      param_double_values_cmp,		/* values_cmp */
1066    };
1067    type = g_param_type_register_static ("GParamDouble", &pspec_info);
1068    g_assert (type == G_TYPE_PARAM_DOUBLE);
1069  }
1070
1071  /* G_TYPE_PARAM_STRING
1072   */
1073  {
1074    static const GParamSpecTypeInfo pspec_info = {
1075      sizeof (GParamSpecString),	/* instance_size */
1076      16,				/* n_preallocs */
1077      param_string_init,		/* instance_init */
1078      G_TYPE_STRING,			/* value_type */
1079      param_string_finalize,		/* finalize */
1080      param_string_set_default,		/* value_set_default */
1081      param_string_validate,		/* value_validate */
1082      param_string_values_cmp,		/* values_cmp */
1083    };
1084    type = g_param_type_register_static ("GParamString", &pspec_info);
1085    g_assert (type == G_TYPE_PARAM_STRING);
1086  }
1087
1088  /* G_TYPE_PARAM_PARAM
1089   */
1090  {
1091    static const GParamSpecTypeInfo pspec_info = {
1092      sizeof (GParamSpecParam),	/* instance_size */
1093      16,			/* n_preallocs */
1094      param_param_init,		/* instance_init */
1095      G_TYPE_PARAM,		/* value_type */
1096      NULL,			/* finalize */
1097      param_param_set_default,	/* value_set_default */
1098      param_param_validate,	/* value_validate */
1099      param_pointer_values_cmp,	/* values_cmp */
1100    };
1101    type = g_param_type_register_static ("GParamParam", &pspec_info);
1102    g_assert (type == G_TYPE_PARAM_PARAM);
1103  }
1104
1105  /* G_TYPE_PARAM_BOXED
1106   */
1107  {
1108    static const GParamSpecTypeInfo pspec_info = {
1109      sizeof (GParamSpecBoxed),	/* instance_size */
1110      4,			/* n_preallocs */
1111      param_boxed_init,		/* instance_init */
1112      G_TYPE_BOXED,		/* value_type */
1113      NULL,			/* finalize */
1114      param_boxed_set_default,	/* value_set_default */
1115      param_boxed_validate,	/* value_validate */
1116      param_boxed_values_cmp,	/* values_cmp */
1117    };
1118    type = g_param_type_register_static ("GParamBoxed", &pspec_info);
1119    g_assert (type == G_TYPE_PARAM_BOXED);
1120  }
1121
1122  /* G_TYPE_PARAM_POINTER
1123   */
1124  {
1125    static const GParamSpecTypeInfo pspec_info = {
1126      sizeof (GParamSpecPointer),  /* instance_size */
1127      0,                           /* n_preallocs */
1128      param_pointer_init,	   /* instance_init */
1129      G_TYPE_POINTER,  		   /* value_type */
1130      NULL,			   /* finalize */
1131      param_pointer_set_default,   /* value_set_default */
1132      param_pointer_validate,	   /* value_validate */
1133      param_pointer_values_cmp,	   /* values_cmp */
1134    };
1135    type = g_param_type_register_static ("GParamPointer", &pspec_info);
1136    g_assert (type == G_TYPE_PARAM_POINTER);
1137  }
1138
1139  /* G_TYPE_PARAM_VALUE_ARRAY
1140   */
1141  {
1142    static const GParamSpecTypeInfo pspec_info = {
1143      sizeof (GParamSpecValueArray),	/* instance_size */
1144      0,				/* n_preallocs */
1145      param_value_array_init,		/* instance_init */
1146      G_TYPE_VALUE_ARRAY,		/* value_type */
1147      param_value_array_finalize,	/* finalize */
1148      param_value_array_set_default,	/* value_set_default */
1149      param_value_array_validate,	/* value_validate */
1150      param_value_array_values_cmp,	/* values_cmp */
1151    };
1152    type = g_param_type_register_static ("GParamValueArray", &pspec_info);
1153    g_assert (type == G_TYPE_PARAM_VALUE_ARRAY);
1154  }
1155
1156  /* G_TYPE_PARAM_CLOSURE
1157   */
1158  {
1159    static const GParamSpecTypeInfo pspec_info = {
1160      sizeof (GParamSpecClosure),   /* instance_size */
1161      0,                            /* n_preallocs */
1162      param_closure_init,	    /* instance_init */
1163      G_TYPE_CLOSURE,		    /* value_type */
1164      NULL,			    /* finalize */
1165      param_closure_set_default,    /* value_set_default */
1166      param_closure_validate,	    /* value_validate */
1167      param_closure_values_cmp,     /* values_cmp */
1168    };
1169    type = g_param_type_register_static ("GParamClosure", &pspec_info);
1170    g_assert (type == G_TYPE_PARAM_CLOSURE);
1171  }
1172
1173  /* G_TYPE_PARAM_OBJECT
1174   */
1175  {
1176    static const GParamSpecTypeInfo pspec_info = {
1177      sizeof (GParamSpecObject), /* instance_size */
1178      16,                        /* n_preallocs */
1179      param_object_init,	 /* instance_init */
1180      G_TYPE_OBJECT,		 /* value_type */
1181      NULL,			 /* finalize */
1182      param_object_set_default,	 /* value_set_default */
1183      param_object_validate,	 /* value_validate */
1184      param_object_values_cmp,	 /* values_cmp */
1185    };
1186    type = g_param_type_register_static ("GParamObject", &pspec_info);
1187    g_assert (type == G_TYPE_PARAM_OBJECT);
1188  }
1189}
1190
1191
1192/* --- GParamSpec initialization --- */
1193GParamSpec*
1194g_param_spec_char (const gchar *name,
1195		   const gchar *nick,
1196		   const gchar *blurb,
1197		   gint8	minimum,
1198		   gint8	maximum,
1199		   gint8	default_value,
1200		   GParamFlags	flags)
1201{
1202  GParamSpecChar *cspec = g_param_spec_internal (G_TYPE_PARAM_CHAR,
1203						 name,
1204						 nick,
1205						 blurb,
1206						 flags);
1207
1208  cspec->minimum = minimum;
1209  cspec->maximum = maximum;
1210  cspec->default_value = default_value;
1211
1212  return G_PARAM_SPEC (cspec);
1213}
1214
1215GParamSpec*
1216g_param_spec_uchar (const gchar *name,
1217		    const gchar *nick,
1218		    const gchar *blurb,
1219		    guint8	 minimum,
1220		    guint8	 maximum,
1221		    guint8	 default_value,
1222		    GParamFlags	 flags)
1223{
1224  GParamSpecUChar *uspec = g_param_spec_internal (G_TYPE_PARAM_UCHAR,
1225						  name,
1226						  nick,
1227						  blurb,
1228						  flags);
1229
1230  uspec->minimum = minimum;
1231  uspec->maximum = maximum;
1232  uspec->default_value = default_value;
1233
1234  return G_PARAM_SPEC (uspec);
1235}
1236
1237GParamSpec*
1238g_param_spec_boolean (const gchar *name,
1239		      const gchar *nick,
1240		      const gchar *blurb,
1241		      gboolean	   default_value,
1242		      GParamFlags  flags)
1243{
1244  GParamSpecBoolean *bspec = g_param_spec_internal (G_TYPE_PARAM_BOOLEAN,
1245						    name,
1246						    nick,
1247						    blurb,
1248						    flags);
1249
1250  bspec->default_value = default_value;
1251
1252  return G_PARAM_SPEC (bspec);
1253}
1254
1255GParamSpec*
1256g_param_spec_int (const gchar *name,
1257		  const gchar *nick,
1258		  const gchar *blurb,
1259		  gint	       minimum,
1260		  gint	       maximum,
1261		  gint	       default_value,
1262		  GParamFlags  flags)
1263{
1264  GParamSpecInt *ispec = g_param_spec_internal (G_TYPE_PARAM_INT,
1265						name,
1266						nick,
1267						blurb,
1268						flags);
1269
1270  ispec->minimum = minimum;
1271  ispec->maximum = maximum;
1272  ispec->default_value = default_value;
1273
1274  return G_PARAM_SPEC (ispec);
1275}
1276
1277GParamSpec*
1278g_param_spec_uint (const gchar *name,
1279		   const gchar *nick,
1280		   const gchar *blurb,
1281		   guint	minimum,
1282		   guint	maximum,
1283		   guint	default_value,
1284		   GParamFlags	flags)
1285{
1286  GParamSpecUInt *uspec = g_param_spec_internal (G_TYPE_PARAM_UINT,
1287						 name,
1288						 nick,
1289						 blurb,
1290						 flags);
1291
1292  uspec->minimum = minimum;
1293  uspec->maximum = maximum;
1294  uspec->default_value = default_value;
1295
1296  return G_PARAM_SPEC (uspec);
1297}
1298
1299GParamSpec*
1300g_param_spec_long (const gchar *name,
1301		   const gchar *nick,
1302		   const gchar *blurb,
1303		   glong	minimum,
1304		   glong	maximum,
1305		   glong	default_value,
1306		   GParamFlags	flags)
1307{
1308  GParamSpecLong *lspec = g_param_spec_internal (G_TYPE_PARAM_LONG,
1309						 name,
1310						 nick,
1311						 blurb,
1312						 flags);
1313
1314  lspec->minimum = minimum;
1315  lspec->maximum = maximum;
1316  lspec->default_value = default_value;
1317
1318  return G_PARAM_SPEC (lspec);
1319}
1320
1321GParamSpec*
1322g_param_spec_ulong (const gchar *name,
1323		    const gchar *nick,
1324		    const gchar *blurb,
1325		    gulong	 minimum,
1326		    gulong	 maximum,
1327		    gulong	 default_value,
1328		    GParamFlags	 flags)
1329{
1330  GParamSpecULong *uspec = g_param_spec_internal (G_TYPE_PARAM_ULONG,
1331						  name,
1332						  nick,
1333						  blurb,
1334						  flags);
1335
1336  uspec->minimum = minimum;
1337  uspec->maximum = maximum;
1338  uspec->default_value = default_value;
1339
1340  return G_PARAM_SPEC (uspec);
1341}
1342
1343GParamSpec*
1344g_param_spec_enum (const gchar *name,
1345		   const gchar *nick,
1346		   const gchar *blurb,
1347		   GType	enum_type,
1348		   gint		default_value,
1349		   GParamFlags	flags)
1350{
1351  GParamSpecEnum *espec;
1352
1353  g_return_val_if_fail (G_TYPE_IS_ENUM (enum_type), NULL);
1354
1355  espec = g_param_spec_internal (G_TYPE_PARAM_ENUM,
1356				 name,
1357				 nick,
1358				 blurb,
1359				 flags);
1360
1361  espec->enum_class = g_type_class_ref (enum_type);
1362  espec->default_value = default_value;
1363  G_PARAM_SPEC (espec)->value_type = enum_type;
1364
1365  return G_PARAM_SPEC (espec);
1366}
1367
1368GParamSpec*
1369g_param_spec_flags (const gchar *name,
1370		    const gchar *nick,
1371		    const gchar *blurb,
1372		    GType	 flags_type,
1373		    guint	 default_value,
1374		    GParamFlags	 flags)
1375{
1376  GParamSpecFlags *fspec;
1377
1378  g_return_val_if_fail (G_TYPE_IS_FLAGS (flags_type), NULL);
1379
1380  fspec = g_param_spec_internal (G_TYPE_PARAM_FLAGS,
1381				 name,
1382				 nick,
1383				 blurb,
1384				 flags);
1385
1386  fspec->flags_class = g_type_class_ref (flags_type);
1387  fspec->default_value = default_value;
1388  G_PARAM_SPEC (fspec)->value_type = flags_type;
1389
1390  return G_PARAM_SPEC (fspec);
1391}
1392
1393GParamSpec*
1394g_param_spec_float (const gchar *name,
1395		    const gchar *nick,
1396		    const gchar *blurb,
1397		    gfloat	 minimum,
1398		    gfloat	 maximum,
1399		    gfloat	 default_value,
1400		    GParamFlags	 flags)
1401{
1402  GParamSpecFloat *fspec = g_param_spec_internal (G_TYPE_PARAM_FLOAT,
1403						  name,
1404						  nick,
1405						  blurb,
1406						  flags);
1407
1408  fspec->minimum = minimum;
1409  fspec->maximum = maximum;
1410  fspec->default_value = default_value;
1411
1412  return G_PARAM_SPEC (fspec);
1413}
1414
1415GParamSpec*
1416g_param_spec_double (const gchar *name,
1417		     const gchar *nick,
1418		     const gchar *blurb,
1419		     gdouble	  minimum,
1420		     gdouble	  maximum,
1421		     gdouble	  default_value,
1422		     GParamFlags  flags)
1423{
1424  GParamSpecDouble *dspec = g_param_spec_internal (G_TYPE_PARAM_DOUBLE,
1425						   name,
1426						   nick,
1427						   blurb,
1428						   flags);
1429
1430  dspec->minimum = minimum;
1431  dspec->maximum = maximum;
1432  dspec->default_value = default_value;
1433
1434  return G_PARAM_SPEC (dspec);
1435}
1436
1437GParamSpec*
1438g_param_spec_string (const gchar *name,
1439		     const gchar *nick,
1440		     const gchar *blurb,
1441		     const gchar *default_value,
1442		     GParamFlags  flags)
1443{
1444  GParamSpecString *sspec = g_param_spec_internal (G_TYPE_PARAM_STRING,
1445						   name,
1446						   nick,
1447						   blurb,
1448						   flags);
1449  g_free (sspec->default_value);
1450  sspec->default_value = g_strdup (default_value);
1451
1452  return G_PARAM_SPEC (sspec);
1453}
1454
1455GParamSpec*
1456g_param_spec_stringc (const gchar *name,
1457		      const gchar *nick,
1458		      const gchar *blurb,
1459		      const gchar *default_value,
1460		      GParamFlags  flags)
1461{
1462  GParamSpecString *sspec = g_param_spec_internal (G_TYPE_PARAM_STRING,
1463						   name,
1464						   nick,
1465						   blurb,
1466						   flags);
1467  g_free (sspec->default_value);
1468  sspec->default_value = g_strdup (default_value);
1469  g_free (sspec->cset_first);
1470  sspec->cset_first = g_strdup (G_CSET_a_2_z "_" G_CSET_A_2_Z);
1471  g_free (sspec->cset_nth);
1472  sspec->cset_nth = g_strdup (G_CSET_a_2_z
1473			      "_0123456789"
1474			      /* G_CSET_LATINS G_CSET_LATINC */
1475			      G_CSET_A_2_Z);
1476
1477  return G_PARAM_SPEC (sspec);
1478}
1479
1480GParamSpec*
1481g_param_spec_param (const gchar *name,
1482		    const gchar *nick,
1483		    const gchar *blurb,
1484		    GType	 param_type,
1485		    GParamFlags  flags)
1486{
1487  GParamSpecParam *pspec;
1488
1489  g_return_val_if_fail (G_TYPE_IS_PARAM (param_type), NULL);
1490
1491  pspec = g_param_spec_internal (G_TYPE_PARAM_PARAM,
1492				 name,
1493				 nick,
1494				 blurb,
1495				 flags);
1496  G_PARAM_SPEC (pspec)->value_type = param_type;
1497
1498  return G_PARAM_SPEC (pspec);
1499}
1500
1501GParamSpec*
1502g_param_spec_boxed (const gchar *name,
1503		    const gchar *nick,
1504		    const gchar *blurb,
1505		    GType	 boxed_type,
1506		    GParamFlags  flags)
1507{
1508  GParamSpecBoxed *bspec;
1509
1510  g_return_val_if_fail (G_TYPE_IS_BOXED (boxed_type), NULL);
1511  g_return_val_if_fail (G_TYPE_IS_DERIVED (boxed_type), NULL);
1512
1513  bspec = g_param_spec_internal (G_TYPE_PARAM_BOXED,
1514				 name,
1515				 nick,
1516				 blurb,
1517				 flags);
1518  G_PARAM_SPEC (bspec)->value_type = boxed_type;
1519
1520  return G_PARAM_SPEC (bspec);
1521}
1522
1523GParamSpec*
1524g_param_spec_pointer (const gchar *name,
1525		      const gchar *nick,
1526		      const gchar *blurb,
1527		      GParamFlags  flags)
1528{
1529  GParamSpecPointer *pspec;
1530
1531  pspec = g_param_spec_internal (G_TYPE_PARAM_POINTER,
1532				 name,
1533				 nick,
1534				 blurb,
1535				 flags);
1536  return G_PARAM_SPEC (pspec);
1537}
1538
1539GParamSpec*
1540g_param_spec_value_array (const gchar *name,
1541			  const gchar *nick,
1542			  const gchar *blurb,
1543			  GParamSpec  *element_spec,
1544			  GParamFlags  flags)
1545{
1546  GParamSpecValueArray *aspec;
1547
1548  if (element_spec)
1549    g_return_val_if_fail (G_IS_PARAM_SPEC (element_spec), NULL);
1550
1551  aspec = g_param_spec_internal (G_TYPE_PARAM_VALUE_ARRAY,
1552				 name,
1553				 nick,
1554				 blurb,
1555				 flags);
1556  if (element_spec)
1557    {
1558      aspec->element_spec = g_param_spec_ref (element_spec);
1559      g_param_spec_sink (element_spec);
1560    }
1561
1562  return G_PARAM_SPEC (aspec);
1563}
1564
1565GParamSpec*
1566g_param_spec_closure (const gchar *name,
1567		      const gchar *nick,
1568		      const gchar *blurb,
1569		      GParamFlags  flags)
1570{
1571  GParamSpecClosure *cspec;
1572
1573  cspec = g_param_spec_internal (G_TYPE_PARAM_CLOSURE,
1574				 name,
1575				 nick,
1576				 blurb,
1577				 flags);
1578  return G_PARAM_SPEC (cspec);
1579}
1580
1581GParamSpec*
1582g_param_spec_object (const gchar *name,
1583		     const gchar *nick,
1584		     const gchar *blurb,
1585		     GType	  object_type,
1586		     GParamFlags  flags)
1587{
1588  GParamSpecObject *ospec;
1589
1590  g_return_val_if_fail (G_TYPE_IS_OBJECT (object_type), NULL);
1591
1592  ospec = g_param_spec_internal (G_TYPE_PARAM_OBJECT,
1593				 name,
1594				 nick,
1595				 blurb,
1596				 flags);
1597  G_PARAM_SPEC (ospec)->value_type = object_type;
1598
1599  return G_PARAM_SPEC (ospec);
1600}
1601