~ubuntu-branches/ubuntu/jaunty/gimp/jaunty-security

« back to all changes in this revision

Viewing changes to libgimpconfig/gimpconfig-deserialize.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Holbach
  • Date: 2007-05-02 16:33:03 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20070502163303-bvzhjzbpw8qglc4y
Tags: 2.3.16-1ubuntu1
* Resynchronized with Debian, remaining Ubuntu changes:
  - debian/rules: i18n magic.
* debian/control.in:
  - Maintainer: Ubuntu Core Developers <ubuntu-devel@lists.ubuntu.com>
* debian/patches/02_help-message.patch,
  debian/patches/03_gimp.desktop.in.in.patch,
  debian/patches/10_dont_show_wizard.patch: updated.
* debian/patches/04_composite-signedness.patch,
  debian/patches/05_add-letter-spacing.patch: dropped, used upstream.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* LIBGIMP - The GIMP Library
 
2
 * Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis
 
3
 *
 
4
 * Object properties deserialization routines
 
5
 * Copyright (C) 2001-2002  Sven Neumann <sven@gimp.org>
 
6
 *
 
7
 * This library is free software; you can redistribute it and/or
 
8
 * modify it under the terms of the GNU Lesser General Public
 
9
 * License as published by the Free Software Foundation; either
 
10
 * version 2 of the License, or (at your option) any later version.
 
11
 *
 
12
 * This library is distributed in the hope that it will be useful,
 
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
15
 * Library General Public License for more details.
 
16
 *
 
17
 * You should have received a copy of the GNU Lesser General Public
 
18
 * License along with this library; if not, write to the
 
19
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
20
 * Boston, MA 02111-1307, USA.
 
21
 */
 
22
 
 
23
#include "config.h"
 
24
 
 
25
#include <glib-object.h>
 
26
 
 
27
#include "libgimpbase/gimpbase.h"
 
28
#include "libgimpcolor/gimpcolor.h"
 
29
#include "libgimpmath/gimpmath.h"
 
30
 
 
31
#include "gimpconfigtypes.h"
 
32
 
 
33
#include "gimpconfigwriter.h"
 
34
#include "gimpconfig-iface.h"
 
35
#include "gimpconfig-deserialize.h"
 
36
#include "gimpconfig-params.h"
 
37
#include "gimpconfig-path.h"
 
38
#include "gimpscanner.h"
 
39
 
 
40
#include "libgimp/libgimp-intl.h"
 
41
 
 
42
 
 
43
/*
 
44
 *  All functions return G_TOKEN_RIGHT_PAREN on success,
 
45
 *  the GTokenType they would have expected but didn't get
 
46
 *  or G_TOKEN_NONE if they got the expected token but
 
47
 *  couldn't parse it.
 
48
 */
 
49
 
 
50
static GTokenType  gimp_config_deserialize_value       (GValue     *value,
 
51
                                                        GimpConfig *config,
 
52
                                                        GParamSpec *prop_spec,
 
53
                                                        GScanner   *scanner);
 
54
static GTokenType  gimp_config_deserialize_fundamental (GValue     *value,
 
55
                                                        GParamSpec *prop_spec,
 
56
                                                        GScanner   *scanner);
 
57
static GTokenType  gimp_config_deserialize_enum        (GValue     *value,
 
58
                                                        GParamSpec *prop_spec,
 
59
                                                        GScanner   *scanner);
 
60
static GTokenType  gimp_config_deserialize_memsize     (GValue     *value,
 
61
                                                        GParamSpec *prop_spec,
 
62
                                                        GScanner   *scanner);
 
63
static GTokenType  gimp_config_deserialize_path        (GValue     *value,
 
64
                                                        GParamSpec *prop_spec,
 
65
                                                        GScanner   *scanner);
 
66
static GTokenType  gimp_config_deserialize_rgb         (GValue     *value,
 
67
                                                        GParamSpec *prop_spec,
 
68
                                                        GScanner   *scanner);
 
69
static GTokenType  gimp_config_deserialize_matrix2     (GValue     *value,
 
70
                                                        GParamSpec *prop_spec,
 
71
                                                        GScanner   *scanner);
 
72
static GTokenType  gimp_config_deserialize_object      (GValue     *value,
 
73
                                                        GimpConfig *config,
 
74
                                                        GParamSpec *prop_spec,
 
75
                                                        GScanner   *scanner,
 
76
                                                        gint        nest_level);
 
77
static GTokenType  gimp_config_deserialize_value_array (GValue     *value,
 
78
                                                        GimpConfig *config,
 
79
                                                        GParamSpec *prop_spec,
 
80
                                                        GScanner   *scanner);
 
81
static GTokenType  gimp_config_deserialize_any         (GValue     *value,
 
82
                                                        GParamSpec *prop_spec,
 
83
                                                        GScanner   *scanner);
 
84
 
 
85
static inline gboolean  scanner_string_utf8_valid (GScanner    *scanner,
 
86
                                                   const gchar *token_name);
 
87
 
 
88
static inline gboolean
 
89
scanner_string_utf8_valid (GScanner    *scanner,
 
90
                           const gchar *token_name)
 
91
{
 
92
  if (g_utf8_validate (scanner->value.v_string, -1, NULL))
 
93
    return TRUE;
 
94
 
 
95
  g_scanner_error (scanner,
 
96
                   _("value for token %s is not a valid UTF-8 string"),
 
97
                   token_name);
 
98
 
 
99
  return FALSE;
 
100
}
 
101
 
 
102
/**
 
103
 * gimp_config_deserialize_properties:
 
104
 * @config: a #GimpConfig.
 
105
 * @scanner: a #GScanner.
 
106
 * @nest_level:
 
107
 *
 
108
 * This function uses the @scanner to configure the properties of @config.
 
109
 *
 
110
 * Return value: %TRUE on success, %FALSE otherwise.
 
111
 *
 
112
 * Since: GIMP 2.4
 
113
 **/
 
114
gboolean
 
115
gimp_config_deserialize_properties (GimpConfig *config,
 
116
                                    GScanner   *scanner,
 
117
                                    gint        nest_level)
 
118
{
 
119
  GObjectClass  *klass;
 
120
  GParamSpec   **property_specs;
 
121
  guint          n_property_specs;
 
122
  guint          i;
 
123
  guint          scope_id;
 
124
  guint          old_scope_id;
 
125
  GTokenType         token;
 
126
  GTokenType         next;
 
127
 
 
128
  g_return_val_if_fail (GIMP_IS_CONFIG (config), FALSE);
 
129
 
 
130
  klass = G_OBJECT_GET_CLASS (config);
 
131
  property_specs = g_object_class_list_properties (klass, &n_property_specs);
 
132
 
 
133
  if (!property_specs)
 
134
    return TRUE;
 
135
 
 
136
  scope_id = g_type_qname (G_TYPE_FROM_INSTANCE (config));
 
137
  old_scope_id = g_scanner_set_scope (scanner, scope_id);
 
138
 
 
139
  for (i = 0; i < n_property_specs; i++)
 
140
    {
 
141
      GParamSpec *prop_spec = property_specs[i];
 
142
 
 
143
      if (prop_spec->flags & GIMP_CONFIG_PARAM_SERIALIZE)
 
144
        {
 
145
          g_scanner_scope_add_symbol (scanner, scope_id,
 
146
                                      prop_spec->name, prop_spec);
 
147
        }
 
148
    }
 
149
 
 
150
  g_free (property_specs);
 
151
 
 
152
  g_object_freeze_notify (G_OBJECT (config));
 
153
 
 
154
  token = G_TOKEN_LEFT_PAREN;
 
155
 
 
156
  while (TRUE)
 
157
    {
 
158
      next = g_scanner_peek_next_token (scanner);
 
159
 
 
160
      if (next != token)
 
161
        break;
 
162
 
 
163
      token = g_scanner_get_next_token (scanner);
 
164
 
 
165
      switch (token)
 
166
        {
 
167
        case G_TOKEN_LEFT_PAREN:
 
168
          token = G_TOKEN_SYMBOL;
 
169
          break;
 
170
 
 
171
        case G_TOKEN_SYMBOL:
 
172
          token = gimp_config_deserialize_property (config,
 
173
                                                    scanner, nest_level);
 
174
          break;
 
175
 
 
176
        case G_TOKEN_RIGHT_PAREN:
 
177
          token = G_TOKEN_LEFT_PAREN;
 
178
          break;
 
179
 
 
180
        default: /* do nothing */
 
181
          break;
 
182
        }
 
183
    }
 
184
 
 
185
  g_scanner_set_scope (scanner, old_scope_id);
 
186
 
 
187
  g_object_thaw_notify (G_OBJECT (config));
 
188
 
 
189
  if (token == G_TOKEN_NONE)
 
190
    return FALSE;
 
191
 
 
192
  return gimp_config_deserialize_return (scanner, token, nest_level);
 
193
}
 
194
 
 
195
/**
 
196
 * gimp_config_deserialize_property:
 
197
 * @config: a #GimpConfig.
 
198
 * @scanner: a #GScanner.
 
199
 * @nest_level:
 
200
 *
 
201
 * This function deserializes a single property of @config. You
 
202
 * shouldn't need to call this function directly. If possible, use
 
203
 * gimp_config_deserialize_properties() instead.
 
204
 *
 
205
 * Return value: %G_TOKEN_RIGHT_PAREN on success, otherwise the
 
206
 * expected #GTokenType or %G_TOKEN_NONE if the expected token was
 
207
 * found but couldn't be parsed.
 
208
 *
 
209
 * Since: GIMP 2.4
 
210
 **/
 
211
GTokenType
 
212
gimp_config_deserialize_property (GimpConfig *config,
 
213
                                  GScanner   *scanner,
 
214
                                  gint        nest_level)
 
215
{
 
216
  GimpConfigInterface *config_iface = NULL;
 
217
  GimpConfigInterface *parent_iface = NULL;
 
218
  GParamSpec          *prop_spec;
 
219
  GTokenType           token = G_TOKEN_RIGHT_PAREN;
 
220
  GValue               value = { 0, };
 
221
  guint                old_scope_id;
 
222
 
 
223
  old_scope_id = g_scanner_set_scope (scanner, 0);
 
224
 
 
225
  prop_spec = G_PARAM_SPEC (scanner->value.v_symbol);
 
226
 
 
227
  g_value_init (&value, prop_spec->value_type);
 
228
 
 
229
  if (G_TYPE_IS_OBJECT (prop_spec->owner_type))
 
230
    {
 
231
      GTypeClass *owner_class = g_type_class_peek (prop_spec->owner_type);
 
232
 
 
233
      config_iface = g_type_interface_peek (owner_class, GIMP_TYPE_CONFIG);
 
234
 
 
235
      /*  We must call deserialize_property() *only* if the *exact* class
 
236
       *  which implements it is param_spec->owner_type's class.
 
237
       *
 
238
       *  Therefore, we ask param_spec->owner_type's immediate parent class
 
239
       *  for it's GimpConfigInterface and check if we get a different
 
240
       *  pointer.
 
241
       *
 
242
       *  (if the pointers are the same, param_spec->owner_type's
 
243
       *   GimpConfigInterface is inherited from one of it's parent classes
 
244
       *   and thus not able to handle param_spec->owner_type's properties).
 
245
       */
 
246
      if (config_iface)
 
247
        {
 
248
          GTypeClass *owner_parent_class;
 
249
 
 
250
          owner_parent_class = g_type_class_peek_parent (owner_class);
 
251
 
 
252
          parent_iface = g_type_interface_peek (owner_parent_class,
 
253
                                                GIMP_TYPE_CONFIG);
 
254
        }
 
255
    }
 
256
 
 
257
  if (config_iface                       &&
 
258
      config_iface != parent_iface       && /* see comment above */
 
259
      config_iface->deserialize_property &&
 
260
      config_iface->deserialize_property (config,
 
261
                                          prop_spec->param_id,
 
262
                                          &value,
 
263
                                          prop_spec,
 
264
                                          scanner,
 
265
                                          &token))
 
266
    {
 
267
      /* nop */
 
268
    }
 
269
  else
 
270
    {
 
271
      if (G_VALUE_HOLDS_OBJECT (&value))
 
272
        token = gimp_config_deserialize_object (&value,
 
273
                                                config, prop_spec,
 
274
                                                scanner, nest_level);
 
275
      else
 
276
        token = gimp_config_deserialize_value (&value,
 
277
                                               config, prop_spec, scanner);
 
278
    }
 
279
 
 
280
  if (token == G_TOKEN_RIGHT_PAREN &&
 
281
      g_scanner_peek_next_token (scanner) == token)
 
282
    {
 
283
      if (! (G_VALUE_HOLDS_OBJECT (&value) &&
 
284
             (prop_spec->flags & GIMP_CONFIG_PARAM_AGGREGATE)))
 
285
        g_object_set_property (G_OBJECT (config), prop_spec->name, &value);
 
286
    }
 
287
#ifdef CONFIG_DEBUG
 
288
  else
 
289
    {
 
290
      g_warning ("%s: couldn't deserialize property %s::%s of type %s",
 
291
                 G_STRFUNC,
 
292
                 g_type_name (G_TYPE_FROM_INSTANCE (config)),
 
293
                 prop_spec->name,
 
294
                 g_type_name (prop_spec->value_type));
 
295
    }
 
296
#endif
 
297
 
 
298
  g_value_unset (&value);
 
299
 
 
300
  g_scanner_set_scope (scanner, old_scope_id);
 
301
 
 
302
  return token;
 
303
}
 
304
 
 
305
static GTokenType
 
306
gimp_config_deserialize_value (GValue     *value,
 
307
                               GimpConfig *config,
 
308
                               GParamSpec *prop_spec,
 
309
                               GScanner   *scanner)
 
310
{
 
311
  if (G_TYPE_FUNDAMENTAL (prop_spec->value_type) == G_TYPE_ENUM)
 
312
    {
 
313
      return gimp_config_deserialize_enum (value, prop_spec, scanner);
 
314
    }
 
315
  else if (G_TYPE_IS_FUNDAMENTAL (prop_spec->value_type))
 
316
    {
 
317
      return gimp_config_deserialize_fundamental (value, prop_spec, scanner);
 
318
    }
 
319
  else if (prop_spec->value_type == GIMP_TYPE_MEMSIZE)
 
320
    {
 
321
      return gimp_config_deserialize_memsize (value, prop_spec, scanner);
 
322
    }
 
323
  else if (prop_spec->value_type == GIMP_TYPE_CONFIG_PATH)
 
324
    {
 
325
      return  gimp_config_deserialize_path (value, prop_spec, scanner);
 
326
    }
 
327
  else if (prop_spec->value_type == GIMP_TYPE_RGB)
 
328
    {
 
329
      return gimp_config_deserialize_rgb (value, prop_spec, scanner);
 
330
    }
 
331
  else if (prop_spec->value_type == GIMP_TYPE_MATRIX2)
 
332
    {
 
333
      return gimp_config_deserialize_matrix2 (value, prop_spec, scanner);
 
334
    }
 
335
  else if (prop_spec->value_type == G_TYPE_VALUE_ARRAY)
 
336
    {
 
337
      return gimp_config_deserialize_value_array (value,
 
338
                                                  config, prop_spec, scanner);
 
339
    }
 
340
 
 
341
  /*  This fallback will only work for value_types that
 
342
   *  can be transformed from a string value.
 
343
   */
 
344
  return gimp_config_deserialize_any (value, prop_spec, scanner);
 
345
}
 
346
 
 
347
static GTokenType
 
348
gimp_config_deserialize_fundamental (GValue     *value,
 
349
                                     GParamSpec *prop_spec,
 
350
                                     GScanner   *scanner)
 
351
{
 
352
  GTokenType token;
 
353
  GType      value_type;
 
354
  gboolean   negate = FALSE;
 
355
 
 
356
  value_type = G_TYPE_FUNDAMENTAL (prop_spec->value_type);
 
357
 
 
358
  switch (value_type)
 
359
    {
 
360
    case G_TYPE_STRING:
 
361
      token = G_TOKEN_STRING;
 
362
      break;
 
363
 
 
364
    case G_TYPE_BOOLEAN:
 
365
      token = G_TOKEN_IDENTIFIER;
 
366
      break;
 
367
 
 
368
    case G_TYPE_INT:
 
369
    case G_TYPE_LONG:
 
370
    case G_TYPE_INT64:
 
371
      if (g_scanner_peek_next_token (scanner) == '-')
 
372
        {
 
373
          negate = TRUE;
 
374
          g_scanner_get_next_token (scanner);
 
375
        }
 
376
      /*  fallthrough  */
 
377
    case G_TYPE_UINT:
 
378
    case G_TYPE_ULONG:
 
379
    case G_TYPE_UINT64:
 
380
      token = G_TOKEN_INT;
 
381
      break;
 
382
 
 
383
    case G_TYPE_FLOAT:
 
384
    case G_TYPE_DOUBLE:
 
385
      if (g_scanner_peek_next_token (scanner) == '-')
 
386
        {
 
387
          negate = TRUE;
 
388
          g_scanner_get_next_token (scanner);
 
389
        }
 
390
      token = G_TOKEN_FLOAT;
 
391
      break;
 
392
 
 
393
    default:
 
394
      token = G_TOKEN_NONE;
 
395
      g_assert_not_reached ();
 
396
      break;
 
397
    }
 
398
 
 
399
  if (g_scanner_peek_next_token (scanner) != token)
 
400
    {
 
401
      return token;
 
402
    }
 
403
 
 
404
  g_scanner_get_next_token (scanner);
 
405
 
 
406
  switch (value_type)
 
407
    {
 
408
    case G_TYPE_STRING:
 
409
      if (scanner_string_utf8_valid (scanner, prop_spec->name))
 
410
        g_value_set_static_string (value, scanner->value.v_string);
 
411
      else
 
412
        return G_TOKEN_NONE;
 
413
      break;
 
414
 
 
415
    case G_TYPE_BOOLEAN:
 
416
      if (! g_ascii_strcasecmp (scanner->value.v_identifier, "yes") ||
 
417
          ! g_ascii_strcasecmp (scanner->value.v_identifier, "true"))
 
418
        g_value_set_boolean (value, TRUE);
 
419
      else if (! g_ascii_strcasecmp (scanner->value.v_identifier, "no") ||
 
420
               ! g_ascii_strcasecmp (scanner->value.v_identifier, "false"))
 
421
        g_value_set_boolean (value, FALSE);
 
422
      else
 
423
        {
 
424
          g_scanner_error
 
425
            (scanner,
 
426
             /* please don't translate 'yes' and 'no' */
 
427
             _("expected 'yes' or 'no' for boolean token %s, got '%s'"),
 
428
             prop_spec->name, scanner->value.v_identifier);
 
429
          return G_TOKEN_NONE;
 
430
        }
 
431
      break;
 
432
 
 
433
    case G_TYPE_INT:
 
434
      g_value_set_int (value, (negate ?
 
435
                               - scanner->value.v_int64 :
 
436
                               scanner->value.v_int64));
 
437
      break;
 
438
    case G_TYPE_UINT:
 
439
      g_value_set_uint (value, scanner->value.v_int64);
 
440
      break;
 
441
 
 
442
    case G_TYPE_LONG:
 
443
      g_value_set_long (value, (negate ?
 
444
                                - scanner->value.v_int64 :
 
445
                                scanner->value.v_int64));
 
446
      break;
 
447
    case G_TYPE_ULONG:
 
448
      g_value_set_ulong (value, scanner->value.v_int64);
 
449
      break;
 
450
 
 
451
    case G_TYPE_INT64:
 
452
      g_value_set_int64 (value, (negate ?
 
453
                                 - scanner->value.v_int64 :
 
454
                                 scanner->value.v_int64));
 
455
      break;
 
456
    case G_TYPE_UINT64:
 
457
      g_value_set_uint64 (value, scanner->value.v_int64);
 
458
      break;
 
459
 
 
460
    case G_TYPE_FLOAT:
 
461
      g_value_set_float (value, negate ?
 
462
                         - scanner->value.v_float : scanner->value.v_float);
 
463
      break;
 
464
    case G_TYPE_DOUBLE:
 
465
      g_value_set_double (value, negate ?
 
466
                          - scanner->value.v_float: scanner->value.v_float);
 
467
      break;
 
468
 
 
469
    default:
 
470
      g_assert_not_reached ();
 
471
      break;
 
472
    }
 
473
 
 
474
  return G_TOKEN_RIGHT_PAREN;
 
475
}
 
476
 
 
477
static GTokenType
 
478
gimp_config_deserialize_enum (GValue     *value,
 
479
                              GParamSpec *prop_spec,
 
480
                              GScanner   *scanner)
 
481
{
 
482
  GEnumClass *enum_class;
 
483
  GEnumValue *enum_value;
 
484
 
 
485
  enum_class = g_type_class_peek (G_VALUE_TYPE (value));
 
486
 
 
487
  switch (g_scanner_peek_next_token (scanner))
 
488
    {
 
489
    case G_TOKEN_IDENTIFIER:
 
490
      g_scanner_get_next_token (scanner);
 
491
 
 
492
      enum_value = g_enum_get_value_by_nick (enum_class,
 
493
                                             scanner->value.v_identifier);
 
494
      if (!enum_value)
 
495
        enum_value = g_enum_get_value_by_name (enum_class,
 
496
                                               scanner->value.v_identifier);
 
497
 
 
498
      if (!enum_value)
 
499
        {
 
500
          g_scanner_error (scanner,
 
501
                           _("invalid value '%s' for token %s"),
 
502
                           scanner->value.v_identifier, prop_spec->name);
 
503
          return G_TOKEN_NONE;
 
504
        }
 
505
      break;
 
506
 
 
507
    case G_TOKEN_INT:
 
508
      g_scanner_get_next_token (scanner);
 
509
 
 
510
      enum_value = g_enum_get_value (enum_class,
 
511
                                     (gint) scanner->value.v_int64);
 
512
 
 
513
      if (!enum_value)
 
514
        {
 
515
          g_scanner_error (scanner,
 
516
                           _("invalid value '%ld' for token %s"),
 
517
                           (glong) scanner->value.v_int64, prop_spec->name);
 
518
          return G_TOKEN_NONE;
 
519
        }
 
520
      break;
 
521
 
 
522
    default:
 
523
      return G_TOKEN_IDENTIFIER;
 
524
    }
 
525
 
 
526
  g_value_set_enum (value, enum_value->value);
 
527
 
 
528
  return G_TOKEN_RIGHT_PAREN;
 
529
}
 
530
 
 
531
static GTokenType
 
532
gimp_config_deserialize_memsize (GValue     *value,
 
533
                                 GParamSpec *prop_spec,
 
534
                                 GScanner   *scanner)
 
535
{
 
536
  gchar   *orig_cset_first = scanner->config->cset_identifier_first;
 
537
  gchar   *orig_cset_nth   = scanner->config->cset_identifier_nth;
 
538
  guint64  memsize;
 
539
 
 
540
  scanner->config->cset_identifier_first = G_CSET_DIGITS;
 
541
  scanner->config->cset_identifier_nth   = G_CSET_DIGITS "gGmMkKbB";
 
542
 
 
543
  if (g_scanner_peek_next_token (scanner) != G_TOKEN_IDENTIFIER)
 
544
    return G_TOKEN_IDENTIFIER;
 
545
 
 
546
  g_scanner_get_next_token (scanner);
 
547
 
 
548
  scanner->config->cset_identifier_first = orig_cset_first;
 
549
  scanner->config->cset_identifier_nth   = orig_cset_nth;
 
550
 
 
551
  if (! gimp_memsize_deserialize (scanner->value.v_identifier, &memsize))
 
552
    return G_TOKEN_NONE;
 
553
 
 
554
  g_value_set_uint64 (value, memsize);
 
555
 
 
556
  return G_TOKEN_RIGHT_PAREN;
 
557
}
 
558
 
 
559
static GTokenType
 
560
gimp_config_deserialize_path (GValue     *value,
 
561
                              GParamSpec *prop_spec,
 
562
                              GScanner   *scanner)
 
563
{
 
564
  GError *error = NULL;
 
565
 
 
566
  if (g_scanner_peek_next_token (scanner) != G_TOKEN_STRING)
 
567
    return G_TOKEN_STRING;
 
568
 
 
569
  g_scanner_get_next_token (scanner);
 
570
 
 
571
  if (!scanner_string_utf8_valid (scanner, prop_spec->name))
 
572
    return G_TOKEN_NONE;
 
573
 
 
574
  if (scanner->value.v_string)
 
575
    {
 
576
      /*  Check if the string can be expanded
 
577
       *  and converted to the filesystem encoding.
 
578
       */
 
579
      gchar *expand = gimp_config_path_expand (scanner->value.v_string,
 
580
                                               TRUE, &error);
 
581
 
 
582
      if (!expand)
 
583
        {
 
584
          g_scanner_error (scanner,
 
585
                           _("while parsing token '%s': %s"),
 
586
                           prop_spec->name, error->message);
 
587
          g_error_free (error);
 
588
 
 
589
          return G_TOKEN_NONE;
 
590
        }
 
591
 
 
592
      g_free (expand);
 
593
 
 
594
      g_value_set_static_string (value, scanner->value.v_string);
 
595
    }
 
596
 
 
597
  return G_TOKEN_RIGHT_PAREN;
 
598
}
 
599
 
 
600
static GTokenType
 
601
gimp_config_deserialize_rgb (GValue     *value,
 
602
                             GParamSpec *prop_spec,
 
603
                             GScanner   *scanner)
 
604
{
 
605
  GimpRGB rgb;
 
606
 
 
607
  if (! gimp_scanner_parse_color (scanner, &rgb))
 
608
    return G_TOKEN_NONE;
 
609
 
 
610
  g_value_set_boxed (value, &rgb);
 
611
 
 
612
  return G_TOKEN_RIGHT_PAREN;
 
613
}
 
614
 
 
615
static GTokenType
 
616
gimp_config_deserialize_matrix2 (GValue     *value,
 
617
                                 GParamSpec *prop_spec,
 
618
                                 GScanner   *scanner)
 
619
{
 
620
  GimpMatrix2 matrix;
 
621
 
 
622
  if (! gimp_scanner_parse_matrix2 (scanner, &matrix))
 
623
    return G_TOKEN_NONE;
 
624
 
 
625
  g_value_set_boxed (value, &matrix);
 
626
 
 
627
  return G_TOKEN_RIGHT_PAREN;
 
628
}
 
629
 
 
630
static GTokenType
 
631
gimp_config_deserialize_object (GValue     *value,
 
632
                                GimpConfig *config,
 
633
                                GParamSpec *prop_spec,
 
634
                                GScanner   *scanner,
 
635
                                gint        nest_level)
 
636
{
 
637
  GimpConfigInterface *config_iface;
 
638
  GimpConfig          *prop_object;
 
639
 
 
640
  g_object_get_property (G_OBJECT (config), prop_spec->name, value);
 
641
 
 
642
  prop_object = g_value_get_object (value);
 
643
 
 
644
  if (! prop_object)
 
645
    {
 
646
      /*  if the object property is not GIMP_CONFIG_PARAM_AGGREGATE, read
 
647
       *  the type of the object and create it
 
648
       */
 
649
      if (! (prop_spec->flags & GIMP_CONFIG_PARAM_AGGREGATE))
 
650
        {
 
651
          gchar *type_name;
 
652
          GType  type;
 
653
 
 
654
          if (! gimp_scanner_parse_string (scanner, &type_name))
 
655
            return G_TOKEN_STRING;
 
656
 
 
657
          type = g_type_from_name (type_name);
 
658
          g_free (type_name);
 
659
 
 
660
          if (! g_type_is_a (type, prop_spec->value_type))
 
661
            return G_TOKEN_STRING;
 
662
 
 
663
          prop_object = g_object_new (type, NULL);
 
664
 
 
665
          g_value_take_object (value, prop_object);
 
666
        }
 
667
      else
 
668
        {
 
669
          return G_TOKEN_RIGHT_PAREN;
 
670
        }
 
671
    }
 
672
 
 
673
  config_iface = GIMP_CONFIG_GET_INTERFACE (prop_object);
 
674
 
 
675
  if (! config_iface)
 
676
    return gimp_config_deserialize_any (value, prop_spec, scanner);
 
677
 
 
678
  if (! config_iface->deserialize (prop_object, scanner, nest_level + 1, NULL))
 
679
    return G_TOKEN_NONE;
 
680
 
 
681
  return G_TOKEN_RIGHT_PAREN;
 
682
}
 
683
 
 
684
static GTokenType
 
685
gimp_config_deserialize_value_array (GValue     *value,
 
686
                                     GimpConfig *config,
 
687
                                     GParamSpec *prop_spec,
 
688
                                     GScanner   *scanner)
 
689
{
 
690
  GParamSpecValueArray *array_spec;
 
691
  GValueArray          *array;
 
692
  GValue                array_value = { 0, };
 
693
  gint                  n_values;
 
694
  GTokenType            token;
 
695
  gint                  i;
 
696
 
 
697
  array_spec = G_PARAM_SPEC_VALUE_ARRAY (prop_spec);
 
698
 
 
699
  if (! gimp_scanner_parse_int (scanner, &n_values))
 
700
    return G_TOKEN_INT;
 
701
 
 
702
  array = g_value_array_new (n_values);
 
703
 
 
704
  for (i = 0; i < n_values; i++)
 
705
    {
 
706
      g_value_init (&array_value, array_spec->element_spec->value_type);
 
707
 
 
708
      token = gimp_config_deserialize_value (&array_value,
 
709
                                             config,
 
710
                                             array_spec->element_spec,
 
711
                                             scanner);
 
712
 
 
713
      if (token == G_TOKEN_RIGHT_PAREN)
 
714
        g_value_array_append (array, &array_value);
 
715
 
 
716
      g_value_unset (&array_value);
 
717
 
 
718
      if (token != G_TOKEN_RIGHT_PAREN)
 
719
        return token;
 
720
    }
 
721
 
 
722
  g_value_take_boxed (value, array);
 
723
 
 
724
  return G_TOKEN_RIGHT_PAREN;
 
725
}
 
726
 
 
727
static GTokenType
 
728
gimp_config_deserialize_any (GValue     *value,
 
729
                             GParamSpec *prop_spec,
 
730
                             GScanner   *scanner)
 
731
{
 
732
  GValue src = { 0, };
 
733
 
 
734
  if (!g_value_type_transformable (G_TYPE_STRING, prop_spec->value_type))
 
735
    {
 
736
      g_warning ("%s: %s can not be transformed from a string",
 
737
                 G_STRFUNC, g_type_name (prop_spec->value_type));
 
738
      return G_TOKEN_NONE;
 
739
    }
 
740
 
 
741
  if (g_scanner_peek_next_token (scanner) != G_TOKEN_IDENTIFIER)
 
742
    return G_TOKEN_IDENTIFIER;
 
743
 
 
744
  g_scanner_get_next_token (scanner);
 
745
 
 
746
  g_value_init (&src, G_TYPE_STRING);
 
747
  g_value_set_static_string (&src, scanner->value.v_identifier);
 
748
  g_value_transform (&src, value);
 
749
  g_value_unset (&src);
 
750
 
 
751
  return G_TOKEN_RIGHT_PAREN;
 
752
}