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

« back to all changes in this revision

Viewing changes to app/config/gimpconfig.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
 
/* The GIMP -- an image manipulation program
2
 
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3
 
 *
4
 
 * Config file serialization and deserialization interface
5
 
 * Copyright (C) 2001-2002  Sven Neumann <sven@gimp.org>
6
 
 *
7
 
 * This program is free software; you can redistribute it and/or modify
8
 
 * it under the terms of the GNU General Public License as published by
9
 
 * the Free Software Foundation; either version 2 of the License, or
10
 
 * (at your option) any later version.
11
 
 *
12
 
 * This program 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
15
 
 * GNU General Public License for more details.
16
 
 *
17
 
 * You should have received a copy of the GNU General Public License
18
 
 * along with this program; if not, write to the Free Software
19
 
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20
 
 */
21
 
 
22
 
#include "config.h"
23
 
 
24
 
#include <string.h>
25
 
 
26
 
#include <glib-object.h>
27
 
 
28
 
#include "libgimpbase/gimpbase.h"
29
 
 
30
 
#include "config-types.h"
31
 
 
32
 
#include "gimpconfig.h"
33
 
#include "gimpconfig-deserialize.h"
34
 
#include "gimpconfig-serialize.h"
35
 
#include "gimpconfig-params.h"
36
 
#include "gimpconfig-utils.h"
37
 
#include "gimpconfigwriter.h"
38
 
#include "gimpscanner.h"
39
 
 
40
 
#include "gimp-intl.h"
41
 
 
42
 
 
43
 
/*
44
 
 * The GimpConfig serialization and deserialization interface.
45
 
 */
46
 
 
47
 
static void         gimp_config_iface_base_init (GimpConfigInterface  *config_iface);
48
 
 
49
 
static gboolean     gimp_config_iface_serialize   (GimpConfig       *config,
50
 
                                                   GimpConfigWriter *writer,
51
 
                                                   gpointer          data);
52
 
static gboolean     gimp_config_iface_deserialize (GimpConfig       *config,
53
 
                                                   GScanner         *scanner,
54
 
                                                   gint              nest_level,
55
 
                                                   gpointer          data);
56
 
static GimpConfig * gimp_config_iface_duplicate   (GimpConfig       *config);
57
 
static gboolean     gimp_config_iface_equal       (GimpConfig       *a,
58
 
                                                   GimpConfig       *b);
59
 
static void         gimp_config_iface_reset       (GimpConfig       *config);
60
 
 
61
 
 
62
 
GType
63
 
gimp_config_interface_get_type (void)
64
 
{
65
 
  static GType config_iface_type = 0;
66
 
 
67
 
  if (!config_iface_type)
68
 
    {
69
 
      static const GTypeInfo config_iface_info =
70
 
      {
71
 
        sizeof (GimpConfigInterface),
72
 
        (GBaseInitFunc)     gimp_config_iface_base_init,
73
 
        (GBaseFinalizeFunc) NULL,
74
 
      };
75
 
 
76
 
      config_iface_type = g_type_register_static (G_TYPE_INTERFACE,
77
 
                                                  "GimpConfigInterface",
78
 
                                                  &config_iface_info,
79
 
                                                  0);
80
 
 
81
 
      g_type_interface_add_prerequisite (config_iface_type, G_TYPE_OBJECT);
82
 
    }
83
 
 
84
 
  return config_iface_type;
85
 
}
86
 
 
87
 
static void
88
 
gimp_config_iface_base_init (GimpConfigInterface *config_iface)
89
 
{
90
 
  if (! config_iface->serialize)
91
 
    {
92
 
      config_iface->serialize   = gimp_config_iface_serialize;
93
 
      config_iface->deserialize = gimp_config_iface_deserialize;
94
 
      config_iface->duplicate   = gimp_config_iface_duplicate;
95
 
      config_iface->equal       = gimp_config_iface_equal;
96
 
      config_iface->reset       = gimp_config_iface_reset;
97
 
    }
98
 
 
99
 
  /*  always set these to NULL since we don't want to inherit them
100
 
   *  from parent classes
101
 
   */
102
 
  config_iface->serialize_property   = NULL;
103
 
  config_iface->deserialize_property = NULL;
104
 
}
105
 
 
106
 
static gboolean
107
 
gimp_config_iface_serialize (GimpConfig       *config,
108
 
                             GimpConfigWriter *writer,
109
 
                             gpointer          data)
110
 
{
111
 
  return gimp_config_serialize_properties (config, writer);
112
 
}
113
 
 
114
 
static gboolean
115
 
gimp_config_iface_deserialize (GimpConfig *config,
116
 
                               GScanner   *scanner,
117
 
                               gint        nest_level,
118
 
                               gpointer    data)
119
 
{
120
 
  return gimp_config_deserialize_properties (config,
121
 
                                             scanner, nest_level, FALSE);
122
 
}
123
 
 
124
 
static GimpConfig *
125
 
gimp_config_iface_duplicate (GimpConfig *config)
126
 
{
127
 
  GObjectClass  *klass;
128
 
  GParamSpec   **property_specs;
129
 
  guint          n_property_specs;
130
 
  GParameter    *construct_params   = NULL;
131
 
  gint           n_construct_params = 0;
132
 
  guint          i;
133
 
  GimpConfig    *dup;
134
 
 
135
 
  klass = G_OBJECT_GET_CLASS (config);
136
 
 
137
 
  property_specs = g_object_class_list_properties (klass, &n_property_specs);
138
 
 
139
 
  construct_params = g_new0 (GParameter, n_property_specs);
140
 
 
141
 
  for (i = 0; i < n_property_specs; i++)
142
 
    {
143
 
      GParamSpec *prop_spec = property_specs[i];
144
 
 
145
 
      if ((prop_spec->flags & G_PARAM_READABLE) &&
146
 
          (prop_spec->flags & G_PARAM_WRITABLE) &&
147
 
          (prop_spec->flags & G_PARAM_CONSTRUCT_ONLY))
148
 
        {
149
 
          GParameter *construct_param;
150
 
 
151
 
          construct_param = &construct_params[n_construct_params++];
152
 
 
153
 
          construct_param->name = prop_spec->name;
154
 
 
155
 
          g_value_init (&construct_param->value, prop_spec->value_type);
156
 
          g_object_get_property (G_OBJECT (config), prop_spec->name,
157
 
                                 &construct_param->value);
158
 
        }
159
 
    }
160
 
 
161
 
  g_free (property_specs);
162
 
 
163
 
  dup = g_object_newv (G_TYPE_FROM_INSTANCE (config),
164
 
                       n_construct_params, construct_params);
165
 
 
166
 
  for (i = 0; i < n_construct_params; i++)
167
 
    g_value_unset (&construct_params[i].value);
168
 
 
169
 
  g_free (construct_params);
170
 
 
171
 
  gimp_config_sync (config, dup, 0);
172
 
 
173
 
  return dup;
174
 
}
175
 
 
176
 
static gboolean
177
 
gimp_config_iface_equal (GimpConfig *a,
178
 
                         GimpConfig *b)
179
 
{
180
 
  GObjectClass  *klass;
181
 
  GParamSpec   **property_specs;
182
 
  guint          n_property_specs;
183
 
  guint          i;
184
 
  gboolean       equal = TRUE;
185
 
 
186
 
  klass = G_OBJECT_GET_CLASS (a);
187
 
 
188
 
  property_specs = g_object_class_list_properties (klass, &n_property_specs);
189
 
 
190
 
  for (i = 0; equal && i < n_property_specs; i++)
191
 
    {
192
 
      GParamSpec  *prop_spec;
193
 
      GValue       a_value = { 0, };
194
 
      GValue       b_value = { 0, };
195
 
 
196
 
      prop_spec = property_specs[i];
197
 
 
198
 
      if (! (prop_spec->flags & G_PARAM_READABLE))
199
 
        continue;
200
 
 
201
 
      g_value_init (&a_value, prop_spec->value_type);
202
 
      g_value_init (&b_value, prop_spec->value_type);
203
 
      g_object_get_property (G_OBJECT (a), prop_spec->name, &a_value);
204
 
      g_object_get_property (G_OBJECT (b), prop_spec->name, &b_value);
205
 
 
206
 
      if (g_param_values_cmp (prop_spec, &a_value, &b_value))
207
 
        {
208
 
          if ((prop_spec->flags & GIMP_PARAM_AGGREGATE) &&
209
 
              G_IS_PARAM_SPEC_OBJECT (prop_spec)        &&
210
 
              g_type_interface_peek (g_type_class_peek (prop_spec->value_type),
211
 
                                     GIMP_TYPE_CONFIG))
212
 
            {
213
 
              if (! gimp_config_is_equal_to (g_value_get_object (&a_value),
214
 
                                             g_value_get_object (&b_value)))
215
 
                {
216
 
                  equal = FALSE;
217
 
                }
218
 
            }
219
 
          else
220
 
            {
221
 
              equal = FALSE;
222
 
            }
223
 
        }
224
 
 
225
 
      g_value_unset (&a_value);
226
 
      g_value_unset (&b_value);
227
 
    }
228
 
 
229
 
  g_free (property_specs);
230
 
 
231
 
  return equal;
232
 
}
233
 
 
234
 
static void
235
 
gimp_config_iface_reset (GimpConfig *config)
236
 
{
237
 
  gimp_config_reset_properties (config);
238
 
}
239
 
 
240
 
/**
241
 
 * gimp_config_serialize_to_file:
242
 
 * @config: a #GObject that implements the #GimpConfigInterface.
243
 
 * @filename: the name of the file to write the configuration to.
244
 
 * @header: optional file header (must be ASCII only)
245
 
 * @footer: optional file footer (must be ASCII only)
246
 
 * @data: user data passed to the serialize implementation.
247
 
 * @error:
248
 
 *
249
 
 * Serializes the object properties of @config to the file specified
250
 
 * by @filename. If a file with that name already exists, it is
251
 
 * overwritten. Basically this function opens @filename for you and
252
 
 * calls the serialize function of the @config's #GimpConfigInterface.
253
 
 *
254
 
 * Return value: %TRUE if serialization succeeded, %FALSE otherwise.
255
 
 **/
256
 
gboolean
257
 
gimp_config_serialize_to_file (GimpConfig   *config,
258
 
                               const gchar  *filename,
259
 
                               const gchar  *header,
260
 
                               const gchar  *footer,
261
 
                               gpointer      data,
262
 
                               GError      **error)
263
 
{
264
 
  GimpConfigWriter *writer;
265
 
 
266
 
  g_return_val_if_fail (GIMP_IS_CONFIG (config), FALSE);
267
 
  g_return_val_if_fail (filename != NULL, FALSE);
268
 
  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
269
 
 
270
 
  writer = gimp_config_writer_new_file (filename, TRUE, header, error);
271
 
  if (!writer)
272
 
    return FALSE;
273
 
 
274
 
  GIMP_CONFIG_GET_INTERFACE (config)->serialize (config, writer, data);
275
 
 
276
 
  return gimp_config_writer_finish (writer, footer, error);
277
 
}
278
 
 
279
 
gboolean
280
 
gimp_config_serialize_to_fd (GimpConfig *config,
281
 
                             gint        fd,
282
 
                             gpointer    data)
283
 
{
284
 
  GimpConfigWriter *writer;
285
 
 
286
 
  g_return_val_if_fail (GIMP_IS_CONFIG (config), FALSE);
287
 
  g_return_val_if_fail (fd > 0, FALSE);
288
 
 
289
 
  writer = gimp_config_writer_new_fd (fd);
290
 
  if (!writer)
291
 
    return FALSE;
292
 
 
293
 
  GIMP_CONFIG_GET_INTERFACE (config)->serialize (config, writer, data);
294
 
 
295
 
  return gimp_config_writer_finish (writer, NULL, NULL);
296
 
}
297
 
 
298
 
/**
299
 
 * gimp_config_serialize_to_string:
300
 
 * @config: a #GObject that implements the #GimpConfigInterface.
301
 
 * @data: user data passed to the serialize implementation.
302
 
 *
303
 
 * Serializes the object properties of @config to a string.
304
 
 *
305
 
 * Return value: a newly allocated %NUL-terminated string.
306
 
 **/
307
 
gchar *
308
 
gimp_config_serialize_to_string (GimpConfig *config,
309
 
                                 gpointer    data)
310
 
{
311
 
  GimpConfigWriter *writer;
312
 
  GString          *str;
313
 
 
314
 
  g_return_val_if_fail (GIMP_IS_CONFIG (config), NULL);
315
 
 
316
 
  str = g_string_new (NULL);
317
 
  writer = gimp_config_writer_new_string (str);
318
 
 
319
 
  GIMP_CONFIG_GET_INTERFACE (config)->serialize (config, writer, data);
320
 
 
321
 
  gimp_config_writer_finish (writer, NULL, NULL);
322
 
 
323
 
  return g_string_free (str, FALSE);
324
 
}
325
 
 
326
 
/**
327
 
 * gimp_config_deserialize:
328
 
 * @config: a #GObject that implements the #GimpConfigInterface.
329
 
 * @filename: the name of the file to read configuration from.
330
 
 * @data: user data passed to the deserialize implementation.
331
 
 * @error:
332
 
 *
333
 
 * Opens the file specified by @filename, reads configuration data
334
 
 * from it and configures @config accordingly. Basically this function
335
 
 * creates a properly configured #GScanner for you and calls the
336
 
 * deserialize function of the @config's #GimpConfigInterface.
337
 
 *
338
 
 * Return value: %TRUE if deserialization succeeded, %FALSE otherwise.
339
 
 **/
340
 
gboolean
341
 
gimp_config_deserialize_file (GimpConfig   *config,
342
 
                              const gchar  *filename,
343
 
                              gpointer      data,
344
 
                              GError      **error)
345
 
{
346
 
  GScanner *scanner;
347
 
  gboolean  success;
348
 
 
349
 
  g_return_val_if_fail (GIMP_IS_CONFIG (config), FALSE);
350
 
  g_return_val_if_fail (filename != NULL, FALSE);
351
 
  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
352
 
 
353
 
  scanner = gimp_scanner_new_file (filename, error);
354
 
  if (! scanner)
355
 
    return FALSE;
356
 
 
357
 
  success = GIMP_CONFIG_GET_INTERFACE (config)->deserialize (config,
358
 
                                                             scanner, 0, data);
359
 
 
360
 
  gimp_scanner_destroy (scanner);
361
 
 
362
 
  if (! success)
363
 
    g_assert (error == NULL || *error != NULL);
364
 
 
365
 
  return success;
366
 
}
367
 
 
368
 
/**
369
 
 * gimp_config_deserialize_string:
370
 
 * @config: a #GObject that implements the #GimpConfigInterface.
371
 
 * @text: string to deserialize (in UTF-8 encoding)
372
 
 * @text_len: length of @text in bytes or -1
373
 
 * @data:
374
 
 * @error:
375
 
 *
376
 
 * Configures @config from @text. Basically this function creates a
377
 
 * properly configured #GScanner for you and calls the deserialize
378
 
 * function of the @config's #GimpConfigInterface.
379
 
 *
380
 
 * Returns: %TRUE if deserialization succeeded, %FALSE otherwise.
381
 
 **/
382
 
gboolean
383
 
gimp_config_deserialize_string (GimpConfig      *config,
384
 
                                const gchar  *text,
385
 
                                gint          text_len,
386
 
                                gpointer      data,
387
 
                                GError      **error)
388
 
{
389
 
  GScanner *scanner;
390
 
  gboolean  success;
391
 
 
392
 
  g_return_val_if_fail (GIMP_IS_CONFIG (config), FALSE);
393
 
  g_return_val_if_fail (text != NULL || text_len == 0, FALSE);
394
 
  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
395
 
 
396
 
  scanner = gimp_scanner_new_string (text, text_len, error);
397
 
 
398
 
  success = GIMP_CONFIG_GET_INTERFACE (config)->deserialize (config,
399
 
                                                             scanner, 0, data);
400
 
 
401
 
  gimp_scanner_destroy (scanner);
402
 
 
403
 
  if (! success)
404
 
    g_assert (error == NULL || *error != NULL);
405
 
 
406
 
  return success;
407
 
}
408
 
 
409
 
gboolean
410
 
gimp_config_deserialize_return (GScanner     *scanner,
411
 
                                GTokenType    expected_token,
412
 
                                gint          nest_level)
413
 
{
414
 
  GTokenType next_token;
415
 
 
416
 
  g_return_val_if_fail (scanner != NULL, FALSE);
417
 
 
418
 
  next_token = g_scanner_peek_next_token (scanner);
419
 
 
420
 
  if (expected_token != G_TOKEN_LEFT_PAREN)
421
 
    {
422
 
      g_scanner_get_next_token (scanner);
423
 
      g_scanner_unexp_token (scanner, expected_token, NULL, NULL, NULL,
424
 
                             _("fatal parse error"), TRUE);
425
 
      return FALSE;
426
 
    }
427
 
  else
428
 
    {
429
 
      if (nest_level > 0 && next_token == G_TOKEN_RIGHT_PAREN)
430
 
        {
431
 
          return TRUE;
432
 
        }
433
 
      else if (next_token != G_TOKEN_EOF)
434
 
        {
435
 
          g_scanner_get_next_token (scanner);
436
 
          g_scanner_unexp_token (scanner, expected_token, NULL, NULL, NULL,
437
 
                                 _("fatal parse error"), TRUE);
438
 
          return FALSE;
439
 
        }
440
 
    }
441
 
 
442
 
  return TRUE;
443
 
}
444
 
 
445
 
 
446
 
/**
447
 
 * gimp_config_duplicate:
448
 
 * @config: a #GObject that implements the #GimpConfigInterface.
449
 
 *
450
 
 * Creates a copy of the passed object by copying all object
451
 
 * properties. The default implementation of the #GimpConfigInterface
452
 
 * only works for objects that are completely defined by their
453
 
 * properties.
454
 
 *
455
 
 * Return value: the duplicated #GimpConfig object
456
 
 **/
457
 
gpointer
458
 
gimp_config_duplicate (GimpConfig *config)
459
 
{
460
 
  g_return_val_if_fail (GIMP_IS_CONFIG (config), NULL);
461
 
 
462
 
  return GIMP_CONFIG_GET_INTERFACE (config)->duplicate (config);
463
 
}
464
 
 
465
 
/**
466
 
 * gimp_config_is_equal_to:
467
 
 * @a: a #GObject that implements the #GimpConfigInterface.
468
 
 * @b: another #GObject of the same type as @a.
469
 
 *
470
 
 * Compares the two objects. The default implementation of the
471
 
 * #GimpConfigInterface compares the object properties and thus only
472
 
 * works for objects that are completely defined by their
473
 
 * properties.
474
 
 *
475
 
 * Return value: %TRUE if the two objects are equal.
476
 
 **/
477
 
gboolean
478
 
gimp_config_is_equal_to (GimpConfig *a,
479
 
                         GimpConfig *b)
480
 
{
481
 
  g_return_val_if_fail (GIMP_IS_CONFIG (a), FALSE);
482
 
  g_return_val_if_fail (GIMP_IS_CONFIG (b), FALSE);
483
 
  g_return_val_if_fail (G_TYPE_FROM_INSTANCE (a) == G_TYPE_FROM_INSTANCE (b),
484
 
                        FALSE);
485
 
 
486
 
  return GIMP_CONFIG_GET_INTERFACE (a)->equal (a, b);
487
 
}
488
 
 
489
 
/**
490
 
 * gimp_config_reset:
491
 
 * @config: a #GObject that implements the #GimpConfigInterface.
492
 
 *
493
 
 * Resets the object to its default state. The default implementation of the
494
 
 * #GimpConfigInterface only works for objects that are completely defined by
495
 
 * their properties.
496
 
 **/
497
 
void
498
 
gimp_config_reset (GimpConfig *config)
499
 
{
500
 
  g_return_if_fail (GIMP_IS_CONFIG (config));
501
 
 
502
 
  GIMP_CONFIG_GET_INTERFACE (config)->reset (config);
503
 
}
504
 
 
505
 
 
506
 
/*
507
 
 * Code to store and lookup unknown tokens (string key/value pairs).
508
 
 */
509
 
 
510
 
#define GIMP_CONFIG_UNKNOWN_TOKENS "gimp-config-unknown-tokens"
511
 
 
512
 
typedef struct
513
 
{
514
 
  gchar *key;
515
 
  gchar *value;
516
 
} GimpConfigToken;
517
 
 
518
 
static void  gimp_config_destroy_unknown_tokens (GSList   *unknown_tokens);
519
 
 
520
 
 
521
 
/**
522
 
 * gimp_config_add_unknown_token:
523
 
 * @config: a #GObject.
524
 
 * @key: a nul-terminated string to identify the value.
525
 
 * @value: a nul-terminated string representing the value.
526
 
 *
527
 
 * This function allows to add arbitrary key/value pairs to a GObject.
528
 
 * It's purpose is to attach additional data to a #GimpConfig object
529
 
 * that can be stored along with the object properties when
530
 
 * serializing the object to a configuration file. Please note however
531
 
 * that the default gimp_config_serialize() implementation does not
532
 
 * serialize unknown tokens.
533
 
 *
534
 
 * If you want to remove a key/value pair from the object, call this
535
 
 * function with a %NULL @value.
536
 
 **/
537
 
void
538
 
gimp_config_add_unknown_token (GimpConfig  *config,
539
 
                               const gchar *key,
540
 
                               const gchar *value)
541
 
{
542
 
  GimpConfigToken *token;
543
 
  GSList          *unknown_tokens;
544
 
  GSList          *last;
545
 
  GSList          *list;
546
 
 
547
 
  g_return_if_fail (GIMP_IS_CONFIG (config));
548
 
  g_return_if_fail (key != NULL);
549
 
 
550
 
  unknown_tokens = (GSList *) g_object_get_data (G_OBJECT (config),
551
 
                                                 GIMP_CONFIG_UNKNOWN_TOKENS);
552
 
 
553
 
  for (last = NULL, list = unknown_tokens;
554
 
       list;
555
 
       last = list, list = g_slist_next (list))
556
 
    {
557
 
      token = (GimpConfigToken *) list->data;
558
 
 
559
 
      if (strcmp (token->key, key) == 0)
560
 
        {
561
 
          g_free (token->value);
562
 
 
563
 
          if (value)
564
 
            {
565
 
              token->value = g_strdup (value);
566
 
            }
567
 
          else
568
 
            {
569
 
              g_free (token->key);
570
 
 
571
 
              unknown_tokens = g_slist_remove (unknown_tokens, token);
572
 
              g_object_set_data_full (G_OBJECT (config),
573
 
                                      GIMP_CONFIG_UNKNOWN_TOKENS,
574
 
                                      unknown_tokens,
575
 
                     (GDestroyNotify) gimp_config_destroy_unknown_tokens);
576
 
            }
577
 
 
578
 
          return;
579
 
        }
580
 
    }
581
 
 
582
 
  if (!value)
583
 
    return;
584
 
 
585
 
  token = g_new (GimpConfigToken, 1);
586
 
  token->key   = g_strdup (key);
587
 
  token->value = g_strdup (value);
588
 
 
589
 
  if (last)
590
 
    {
591
 
      g_slist_append (last, token);
592
 
    }
593
 
  else
594
 
    {
595
 
      unknown_tokens = g_slist_append (NULL, token);
596
 
 
597
 
      g_object_set_data_full (G_OBJECT (config),
598
 
                              GIMP_CONFIG_UNKNOWN_TOKENS,
599
 
                              unknown_tokens,
600
 
             (GDestroyNotify) gimp_config_destroy_unknown_tokens);
601
 
    }
602
 
}
603
 
 
604
 
/**
605
 
 * gimp_config_lookup_unknown_token:
606
 
 * @config: a #GObject.
607
 
 * @key: a nul-terminated string to identify the value.
608
 
 *
609
 
 * This function retrieves data that was previously attached using
610
 
 * gimp_config_add_unknown_token(). You should not free or modify
611
 
 * the returned string.
612
 
 *
613
 
 * Returns: a pointer to a constant string.
614
 
 **/
615
 
const gchar *
616
 
gimp_config_lookup_unknown_token (GimpConfig  *config,
617
 
                                  const gchar *key)
618
 
{
619
 
  GimpConfigToken *token;
620
 
  GSList          *unknown_tokens;
621
 
  GSList          *list;
622
 
 
623
 
  g_return_val_if_fail (GIMP_IS_CONFIG (config), NULL);
624
 
  g_return_val_if_fail (key != NULL, NULL);
625
 
 
626
 
  unknown_tokens = (GSList *) g_object_get_data (G_OBJECT (config),
627
 
                                                 GIMP_CONFIG_UNKNOWN_TOKENS);
628
 
 
629
 
  for (list = unknown_tokens; list; list = g_slist_next (list))
630
 
    {
631
 
      token = (GimpConfigToken *) list->data;
632
 
 
633
 
      if (strcmp (token->key, key) == 0)
634
 
        return token->value;
635
 
    }
636
 
 
637
 
  return NULL;
638
 
}
639
 
 
640
 
/**
641
 
 * gimp_config_foreach_unknown_token:
642
 
 * @config: a #GObject.
643
 
 * @func: a function to call for each key/value pair.
644
 
 * @user_data: data to pass to @func.
645
 
 *
646
 
 * Calls @func for each key/value stored with the @config using
647
 
 * gimp_config_add_unknown_token().
648
 
 **/
649
 
void
650
 
gimp_config_foreach_unknown_token (GimpConfig            *config,
651
 
                                   GimpConfigForeachFunc  func,
652
 
                                   gpointer               user_data)
653
 
{
654
 
  GimpConfigToken *token;
655
 
  GSList          *unknown_tokens;
656
 
  GSList          *list;
657
 
 
658
 
  g_return_if_fail (GIMP_IS_CONFIG (config));
659
 
  g_return_if_fail (func != NULL);
660
 
 
661
 
  unknown_tokens = (GSList *) g_object_get_data (G_OBJECT (config),
662
 
                                                 GIMP_CONFIG_UNKNOWN_TOKENS);
663
 
 
664
 
  for (list = unknown_tokens; list; list = g_slist_next (list))
665
 
    {
666
 
      token = (GimpConfigToken *) list->data;
667
 
 
668
 
      func (token->key, token->value, user_data);
669
 
    }
670
 
}
671
 
 
672
 
static void
673
 
gimp_config_destroy_unknown_tokens (GSList *unknown_tokens)
674
 
{
675
 
  GimpConfigToken *token;
676
 
  GSList          *list;
677
 
 
678
 
  for (list = unknown_tokens; list; list = g_slist_next (list))
679
 
    {
680
 
      token = (GimpConfigToken *) list->data;
681
 
 
682
 
      g_free (token->key);
683
 
      g_free (token->value);
684
 
      g_free (token);
685
 
    }
686
 
 
687
 
  g_slist_free (unknown_tokens);
688
 
}