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