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