Update.
[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_closure_init (GParamSpec *pspec)
778 {
779   /* GParamSpecClosure *cspec = G_PARAM_SPEC_CLOSURE (pspec); */
780 }
781
782 static void
783 param_closure_set_default (GParamSpec *pspec,
784                            GValue     *value)
785 {
786   value->data[0].v_pointer = NULL;
787 }
788
789 static gboolean
790 param_closure_validate (GParamSpec *pspec,
791                         GValue     *value)
792 {
793   /* GParamSpecClosure *cspec = G_PARAM_SPEC_CLOSURE (pspec); */
794   /* GClosure *closure = value->data[0].v_pointer; */
795   guint changed = 0;
796
797   /* we don't actually have necessary means to ensure closure validity */
798
799   return changed;
800 }
801
802 static gint
803 param_closure_values_cmp (GParamSpec   *pspec,
804                           const GValue *value1,
805                           const GValue *value2)
806 {
807   guint8 *p1 = value1->data[0].v_pointer;
808   guint8 *p2 = value2->data[0].v_pointer;
809
810   /* not much to compare here, try to at least provide stable lesser/greater result */
811
812   return p1 < p2 ? -1 : p1 > p2;
813 }
814
815 static void
816 param_value_array_init (GParamSpec *pspec)
817 {
818   GParamSpecValueArray *aspec = G_PARAM_SPEC_VALUE_ARRAY (pspec);
819
820   aspec->element_spec = NULL;
821   aspec->fixed_n_elements = 0; /* disable */
822 }
823
824 static inline guint
825 value_array_ensure_size (GValueArray *value_array,
826                          guint        fixed_n_elements)
827 {
828   guint changed = 0;
829
830   if (fixed_n_elements)
831     {
832       while (value_array->n_values < fixed_n_elements)
833         {
834           g_value_array_append (value_array, NULL);
835           changed++;
836         }
837       while (value_array->n_values > fixed_n_elements)
838         {
839           g_value_array_remove (value_array, value_array->n_values - 1);
840           changed++;
841         }
842     }
843   return changed;
844 }
845
846 static void
847 param_value_array_finalize (GParamSpec *pspec)
848 {
849   GParamSpecValueArray *aspec = G_PARAM_SPEC_VALUE_ARRAY (pspec);
850   GParamSpecClass *parent_class = g_type_class_peek (g_type_parent (G_TYPE_PARAM_VALUE_ARRAY));
851
852   if (aspec->element_spec)
853     {
854       g_param_spec_unref (aspec->element_spec);
855       aspec->element_spec = NULL;
856     }
857
858   parent_class->finalize (pspec);
859 }
860
861 static void
862 param_value_array_set_default (GParamSpec *pspec,
863                                GValue     *value)
864 {
865   GParamSpecValueArray *aspec = G_PARAM_SPEC_VALUE_ARRAY (pspec);
866
867   g_return_if_fail (value->data[0].v_pointer != NULL);  /* paranoid */
868   
869   /* g_value_reset (value);  already done */
870   value_array_ensure_size (value->data[0].v_pointer, aspec->fixed_n_elements);
871 }
872
873 static gboolean
874 param_value_array_validate (GParamSpec *pspec,
875                             GValue     *value)
876 {
877   GParamSpecValueArray *aspec = G_PARAM_SPEC_VALUE_ARRAY (pspec);
878   GValueArray *value_array = value->data[0].v_pointer;
879   guint changed = 0;
880
881   g_return_val_if_fail (value->data[0].v_pointer != NULL, FALSE);       /* paranoid */
882
883   /* ensure array size validity */
884   changed += value_array_ensure_size (value_array, aspec->fixed_n_elements);
885
886   /* ensure array values validity against a present element spec */
887   if (aspec->element_spec)
888     {
889       GParamSpec *element_spec = aspec->element_spec;
890       guint i;
891
892       for (i = 0; i < value_array->n_values; i++)
893         {
894           GValue *element = value_array->values + i;
895
896           /* need to fixup value type, or ensure that the array value is initialized at all */
897           if (!g_value_type_compatible (G_VALUE_TYPE (element), G_PARAM_SPEC_VALUE_TYPE (element_spec)))
898             {
899               if (G_VALUE_TYPE (element) != 0)
900                 g_value_unset (element);
901               g_value_init (element, G_PARAM_SPEC_VALUE_TYPE (element_spec));
902               g_param_value_set_default (element_spec, element);
903               changed++;
904             }
905           /* validate array value against element_spec */
906           changed += g_param_value_validate (element_spec, element);
907         }
908     }
909
910   return changed;
911 }
912
913 static gint
914 param_value_array_values_cmp (GParamSpec   *pspec,
915                               const GValue *value1,
916                               const GValue *value2)
917 {
918   GParamSpecValueArray *aspec = G_PARAM_SPEC_VALUE_ARRAY (pspec);
919   GValueArray *value_array1 = value1->data[0].v_pointer;
920   GValueArray *value_array2 = value2->data[0].v_pointer;
921
922   g_return_val_if_fail (value1->data[0].v_pointer != NULL, -1); /* paranoid */
923   g_return_val_if_fail (value2->data[0].v_pointer != NULL, 1);  /* paranoid */
924
925   if (value_array1->n_values != value_array2->n_values)
926     return value_array1->n_values < value_array2->n_values ? -1 : 1;
927   else if (!aspec->element_spec)
928     {
929       /* we need an element specification for comparisons, so there's not much
930        * to compare here, try to at least provide stable lesser/greater result
931        */
932       return value_array1->n_values < value_array2->n_values ? -1 : value_array1->n_values > value_array2->n_values;
933     }
934   else /* value_array1->n_values == value_array2->n_values */
935     {
936       guint i;
937
938       for (i = 0; i < value_array1->n_values; i++)
939         {
940           GValue *element1 = value_array1->values + i;
941           GValue *element2 = value_array2->values + i;
942           gint cmp;
943
944           /* need corresponding element types, provide stable result otherwise */
945           if (G_VALUE_TYPE (element1) != G_VALUE_TYPE (element2))
946             return G_VALUE_TYPE (element1) < G_VALUE_TYPE (element2) ? -1 : 1;
947           cmp = g_param_values_cmp (aspec->element_spec, element1, element2);
948           if (cmp)
949             return cmp;
950         }
951       return 0;
952     }
953 }
954
955 static void
956 param_object_init (GParamSpec *pspec)
957 {
958   /* GParamSpecObject *ospec = G_PARAM_SPEC_OBJECT (pspec); */
959 }
960
961 static void
962 param_object_set_default (GParamSpec *pspec,
963                           GValue     *value)
964 {
965   value->data[0].v_pointer = NULL;
966 }
967
968 static gboolean
969 param_object_validate (GParamSpec *pspec,
970                        GValue     *value)
971 {
972   GParamSpecObject *ospec = G_PARAM_SPEC_OBJECT (pspec);
973   GObject *object = value->data[0].v_pointer;
974   guint changed = 0;
975   
976   if (object && !g_value_type_compatible (G_OBJECT_TYPE (object), G_PARAM_SPEC_VALUE_TYPE (ospec)))
977     {
978       g_object_unref (object);
979       value->data[0].v_pointer = NULL;
980       changed++;
981     }
982   
983   return changed;
984 }
985
986 static gint
987 param_object_values_cmp (GParamSpec   *pspec,
988                          const GValue *value1,
989                          const GValue *value2)
990 {
991   guint8 *p1 = value1->data[0].v_pointer;
992   guint8 *p2 = value2->data[0].v_pointer;
993
994   /* not much to compare here, try to at least provide stable lesser/greater result */
995
996   return p1 < p2 ? -1 : p1 > p2;
997 }
998
999
1000 /* --- type initialization --- */
1001 void
1002 g_param_spec_types_init (void)  /* sync with gtype.c */
1003 {
1004   GType type;
1005   
1006   /* G_TYPE_PARAM_CHAR
1007    */
1008   {
1009     static const GParamSpecTypeInfo pspec_info = {
1010       sizeof (GParamSpecChar),  /* instance_size */
1011       16,                       /* n_preallocs */
1012       param_char_init,          /* instance_init */
1013       G_TYPE_CHAR,              /* value_type */
1014       NULL,                     /* finalize */
1015       param_char_set_default,   /* value_set_default */
1016       param_char_validate,      /* value_validate */
1017       param_int_values_cmp,     /* values_cmp */
1018     };
1019     type = g_param_type_register_static ("GParamChar", &pspec_info);
1020     g_assert (type == G_TYPE_PARAM_CHAR);
1021   }
1022   
1023   /* G_TYPE_PARAM_UCHAR
1024    */
1025   {
1026     static const GParamSpecTypeInfo pspec_info = {
1027       sizeof (GParamSpecUChar), /* instance_size */
1028       16,                       /* n_preallocs */
1029       param_uchar_init,         /* instance_init */
1030       G_TYPE_UCHAR,             /* value_type */
1031       NULL,                     /* finalize */
1032       param_uchar_set_default,  /* value_set_default */
1033       param_uchar_validate,     /* value_validate */
1034       param_uint_values_cmp,    /* values_cmp */
1035     };
1036     type = g_param_type_register_static ("GParamUChar", &pspec_info);
1037     g_assert (type == G_TYPE_PARAM_UCHAR);
1038   }
1039   
1040   /* G_TYPE_PARAM_BOOLEAN
1041    */
1042   {
1043     static const GParamSpecTypeInfo pspec_info = {
1044       sizeof (GParamSpecBoolean), /* instance_size */
1045       16,                         /* n_preallocs */
1046       NULL,                       /* instance_init */
1047       G_TYPE_BOOLEAN,             /* value_type */
1048       NULL,                       /* finalize */
1049       param_boolean_set_default,  /* value_set_default */
1050       param_boolean_validate,     /* value_validate */
1051       param_int_values_cmp,       /* values_cmp */
1052     };
1053     type = g_param_type_register_static ("GParamBoolean", &pspec_info);
1054     g_assert (type == G_TYPE_PARAM_BOOLEAN);
1055   }
1056   
1057   /* G_TYPE_PARAM_INT
1058    */
1059   {
1060     static const GParamSpecTypeInfo pspec_info = {
1061       sizeof (GParamSpecInt),   /* instance_size */
1062       16,                       /* n_preallocs */
1063       param_int_init,           /* instance_init */
1064       G_TYPE_INT,               /* value_type */
1065       NULL,                     /* finalize */
1066       param_int_set_default,    /* value_set_default */
1067       param_int_validate,       /* value_validate */
1068       param_int_values_cmp,     /* values_cmp */
1069     };
1070     type = g_param_type_register_static ("GParamInt", &pspec_info);
1071     g_assert (type == G_TYPE_PARAM_INT);
1072   }
1073   
1074   /* G_TYPE_PARAM_UINT
1075    */
1076   {
1077     static const GParamSpecTypeInfo pspec_info = {
1078       sizeof (GParamSpecUInt),  /* instance_size */
1079       16,                       /* n_preallocs */
1080       param_uint_init,          /* instance_init */
1081       G_TYPE_UINT,              /* value_type */
1082       NULL,                     /* finalize */
1083       param_uint_set_default,   /* value_set_default */
1084       param_uint_validate,      /* value_validate */
1085       param_uint_values_cmp,    /* values_cmp */
1086     };
1087     type = g_param_type_register_static ("GParamUInt", &pspec_info);
1088     g_assert (type == G_TYPE_PARAM_UINT);
1089   }
1090   
1091   /* G_TYPE_PARAM_LONG
1092    */
1093   {
1094     static const GParamSpecTypeInfo pspec_info = {
1095       sizeof (GParamSpecLong),  /* instance_size */
1096       16,                       /* n_preallocs */
1097       param_long_init,          /* instance_init */
1098       G_TYPE_LONG,              /* value_type */
1099       NULL,                     /* finalize */
1100       param_long_set_default,   /* value_set_default */
1101       param_long_validate,      /* value_validate */
1102       param_long_values_cmp,    /* values_cmp */
1103     };
1104     type = g_param_type_register_static ("GParamLong", &pspec_info);
1105     g_assert (type == G_TYPE_PARAM_LONG);
1106   }
1107   
1108   /* G_TYPE_PARAM_ULONG
1109    */
1110   {
1111     static const GParamSpecTypeInfo pspec_info = {
1112       sizeof (GParamSpecULong), /* instance_size */
1113       16,                       /* n_preallocs */
1114       param_ulong_init,         /* instance_init */
1115       G_TYPE_ULONG,             /* value_type */
1116       NULL,                     /* finalize */
1117       param_ulong_set_default,  /* value_set_default */
1118       param_ulong_validate,     /* value_validate */
1119       param_ulong_values_cmp,   /* values_cmp */
1120     };
1121     type = g_param_type_register_static ("GParamULong", &pspec_info);
1122     g_assert (type == G_TYPE_PARAM_ULONG);
1123   }
1124
1125   /* G_TYPE_PARAM_INT64
1126    */
1127   {
1128     static const GParamSpecTypeInfo pspec_info = {
1129       sizeof (GParamSpecInt64),  /* instance_size */
1130       16,                       /* n_preallocs */
1131       param_int64_init,         /* instance_init */
1132       G_TYPE_INT64,             /* value_type */
1133       NULL,                     /* finalize */
1134       param_int64_set_default,  /* value_set_default */
1135       param_int64_validate,     /* value_validate */
1136       param_int64_values_cmp,   /* values_cmp */
1137     };
1138     type = g_param_type_register_static ("GParamInt64", &pspec_info);
1139     g_assert (type == G_TYPE_PARAM_INT64);
1140   }
1141   
1142   /* G_TYPE_PARAM_UINT64
1143    */
1144   {
1145     static const GParamSpecTypeInfo pspec_info = {
1146       sizeof (GParamSpecUInt64), /* instance_size */
1147       16,                       /* n_preallocs */
1148       param_uint64_init,        /* instance_init */
1149       G_TYPE_UINT64,            /* value_type */
1150       NULL,                     /* finalize */
1151       param_uint64_set_default, /* value_set_default */
1152       param_uint64_validate,    /* value_validate */
1153       param_uint64_values_cmp,  /* values_cmp */
1154     };
1155     type = g_param_type_register_static ("GParamUInt64", &pspec_info);
1156     g_assert (type == G_TYPE_PARAM_UINT64);
1157   }
1158
1159   /* G_TYPE_PARAM_UNICHAR
1160    */
1161   {
1162     static const GParamSpecTypeInfo pspec_info = {
1163       sizeof (GParamSpecUnichar), /* instance_size */
1164       16,                        /* n_preallocs */
1165       param_unichar_init,        /* instance_init */
1166       G_TYPE_UINT,               /* value_type */
1167       NULL,                      /* finalize */
1168       param_unichar_set_default, /* value_set_default */
1169       param_unichar_validate,    /* value_validate */
1170       param_unichar_values_cmp,  /* values_cmp */
1171     };
1172     type = g_param_type_register_static ("GParamUnichar", &pspec_info);
1173     g_assert (type == G_TYPE_PARAM_UNICHAR);
1174   }
1175
1176  /* G_TYPE_PARAM_ENUM
1177    */
1178   {
1179     static const GParamSpecTypeInfo pspec_info = {
1180       sizeof (GParamSpecEnum),  /* instance_size */
1181       16,                       /* n_preallocs */
1182       param_enum_init,          /* instance_init */
1183       G_TYPE_ENUM,              /* value_type */
1184       param_enum_finalize,      /* finalize */
1185       param_enum_set_default,   /* value_set_default */
1186       param_enum_validate,      /* value_validate */
1187       param_long_values_cmp,    /* values_cmp */
1188     };
1189     type = g_param_type_register_static ("GParamEnum", &pspec_info);
1190     g_assert (type == G_TYPE_PARAM_ENUM);
1191   }
1192   
1193   /* G_TYPE_PARAM_FLAGS
1194    */
1195   {
1196     static const GParamSpecTypeInfo pspec_info = {
1197       sizeof (GParamSpecFlags), /* instance_size */
1198       16,                       /* n_preallocs */
1199       param_flags_init,         /* instance_init */
1200       G_TYPE_FLAGS,             /* value_type */
1201       param_flags_finalize,     /* finalize */
1202       param_flags_set_default,  /* value_set_default */
1203       param_flags_validate,     /* value_validate */
1204       param_ulong_values_cmp,   /* values_cmp */
1205     };
1206     type = g_param_type_register_static ("GParamFlags", &pspec_info);
1207     g_assert (type == G_TYPE_PARAM_FLAGS);
1208   }
1209   
1210   /* G_TYPE_PARAM_FLOAT
1211    */
1212   {
1213     static const GParamSpecTypeInfo pspec_info = {
1214       sizeof (GParamSpecFloat), /* instance_size */
1215       16,                       /* n_preallocs */
1216       param_float_init,         /* instance_init */
1217       G_TYPE_FLOAT,             /* value_type */
1218       NULL,                     /* finalize */
1219       param_float_set_default,  /* value_set_default */
1220       param_float_validate,     /* value_validate */
1221       param_float_values_cmp,   /* values_cmp */
1222     };
1223     type = g_param_type_register_static ("GParamFloat", &pspec_info);
1224     g_assert (type == G_TYPE_PARAM_FLOAT);
1225   }
1226   
1227   /* G_TYPE_PARAM_DOUBLE
1228    */
1229   {
1230     static const GParamSpecTypeInfo pspec_info = {
1231       sizeof (GParamSpecDouble),        /* instance_size */
1232       16,                               /* n_preallocs */
1233       param_double_init,                /* instance_init */
1234       G_TYPE_DOUBLE,                    /* value_type */
1235       NULL,                             /* finalize */
1236       param_double_set_default,         /* value_set_default */
1237       param_double_validate,            /* value_validate */
1238       param_double_values_cmp,          /* values_cmp */
1239     };
1240     type = g_param_type_register_static ("GParamDouble", &pspec_info);
1241     g_assert (type == G_TYPE_PARAM_DOUBLE);
1242   }
1243   
1244   /* G_TYPE_PARAM_STRING
1245    */
1246   {
1247     static const GParamSpecTypeInfo pspec_info = {
1248       sizeof (GParamSpecString),        /* instance_size */
1249       16,                               /* n_preallocs */
1250       param_string_init,                /* instance_init */
1251       G_TYPE_STRING,                    /* value_type */
1252       param_string_finalize,            /* finalize */
1253       param_string_set_default,         /* value_set_default */
1254       param_string_validate,            /* value_validate */
1255       param_string_values_cmp,          /* values_cmp */
1256     };
1257     type = g_param_type_register_static ("GParamString", &pspec_info);
1258     g_assert (type == G_TYPE_PARAM_STRING);
1259   }
1260   
1261   /* G_TYPE_PARAM_PARAM
1262    */
1263   {
1264     static const GParamSpecTypeInfo pspec_info = {
1265       sizeof (GParamSpecParam), /* instance_size */
1266       16,                       /* n_preallocs */
1267       param_param_init,         /* instance_init */
1268       G_TYPE_PARAM,             /* value_type */
1269       NULL,                     /* finalize */
1270       param_param_set_default,  /* value_set_default */
1271       param_param_validate,     /* value_validate */
1272       param_pointer_values_cmp, /* values_cmp */
1273     };
1274     type = g_param_type_register_static ("GParamParam", &pspec_info);
1275     g_assert (type == G_TYPE_PARAM_PARAM);
1276   }
1277   
1278   /* G_TYPE_PARAM_BOXED
1279    */
1280   {
1281     static const GParamSpecTypeInfo pspec_info = {
1282       sizeof (GParamSpecBoxed), /* instance_size */
1283       4,                        /* n_preallocs */
1284       param_boxed_init,         /* instance_init */
1285       G_TYPE_BOXED,             /* value_type */
1286       NULL,                     /* finalize */
1287       param_boxed_set_default,  /* value_set_default */
1288       param_boxed_validate,     /* value_validate */
1289       param_boxed_values_cmp,   /* values_cmp */
1290     };
1291     type = g_param_type_register_static ("GParamBoxed", &pspec_info);
1292     g_assert (type == G_TYPE_PARAM_BOXED);
1293   }
1294
1295   /* G_TYPE_PARAM_POINTER
1296    */
1297   {
1298     static const GParamSpecTypeInfo pspec_info = {
1299       sizeof (GParamSpecPointer),  /* instance_size */
1300       0,                           /* n_preallocs */
1301       param_pointer_init,          /* instance_init */
1302       G_TYPE_POINTER,              /* value_type */
1303       NULL,                        /* finalize */
1304       param_pointer_set_default,   /* value_set_default */
1305       param_pointer_validate,      /* value_validate */
1306       param_pointer_values_cmp,    /* values_cmp */
1307     };
1308     type = g_param_type_register_static ("GParamPointer", &pspec_info);
1309     g_assert (type == G_TYPE_PARAM_POINTER);
1310   }
1311   
1312   /* G_TYPE_PARAM_VALUE_ARRAY
1313    */
1314   {
1315     static const GParamSpecTypeInfo pspec_info = {
1316       sizeof (GParamSpecValueArray),    /* instance_size */
1317       0,                                /* n_preallocs */
1318       param_value_array_init,           /* instance_init */
1319       G_TYPE_VALUE_ARRAY,               /* value_type */
1320       param_value_array_finalize,       /* finalize */
1321       param_value_array_set_default,    /* value_set_default */
1322       param_value_array_validate,       /* value_validate */
1323       param_value_array_values_cmp,     /* values_cmp */
1324     };
1325     type = g_param_type_register_static ("GParamValueArray", &pspec_info);
1326     g_assert (type == G_TYPE_PARAM_VALUE_ARRAY);
1327   }
1328
1329   /* G_TYPE_PARAM_CLOSURE
1330    */
1331   {
1332     static const GParamSpecTypeInfo pspec_info = {
1333       sizeof (GParamSpecClosure),   /* instance_size */
1334       0,                            /* n_preallocs */
1335       param_closure_init,           /* instance_init */
1336       G_TYPE_CLOSURE,               /* value_type */
1337       NULL,                         /* finalize */
1338       param_closure_set_default,    /* value_set_default */
1339       param_closure_validate,       /* value_validate */
1340       param_closure_values_cmp,     /* values_cmp */
1341     };
1342     type = g_param_type_register_static ("GParamClosure", &pspec_info);
1343     g_assert (type == G_TYPE_PARAM_CLOSURE);
1344   }
1345   
1346   /* G_TYPE_PARAM_OBJECT
1347    */
1348   {
1349     static const GParamSpecTypeInfo pspec_info = {
1350       sizeof (GParamSpecObject), /* instance_size */
1351       16,                        /* n_preallocs */
1352       param_object_init,         /* instance_init */
1353       G_TYPE_OBJECT,             /* value_type */
1354       NULL,                      /* finalize */
1355       param_object_set_default,  /* value_set_default */
1356       param_object_validate,     /* value_validate */
1357       param_object_values_cmp,   /* values_cmp */
1358     };
1359     type = g_param_type_register_static ("GParamObject", &pspec_info);
1360     g_assert (type == G_TYPE_PARAM_OBJECT);
1361   }
1362 }
1363
1364
1365 /* --- GParamSpec initialization --- */
1366 GParamSpec*
1367 g_param_spec_char (const gchar *name,
1368                    const gchar *nick,
1369                    const gchar *blurb,
1370                    gint8        minimum,
1371                    gint8        maximum,
1372                    gint8        default_value,
1373                    GParamFlags  flags)
1374 {
1375   GParamSpecChar *cspec;
1376
1377   g_return_val_if_fail (default_value >= minimum && default_value <= maximum, NULL);
1378
1379   cspec = g_param_spec_internal (G_TYPE_PARAM_CHAR,
1380                                  name,
1381                                  nick,
1382                                  blurb,
1383                                  flags);
1384   
1385   cspec->minimum = minimum;
1386   cspec->maximum = maximum;
1387   cspec->default_value = default_value;
1388   
1389   return G_PARAM_SPEC (cspec);
1390 }
1391
1392 GParamSpec*
1393 g_param_spec_uchar (const gchar *name,
1394                     const gchar *nick,
1395                     const gchar *blurb,
1396                     guint8       minimum,
1397                     guint8       maximum,
1398                     guint8       default_value,
1399                     GParamFlags  flags)
1400 {
1401   GParamSpecUChar *uspec;
1402
1403   g_return_val_if_fail (default_value >= minimum && default_value <= maximum, NULL);
1404
1405   uspec = g_param_spec_internal (G_TYPE_PARAM_UCHAR,
1406                                  name,
1407                                  nick,
1408                                  blurb,
1409                                  flags);
1410   
1411   uspec->minimum = minimum;
1412   uspec->maximum = maximum;
1413   uspec->default_value = default_value;
1414   
1415   return G_PARAM_SPEC (uspec);
1416 }
1417
1418 GParamSpec*
1419 g_param_spec_boolean (const gchar *name,
1420                       const gchar *nick,
1421                       const gchar *blurb,
1422                       gboolean     default_value,
1423                       GParamFlags  flags)
1424 {
1425   GParamSpecBoolean *bspec;
1426
1427   g_return_val_if_fail (default_value == TRUE || default_value == FALSE, NULL);
1428
1429   bspec = g_param_spec_internal (G_TYPE_PARAM_BOOLEAN,
1430                                  name,
1431                                  nick,
1432                                  blurb,
1433                                  flags);
1434   
1435   bspec->default_value = default_value;
1436   
1437   return G_PARAM_SPEC (bspec);
1438 }
1439
1440 GParamSpec*
1441 g_param_spec_int (const gchar *name,
1442                   const gchar *nick,
1443                   const gchar *blurb,
1444                   gint         minimum,
1445                   gint         maximum,
1446                   gint         default_value,
1447                   GParamFlags  flags)
1448 {
1449   GParamSpecInt *ispec;
1450
1451   g_return_val_if_fail (default_value >= minimum && default_value <= maximum, NULL);
1452
1453   ispec = g_param_spec_internal (G_TYPE_PARAM_INT,
1454                                  name,
1455                                  nick,
1456                                  blurb,
1457                                  flags);
1458   
1459   ispec->minimum = minimum;
1460   ispec->maximum = maximum;
1461   ispec->default_value = default_value;
1462   
1463   return G_PARAM_SPEC (ispec);
1464 }
1465
1466 GParamSpec*
1467 g_param_spec_uint (const gchar *name,
1468                    const gchar *nick,
1469                    const gchar *blurb,
1470                    guint        minimum,
1471                    guint        maximum,
1472                    guint        default_value,
1473                    GParamFlags  flags)
1474 {
1475   GParamSpecUInt *uspec;
1476
1477   g_return_val_if_fail (default_value >= minimum && default_value <= maximum, NULL);
1478
1479   uspec = g_param_spec_internal (G_TYPE_PARAM_UINT,
1480                                  name,
1481                                  nick,
1482                                  blurb,
1483                                  flags);
1484   
1485   uspec->minimum = minimum;
1486   uspec->maximum = maximum;
1487   uspec->default_value = default_value;
1488   
1489   return G_PARAM_SPEC (uspec);
1490 }
1491
1492 GParamSpec*
1493 g_param_spec_long (const gchar *name,
1494                    const gchar *nick,
1495                    const gchar *blurb,
1496                    glong        minimum,
1497                    glong        maximum,
1498                    glong        default_value,
1499                    GParamFlags  flags)
1500 {
1501   GParamSpecLong *lspec;
1502
1503   g_return_val_if_fail (default_value >= minimum && default_value <= maximum, NULL);
1504
1505   lspec = g_param_spec_internal (G_TYPE_PARAM_LONG,
1506                                  name,
1507                                  nick,
1508                                  blurb,
1509                                  flags);
1510   
1511   lspec->minimum = minimum;
1512   lspec->maximum = maximum;
1513   lspec->default_value = default_value;
1514   
1515   return G_PARAM_SPEC (lspec);
1516 }
1517
1518 GParamSpec*
1519 g_param_spec_ulong (const gchar *name,
1520                     const gchar *nick,
1521                     const gchar *blurb,
1522                     gulong       minimum,
1523                     gulong       maximum,
1524                     gulong       default_value,
1525                     GParamFlags  flags)
1526 {
1527   GParamSpecULong *uspec;
1528
1529   g_return_val_if_fail (default_value >= minimum && default_value <= maximum, NULL);
1530
1531   uspec = g_param_spec_internal (G_TYPE_PARAM_ULONG,
1532                                  name,
1533                                  nick,
1534                                  blurb,
1535                                  flags);
1536   
1537   uspec->minimum = minimum;
1538   uspec->maximum = maximum;
1539   uspec->default_value = default_value;
1540   
1541   return G_PARAM_SPEC (uspec);
1542 }
1543
1544 GParamSpec*
1545 g_param_spec_int64 (const gchar *name,
1546                     const gchar *nick,
1547                     const gchar *blurb,
1548                     gint64       minimum,
1549                     gint64       maximum,
1550                     gint64       default_value,
1551                     GParamFlags  flags)
1552 {
1553   GParamSpecInt64 *lspec;
1554   
1555   g_return_val_if_fail (default_value >= minimum && default_value <= maximum, NULL);
1556
1557   lspec = g_param_spec_internal (G_TYPE_PARAM_INT64,
1558                                  name,
1559                                  nick,
1560                                  blurb,
1561                                  flags);
1562   
1563   lspec->minimum = minimum;
1564   lspec->maximum = maximum;
1565   lspec->default_value = default_value;
1566   
1567   return G_PARAM_SPEC (lspec);
1568 }
1569
1570 GParamSpec*
1571 g_param_spec_uint64 (const gchar *name,
1572                      const gchar *nick,
1573                      const gchar *blurb,
1574                      guint64      minimum,
1575                      guint64      maximum,
1576                      guint64      default_value,
1577                      GParamFlags  flags)
1578 {
1579   GParamSpecUInt64 *uspec;
1580   
1581   g_return_val_if_fail (default_value >= minimum && default_value <= maximum, NULL);
1582   
1583   uspec = g_param_spec_internal (G_TYPE_PARAM_UINT64,
1584                                  name,
1585                                  nick,
1586                                  blurb,
1587                                  flags);
1588   
1589   uspec->minimum = minimum;
1590   uspec->maximum = maximum;
1591   uspec->default_value = default_value;
1592   
1593   return G_PARAM_SPEC (uspec);
1594 }
1595
1596 GParamSpec*
1597 g_param_spec_unichar (const gchar *name,
1598                       const gchar *nick,
1599                       const gchar *blurb,
1600                       gunichar     default_value,
1601                       GParamFlags  flags)
1602 {
1603   GParamSpecUnichar *uspec;
1604
1605   uspec = g_param_spec_internal (G_TYPE_PARAM_UNICHAR,
1606                                  name,
1607                                  nick,
1608                                  blurb,
1609                                  flags);
1610   
1611   uspec->default_value = default_value;
1612   
1613   return G_PARAM_SPEC (uspec);
1614 }
1615
1616 GParamSpec*
1617 g_param_spec_enum (const gchar *name,
1618                    const gchar *nick,
1619                    const gchar *blurb,
1620                    GType        enum_type,
1621                    gint         default_value,
1622                    GParamFlags  flags)
1623 {
1624   GParamSpecEnum *espec;
1625   GEnumClass *enum_class;
1626   
1627   g_return_val_if_fail (G_TYPE_IS_ENUM (enum_type), NULL);
1628
1629   enum_class = g_type_class_ref (enum_type);
1630
1631   g_return_val_if_fail (g_enum_get_value (enum_class, default_value) != NULL, NULL);
1632   
1633   espec = g_param_spec_internal (G_TYPE_PARAM_ENUM,
1634                                  name,
1635                                  nick,
1636                                  blurb,
1637                                  flags);
1638   
1639   espec->enum_class = enum_class;
1640   espec->default_value = default_value;
1641   G_PARAM_SPEC (espec)->value_type = enum_type;
1642   
1643   return G_PARAM_SPEC (espec);
1644 }
1645
1646 GParamSpec*
1647 g_param_spec_flags (const gchar *name,
1648                     const gchar *nick,
1649                     const gchar *blurb,
1650                     GType        flags_type,
1651                     guint        default_value,
1652                     GParamFlags  flags)
1653 {
1654   GParamSpecFlags *fspec;
1655   GFlagsClass *flags_class;
1656   
1657   g_return_val_if_fail (G_TYPE_IS_FLAGS (flags_type), NULL);
1658
1659   flags_class = g_type_class_ref (flags_type);
1660
1661   g_return_val_if_fail ((default_value & flags_class->mask) == default_value, NULL);
1662   
1663   fspec = g_param_spec_internal (G_TYPE_PARAM_FLAGS,
1664                                  name,
1665                                  nick,
1666                                  blurb,
1667                                  flags);
1668   
1669   fspec->flags_class = flags_class;
1670   fspec->default_value = default_value;
1671   G_PARAM_SPEC (fspec)->value_type = flags_type;
1672   
1673   return G_PARAM_SPEC (fspec);
1674 }
1675
1676 GParamSpec*
1677 g_param_spec_float (const gchar *name,
1678                     const gchar *nick,
1679                     const gchar *blurb,
1680                     gfloat       minimum,
1681                     gfloat       maximum,
1682                     gfloat       default_value,
1683                     GParamFlags  flags)
1684 {
1685   GParamSpecFloat *fspec;
1686
1687   g_return_val_if_fail (default_value >= minimum && default_value <= maximum, NULL);
1688
1689   fspec = g_param_spec_internal (G_TYPE_PARAM_FLOAT,
1690                                  name,
1691                                  nick,
1692                                  blurb,
1693                                  flags);
1694   
1695   fspec->minimum = minimum;
1696   fspec->maximum = maximum;
1697   fspec->default_value = default_value;
1698   
1699   return G_PARAM_SPEC (fspec);
1700 }
1701
1702 GParamSpec*
1703 g_param_spec_double (const gchar *name,
1704                      const gchar *nick,
1705                      const gchar *blurb,
1706                      gdouble      minimum,
1707                      gdouble      maximum,
1708                      gdouble      default_value,
1709                      GParamFlags  flags)
1710 {
1711   GParamSpecDouble *dspec;
1712
1713   g_return_val_if_fail (default_value >= minimum && default_value <= maximum, NULL);
1714
1715   dspec = g_param_spec_internal (G_TYPE_PARAM_DOUBLE,
1716                                  name,
1717                                  nick,
1718                                  blurb,
1719                                  flags);
1720   
1721   dspec->minimum = minimum;
1722   dspec->maximum = maximum;
1723   dspec->default_value = default_value;
1724   
1725   return G_PARAM_SPEC (dspec);
1726 }
1727
1728 GParamSpec*
1729 g_param_spec_string (const gchar *name,
1730                      const gchar *nick,
1731                      const gchar *blurb,
1732                      const gchar *default_value,
1733                      GParamFlags  flags)
1734 {
1735   GParamSpecString *sspec = g_param_spec_internal (G_TYPE_PARAM_STRING,
1736                                                    name,
1737                                                    nick,
1738                                                    blurb,
1739                                                    flags);
1740   g_free (sspec->default_value);
1741   sspec->default_value = g_strdup (default_value);
1742   
1743   return G_PARAM_SPEC (sspec);
1744 }
1745
1746 GParamSpec*
1747 g_param_spec_param (const gchar *name,
1748                     const gchar *nick,
1749                     const gchar *blurb,
1750                     GType        param_type,
1751                     GParamFlags  flags)
1752 {
1753   GParamSpecParam *pspec;
1754   
1755   g_return_val_if_fail (G_TYPE_IS_PARAM (param_type), NULL);
1756   
1757   pspec = g_param_spec_internal (G_TYPE_PARAM_PARAM,
1758                                  name,
1759                                  nick,
1760                                  blurb,
1761                                  flags);
1762   G_PARAM_SPEC (pspec)->value_type = param_type;
1763   
1764   return G_PARAM_SPEC (pspec);
1765 }
1766
1767 GParamSpec*
1768 g_param_spec_boxed (const gchar *name,
1769                     const gchar *nick,
1770                     const gchar *blurb,
1771                     GType        boxed_type,
1772                     GParamFlags  flags)
1773 {
1774   GParamSpecBoxed *bspec;
1775   
1776   g_return_val_if_fail (G_TYPE_IS_BOXED (boxed_type), NULL);
1777   g_return_val_if_fail (G_TYPE_IS_VALUE_TYPE (boxed_type), NULL);
1778   
1779   bspec = g_param_spec_internal (G_TYPE_PARAM_BOXED,
1780                                  name,
1781                                  nick,
1782                                  blurb,
1783                                  flags);
1784   G_PARAM_SPEC (bspec)->value_type = boxed_type;
1785   
1786   return G_PARAM_SPEC (bspec);
1787 }
1788
1789 GParamSpec*
1790 g_param_spec_pointer (const gchar *name,
1791                       const gchar *nick,
1792                       const gchar *blurb,
1793                       GParamFlags  flags)
1794 {
1795   GParamSpecPointer *pspec;
1796   
1797   pspec = g_param_spec_internal (G_TYPE_PARAM_POINTER,
1798                                  name,
1799                                  nick,
1800                                  blurb,
1801                                  flags);
1802   return G_PARAM_SPEC (pspec);
1803 }
1804
1805 GParamSpec*
1806 g_param_spec_value_array (const gchar *name,
1807                           const gchar *nick,
1808                           const gchar *blurb,
1809                           GParamSpec  *element_spec,
1810                           GParamFlags  flags)
1811 {
1812   GParamSpecValueArray *aspec;
1813   
1814   if (element_spec)
1815     g_return_val_if_fail (G_IS_PARAM_SPEC (element_spec), NULL);
1816   
1817   aspec = g_param_spec_internal (G_TYPE_PARAM_VALUE_ARRAY,
1818                                  name,
1819                                  nick,
1820                                  blurb,
1821                                  flags);
1822   if (element_spec)
1823     {
1824       aspec->element_spec = g_param_spec_ref (element_spec);
1825       g_param_spec_sink (element_spec);
1826     }
1827
1828   return G_PARAM_SPEC (aspec);
1829 }
1830
1831 GParamSpec*
1832 g_param_spec_closure (const gchar *name,
1833                       const gchar *nick,
1834                       const gchar *blurb,
1835                       GParamFlags  flags)
1836 {
1837   GParamSpecClosure *cspec;
1838   
1839   cspec = g_param_spec_internal (G_TYPE_PARAM_CLOSURE,
1840                                  name,
1841                                  nick,
1842                                  blurb,
1843                                  flags);
1844   return G_PARAM_SPEC (cspec);
1845 }
1846
1847 GParamSpec*
1848 g_param_spec_object (const gchar *name,
1849                      const gchar *nick,
1850                      const gchar *blurb,
1851                      GType        object_type,
1852                      GParamFlags  flags)
1853 {
1854   GParamSpecObject *ospec;
1855   
1856   g_return_val_if_fail (g_type_is_a (object_type, G_TYPE_OBJECT), NULL);
1857   
1858   ospec = g_param_spec_internal (G_TYPE_PARAM_OBJECT,
1859                                  name,
1860                                  nick,
1861                                  blurb,
1862                                  flags);
1863   G_PARAM_SPEC (ospec)->value_type = object_type;
1864   
1865   return G_PARAM_SPEC (ospec);
1866 }