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