1 /* This file is part of GEGL
2  *
3  * GEGL is free software; you can redistribute it and/or
4  * modify it under the terms of the GNU Lesser General Public
5  * License as published by the Free Software Foundation; either
6  * version 3 of the License, or (at your option) any later version.
7  *
8  * GEGL is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  * Lesser General Public License for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public
14  * License along with GEGL; if not, see <https://www.gnu.org/licenses/>.
15  *
16  * Copyright 2003 Calvin Williamson
17  *           2006 Øyvind Kolås
18  *
19  * Original contents copied from gimp/app/core/gimpparamspecs.h
20  * (c) 1995-2006 Spencer Kimball, Peter Mattis and others.
21  */
22 
23 #include "config.h"
24 
25 #include <glib.h>
26 #include <glib-object.h>
27 #include "gegl-paramspecs.h"
28 #include "gegl-types.h"
29 #include <babl/babl.h>
30 #include "gegl-color.h"
31 #include "gegl-audio-fragment.h"
32 #include "gegl-curve.h"
33 #include "gegl-path.h"
34 
35 static void       gegl_param_double_class_init (GParamSpecClass *klass);
36 static void       gegl_param_double_init       (GParamSpec      *pspec);
37 
38 GType
gegl_param_double_get_type(void)39 gegl_param_double_get_type (void)
40 {
41   static GType type = 0;
42 
43   if (!type)
44     {
45       const GTypeInfo info =
46       {
47         sizeof (GParamSpecClass),
48         NULL, NULL,
49         (GClassInitFunc) gegl_param_double_class_init,
50         NULL, NULL,
51         sizeof (GeglParamSpecDouble),
52         0,
53         (GInstanceInitFunc) gegl_param_double_init
54       };
55       type = g_type_register_static (G_TYPE_PARAM_DOUBLE,
56                                      "GeglParamDouble", &info, 0);
57     }
58   return type;
59 }
60 
61 static void
gegl_param_double_class_init(GParamSpecClass * klass)62 gegl_param_double_class_init (GParamSpecClass *klass)
63 {
64   klass->value_type     = G_TYPE_DOUBLE;
65 }
66 
67 static void
gegl_param_double_init(GParamSpec * pspec)68 gegl_param_double_init (GParamSpec *pspec)
69 {
70   GParamSpecDouble    *dpspec  = G_PARAM_SPEC_DOUBLE (pspec);
71   GeglParamSpecDouble *gdpspec = GEGL_PARAM_SPEC_DOUBLE (pspec);
72   gdpspec->ui_minimum = dpspec->minimum;
73   gdpspec->ui_maximum = dpspec->maximum;
74   gdpspec->ui_gamma   = 1.0;
75 }
76 
77 GParamSpec *
gegl_param_spec_double(const gchar * name,const gchar * nick,const gchar * blurb,gdouble minimum,gdouble maximum,gdouble default_value,gdouble ui_minimum,gdouble ui_maximum,gdouble ui_gamma,GParamFlags flags)78 gegl_param_spec_double (const gchar *name,
79                         const gchar *nick,
80                         const gchar *blurb,
81                         gdouble      minimum,
82                         gdouble      maximum,
83                         gdouble      default_value,
84                         gdouble      ui_minimum,
85                         gdouble      ui_maximum,
86                         gdouble      ui_gamma,
87                         GParamFlags  flags)
88 {
89   GeglParamSpecDouble *pspec;
90   GParamSpecDouble *dspec;
91 
92   pspec = g_param_spec_internal (GEGL_TYPE_PARAM_DOUBLE,
93                                  name, nick, blurb, flags);
94   dspec = G_PARAM_SPEC_DOUBLE (pspec);
95 
96   dspec->minimum = minimum;
97   dspec->maximum = maximum;
98   dspec->default_value = default_value;
99   pspec->ui_minimum = ui_minimum;
100   pspec->ui_maximum = ui_maximum;
101   pspec->ui_gamma   = ui_gamma;
102   gegl_param_spec_double_set_steps (pspec, 0.1, 1.0);
103   gegl_param_spec_double_set_digits (pspec, 2);
104 
105   return G_PARAM_SPEC (pspec);
106 }
107 
108 void
gegl_param_spec_double_set_steps(GeglParamSpecDouble * pspec,gdouble step_small,gdouble step_big)109 gegl_param_spec_double_set_steps (GeglParamSpecDouble *pspec,
110                                   gdouble              step_small,
111                                   gdouble              step_big)
112 {
113   g_return_if_fail (GEGL_IS_PARAM_SPEC_DOUBLE (pspec));
114 
115   pspec->ui_step_small = step_small;
116   pspec->ui_step_big = step_big;
117 }
118 
gegl_param_spec_double_set_digits(GeglParamSpecDouble * pspec,gint digits)119 void gegl_param_spec_double_set_digits (GeglParamSpecDouble *pspec,
120                                         gint                 digits)
121 {
122   g_return_if_fail (GEGL_IS_PARAM_SPEC_DOUBLE (pspec));
123 
124   pspec->ui_digits = digits;
125 }
126 
127 gdouble gegl_param_spec_double_get_step_size (GeglParamSpecDouble *pspec);
128 gdouble gegl_param_spec_double_get_page_size (GeglParamSpecDouble *pspec);
129 
130 static void       gegl_param_int_class_init (GParamSpecClass *klass);
131 static void       gegl_param_int_init       (GParamSpec      *pspec);
132 
133 GType
gegl_param_int_get_type(void)134 gegl_param_int_get_type (void)
135 {
136   static GType type = 0;
137 
138   if (!type)
139     {
140       const GTypeInfo info =
141       {
142         sizeof (GParamSpecClass),
143         NULL, NULL,
144         (GClassInitFunc) gegl_param_int_class_init,
145         NULL, NULL,
146         sizeof (GeglParamSpecInt),
147         0,
148         (GInstanceInitFunc) gegl_param_int_init
149       };
150       type = g_type_register_static (G_TYPE_PARAM_INT,
151                                      "GeglParamInt", &info, 0);
152     }
153   return type;
154 }
155 
156 static void
gegl_param_int_class_init(GParamSpecClass * klass)157 gegl_param_int_class_init (GParamSpecClass *klass)
158 {
159   klass->value_type     = G_TYPE_INT;
160 }
161 
162 static void
gegl_param_int_init(GParamSpec * pspec)163 gegl_param_int_init (GParamSpec *pspec)
164 {
165   GParamSpecInt    *dpspec  = G_PARAM_SPEC_INT (pspec);
166   GeglParamSpecInt *gdpspec = GEGL_PARAM_SPEC_INT (pspec);
167   gdpspec->ui_minimum = dpspec->minimum;
168   gdpspec->ui_maximum = dpspec->maximum;
169   gdpspec->ui_gamma = 1.0;
170 }
171 
172 GParamSpec *
gegl_param_spec_int(const gchar * name,const gchar * nick,const gchar * blurb,gint minimum,gint maximum,gint default_value,gint ui_minimum,gint ui_maximum,gdouble ui_gamma,GParamFlags flags)173 gegl_param_spec_int (const gchar *name,
174                      const gchar *nick,
175                      const gchar *blurb,
176                      gint         minimum,
177                      gint         maximum,
178                      gint         default_value,
179                      gint         ui_minimum,
180                      gint         ui_maximum,
181                      gdouble      ui_gamma,
182                      GParamFlags  flags)
183 {
184   GeglParamSpecInt *pspec;
185   GParamSpecInt *ispec;
186 
187 
188   pspec = g_param_spec_internal (GEGL_TYPE_PARAM_INT,
189                                  name, nick, blurb, flags);
190   ispec = G_PARAM_SPEC_INT (pspec);
191 
192   ispec->minimum = minimum;
193   ispec->maximum = maximum;
194   ispec->default_value = default_value;
195   pspec->ui_minimum = ui_minimum;
196   pspec->ui_maximum = ui_maximum;
197   pspec->ui_gamma = ui_gamma;
198 
199   gegl_param_spec_int_set_steps (pspec, 1, 5);
200   return G_PARAM_SPEC (pspec);
201 }
202 
203 void
gegl_param_spec_int_set_steps(GeglParamSpecInt * pspec,gint step_small,gint step_big)204 gegl_param_spec_int_set_steps (GeglParamSpecInt *pspec,
205                                gint              step_small,
206                                gint              step_big)
207 {
208   g_return_if_fail (GEGL_IS_PARAM_SPEC_INT (pspec));
209 
210   pspec->ui_step_small = step_small;
211   pspec->ui_step_big = step_big;
212 }
213 
214 /*
215  * GEGL_TYPE_PARAM_STRING
216  */
217 
218 static void       gegl_param_string_class_init (GParamSpecClass *klass);
219 static void       gegl_param_string_init (GParamSpec *pspec);
220 static gboolean   gegl_param_string_validate (GParamSpec *pspec,
221                                               GValue     *value);
222 
223 GType
gegl_param_string_get_type(void)224 gegl_param_string_get_type (void)
225 {
226   static GType type = 0;
227 
228   if (!type)
229     {
230       const GTypeInfo info =
231       {
232         sizeof (GParamSpecClass),
233         NULL,                                          NULL,
234         (GClassInitFunc) gegl_param_string_class_init,
235         NULL,                                          NULL,
236         sizeof (GeglParamSpecString),
237         0,
238         (GInstanceInitFunc) gegl_param_string_init
239       };
240 
241       type = g_type_register_static (G_TYPE_PARAM_STRING,
242                                      "GeglParamString", &info, 0);
243     }
244 
245   return type;
246 }
247 
248 static void
gegl_param_string_class_init(GParamSpecClass * klass)249 gegl_param_string_class_init (GParamSpecClass *klass)
250 {
251   klass->value_type     = G_TYPE_STRING;
252   klass->value_validate = gegl_param_string_validate;
253 }
254 
255 static void
gegl_param_string_init(GParamSpec * pspec)256 gegl_param_string_init (GParamSpec *pspec)
257 {
258   GeglParamSpecString *sspec = GEGL_PARAM_SPEC_STRING (pspec);
259 
260   sspec->no_validate = FALSE;
261   sspec->null_ok     = FALSE;
262 }
263 
264 static gboolean
gegl_param_string_validate(GParamSpec * pspec,GValue * value)265 gegl_param_string_validate (GParamSpec *pspec,
266                             GValue     *value)
267 {
268   GeglParamSpecString *sspec  = GEGL_PARAM_SPEC_STRING (pspec);
269   gchar               *string = value->data[0].v_pointer;
270 
271   if (string)
272     {
273       gchar *s;
274 
275       if (!sspec->no_validate &&
276           !g_utf8_validate (string, -1, (const gchar **) &s))
277         {
278           for (; *s; s++)
279             if (*s < ' ')
280               *s = '?';
281 
282           return TRUE;
283         }
284     }
285   else if (!sspec->null_ok)
286     {
287       value->data[0].v_pointer = g_strdup ("");
288       return TRUE;
289     }
290 
291   return FALSE;
292 }
293 
294 GParamSpec *
gegl_param_spec_string(const gchar * name,const gchar * nick,const gchar * blurb,gboolean no_validate,gboolean null_ok,const gchar * default_value,GParamFlags flags)295 gegl_param_spec_string (const gchar *name,
296                         const gchar *nick,
297                         const gchar *blurb,
298                         gboolean     no_validate,
299                         gboolean     null_ok,
300                         const gchar *default_value,
301                         GParamFlags  flags)
302 {
303   GeglParamSpecString *sspec;
304 
305   sspec = g_param_spec_internal (GEGL_TYPE_PARAM_STRING,
306                                  name, nick, blurb, flags);
307 
308   if (sspec)
309     {
310       g_free (G_PARAM_SPEC_STRING (sspec)->default_value);
311       G_PARAM_SPEC_STRING (sspec)->default_value = g_strdup (default_value);
312 
313       sspec->no_validate = no_validate ? TRUE : FALSE;
314       sspec->null_ok     = null_ok     ? TRUE : FALSE;
315     }
316 
317   return G_PARAM_SPEC (sspec);
318 }
319 
320 
321 /*
322  * GEGL_TYPE_PARAM_FILE_PATH
323  */
324 
325 static void       gegl_param_file_path_class_init (GParamSpecClass *klass);
326 static void       gegl_param_file_path_init       (GParamSpec *pspec);
327 static gboolean   gegl_param_file_path_validate   (GParamSpec *pspec,
328                                                    GValue     *value);
329 
330 GType
gegl_param_file_path_get_type(void)331 gegl_param_file_path_get_type (void)
332 {
333   static GType type = 0;
334 
335   if (!type)
336     {
337       const GTypeInfo info =
338       {
339         sizeof (GParamSpecClass),
340         NULL,                                        NULL,
341         (GClassInitFunc) gegl_param_file_path_class_init,
342         NULL,                                        NULL,
343         sizeof (GeglParamSpecString),
344         0,
345         (GInstanceInitFunc) gegl_param_file_path_init
346       };
347 
348       type = g_type_register_static (G_TYPE_PARAM_STRING,
349                                      "GeglParamFilePath", &info, 0);
350     }
351 
352   return type;
353 }
354 
355 static void
gegl_param_file_path_class_init(GParamSpecClass * klass)356 gegl_param_file_path_class_init (GParamSpecClass *klass)
357 {
358   klass->value_type     = G_TYPE_STRING;
359   klass->value_validate = gegl_param_file_path_validate;
360 }
361 
362 static void
gegl_param_file_path_init(GParamSpec * pspec)363 gegl_param_file_path_init (GParamSpec *pspec)
364 {
365   GeglParamSpecFilePath *sspec = GEGL_PARAM_SPEC_FILE_PATH (pspec);
366 
367   sspec->no_validate = FALSE;
368   sspec->null_ok     = FALSE;
369 }
370 
371 static gboolean
gegl_param_file_path_validate(GParamSpec * pspec,GValue * value)372 gegl_param_file_path_validate (GParamSpec *pspec,
373                                GValue     *value)
374 {
375   GeglParamSpecFilePath *sspec = GEGL_PARAM_SPEC_FILE_PATH (pspec);
376   gchar                 *path  = value->data[0].v_pointer;
377 
378   if (path)
379     {
380       gchar *s;
381 
382       if (!sspec->no_validate &&
383           !g_utf8_validate (path, -1, (const gchar **) &s))
384         {
385           for (; *s; s++)
386             if (*s < ' ')
387               *s = '?';
388 
389           return TRUE;
390         }
391     }
392   else if (!sspec->null_ok)
393     {
394       value->data[0].v_pointer = g_strdup ("");
395       return TRUE;
396     }
397 
398   return FALSE;
399 }
400 
401 GParamSpec *
gegl_param_spec_file_path(const gchar * name,const gchar * nick,const gchar * blurb,gboolean no_validate,gboolean null_ok,const gchar * default_value,GParamFlags flags)402 gegl_param_spec_file_path (const gchar *name,
403                            const gchar *nick,
404                            const gchar *blurb,
405                            gboolean     no_validate,
406                            gboolean     null_ok,
407                            const gchar *default_value,
408                            GParamFlags  flags)
409 {
410   GeglParamSpecFilePath *sspec;
411 
412   sspec = g_param_spec_internal (GEGL_TYPE_PARAM_FILE_PATH,
413                                  name, nick, blurb, flags);
414 
415   if (sspec)
416     {
417       g_free (G_PARAM_SPEC_STRING (sspec)->default_value);
418       G_PARAM_SPEC_STRING (sspec)->default_value = g_strdup (default_value);
419 
420       sspec->no_validate = no_validate ? TRUE : FALSE;
421       sspec->null_ok     = null_ok     ? TRUE : FALSE;
422     }
423 
424   return G_PARAM_SPEC (sspec);
425 }
426 
427 /*
428  * GEGL_TYPE_PARAM_ENUM
429  */
430 
431 static void       gegl_param_enum_class_init (GParamSpecClass *klass);
432 static void       gegl_param_enum_init       (GParamSpec      *pspec);
433 static void       gegl_param_enum_finalize   (GParamSpec      *pspec);
434 static gboolean   gegl_param_enum_validate   (GParamSpec      *pspec,
435                                               GValue          *value);
436 
437 GType
gegl_param_enum_get_type(void)438 gegl_param_enum_get_type (void)
439 {
440   static GType type = 0;
441 
442   if (!type)
443     {
444       const GTypeInfo info =
445       {
446         sizeof (GParamSpecClass),
447         NULL,                                        NULL,
448         (GClassInitFunc) gegl_param_enum_class_init,
449         NULL,                                        NULL,
450         sizeof (GeglParamSpecEnum),
451         0,
452         (GInstanceInitFunc) gegl_param_enum_init
453       };
454 
455       type = g_type_register_static (G_TYPE_PARAM_ENUM,
456                                      "GeglParamEnum", &info, 0);
457     }
458 
459   return type;
460 }
461 
462 static void
gegl_param_enum_class_init(GParamSpecClass * klass)463 gegl_param_enum_class_init (GParamSpecClass *klass)
464 {
465   klass->value_type     = G_TYPE_ENUM;
466   klass->finalize       = gegl_param_enum_finalize;
467   klass->value_validate = gegl_param_enum_validate;
468 }
469 
470 static void
gegl_param_enum_init(GParamSpec * pspec)471 gegl_param_enum_init (GParamSpec *pspec)
472 {
473   GeglParamSpecEnum *espec = GEGL_PARAM_SPEC_ENUM (pspec);
474 
475   espec->excluded_values = NULL;
476 }
477 
478 static void
gegl_param_enum_finalize(GParamSpec * pspec)479 gegl_param_enum_finalize (GParamSpec *pspec)
480 {
481   GeglParamSpecEnum *espec = GEGL_PARAM_SPEC_ENUM (pspec);
482   GParamSpecClass   *parent_class;
483 
484   parent_class = g_type_class_peek (g_type_parent (GEGL_TYPE_PARAM_ENUM));
485 
486   g_slist_free (espec->excluded_values);
487 
488   parent_class->finalize (pspec);
489 }
490 
491 static gboolean
gegl_param_enum_validate(GParamSpec * pspec,GValue * value)492 gegl_param_enum_validate (GParamSpec *pspec,
493                           GValue     *value)
494 {
495   GeglParamSpecEnum *espec = GEGL_PARAM_SPEC_ENUM (pspec);
496   GParamSpecClass   *parent_class;
497   GSList            *list;
498 
499   parent_class = g_type_class_peek (g_type_parent (GEGL_TYPE_PARAM_ENUM));
500 
501   if (parent_class->value_validate (pspec, value))
502     return TRUE;
503 
504   for (list = espec->excluded_values; list; list = g_slist_next (list))
505     {
506       if (GPOINTER_TO_INT (list->data) == value->data[0].v_long)
507         {
508           value->data[0].v_long = G_PARAM_SPEC_ENUM (pspec)->default_value;
509           return TRUE;
510         }
511     }
512 
513   return FALSE;
514 }
515 
516 GParamSpec *
gegl_param_spec_enum(const gchar * name,const gchar * nick,const gchar * blurb,GType enum_type,gint default_value,GParamFlags flags)517 gegl_param_spec_enum (const gchar *name,
518                       const gchar *nick,
519                       const gchar *blurb,
520                       GType        enum_type,
521                       gint         default_value,
522                       GParamFlags  flags)
523 {
524   GeglParamSpecEnum *espec;
525   GEnumClass        *enum_class;
526 
527   g_return_val_if_fail (G_TYPE_IS_ENUM (enum_type), NULL);
528 
529   enum_class = g_type_class_ref (enum_type);
530 
531   g_return_val_if_fail (g_enum_get_value (enum_class, default_value) != NULL,
532                         NULL);
533 
534   espec = g_param_spec_internal (GEGL_TYPE_PARAM_ENUM,
535                                  name, nick, blurb, flags);
536 
537   G_PARAM_SPEC_ENUM (espec)->enum_class    = enum_class;
538   G_PARAM_SPEC_ENUM (espec)->default_value = default_value;
539   G_PARAM_SPEC (espec)->value_type         = enum_type;
540 
541   return G_PARAM_SPEC (espec);
542 }
543 
544 void
gegl_param_spec_enum_exclude_value(GeglParamSpecEnum * espec,gint value)545 gegl_param_spec_enum_exclude_value (GeglParamSpecEnum *espec,
546                                     gint               value)
547 {
548   g_return_if_fail (GEGL_IS_PARAM_SPEC_ENUM (espec));
549   g_return_if_fail (g_enum_get_value (G_PARAM_SPEC_ENUM (espec)->enum_class,
550                                       value) != NULL);
551 
552   espec->excluded_values = g_slist_prepend (espec->excluded_values,
553                                             GINT_TO_POINTER (value));
554 }
555 
556 /*
557  * GEGL_TYPE_PARAM_SEED
558  */
559 
560 static void       gegl_param_seed_class_init (GParamSpecClass *klass);
561 static void       gegl_param_seed_init       (GParamSpec      *pspec);
562 
563 GType
gegl_param_seed_get_type(void)564 gegl_param_seed_get_type (void)
565 {
566   static GType type = 0;
567 
568   if (!type)
569     {
570       const GTypeInfo info =
571       {
572         sizeof (GParamSpecClass),
573         NULL, NULL,
574         (GClassInitFunc) gegl_param_seed_class_init,
575         NULL, NULL,
576         sizeof (GeglParamSpecSeed),
577         0,
578         (GInstanceInitFunc) gegl_param_seed_init
579       };
580       type = g_type_register_static (G_TYPE_PARAM_UINT,
581                                      "GeglParamSeed", &info, 0);
582     }
583   return type;
584 }
585 
586 static void
gegl_param_seed_class_init(GParamSpecClass * klass)587 gegl_param_seed_class_init (GParamSpecClass *klass)
588 {
589   klass->value_type = G_TYPE_UINT;
590 }
591 
592 static void
gegl_param_seed_init(GParamSpec * pspec)593 gegl_param_seed_init (GParamSpec *pspec)
594 {
595   GeglParamSpecSeed *gdpspec = GEGL_PARAM_SPEC_SEED (pspec);
596 
597   gdpspec->ui_minimum = 0;
598   gdpspec->ui_maximum = G_MAXUINT;
599 }
600 
601 GParamSpec *
gegl_param_spec_seed(const gchar * name,const gchar * nick,const gchar * blurb,GParamFlags flags)602 gegl_param_spec_seed (const gchar *name,
603                       const gchar *nick,
604                       const gchar *blurb,
605                       GParamFlags  flags)
606 {
607   GeglParamSpecSeed *pspec;
608   GParamSpecUInt    *ispec;
609 
610   pspec = g_param_spec_internal (GEGL_TYPE_PARAM_SEED,
611                                  name, nick, blurb, flags);
612   ispec = G_PARAM_SPEC_UINT (pspec);
613 
614   ispec->minimum = 0;
615   ispec->maximum = G_MAXUINT;
616   ispec->default_value = 0;
617   pspec->ui_minimum = 0;
618   pspec->ui_maximum = G_MAXUINT;
619 
620   return G_PARAM_SPEC (pspec);
621 }
622 
623 /*
624  * GEGL_TYPE_PARAM_FORMAT
625  */
626 
627 static void       gegl_param_format_class_init (GParamSpecClass *klass);
628 static void       gegl_param_format_init       (GParamSpec      *pspec);
629 
630 GType
gegl_param_format_get_type(void)631 gegl_param_format_get_type (void)
632 {
633   static GType type = 0;
634 
635   if (!type)
636     {
637       const GTypeInfo info =
638       {
639         sizeof (GParamSpecClass),
640         NULL, NULL,
641         (GClassInitFunc) gegl_param_format_class_init,
642         NULL, NULL,
643         sizeof (GeglParamSpecFormat),
644         0,
645         (GInstanceInitFunc) gegl_param_format_init
646       };
647       type = g_type_register_static (G_TYPE_PARAM_POINTER,
648                                      "GeglParamFormat", &info, 0);
649     }
650   return type;
651 }
652 
653 static void
gegl_param_format_class_init(GParamSpecClass * klass)654 gegl_param_format_class_init (GParamSpecClass *klass)
655 {
656   klass->value_type = G_TYPE_POINTER;
657 }
658 
659 static void
gegl_param_format_init(GParamSpec * pspec)660 gegl_param_format_init (GParamSpec *pspec)
661 {
662 }
663 
664 GParamSpec *
gegl_param_spec_format(const gchar * name,const gchar * nick,const gchar * blurb,GParamFlags flags)665 gegl_param_spec_format (const gchar *name,
666                         const gchar *nick,
667                         const gchar *blurb,
668                         GParamFlags  flags)
669 {
670   GeglParamSpecFormat *pspec;
671 
672   pspec = g_param_spec_internal (GEGL_TYPE_PARAM_FORMAT,
673                                  name, nick, blurb, flags);
674 
675   return G_PARAM_SPEC (pspec);
676 }
677 
678 /*
679  * GEGL_TYPE_PARAM_URI
680  */
681 
682 static void       gegl_param_uri_class_init (GParamSpecClass *klass);
683 static void       gegl_param_uri_init       (GParamSpec *pspec);
684 static gboolean   gegl_param_uri_validate   (GParamSpec *pspec,
685                                                    GValue     *value);
686 
687 GType
gegl_param_uri_get_type(void)688 gegl_param_uri_get_type (void)
689 {
690   static GType type = 0;
691 
692   if (!type)
693     {
694       const GTypeInfo info =
695       {
696         sizeof (GParamSpecClass),
697         NULL,                                        NULL,
698         (GClassInitFunc) gegl_param_uri_class_init,
699         NULL,                                        NULL,
700         sizeof (GeglParamSpecString),
701         0,
702         (GInstanceInitFunc) gegl_param_uri_init
703       };
704 
705       type = g_type_register_static (G_TYPE_PARAM_STRING,
706                                      "GeglParamUri", &info, 0);
707     }
708 
709   return type;
710 }
711 
712 static void
gegl_param_uri_class_init(GParamSpecClass * klass)713 gegl_param_uri_class_init (GParamSpecClass *klass)
714 {
715   klass->value_type     = G_TYPE_STRING;
716   klass->value_validate = gegl_param_uri_validate;
717 }
718 
719 static void
gegl_param_uri_init(GParamSpec * pspec)720 gegl_param_uri_init (GParamSpec *pspec)
721 {
722   GeglParamSpecUri *sspec = GEGL_PARAM_SPEC_URI (pspec);
723 
724   sspec->no_validate = FALSE;
725   sspec->null_ok     = FALSE;
726 }
727 
728 static gboolean
gegl_param_uri_validate(GParamSpec * pspec,GValue * value)729 gegl_param_uri_validate (GParamSpec *pspec,
730                                GValue     *value)
731 {
732   GeglParamSpecUri *sspec = GEGL_PARAM_SPEC_URI (pspec);
733   gchar                 *path  = value->data[0].v_pointer;
734 
735   if (path)
736     {
737       gchar *s;
738 
739       if (!sspec->no_validate &&
740           !g_utf8_validate (path, -1, (const gchar **) &s))
741         {
742           for (; *s; s++)
743             if (*s < ' ')
744               *s = '?';
745 
746           return TRUE;
747         }
748     }
749   else if (!sspec->null_ok)
750     {
751       value->data[0].v_pointer = g_strdup ("");
752       return TRUE;
753     }
754 
755   return FALSE;
756 }
757 
758 GParamSpec *
gegl_param_spec_uri(const gchar * name,const gchar * nick,const gchar * blurb,gboolean no_validate,gboolean null_ok,const gchar * default_value,GParamFlags flags)759 gegl_param_spec_uri (const gchar *name,
760                            const gchar *nick,
761                            const gchar *blurb,
762                            gboolean     no_validate,
763                            gboolean     null_ok,
764                            const gchar *default_value,
765                            GParamFlags  flags)
766 {
767   GeglParamSpecUri *sspec;
768 
769   sspec = g_param_spec_internal (GEGL_TYPE_PARAM_URI,
770                                  name, nick, blurb, flags);
771 
772   if (sspec)
773     {
774       g_free (G_PARAM_SPEC_STRING (sspec)->default_value);
775       G_PARAM_SPEC_STRING (sspec)->default_value = g_strdup (default_value);
776 
777       sspec->no_validate = no_validate ? TRUE : FALSE;
778       sspec->null_ok     = null_ok     ? TRUE : FALSE;
779     }
780 
781   return G_PARAM_SPEC (sspec);
782 }
783 
784