Make some changes to the way that GMainContext works:
[platform/upstream/glib.git] / gobject / gparamspecs.c
1 /* GObject - GLib Type, Object, Parameter and Signal Library
2  * Copyright (C) 1997-1999, 2000-2001 Tim Janik and Red Hat, Inc.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General
15  * Public License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * MT safe
22  */
23
24 #include        "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 --- */
36 static void
37 param_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
46 static void
47 param_char_set_default (GParamSpec *pspec,
48                         GValue     *value)
49 {
50   value->data[0].v_int = G_PARAM_SPEC_CHAR (pspec)->default_value;
51 }
52
53 static gboolean
54 param_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
65 static void
66 param_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
75 static void
76 param_uchar_set_default (GParamSpec *pspec,
77                          GValue     *value)
78 {
79   value->data[0].v_uint = G_PARAM_SPEC_UCHAR (pspec)->default_value;
80 }
81
82 static gboolean
83 param_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
94 static void
95 param_boolean_set_default (GParamSpec *pspec,
96                            GValue     *value)
97 {
98   value->data[0].v_int = G_PARAM_SPEC_BOOLEAN (pspec)->default_value;
99 }
100
101 static gboolean
102 param_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
112 static void
113 param_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
122 static void
123 param_int_set_default (GParamSpec *pspec,
124                        GValue     *value)
125 {
126   value->data[0].v_int = G_PARAM_SPEC_INT (pspec)->default_value;
127 }
128
129 static gboolean
130 param_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
141 static gint
142 param_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
152 static void
153 param_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
162 static void
163 param_uint_set_default (GParamSpec *pspec,
164                         GValue     *value)
165 {
166   value->data[0].v_uint = G_PARAM_SPEC_UINT (pspec)->default_value;
167 }
168
169 static gboolean
170 param_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
181 static gint
182 param_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
192 static void
193 param_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
207 static void
208 param_long_set_default (GParamSpec *pspec,
209                         GValue     *value)
210 {
211   value->data[0].v_long = G_PARAM_SPEC_LONG (pspec)->default_value;
212 }
213
214 static gboolean
215 param_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
226 static gint
227 param_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
237 static void
238 param_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
251 static void
252 param_ulong_set_default (GParamSpec *pspec,
253                          GValue     *value)
254 {
255   value->data[0].v_ulong = G_PARAM_SPEC_ULONG (pspec)->default_value;
256 }
257
258 static gboolean
259 param_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
270 static gint
271 param_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
281 static void
282 param_unichar_init (GParamSpec *pspec)
283 {
284   GParamSpecUnichar *uspec = G_PARAM_SPEC_UNICHAR (pspec);
285   
286   uspec->default_value = 0;
287 }
288
289 static void
290 param_unichar_set_default (GParamSpec *pspec,
291                          GValue     *value)
292 {
293   value->data[0].v_uint = G_PARAM_SPEC_UNICHAR (pspec)->default_value;
294 }
295
296 static gboolean
297 param_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
312 static gint
313 param_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
323 static void
324 param_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
332 static void
333 param_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
347 static void
348 param_enum_set_default (GParamSpec *pspec,
349                         GValue     *value)
350 {
351   value->data[0].v_long = G_PARAM_SPEC_ENUM (pspec)->default_value;
352 }
353
354 static gboolean
355 param_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
368 static void
369 param_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
377 static void
378 param_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
392 static void
393 param_flags_set_default (GParamSpec *pspec,
394                          GValue     *value)
395 {
396   value->data[0].v_ulong = G_PARAM_SPEC_FLAGS (pspec)->default_value;
397 }
398
399 static gboolean
400 param_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
414 static void
415 param_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
425 static void
426 param_float_set_default (GParamSpec *pspec,
427                          GValue     *value)
428 {
429   value->data[0].v_float = G_PARAM_SPEC_FLOAT (pspec)->default_value;
430 }
431
432 static gboolean
433 param_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
444 static gint
445 param_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
457 static void
458 param_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
468 static void
469 param_double_set_default (GParamSpec *pspec,
470                           GValue     *value)
471 {
472   value->data[0].v_double = G_PARAM_SPEC_DOUBLE (pspec)->default_value;
473 }
474
475 static gboolean
476 param_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
487 static gint
488 param_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
500 static void
501 param_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
513 static void
514 param_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
529 static void
530 param_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
536 static gboolean
537 param_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
578 static gint
579 param_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
591 static void
592 param_param_init (GParamSpec *pspec)
593 {
594   /* GParamSpecParam *spec = G_PARAM_SPEC_PARAM (pspec); */
595 }
596
597 static void
598 param_param_set_default (GParamSpec *pspec,
599                          GValue     *value)
600 {
601   value->data[0].v_pointer = NULL;
602 }
603
604 static gboolean
605 param_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
622 static void
623 param_boxed_init (GParamSpec *pspec)
624 {
625   /* GParamSpecBoxed *bspec = G_PARAM_SPEC_BOXED (pspec); */
626 }
627
628 static void
629 param_boxed_set_default (GParamSpec *pspec,
630                          GValue     *value)
631 {
632   value->data[0].v_pointer = NULL;
633 }
634
635 static gboolean
636 param_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
647 static gint
648 param_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
660 static void
661 param_pointer_init (GParamSpec *pspec)
662 {
663   /* GParamSpecPointer *spec = G_PARAM_SPEC_POINTER (pspec); */
664 }
665
666 static void
667 param_pointer_set_default (GParamSpec *pspec,
668                            GValue     *value)
669 {
670   value->data[0].v_pointer = NULL;
671 }
672
673 static gboolean
674 param_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
683 static gint
684 param_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
696 static void
697 param_closure_init (GParamSpec *pspec)
698 {
699   /* GParamSpecClosure *cspec = G_PARAM_SPEC_CLOSURE (pspec); */
700 }
701
702 static void
703 param_closure_set_default (GParamSpec *pspec,
704                            GValue     *value)
705 {
706   value->data[0].v_pointer = NULL;
707 }
708
709 static gboolean
710 param_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
722 static gint
723 param_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
735 static void
736 param_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
744 static inline guint
745 value_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
766 static void
767 param_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
781 static void
782 param_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
793 static gboolean
794 param_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
833 static gint
834 param_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
875 static void
876 param_object_init (GParamSpec *pspec)
877 {
878   /* GParamSpecObject *ospec = G_PARAM_SPEC_OBJECT (pspec); */
879 }
880
881 static void
882 param_object_set_default (GParamSpec *pspec,
883                           GValue     *value)
884 {
885   value->data[0].v_pointer = NULL;
886 }
887
888 static gboolean
889 param_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
906 static gint
907 param_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 --- */
921 void
922 g_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 --- */
1252 GParamSpec*
1253 g_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
1278 GParamSpec*
1279 g_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
1304 GParamSpec*
1305 g_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
1326 GParamSpec*
1327 g_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
1352 GParamSpec*
1353 g_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
1378 GParamSpec*
1379 g_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
1404 GParamSpec*
1405 g_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
1430 GParamSpec*
1431 g_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
1450 GParamSpec*
1451 g_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
1480 GParamSpec*
1481 g_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
1510 GParamSpec*
1511 g_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
1536 GParamSpec*
1537 g_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
1562 GParamSpec*
1563 g_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
1580 GParamSpec*
1581 g_param_spec_param (const gchar *name,
1582                     const gchar *nick,
1583                     const gchar *blurb,
1584                     GType        param_type,
1585                     GParamFlags  flags)
1586 {
1587   GParamSpecParam *pspec;
1588   
1589   g_return_val_if_fail (G_TYPE_IS_PARAM (param_type), NULL);
1590   
1591   pspec = g_param_spec_internal (G_TYPE_PARAM_PARAM,
1592                                  name,
1593                                  nick,
1594                                  blurb,
1595                                  flags);
1596   G_PARAM_SPEC (pspec)->value_type = param_type;
1597   
1598   return G_PARAM_SPEC (pspec);
1599 }
1600
1601 GParamSpec*
1602 g_param_spec_boxed (const gchar *name,
1603                     const gchar *nick,
1604                     const gchar *blurb,
1605                     GType        boxed_type,
1606                     GParamFlags  flags)
1607 {
1608   GParamSpecBoxed *bspec;
1609   
1610   g_return_val_if_fail (G_TYPE_IS_BOXED (boxed_type), NULL);
1611   g_return_val_if_fail (G_TYPE_IS_VALUE_TYPE (boxed_type), NULL);
1612   
1613   bspec = g_param_spec_internal (G_TYPE_PARAM_BOXED,
1614                                  name,
1615                                  nick,
1616                                  blurb,
1617                                  flags);
1618   G_PARAM_SPEC (bspec)->value_type = boxed_type;
1619   
1620   return G_PARAM_SPEC (bspec);
1621 }
1622
1623 GParamSpec*
1624 g_param_spec_pointer (const gchar *name,
1625                       const gchar *nick,
1626                       const gchar *blurb,
1627                       GParamFlags  flags)
1628 {
1629   GParamSpecPointer *pspec;
1630   
1631   pspec = g_param_spec_internal (G_TYPE_PARAM_POINTER,
1632                                  name,
1633                                  nick,
1634                                  blurb,
1635                                  flags);
1636   return G_PARAM_SPEC (pspec);
1637 }
1638
1639 GParamSpec*
1640 g_param_spec_value_array (const gchar *name,
1641                           const gchar *nick,
1642                           const gchar *blurb,
1643                           GParamSpec  *element_spec,
1644                           GParamFlags  flags)
1645 {
1646   GParamSpecValueArray *aspec;
1647   
1648   if (element_spec)
1649     g_return_val_if_fail (G_IS_PARAM_SPEC (element_spec), NULL);
1650   
1651   aspec = g_param_spec_internal (G_TYPE_PARAM_VALUE_ARRAY,
1652                                  name,
1653                                  nick,
1654                                  blurb,
1655                                  flags);
1656   if (element_spec)
1657     {
1658       aspec->element_spec = g_param_spec_ref (element_spec);
1659       g_param_spec_sink (element_spec);
1660     }
1661
1662   return G_PARAM_SPEC (aspec);
1663 }
1664
1665 GParamSpec*
1666 g_param_spec_closure (const gchar *name,
1667                       const gchar *nick,
1668                       const gchar *blurb,
1669                       GParamFlags  flags)
1670 {
1671   GParamSpecClosure *cspec;
1672   
1673   cspec = g_param_spec_internal (G_TYPE_PARAM_CLOSURE,
1674                                  name,
1675                                  nick,
1676                                  blurb,
1677                                  flags);
1678   return G_PARAM_SPEC (cspec);
1679 }
1680
1681 GParamSpec*
1682 g_param_spec_object (const gchar *name,
1683                      const gchar *nick,
1684                      const gchar *blurb,
1685                      GType        object_type,
1686                      GParamFlags  flags)
1687 {
1688   GParamSpecObject *ospec;
1689   
1690   g_return_val_if_fail (g_type_is_a (object_type, G_TYPE_OBJECT), NULL);
1691   
1692   ospec = g_param_spec_internal (G_TYPE_PARAM_OBJECT,
1693                                  name,
1694                                  nick,
1695                                  blurb,
1696                                  flags);
1697   G_PARAM_SPEC (ospec)->value_type = object_type;
1698   
1699   return G_PARAM_SPEC (ospec);
1700 }