updated [and finally fixed my script to produce ready to go de-in(ed)
[platform/upstream/glib.git] / glib / gkeyfile.c
1 /* gkeyfile.c - key file parser
2  *
3  *  Copyright 2004  Red Hat, Inc.  
4  *
5  * Written by Ray Strode <rstrode@redhat.com>
6  *            Matthias Clasen <mclasen@redhat.com>
7  *
8  * GLib is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU Lesser General Public License as
10  * published by the Free Software Foundation; either version 2 of the
11  * License, or (at your option) any later version.
12  *
13  * GLib is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with GLib; see the file COPYING.LIB.  If not,
20  * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  *   Boston, MA 02111-1307, USA.
22  */
23
24 #include "config.h"
25 #include "galias.h"
26
27 #include "gkeyfile.h"
28
29 #include <errno.h>
30 #include <fcntl.h>
31 #include <locale.h>
32 #include <string.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #ifdef HAVE_UNISTD_H
38 #include <unistd.h>
39 #endif
40 #ifdef G_OS_WIN32
41 #include <io.h>
42 #endif
43
44 #include "gconvert.h"
45 #include "gdataset.h"
46 #include "gerror.h"
47 #include "gfileutils.h"
48 #include "ghash.h"
49 #include "glibintl.h"
50 #include "glist.h"
51 #include "gslist.h"
52 #include "gmem.h"
53 #include "gmessages.h"
54 #include "gstdio.h"
55 #include "gstring.h"
56 #include "gstrfuncs.h"
57 #include "gutils.h"
58
59 typedef struct _GKeyFileGroup GKeyFileGroup;
60
61 struct _GKeyFile
62 {
63   GList *groups;
64
65   gchar  *start_group_name;
66
67   GKeyFileGroup *current_group;
68
69   GString *parse_buffer; /* Holds up to one line of not-yet-parsed data */
70
71   /* Used for sizing the output buffer during serialization
72    */
73   gsize approximate_size;
74
75   gchar list_separator;
76
77   GKeyFileFlags flags;
78 };
79
80 typedef struct _GKeyFileKeyValuePair GKeyFileKeyValuePair;
81
82 struct _GKeyFileGroup
83 {
84   const gchar *name;  /* NULL for above first group (which will be comments) */
85
86   GKeyFileKeyValuePair *comment; /* Special comment that is stuck to the top of a group */
87
88   GList *key_value_pairs; 
89
90   /* Used in parallel with key_value_pairs for
91    * increased lookup performance
92    */
93   GHashTable *lookup_map;
94 };
95
96 struct _GKeyFileKeyValuePair
97 {
98   gchar *key;  /* NULL for comments */
99   gchar *value;
100 };
101
102 static gint                  find_file_in_data_dirs            (const gchar            *file,
103                                                                 gchar                 **output_file,
104                                                                 gchar                ***data_dirs,
105                                                                 GError                **error);
106 static gboolean              g_key_file_load_from_fd           (GKeyFile               *key_file,
107                                                                 gint                    fd,
108                                                                 GKeyFileFlags           flags,
109                                                                 GError                **error);
110 static GList                *g_key_file_lookup_group_node      (GKeyFile    *key_file,
111                                                                 const gchar *group_name);
112 static GKeyFileGroup        *g_key_file_lookup_group           (GKeyFile               *key_file,
113                                                                 const gchar            *group_name);
114
115 static GList                *g_key_file_lookup_key_value_pair_node  (GKeyFile       *key_file,
116                                                                      GKeyFileGroup  *group,
117                                                                      const gchar    *key);
118 static GKeyFileKeyValuePair *g_key_file_lookup_key_value_pair       (GKeyFile       *key_file,
119                                                                      GKeyFileGroup  *group,
120                                                                      const gchar    *key);
121
122 static void                  g_key_file_remove_group_node          (GKeyFile      *entry,
123                                                                     GList         *group_node);
124 static void                  g_key_file_remove_key_value_pair_node (GKeyFile      *key_file,
125                                                                     GKeyFileGroup *group,
126                                                                     GList         *pair_node);
127
128 static void                  g_key_file_add_key                (GKeyFile               *entry,
129                                                                 const gchar            *group_name,
130                                                                 const gchar            *key,
131                                                                 const gchar            *value);
132 static void                  g_key_file_add_group              (GKeyFile               *entry,
133                                                                 const gchar            *group_name);
134 static void                  g_key_file_key_value_pair_free    (GKeyFileKeyValuePair   *pair);
135 static gboolean              g_key_file_line_is_comment        (const gchar            *line);
136 static gboolean              g_key_file_line_is_group          (const gchar            *line);
137 static gboolean              g_key_file_line_is_key_value_pair (const gchar            *line);
138 static gchar                *g_key_file_parse_value_as_string  (GKeyFile               *entry,
139                                                                 const gchar            *value,
140                                                                 GSList                **separators,
141                                                                 GError                **error);
142 static gchar                *g_key_file_parse_string_as_value  (GKeyFile               *entry,
143                                                                 const gchar            *string,
144                                                                 gboolean                escape_separator);
145 static gint                  g_key_file_parse_value_as_integer (GKeyFile               *entry,
146                                                                 const gchar            *value,
147                                                                 GError                **error);
148 static gchar                *g_key_file_parse_integer_as_value (GKeyFile               *entry,
149                                                                 gint                    value);
150 static gboolean              g_key_file_parse_value_as_boolean (GKeyFile               *entry,
151                                                                 const gchar            *value,
152                                                                 GError                **error);
153 static gchar                *g_key_file_parse_boolean_as_value (GKeyFile               *entry,
154                                                                 gboolean                value);
155 static gchar                *g_key_file_parse_value_as_comment (GKeyFile *key_file,
156                                                                 const gchar *value);
157 static gchar                *g_key_file_parse_comment_as_value (GKeyFile *key_file,
158                                                                 const gchar *comment);
159 static void                  g_key_file_parse_key_value_pair   (GKeyFile               *entry,
160                                                                 const gchar            *line,
161                                                                 gsize                   length,
162                                                                 GError                **error);
163 static void                  g_key_file_parse_comment          (GKeyFile               *entry,
164                                                                 const gchar            *line,
165                                                                 gsize                   length,
166                                                                 GError                **error);
167 static void                  g_key_file_parse_group            (GKeyFile               *entry,
168                                                                 const gchar            *line,
169                                                                 gsize                   length,
170                                                                 GError                **error);
171 static gchar                *key_get_locale                    (const gchar            *key);
172 static void                  g_key_file_parse_data             (GKeyFile               *entry,
173                                                                 const gchar            *data,
174                                                                 gsize                   length,
175                                                                 GError                **error);
176 static void                  g_key_file_flush_parse_buffer     (GKeyFile               *entry,
177                                                                 GError                **error);
178
179
180 GQuark
181 g_key_file_error_quark (void)
182 {
183   static GQuark error_quark = 0;
184
185   if (error_quark == 0)
186     error_quark = g_quark_from_static_string ("g-key-file-error-quark");
187
188   return error_quark;
189 }
190
191 static void
192 g_key_file_init (GKeyFile *key_file)
193 {  
194   key_file->current_group = g_new0 (GKeyFileGroup, 1);
195   key_file->groups = g_list_prepend (NULL, key_file->current_group);
196   key_file->start_group_name = NULL;
197   key_file->parse_buffer = g_string_sized_new (128);
198   key_file->approximate_size = 0;
199   key_file->list_separator = ';';
200   key_file->flags = 0;
201 }
202
203 static void
204 g_key_file_clear (GKeyFile *key_file)
205 {
206   GList *tmp, *group_node;
207
208   if (key_file->parse_buffer)
209     g_string_free (key_file->parse_buffer, TRUE);
210
211   g_free (key_file->start_group_name);
212
213   tmp = key_file->groups;
214   while (tmp != NULL)
215     {
216       group_node = tmp;
217       tmp = tmp->next;
218       g_key_file_remove_group_node (key_file, group_node);
219     }
220
221   g_assert (key_file->groups == NULL);
222 }
223
224
225 /**
226  * g_key_file_new:
227  *
228  * Creates a new empty #GKeyFile object. Use g_key_file_load_from_file(),
229  * g_key_file_load_from_data() or g_key_file_load_from_data_dirs() to
230  * read an existing key file.
231  *
232  * Return value: an empty #GKeyFile.
233  *
234  * Since: 2.6
235  **/
236 GKeyFile *
237 g_key_file_new (void)
238 {
239   GKeyFile *key_file;
240
241   key_file = g_new0 (GKeyFile, 1);
242   g_key_file_init (key_file);
243
244   return key_file;
245 }
246
247 /**
248  * g_key_file_set_list_separator:
249  * @key_file: a #GKeyFile 
250  * @separator: the separator
251  *
252  * Sets the character which is used to separate
253  * values in lists. Typically ';' or ',' are used
254  * as separators. The default list separator is ';'.
255  *
256  * Since: 2.6
257  */
258 void
259 g_key_file_set_list_separator (GKeyFile *key_file,
260                                gchar     separator)
261 {
262   key_file->list_separator = separator;
263 }
264
265
266 /* Iterates through all the directories in *dirs trying to
267  * open file.  When it successfully locates and opens a file it
268  * returns the file descriptor to the open file.  It also
269  * outputs the absolute path of the file in output_file and
270  * leaves the unchecked directories in *dirs.
271  */
272 static gint
273 find_file_in_data_dirs (const gchar   *file,
274                         gchar        **output_file,
275                         gchar       ***dirs,
276                         GError       **error)
277 {
278   gchar **data_dirs, *data_dir, *path;
279   gint fd;
280
281   path = NULL;
282   fd = -1;
283
284   if (dirs == NULL)
285     return fd;
286
287   data_dirs = *dirs;
288
289   while (data_dirs && (data_dir = *data_dirs) && fd < 0)
290     {
291       gchar *candidate_file, *sub_dir;
292
293       candidate_file = (gchar *) file;
294       sub_dir = g_strdup ("");
295       while (candidate_file != NULL && fd < 0)
296         {
297           gchar *p;
298
299           path = g_build_filename (data_dir, sub_dir,
300                                    candidate_file, NULL);
301
302           fd = g_open (path, O_RDONLY, 0);
303
304           if (fd < 0)
305             {
306               g_free (path);
307               path = NULL;
308             }
309
310           candidate_file = strchr (candidate_file, '-');
311
312           if (candidate_file == NULL)
313             break;
314
315           candidate_file++;
316
317           g_free (sub_dir);
318           sub_dir = g_strndup (file, candidate_file - file - 1);
319
320           for (p = sub_dir; *p != '\0'; p++)
321             {
322               if (*p == '-')
323                 *p = G_DIR_SEPARATOR;
324             }
325         }
326       g_free (sub_dir);
327       data_dirs++;
328     }
329
330   *dirs = data_dirs;
331
332   if (fd < 0)
333     {
334       g_set_error (error, G_KEY_FILE_ERROR,
335                    G_KEY_FILE_ERROR_NOT_FOUND,
336                    _("Valid key file could not be "
337                      "found in data dirs")); 
338     }
339
340   if (output_file != NULL && fd > 0)
341     *output_file = g_strdup (path);
342
343   return fd;
344 }
345
346 static gboolean
347 g_key_file_load_from_fd (GKeyFile       *key_file,
348                          gint            fd,
349                          GKeyFileFlags   flags,
350                          GError        **error)
351 {
352   GError *key_file_error = NULL;
353   gsize bytes_read;
354   struct stat stat_buf;
355   gchar read_buf[4096];
356   
357   if (fstat (fd, &stat_buf) < 0)
358     {
359       g_set_error (error, G_FILE_ERROR,
360                    g_file_error_from_errno (errno),
361                    "%s", g_strerror (errno));
362       return FALSE;
363     }
364
365   if ((stat_buf.st_mode & S_IFMT) != S_IFREG)
366     {
367       g_set_error (error, G_KEY_FILE_ERROR,
368                    G_KEY_FILE_ERROR_PARSE,
369                    _("Not a regular file"));
370       return FALSE;
371     }
372
373   if (stat_buf.st_size == 0)
374     {
375       g_set_error (error, G_KEY_FILE_ERROR,
376                    G_KEY_FILE_ERROR_PARSE,
377                    _("File is empty"));
378       return FALSE;
379     }
380
381   if (key_file->approximate_size > 0)
382     {
383       g_key_file_clear (key_file);
384       g_key_file_init (key_file);
385     }
386   key_file->flags = flags;
387
388   bytes_read = 0;
389   do
390     {
391       bytes_read = read (fd, read_buf, 4096);
392
393       if (bytes_read == 0)  /* End of File */
394         break;
395
396       if (bytes_read < 0)
397         {
398           if (errno == EINTR || errno == EAGAIN)
399             continue;
400
401           g_set_error (error, G_FILE_ERROR,
402                        g_file_error_from_errno (errno),
403                        "%s", g_strerror (errno));
404           return FALSE;
405         }
406
407       g_key_file_parse_data (key_file, 
408                              read_buf, bytes_read,
409                              &key_file_error);
410     }
411   while (!key_file_error);
412
413   if (key_file_error)
414     {
415       g_propagate_error (error, key_file_error);
416       return FALSE;
417     }
418
419   g_key_file_flush_parse_buffer (key_file, &key_file_error);
420
421   if (key_file_error)
422     {
423       g_propagate_error (error, key_file_error);
424       return FALSE;
425     }
426
427   return TRUE;
428 }
429
430 /**
431  * g_key_file_load_from_file:
432  * @key_file: an empty #GKeyFile struct
433  * @file: the path of a filename to load, in the GLib file name encoding
434  * @flags: flags from #GKeyFileFlags
435  * @error: return location for a #GError, or %NULL
436  *
437  * Loads a key file into an empty #GKeyFile structure.
438  * If the file could not be loaded then %error is set to 
439  * either a #GFileError or #GKeyFileError.
440  *
441  * Return value: %TRUE if a key file could be loaded, %FALSE othewise
442  * Since: 2.6
443  **/
444 gboolean
445 g_key_file_load_from_file (GKeyFile       *key_file,
446                            const gchar    *file,
447                            GKeyFileFlags   flags,
448                            GError        **error)
449 {
450   GError *key_file_error = NULL;
451   gint fd;
452
453   g_return_val_if_fail (key_file != NULL, FALSE);
454   g_return_val_if_fail (file != NULL, FALSE);
455
456   fd = g_open (file, O_RDONLY, 0);
457
458   if (fd < 0)
459     {
460       g_set_error (error, G_FILE_ERROR,
461                    g_file_error_from_errno (errno),
462                    "%s", g_strerror (errno));
463       return FALSE;
464     }
465
466   g_key_file_load_from_fd (key_file, fd, flags, &key_file_error);
467   close (fd);
468
469   if (key_file_error)
470     {
471       g_propagate_error (error, key_file_error);
472       return FALSE;
473     }
474
475   return TRUE;
476 }
477
478 /**
479  * g_key_file_load_from_data:
480  * @key_file: an empty #GKeyFile struct
481  * @data: key file loaded in memory.
482  * @length: the length of @data in bytes
483  * @flags: flags from #GKeyFileFlags
484  * @error: return location for a #GError, or %NULL
485  *
486  * Loads a key file from memory into an empty #GKeyFile structure.  
487  * If the object cannot be created then %error is set to a #GKeyFileError.
488  *
489  * Return value: %TRUE if a key file could be loaded, %FALSE othewise
490  * Since: 2.6
491  **/
492 gboolean
493 g_key_file_load_from_data (GKeyFile       *key_file,
494                            const gchar    *data,
495                            gsize           length,
496                            GKeyFileFlags   flags,
497                            GError        **error)
498 {
499   GError *key_file_error = NULL;
500
501   g_return_val_if_fail (key_file != NULL, FALSE);
502   g_return_val_if_fail (data != NULL, FALSE);
503   g_return_val_if_fail (length != 0, FALSE);
504
505   if (key_file->approximate_size > 0)
506     {
507       g_key_file_clear (key_file);
508       g_key_file_init (key_file);
509     }
510   key_file->flags = flags;
511
512   g_key_file_parse_data (key_file, data, length, &key_file_error);
513   
514   if (key_file_error)
515     {
516       g_propagate_error (error, key_file_error);
517       return FALSE;
518     }
519
520   g_key_file_flush_parse_buffer (key_file, &key_file_error);
521   
522   if (key_file_error)
523     {
524       g_propagate_error (error, key_file_error);
525       return FALSE;
526     }
527
528   return TRUE;
529 }
530
531 /**
532  * g_key_file_load_from_data_dirs:
533  * @key_file: an empty #GKeyFile struct
534  * @file: a relative path to a filename to open and parse
535  * @full_path: return location for a string containing the full path
536  *   of the file, or %NULL
537  * @flags: flags from #GKeyFileFlags 
538  * @error: return location for a #GError, or %NULL
539  *
540  * This function looks for a key file named @file in the paths 
541  * returned from g_get_user_data_dir() and g_get_system_data_dirs(), 
542  * loads the file into @key_file and returns the file's full path in 
543  * @full_path.  If the file could not be loaded then an %error is
544  * set to either a #GFileError or #GKeyFileError.
545  *
546  * Return value: %TRUE if a key file could be loaded, %FALSE othewise
547  * Since: 2.6
548  **/
549 gboolean
550 g_key_file_load_from_data_dirs (GKeyFile       *key_file,
551                                 const gchar    *file,
552                                 gchar         **full_path,
553                                 GKeyFileFlags   flags,
554                                 GError        **error)
555 {
556   GError *key_file_error = NULL;
557   gchar **all_data_dirs, **data_dirs;
558   const gchar * user_data_dir;
559   const gchar * const * system_data_dirs;
560   gsize i, j;
561   gchar *output_path;
562   gint fd;
563   gboolean found_file;
564   
565   g_return_val_if_fail (key_file != NULL, FALSE);
566   g_return_val_if_fail (!g_path_is_absolute (file), FALSE);
567
568   user_data_dir = g_get_user_data_dir ();
569   system_data_dirs = g_get_system_data_dirs ();
570   all_data_dirs = g_new0 (gchar *, g_strv_length ((gchar **)system_data_dirs) + 2);
571
572   i = 0;
573   all_data_dirs[i++] = g_strdup (user_data_dir);
574
575   j = 0;
576   while (system_data_dirs[j] != NULL)
577     all_data_dirs[i++] = g_strdup (system_data_dirs[j++]);
578
579   found_file = FALSE;
580   data_dirs = all_data_dirs;
581   while (*data_dirs != NULL && !found_file)
582     {
583       fd = find_file_in_data_dirs (file, &output_path, &data_dirs, 
584                                    &key_file_error);
585       
586       if (fd < 0)
587         {
588           if (key_file_error)
589             g_propagate_error (error, key_file_error);
590           break;
591         }
592
593       found_file = g_key_file_load_from_fd (key_file, fd, flags,
594                                             &key_file_error);
595       close (fd);
596       
597       if (key_file_error)
598         {
599           g_propagate_error (error, key_file_error);
600           g_free (output_path);
601           break;
602         }
603       
604       if (full_path)
605         *full_path = output_path;
606     }
607
608   g_strfreev (all_data_dirs);
609   return found_file;
610 }
611
612 /**
613  * g_key_file_free:
614  * @key_file: a #GKeyFile
615  *
616  * Frees a #GKeyFile.
617  *
618  * Since: 2.6
619  **/
620 void
621 g_key_file_free (GKeyFile *key_file)
622 {
623   g_return_if_fail (key_file != NULL);
624   
625   g_key_file_clear (key_file);
626   g_free (key_file);
627 }
628
629 /* If G_KEY_FILE_KEEP_TRANSLATIONS is not set, only returns
630  * true for locales that match those in g_get_language_names().
631  */
632 static gboolean
633 g_key_file_locale_is_interesting (GKeyFile    *key_file,
634                                   const gchar *locale)
635 {
636   const gchar * const * current_locales;
637   gsize i;
638
639   if (key_file->flags & G_KEY_FILE_KEEP_TRANSLATIONS)
640     return TRUE;
641
642   current_locales = g_get_language_names ();
643
644   for (i = 0; current_locales[i] != NULL; i++)
645     {
646       if (g_ascii_strcasecmp (current_locales[i], locale) == 0)
647         return TRUE;
648     }
649
650   return FALSE;
651 }
652
653 static void
654 g_key_file_parse_line (GKeyFile     *key_file,
655                        const gchar  *line,
656                        gsize         length,
657                        GError      **error)
658 {
659   GError *parse_error = NULL;
660   gchar *line_start;
661
662   g_return_if_fail (key_file != NULL);
663   g_return_if_fail (line != NULL);
664
665   line_start = (gchar *) line;
666   while (g_ascii_isspace (*line_start))
667     line_start++;
668
669   if (g_key_file_line_is_comment (line_start))
670     g_key_file_parse_comment (key_file, line, length, &parse_error);
671   else if (g_key_file_line_is_group (line_start))
672     g_key_file_parse_group (key_file, line_start,
673                             length - (line_start - line),
674                             &parse_error);
675   else if (g_key_file_line_is_key_value_pair (line_start))
676     g_key_file_parse_key_value_pair (key_file, line_start,
677                                      length - (line_start - line),
678                                      &parse_error);
679   else
680     {
681       g_set_error (error, G_KEY_FILE_ERROR,
682                    G_KEY_FILE_ERROR_PARSE,
683                    _("Key file contains line '%s' which is not "
684                      "a key-value pair, group, or comment"), line);
685       return;
686     }
687
688   if (parse_error)
689     g_propagate_error (error, parse_error);
690 }
691
692 static void
693 g_key_file_parse_comment (GKeyFile     *key_file,
694                           const gchar  *line,
695                           gsize         length,
696                           GError      **error)
697 {
698   GKeyFileKeyValuePair *pair;
699   
700   if (!(key_file->flags & G_KEY_FILE_KEEP_COMMENTS))
701     return;
702   
703   g_assert (key_file->current_group != NULL);
704
705   pair = g_new0 (GKeyFileKeyValuePair, 1);
706   
707   pair->key = NULL;
708   pair->value = g_strndup (line, length);
709   
710   key_file->current_group->key_value_pairs =
711     g_list_prepend (key_file->current_group->key_value_pairs, pair);
712 }
713
714 static void
715 g_key_file_parse_group (GKeyFile     *key_file,
716                         const gchar  *line,
717                         gsize         length,
718                         GError      **error)
719 {
720   gchar *group_name;
721   const gchar *group_name_start, *group_name_end;
722   
723   /* advance past opening '['
724    */
725   group_name_start = line + 1;
726   group_name_end = line + length - 1;
727   
728   while (*group_name_end != ']')
729     group_name_end--;
730
731   group_name = g_strndup (group_name_start, 
732                           group_name_end - group_name_start);
733   
734   if (key_file->start_group_name == NULL)
735     key_file->start_group_name = g_strdup (group_name);
736   
737   g_key_file_add_group (key_file, group_name);
738   g_free (group_name);
739 }
740
741 static void
742 g_key_file_parse_key_value_pair (GKeyFile     *key_file,
743                                  const gchar  *line,
744                                  gsize         length,
745                                  GError      **error)
746 {
747   gchar *key, *value, *key_end, *value_start, *locale;
748   gsize key_len, value_len;
749
750   if (key_file->current_group == NULL || key_file->current_group->name == NULL)
751     {
752       g_set_error (error, G_KEY_FILE_ERROR,
753                    G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
754                    _("Key file does not start with a group"));
755       return;
756     }
757
758   key_end = value_start = strchr (line, '=');
759
760   g_assert (key_end != NULL);
761
762   key_end--;
763   value_start++;
764
765   /* Pull the key name from the line (chomping trailing whitespace)
766    */
767   while (g_ascii_isspace (*key_end))
768     key_end--;
769
770   key_len = key_end - line + 2;
771
772   g_assert (key_len <= length);
773
774   key = g_strndup (line, key_len - 1);
775
776   /* Pull the value from the line (chugging leading whitespace)
777    */
778   while (g_ascii_isspace (*value_start))
779     value_start++;
780
781   value_len = line + length - value_start + 1;
782
783   value = g_strndup (value_start, value_len);
784
785   g_assert (key_file->start_group_name != NULL);
786
787   if (key_file->current_group
788       && key_file->current_group->name
789       && strcmp (key_file->start_group_name,
790                  key_file->current_group->name) == 0
791       && strcmp (key, "Encoding") == 0)
792     {
793       if (g_ascii_strcasecmp (value, "UTF-8") != 0)
794         {
795           g_set_error (error, G_KEY_FILE_ERROR,
796                        G_KEY_FILE_ERROR_UNKNOWN_ENCODING,
797                        _("Key file contains unsupported encoding '%s'"), value);
798
799           g_free (key);
800           g_free (value);
801           return;
802         }
803     }
804
805   /* Is this key a translation? If so, is it one that we care about?
806    */
807   locale = key_get_locale (key);
808
809   if (locale == NULL || g_key_file_locale_is_interesting (key_file, locale))
810     g_key_file_add_key (key_file, key_file->current_group->name, key, value);
811
812   g_free (locale);
813   g_free (key);
814   g_free (value);
815 }
816
817 static gchar *
818 key_get_locale (const gchar *key)
819 {
820   gchar *locale;
821
822   locale = g_strrstr (key, "[");
823
824   if (locale && strlen (locale) <= 2)
825     locale = NULL;
826
827   if (locale)
828     locale = g_strndup (locale + 1, strlen (locale) - 2);
829
830   return locale;
831 }
832
833 static void
834 g_key_file_parse_data (GKeyFile     *key_file,
835                        const gchar  *data,
836                        gsize         length,
837                        GError      **error)
838 {
839   GError *parse_error;
840   gsize i;
841
842   g_return_if_fail (key_file != NULL);
843   g_return_if_fail (data != NULL);
844
845   parse_error = NULL;
846
847   for (i = 0; i < length; i++)
848     {
849       if (data[i] == '\n')
850         {
851           /* When a newline is encountered flush the parse buffer so that the
852            * line can be parsed.  Note that completely blank lines won't show
853            * up in the parse buffer, so they get parsed directly.
854            */
855           if (key_file->parse_buffer->len > 0)
856             g_key_file_flush_parse_buffer (key_file, &parse_error);
857           else
858             g_key_file_parse_comment (key_file, "", 1, &parse_error);
859
860           if (parse_error)
861             {
862               g_propagate_error (error, parse_error);
863               return;
864             }
865         }
866       else
867         g_string_append_c (key_file->parse_buffer, data[i]);
868     }
869
870   key_file->approximate_size += length;
871 }
872
873 static void
874 g_key_file_flush_parse_buffer (GKeyFile  *key_file,
875                                GError   **error)
876 {
877   GError *file_error = NULL;
878
879   g_return_if_fail (key_file != NULL);
880
881   file_error = NULL;
882
883   if (key_file->parse_buffer->len > 0)
884     {
885       g_key_file_parse_line (key_file, key_file->parse_buffer->str,
886                              key_file->parse_buffer->len,
887                              &file_error);
888       g_string_erase (key_file->parse_buffer, 0, -1);
889
890       if (file_error)
891         {
892           g_propagate_error (error, file_error);
893           return;
894         }
895     }
896 }
897
898 /**
899  * g_key_file_to_data:
900  * @key_file: a #GKeyFile
901  * @length: return location for the length of the 
902  *   returned string, or %NULL
903  * @error: return location for a #GError, or %NULL
904  *
905  * This function outputs @key_file as a string.  
906  *
907  * Return value: a newly allocated string holding
908  *   the contents of the #GKeyFile 
909  *
910  * Since: 2.6
911  **/
912 gchar *
913 g_key_file_to_data (GKeyFile  *key_file,
914                     gsize     *length,
915                     GError   **error)
916 {
917   GString *data_string;
918   gchar *data;
919   GList *group_node, *key_file_node;
920
921   g_return_val_if_fail (key_file != NULL, NULL);
922
923   data_string = g_string_sized_new (2 * key_file->approximate_size);
924   
925   for (group_node = g_list_last (key_file->groups);
926        group_node != NULL;
927        group_node = group_node->prev)
928     {
929       GKeyFileGroup *group;
930
931       group = (GKeyFileGroup *) group_node->data;
932
933       if (group->comment != NULL)
934         g_string_append_printf (data_string, "%s\n", group->comment->value);
935       if (group->name != NULL)
936         g_string_append_printf (data_string, "[%s]\n", group->name);
937
938       for (key_file_node = g_list_last (group->key_value_pairs);
939            key_file_node != NULL;
940            key_file_node = key_file_node->prev)
941         {
942           GKeyFileKeyValuePair *pair;
943
944           pair = (GKeyFileKeyValuePair *) key_file_node->data;
945
946           if (pair->key != NULL)
947             g_string_append_printf (data_string, "%s=%s\n", pair->key, pair->value);
948           else
949             g_string_append_printf (data_string, "%s\n", pair->value);
950         }
951     }
952
953   if (length)
954     *length = data_string->len;
955
956   data = data_string->str;
957
958   g_string_free (data_string, FALSE);
959
960   return data;
961 }
962
963 /**
964  * g_key_file_get_keys:
965  * @key_file: a #GKeyFile
966  * @group_name: a group name, or %NULL
967  * @length: return location for the number of keys returned, or %NULL
968  * @error: return location for a #GError, or %NULL
969  *
970  * Returns all keys for the group name @group_name. If @group_name is
971  * %NULL, the start group is used. The array of returned keys will be 
972  * %NULL-terminated, so @length may optionally be %NULL.
973  *
974  * Return value: a newly-allocated %NULL-terminated array of
975  * strings. Use g_strfreev() to free it.
976  *
977  * Since: 2.6
978  **/
979 gchar **
980 g_key_file_get_keys (GKeyFile     *key_file,
981                      const gchar  *group_name,
982                      gsize        *length,
983                      GError      **error)
984 {
985   GKeyFileGroup *group;
986   GList *tmp;
987   gchar **keys;
988   gsize i, num_keys;
989   
990   g_return_val_if_fail (key_file != NULL, NULL);
991   g_return_val_if_fail (group_name != NULL, NULL);
992   
993   group = g_key_file_lookup_group (key_file, group_name);
994   
995   if (!group)
996     {
997       g_set_error (error, G_KEY_FILE_ERROR,
998                    G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
999                    _("Key file does not have group '%s'"),
1000                    group_name);
1001       return NULL;
1002     }
1003
1004   num_keys = g_list_length (group->key_value_pairs);
1005   
1006   keys = (gchar **) g_new0 (gchar **, num_keys + 1);
1007
1008   tmp = group->key_value_pairs;
1009   for (i = 0; i < num_keys; i++)
1010     {
1011       GKeyFileKeyValuePair *pair;
1012
1013       pair = (GKeyFileKeyValuePair *) tmp->data;
1014       keys[i] = g_strdup (pair->key);
1015
1016       tmp = tmp->next;
1017     }
1018   keys[i] = NULL;
1019
1020   if (length)
1021     *length = num_keys;
1022
1023   return keys;
1024 }
1025
1026 /**
1027  * g_key_file_get_start_group:
1028  * @key_file: a #GKeyFile
1029  *
1030  * Returns the name of the start group of the file. 
1031  *
1032  * Return value: The start group of the key file.
1033  *
1034  * Since: 2.6
1035  **/
1036 gchar *
1037 g_key_file_get_start_group (GKeyFile *key_file)
1038 {
1039   g_return_val_if_fail (key_file != NULL, NULL);
1040
1041   return g_strdup (key_file->start_group_name);
1042 }
1043
1044 /**
1045  * g_key_file_get_groups:
1046  * @key_file: a #GKeyFile
1047  * @length: return location for the number of returned groups, or %NULL
1048  *
1049  * Returns all groups in the key file loaded with @key_file.  The
1050  * array of returned groups will be %NULL-terminated, so @length may
1051  * optionally be %NULL.
1052  *
1053  * Return value: a newly-allocated %NULL-terminated array of strings. 
1054  *   Use g_strfreev() to free it.
1055  * Since: 2.6
1056  **/
1057 gchar **
1058 g_key_file_get_groups (GKeyFile *key_file,
1059                        gsize    *length)
1060 {
1061   GList *group_node;
1062   gchar **groups;
1063   gsize i, num_groups;
1064
1065   g_return_val_if_fail (key_file != NULL, NULL);
1066
1067   num_groups = g_list_length (key_file->groups);
1068
1069   g_assert (num_groups > 0);
1070
1071   /* Only need num_groups instead of num_groups + 1
1072    * because the first group of the file (last in the
1073    * list) is always the comment group at the top,
1074    * which we skip
1075    */
1076   groups = (gchar **) g_new0 (gchar **, num_groups);
1077
1078   group_node = g_list_last (key_file->groups);
1079   
1080   g_assert (((GKeyFileGroup *) group_node->data)->name == NULL);
1081
1082   i = 0;
1083   for (group_node = group_node->prev;
1084        group_node != NULL;
1085        group_node = group_node->prev)
1086     {
1087       GKeyFileGroup *group;
1088
1089       group = (GKeyFileGroup *) group_node->data;
1090
1091       g_assert (group->name != NULL);
1092
1093       groups[i++] = g_strdup (group->name);
1094     }
1095   groups[i] = NULL;
1096
1097   if (length)
1098     *length = i;
1099
1100   return groups;
1101 }
1102
1103 /**
1104  * g_key_file_get_value:
1105  * @key_file: a #GKeyFile
1106  * @group_name: a group name
1107  * @key: a key
1108  * @error: return location for a #GError, or #NULL
1109  *
1110  * Returns the value associated with @key under @group_name.  
1111  * In the event the key cannot be found, %NULL is returned and 
1112  * @error is set to #G_KEY_FILE_ERROR_KEY_NOT_FOUND.  In the 
1113  * event that the @group_name cannot be found, %NULL is returned 
1114  * and @error is set to #G_KEY_FILE_ERROR_GROUP_NOT_FOUND.
1115  *
1116  * Return value: a string or %NULL if the specified key cannot be
1117  * found.
1118  *
1119  * Since: 2.6
1120  **/
1121 gchar *
1122 g_key_file_get_value (GKeyFile     *key_file,
1123                       const gchar  *group_name,
1124                       const gchar  *key,
1125                       GError      **error)
1126 {
1127   GKeyFileGroup *group;
1128   GKeyFileKeyValuePair *pair;
1129   gchar *value = NULL;
1130
1131   g_return_val_if_fail (key_file != NULL, NULL);
1132   g_return_val_if_fail (group_name != NULL, NULL);
1133   g_return_val_if_fail (key != NULL, NULL);
1134   
1135   group = g_key_file_lookup_group (key_file, group_name);
1136
1137   if (!group)
1138     {
1139       g_set_error (error, G_KEY_FILE_ERROR,
1140                    G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
1141                    _("Key file does not have group '%s'"),
1142                    group_name);
1143       return NULL;
1144     }
1145
1146   pair = g_key_file_lookup_key_value_pair (key_file, group, key);
1147
1148   if (pair)
1149     value = g_strdup (pair->value);
1150   else
1151     g_set_error (error, G_KEY_FILE_ERROR,
1152                  G_KEY_FILE_ERROR_KEY_NOT_FOUND,
1153                  _("Key file does not have key '%s'"), key);
1154
1155   return value;
1156 }
1157
1158 /**
1159  * g_key_file_set_value:
1160  * @key_file: a #GKeyFile
1161  * @group_name: a group name
1162  * @key: a key
1163  * @value: a string
1164  *
1165  * Associates a new value with @key under @group_name.
1166  * If @key cannot be found then it is created. If @group_name
1167  * cannot be found then it is created as well.
1168  *
1169  * Since: 2.6
1170  **/
1171 void
1172 g_key_file_set_value (GKeyFile    *key_file,
1173                       const gchar *group_name,
1174                       const gchar *key,
1175                       const gchar *value)
1176 {
1177   GKeyFileGroup *group;
1178   GKeyFileKeyValuePair *pair;
1179
1180   g_return_if_fail (key_file != NULL);
1181   g_return_if_fail (key != NULL);
1182   g_return_if_fail (value != NULL);
1183
1184   if (!g_key_file_has_key (key_file, group_name, key, NULL))
1185     g_key_file_add_key (key_file, group_name, key, value);
1186   else
1187     {
1188       group = g_key_file_lookup_group (key_file, group_name);
1189       pair = g_key_file_lookup_key_value_pair (key_file, group, key);
1190       g_free (pair->value);
1191       pair->value = g_strdup (value);
1192     }
1193 }
1194
1195 /**
1196  * g_key_file_get_string:
1197  * @key_file: a #GKeyFile
1198  * @group_name: a group name
1199  * @key: a key
1200  * @error: return location for a #GError, or #NULL
1201  *
1202  * Returns the value associated with @key under @group_name.  
1203  * In the event the key cannot be found, %NULL is returned and 
1204  * @error is set to #G_KEY_FILE_ERROR_KEY_NOT_FOUND.  In the 
1205  * event that the @group_name cannot be found, %NULL is returned 
1206  * and @error is set to #G_KEY_FILE_ERROR_GROUP_NOT_FOUND.
1207  *
1208  * Return value: a string or %NULL if the specified key cannot be
1209  * found.
1210  *
1211  * Since: 2.6
1212  **/
1213 gchar *
1214 g_key_file_get_string (GKeyFile     *key_file,
1215                        const gchar  *group_name,
1216                        const gchar  *key,
1217                        GError      **error)
1218 {
1219   gchar *value, *string_value;
1220   GError *key_file_error;
1221
1222   g_return_val_if_fail (key_file != NULL, NULL);
1223   g_return_val_if_fail (group_name != NULL, NULL);
1224   g_return_val_if_fail (key != NULL, NULL);
1225
1226   key_file_error = NULL;
1227
1228   value = g_key_file_get_value (key_file, group_name, key, &key_file_error);
1229
1230   if (key_file_error)
1231     {
1232       g_propagate_error (error, key_file_error);
1233       return NULL;
1234     }
1235
1236   if (!g_utf8_validate (value, -1, NULL))
1237     {
1238       g_set_error (error, G_KEY_FILE_ERROR,
1239                    G_KEY_FILE_ERROR_UNKNOWN_ENCODING,
1240                    _("Key file contains key '%s' with value '%s' "
1241                      "which is not UTF-8"), key, value);
1242       g_free (value);
1243       return NULL;
1244     }
1245
1246   string_value = g_key_file_parse_value_as_string (key_file, value, NULL,
1247                                                    &key_file_error);
1248   g_free (value);
1249
1250   if (key_file_error)
1251     {
1252       if (g_error_matches (key_file_error,
1253                            G_KEY_FILE_ERROR,
1254                            G_KEY_FILE_ERROR_INVALID_VALUE))
1255         {
1256           g_set_error (error, G_KEY_FILE_ERROR,
1257                        G_KEY_FILE_ERROR_INVALID_VALUE,
1258                        _("Key file contains key '%s' "
1259                          "which has value that cannot be interpreted."),
1260                        key);
1261           g_error_free (key_file_error);
1262         }
1263       else
1264         g_propagate_error (error, key_file_error);
1265     }
1266
1267   return string_value;
1268 }
1269
1270 /**
1271  * g_key_file_set_string:
1272  * @key_file: a #GKeyFile
1273  * @group_name: a group name
1274  * @key: a key
1275  * @string: a string
1276  *
1277  * Associates a new string value with @key under @group_name.
1278  * If @key cannot be found then it is created. If @group_name
1279  * cannot be found then it is created as well.
1280  *
1281  * Since: 2.6
1282  **/
1283 void
1284 g_key_file_set_string (GKeyFile    *key_file,
1285                        const gchar *group_name,
1286                        const gchar *key,
1287                        const gchar *string)
1288 {
1289   gchar *value;
1290
1291   g_return_if_fail (key_file != NULL);
1292   g_return_if_fail (group_name != NULL);
1293   g_return_if_fail (key != NULL);
1294   g_return_if_fail (string != NULL);
1295
1296   value = g_key_file_parse_string_as_value (key_file, string, FALSE);
1297   g_key_file_set_value (key_file, group_name, key, value);
1298   g_free (value);
1299 }
1300
1301 /**
1302  * g_key_file_get_string_list:
1303  * @key_file: a #GKeyFile
1304  * @group_name: a group name
1305  * @key: a key
1306  * @length: return location for the number of returned strings, or %NULL
1307  * @error: return location for a #GError, or %NULL
1308  *
1309  * Returns the values associated with @key under @group_name.
1310  * In the event the key cannot be found, %NULL is returned and
1311  * @error is set to #G_KEY_FILE_ERROR_KEY_NOT_FOUND.  In the
1312  * event that the @group_name cannot be found, %NULL is returned
1313  * and @error is set to #G_KEY_FILE_ERROR_GROUP_NOT_FOUND.
1314  *
1315  * Return value: a %NULL-terminated string array or %NULL if the specified 
1316  *   key cannot be found. The array should be freed with g_strfreev().
1317  *
1318  * Since: 2.6
1319  **/
1320 gchar **
1321 g_key_file_get_string_list (GKeyFile     *key_file,
1322                             const gchar  *group_name,
1323                             const gchar  *key,
1324                             gsize        *length,
1325                             GError      **error)
1326 {
1327   GError *key_file_error = NULL;
1328   gchar *value, *string_value, **values;
1329   gint i, len;
1330   GSList *p, *pieces = NULL;
1331
1332   g_return_val_if_fail (key_file != NULL, NULL);
1333   g_return_val_if_fail (group_name != NULL, NULL);
1334   g_return_val_if_fail (key != NULL, NULL);
1335
1336   value = g_key_file_get_value (key_file, group_name, key, &key_file_error);
1337
1338   if (key_file_error)
1339     {
1340       g_propagate_error (error, key_file_error);
1341       return NULL;
1342     }
1343
1344   if (!g_utf8_validate (value, -1, NULL))
1345     {
1346       g_set_error (error, G_KEY_FILE_ERROR,
1347                    G_KEY_FILE_ERROR_UNKNOWN_ENCODING,
1348                    _("Key file contains key '%s' with value '%s' "
1349                      "which is not UTF-8"), key, value);
1350       g_free (value);
1351       return NULL;
1352     }
1353
1354   string_value = g_key_file_parse_value_as_string (key_file, value, &pieces, &key_file_error);
1355   g_free (value);
1356   g_free (string_value);
1357
1358   if (key_file_error)
1359     {
1360       if (g_error_matches (key_file_error,
1361                            G_KEY_FILE_ERROR,
1362                            G_KEY_FILE_ERROR_INVALID_VALUE))
1363         {
1364           g_set_error (error, G_KEY_FILE_ERROR,
1365                        G_KEY_FILE_ERROR_INVALID_VALUE,
1366                        _("Key file contains key '%s' "
1367                          "which has value that cannot be interpreted."),
1368                        key);
1369           g_error_free (key_file_error);
1370         }
1371       else
1372         g_propagate_error (error, key_file_error);
1373     }
1374
1375   len = g_slist_length (pieces);
1376   values = g_new0 (gchar *, len + 1); 
1377   for (p = pieces, i = 0; p; p = p->next)
1378     values[i++] = p->data;
1379   values[len] = NULL;
1380
1381   g_slist_free (pieces);
1382
1383   if (length)
1384     *length = len;
1385
1386   return values;
1387 }
1388
1389 /**
1390  * g_key_file_set_string_list:
1391  * @key_file: a #GKeyFile
1392  * @group_name: a group name
1393  * @key: a key
1394  * @list: an array of locale string values
1395  * @length: number of locale string values in @list
1396  *
1397  * Associates a list of string values for @key under @group_name.
1398  * If the @key cannot be found then it is created.
1399  *
1400  * Since: 2.6
1401  **/
1402 void
1403 g_key_file_set_string_list (GKeyFile            *key_file,
1404                             const gchar         *group_name,
1405                             const gchar         *key,
1406                             const gchar * const  list[],
1407                             gsize                length)
1408 {
1409   GString *value_list;
1410   gsize i;
1411
1412   g_return_if_fail (key_file != NULL);
1413   g_return_if_fail (group_name != NULL);
1414   g_return_if_fail (key != NULL);
1415   g_return_if_fail (list != NULL);
1416
1417   value_list = g_string_sized_new (length * 128);
1418   for (i = 0; list[i] != NULL && i < length; i++)
1419     {
1420       gchar *value;
1421
1422       value = g_key_file_parse_string_as_value (key_file, list[i], TRUE);
1423       g_string_append (value_list, value);
1424       g_string_append_c (value_list, key_file->list_separator);
1425
1426       g_free (value);
1427     }
1428
1429   g_key_file_set_value (key_file, group_name, key, value_list->str);
1430   g_string_free (value_list, TRUE);
1431 }
1432
1433 /**
1434  * g_key_file_set_locale_string:
1435  * @key_file: a #GKeyFile
1436  * @group_name: a group name
1437  * @key: a key
1438  * @locale: a locale
1439  * @string: a string
1440  *
1441  * Associates a string value for @key and @locale under
1442  * @group_name.  If the translation for @key cannot be found 
1443  * then it is created.
1444  *
1445  * Since: 2.6
1446  **/
1447 void
1448 g_key_file_set_locale_string (GKeyFile     *key_file,
1449                               const gchar  *group_name,
1450                               const gchar  *key,
1451                               const gchar  *locale,
1452                               const gchar  *string)
1453 {
1454   gchar *full_key, *value;
1455
1456   g_return_if_fail (key_file != NULL);
1457   g_return_if_fail (group_name != NULL);
1458   g_return_if_fail (key != NULL);
1459   g_return_if_fail (locale != NULL);
1460   g_return_if_fail (string != NULL);
1461
1462   value = g_key_file_parse_string_as_value (key_file, string, FALSE);
1463   full_key = g_strdup_printf ("%s[%s]", key, locale);
1464   g_key_file_set_value (key_file, group_name, full_key, value);
1465   g_free (full_key);
1466   g_free (value);
1467 }
1468
1469 extern GSList *_g_compute_locale_variants (const gchar *locale);
1470
1471 /**
1472  * g_key_file_get_locale_string:
1473  * @key_file: a #GKeyFile
1474  * @group_name: a group name
1475  * @key: a key
1476  * @locale: a locale or %NULL
1477  * @error: return location for a #GError, or %NULL
1478  *
1479  * Returns the value associated with @key under @group_name
1480  * translated in the given @locale if available.  If @locale is
1481  * %NULL then the current locale is assumed. If @key cannot be
1482  * found then %NULL is returned and @error is set to
1483  * #G_KEY_FILE_ERROR_KEY_NOT_FOUND. If the value associated
1484  * with @key cannot be interpreted or no suitable translation can
1485  * be found then the untranslated value is returned and @error is
1486  * set to #G_KEY_FILE_ERROR_INVALID_VALUE and
1487  * #G_KEY_FILE_ERROR_KEY_NOT_FOUND, respectively. In the
1488  * event that the @group_name cannot be found, %NULL is returned
1489  * and @error is set to #G_KEY_FILE_ERROR_GROUP_NOT_FOUND.
1490  *
1491  * Return value: a string or %NULL if the specified key cannot be
1492  *               found.
1493  * Since: 2.6
1494  **/
1495 gchar *
1496 g_key_file_get_locale_string (GKeyFile     *key_file,
1497                               const gchar  *group_name,
1498                               const gchar  *key,
1499                               const gchar  *locale,
1500                               GError      **error)
1501 {
1502   gchar *candidate_key, *translated_value;
1503   GError *key_file_error;
1504   gchar **languages;
1505   gboolean free_languages = FALSE;
1506   gint i;
1507
1508   g_return_val_if_fail (key_file != NULL, NULL);
1509   g_return_val_if_fail (group_name != NULL, NULL);
1510   g_return_val_if_fail (key != NULL, NULL);
1511
1512   candidate_key = NULL;
1513   translated_value = NULL;
1514   key_file_error = NULL;
1515
1516   if (!g_key_file_has_group (key_file, group_name))
1517     {
1518       g_set_error (error, G_KEY_FILE_ERROR,
1519                    G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
1520                    _("Key file does not have group '%s'"),
1521                    group_name);
1522       return NULL;
1523     }
1524
1525   if (locale)
1526     {
1527       GSList *l, *list;
1528
1529       list = _g_compute_locale_variants (locale);
1530
1531       languages = g_new0 (gchar *, g_slist_length (list) + 1);
1532       for (l = list, i = 0; l; l = l->next, i++)
1533         languages[i] = l->data;
1534       languages[i] = NULL;
1535
1536       g_slist_free (list);
1537       free_languages = TRUE;
1538     }
1539   else
1540     {
1541       languages = (gchar **) g_get_language_names ();
1542       free_languages = FALSE;
1543     }
1544   
1545   for (i = 0; languages[i]; i++)
1546     {
1547       candidate_key = g_strdup_printf ("%s[%s]", key, languages[i]);
1548       
1549       translated_value = g_key_file_get_string (key_file,
1550                                                 group_name,
1551                                                 candidate_key, NULL);
1552       g_free (candidate_key);
1553
1554       if (translated_value)
1555         break;
1556    }
1557
1558   if (translated_value && !g_utf8_validate (translated_value, -1, NULL))
1559     {
1560       g_set_error (error, G_KEY_FILE_ERROR,
1561                    G_KEY_FILE_ERROR_INVALID_VALUE,
1562                    _("Key file contains key '%s' "
1563                      "which has value that cannot be interpreted."),
1564                    candidate_key);
1565       g_free (translated_value);
1566       translated_value = NULL;
1567   }
1568
1569   /* Fallback to untranslated key
1570    */
1571   if (!translated_value)
1572     {
1573       translated_value = g_key_file_get_string (key_file, group_name, key,
1574                                                 &key_file_error);
1575       
1576       if (!translated_value)
1577         g_propagate_error (error, key_file_error);
1578       else
1579         g_set_error (error, G_KEY_FILE_ERROR,
1580                      G_KEY_FILE_ERROR_KEY_NOT_FOUND,
1581                      _("Key file contains no translated value "
1582                        "for key '%s' with locale '%s'."),
1583                      key, locale);
1584     }
1585
1586   if (free_languages)
1587     g_strfreev (languages);
1588
1589   return translated_value;
1590 }
1591
1592 /** 
1593  * g_key_file_get_locale_string_list: 
1594  * @key_file: a #GKeyFile
1595  * @group_name: a group name
1596  * @key: a key
1597  * @locale: a locale
1598  * @length: return location for the number of returned strings or %NULL
1599  * @error: return location for a #GError or %NULL
1600  *
1601  * Returns the values associated with @key under @group_name
1602  * translated in the given @locale if available.  If @locale is
1603  * %NULL then the current locale is assumed. If @key cannot be
1604  * found then %NULL is returned and @error is set to
1605  * #G_KEY_FILE_ERROR_KEY_NOT_FOUND. If the values associated
1606  * with @key cannot be interpreted or no suitable translations
1607  * can be found then the untranslated values are returned and
1608  * @error is set to #G_KEY_FILE_ERROR_INVALID_VALUE and
1609  * #G_KEY_FILE_ERROR_KEY_NOT_FOUND, respectively. In the
1610  * event that the @group_name cannot be found, %NULL is returned
1611  * and @error is set to #G_KEY_FILE_ERROR_GROUP_NOT_FOUND.
1612  * The returned array is %NULL-terminated, so @length may optionally be %NULL.
1613  *
1614  * Return value: a newly allocated %NULL-terminated string array
1615  *   or %NULL if the key isn't found. The string array should be freed
1616  *   with g_strfreev().
1617  *
1618  * Since: 2.6
1619  **/
1620 gchar **
1621 g_key_file_get_locale_string_list (GKeyFile     *key_file,
1622                                    const gchar  *group_name,
1623                                    const gchar  *key,
1624                                    const gchar  *locale,
1625                                    gsize        *length,
1626                                    GError      **error)
1627 {
1628   GError *key_file_error;
1629   gchar **values, *value;
1630
1631   g_return_val_if_fail (key_file != NULL, NULL);
1632   g_return_val_if_fail (group_name != NULL, NULL);
1633   g_return_val_if_fail (key != NULL, NULL);
1634
1635   key_file_error = NULL;
1636
1637   value = g_key_file_get_locale_string (key_file, group_name, 
1638                                         key, locale,
1639                                         &key_file_error);
1640   
1641   if (key_file_error)
1642     g_propagate_error (error, key_file_error);
1643   
1644   if (!value)
1645     return NULL;
1646
1647   if (value[strlen (value) - 1] == ';')
1648     value[strlen (value) - 1] = '\0';
1649
1650   values = g_strsplit (value, ";", 0);
1651
1652   g_free (value);
1653
1654   if (length)
1655     *length = g_strv_length (values);
1656
1657   return values;
1658 }
1659
1660 /**
1661  * g_key_file_set_locale_string_list:
1662  * @key_file: a #GKeyFile
1663  * @group_name: a group name
1664  * @key: a key
1665  * @locale: a locale
1666  * @list: a %NULL-terminated array of locale string values
1667  * @length: the length of @list
1668  *
1669  * Associates a list of string values for @key and @locale under
1670  * @group_name.  If the translation for @key cannot be found then
1671  * it is created.
1672  *
1673  * Since: 2.6
1674  **/
1675 void
1676 g_key_file_set_locale_string_list (GKeyFile            *key_file,
1677                                    const gchar         *group_name,
1678                                    const gchar         *key,
1679                                    const gchar         *locale,
1680                                    const gchar * const  list[],
1681                                    gsize                length)
1682 {
1683   GString *value_list;
1684   gchar *full_key;
1685   gsize i;
1686
1687   g_return_if_fail (key_file != NULL);
1688   g_return_if_fail (group_name != NULL);
1689   g_return_if_fail (key != NULL);
1690   g_return_if_fail (locale != NULL);
1691   g_return_if_fail (length != 0);
1692
1693   value_list = g_string_sized_new (length * 128);
1694   for (i = 0; list[i] != NULL && i < length; i++)
1695     {
1696       gchar *value;
1697       
1698       value = g_key_file_parse_string_as_value (key_file, list[i], TRUE);
1699       
1700       g_string_append (value_list, value);
1701       g_string_append_c (value_list, ';');
1702
1703       g_free (value);
1704     }
1705
1706   full_key = g_strdup_printf ("%s[%s]", key, locale);
1707   g_key_file_set_value (key_file, group_name, full_key, value_list->str);
1708   g_free (full_key);
1709   g_string_free (value_list, TRUE);
1710 }
1711
1712 /**
1713  * g_key_file_get_boolean:
1714  * @key_file: a #GKeyFile
1715  * @group_name: a group name
1716  * @key: a key
1717  * @error: return location for a #GError
1718  *
1719  * Returns the value associated with @key under @group_name as a
1720  * boolean.  If @key cannot be found then the return value is
1721  * undefined and @error is set to
1722  * #G_KEY_FILE_ERROR_KEY_NOT_FOUND. Likewise, if the value
1723  * associated with @key cannot be interpreted as a boolean then
1724  * the return value is also undefined and @error is set to
1725  * #G_KEY_FILE_ERROR_INVALID_VALUE.
1726  *
1727  * Return value: the value associated with the key as a boolean
1728  * Since: 2.6
1729  **/
1730 gboolean
1731 g_key_file_get_boolean (GKeyFile     *key_file,
1732                         const gchar  *group_name,
1733                         const gchar  *key,
1734                         GError      **error)
1735 {
1736   GError *key_file_error = NULL;
1737   gchar *value;
1738   gboolean bool_value;
1739
1740   g_return_val_if_fail (key_file != NULL, FALSE);
1741   g_return_val_if_fail (group_name != NULL, FALSE);
1742   g_return_val_if_fail (key != NULL, FALSE);
1743
1744   value = g_key_file_get_value (key_file, group_name, key, &key_file_error);
1745
1746   if (!value)
1747     {
1748       g_propagate_error (error, key_file_error);
1749       return FALSE;
1750     }
1751
1752   bool_value = g_key_file_parse_value_as_boolean (key_file, value,
1753                                                   &key_file_error);
1754   g_free (value);
1755
1756   if (key_file_error)
1757     {
1758       if (g_error_matches (key_file_error,
1759                            G_KEY_FILE_ERROR,
1760                            G_KEY_FILE_ERROR_INVALID_VALUE))
1761         {
1762           g_set_error (error, G_KEY_FILE_ERROR,
1763                        G_KEY_FILE_ERROR_INVALID_VALUE,
1764                        _("Key file contains key '%s' "
1765                          "which has value that cannot be interpreted."),
1766                        key);
1767           g_error_free (key_file_error);
1768         }
1769       else
1770         g_propagate_error (error, key_file_error);
1771     }
1772
1773   return bool_value;
1774 }
1775
1776 /**
1777  * g_key_file_set_boolean:
1778  * @key_file: a #GKeyFile
1779  * @group_name: a group name
1780  * @key: a key
1781  * @value: %TRUE or %FALSE
1782  *
1783  * Associates a new boolean value with @key under @group_name.
1784  * If @key cannot be found then it is created.
1785  *
1786  * Since: 2.6
1787  **/
1788 void
1789 g_key_file_set_boolean (GKeyFile    *key_file,
1790                         const gchar *group_name,
1791                         const gchar *key,
1792                         gboolean     value)
1793 {
1794   gchar *result;
1795
1796   g_return_if_fail (key_file != NULL);
1797   g_return_if_fail (group_name != NULL);
1798   g_return_if_fail (key != NULL);
1799
1800   result = g_key_file_parse_boolean_as_value (key_file, value);
1801   g_key_file_set_value (key_file, group_name, key, result);
1802   g_free (result);
1803 }
1804
1805 /**
1806  * g_key_file_get_boolean_list:
1807  * @key_file: a #GKeyFile
1808  * @group_name: a group name
1809  * @key: a key
1810  * @length: the number of booleans returned
1811  * @error: return location for a #GError
1812  *
1813  * Returns the values associated with @key under @group_name as
1814  * booleans.  If @key cannot be found then the return value is
1815  * undefined and @error is set to
1816  * #G_KEY_FILE_ERROR_KEY_NOT_FOUND. Likewise, if the values
1817  * associated with @key cannot be interpreted as booleans then
1818  * the return value is also undefined and @error is set to
1819  * #G_KEY_FILE_ERROR_INVALID_VALUE.
1820  *
1821  * Return value: the values associated with the key as a boolean
1822  * 
1823  * Since: 2.6
1824  **/
1825 gboolean *
1826 g_key_file_get_boolean_list (GKeyFile     *key_file,
1827                              const gchar  *group_name,
1828                              const gchar  *key,
1829                              gsize        *length,
1830                              GError      **error)
1831 {
1832   GError *key_file_error;
1833   gchar **values;
1834   gboolean *bool_values;
1835   gsize i, num_bools;
1836
1837   g_return_val_if_fail (key_file != NULL, NULL);
1838   g_return_val_if_fail (group_name != NULL, NULL);
1839   g_return_val_if_fail (key != NULL, NULL);
1840
1841   key_file_error = NULL;
1842
1843   values = g_key_file_get_string_list (key_file, group_name, key,
1844                                        &num_bools, &key_file_error);
1845
1846   if (key_file_error)
1847     g_propagate_error (error, key_file_error);
1848
1849   if (!values)
1850     return NULL;
1851
1852   bool_values = g_new0 (gboolean, num_bools);
1853
1854   for (i = 0; i < num_bools; i++)
1855     {
1856       bool_values[i] = g_key_file_parse_value_as_boolean (key_file,
1857                                                           values[i],
1858                                                           &key_file_error);
1859
1860       if (key_file_error)
1861         {
1862           g_propagate_error (error, key_file_error);
1863           g_strfreev (values);
1864           g_free (bool_values);
1865
1866           return NULL;
1867         }
1868     }
1869   g_strfreev (values);
1870
1871   if (length)
1872     *length = num_bools;
1873
1874   return bool_values;
1875 }
1876
1877 /**
1878  * g_key_file_set_boolean_list:
1879  * @key_file: a #GKeyFile
1880  * @group_name: a group name
1881  * @key: a key
1882  * @list: an array of boolean values
1883  * @length: length of @list
1884  *
1885  * Associates a list of boolean values with @key under
1886  * @group_name.  If @key cannot be found then it is created.
1887  *
1888  * Since: 2.6
1889  **/
1890 void
1891 g_key_file_set_boolean_list (GKeyFile    *key_file,
1892                              const gchar *group_name,
1893                              const gchar *key,
1894                              gboolean     list[],
1895                              gsize        length)
1896 {
1897   GString *value_list;
1898   gsize i;
1899
1900   g_return_if_fail (key_file != NULL);
1901   g_return_if_fail (group_name != NULL);
1902   g_return_if_fail (key != NULL);
1903   g_return_if_fail (list != NULL);
1904
1905   value_list = g_string_sized_new (length * 8);
1906   for (i = 0; i < length; i++)
1907     {
1908       gchar *value;
1909
1910       value = g_key_file_parse_boolean_as_value (key_file, list[i]);
1911
1912       g_string_append (value_list, value);
1913       g_string_append_c (value_list, key_file->list_separator);
1914
1915       g_free (value);
1916     }
1917
1918   g_key_file_set_value (key_file, group_name, key, value_list->str);
1919   g_string_free (value_list, TRUE);
1920 }
1921
1922 /**
1923  * g_key_file_get_integer:
1924  * @key_file: a #GKeyFile
1925  * @group_name: a group name
1926  * @key: a key
1927  * @error: return location for a #GError
1928  *
1929  * Returns the value associated with @key under @group_name as an
1930  * integer. If @key cannot be found then the return value is
1931  * undefined and @error is set to
1932  * #G_KEY_FILE_ERROR_KEY_NOT_FOUND. Likewise, if the value
1933  * associated with @key cannot be interpreted as an integer then
1934  * the return value is also undefined and @error is set to
1935  * #G_KEY_FILE_ERROR_INVALID_VALUE.
1936  *
1937  * Return value: the value associated with the key as an integer.
1938  *
1939  * Since: 2.6
1940  **/
1941 gint
1942 g_key_file_get_integer (GKeyFile     *key_file,
1943                         const gchar  *group_name,
1944                         const gchar  *key,
1945                         GError      **error)
1946 {
1947   GError *key_file_error;
1948   gchar *value;
1949   gint int_value;
1950
1951   g_return_val_if_fail (key_file != NULL, -1);
1952   g_return_val_if_fail (group_name != NULL, -1);
1953   g_return_val_if_fail (key != NULL, -1);
1954
1955   key_file_error = NULL;
1956
1957   value = g_key_file_get_value (key_file, group_name, key, &key_file_error);
1958
1959   if (key_file_error)
1960     {
1961       g_propagate_error (error, key_file_error);
1962       return 0;
1963     }
1964
1965   int_value = g_key_file_parse_value_as_integer (key_file, value,
1966                                                  &key_file_error);
1967   g_free (value);
1968
1969   if (key_file_error)
1970     {
1971       if (g_error_matches (key_file_error,
1972                            G_KEY_FILE_ERROR,
1973                            G_KEY_FILE_ERROR_INVALID_VALUE))
1974         {
1975           g_set_error (error, G_KEY_FILE_ERROR,
1976                        G_KEY_FILE_ERROR_INVALID_VALUE,
1977                        _("Key file contains key '%s' in group '%s' "
1978                          "which has value that cannot be interpreted."), key, 
1979                        group_name);
1980           g_error_free (key_file_error);
1981         }
1982       else
1983         g_propagate_error (error, key_file_error);
1984     }
1985
1986   return int_value;
1987 }
1988
1989 /**
1990  * g_key_file_set_integer:
1991  * @key_file: a #GKeyFile
1992  * @group_name: a group name
1993  * @key: a key
1994  * @value: an integer value
1995  *
1996  * Associates a new integer value with @key under @group_name.
1997  * If @key cannot be found then it is created.
1998  *
1999  * Since: 2.6
2000  **/
2001 void
2002 g_key_file_set_integer (GKeyFile    *key_file,
2003                         const gchar *group_name,
2004                         const gchar *key,
2005                         gint         value)
2006 {
2007   gchar *result;
2008
2009   g_return_if_fail (key_file != NULL);
2010   g_return_if_fail (group_name != NULL);
2011   g_return_if_fail (key != NULL);
2012
2013   result = g_key_file_parse_integer_as_value (key_file, value);
2014   g_key_file_set_value (key_file, group_name, key, result);
2015   g_free (result);
2016 }
2017
2018 /**
2019  * g_key_file_get_integer_list:
2020  * @key_file: a #GKeyFile
2021  * @group_name: a group name
2022  * @key: a key
2023  * @length: the number of integers returned
2024  * @error: return location for a #GError
2025  *
2026  * Returns the values associated with @key under @group_name as
2027  * integers.  If @key cannot be found then the return value is
2028  * undefined and @error is set to
2029  * #G_KEY_FILE_ERROR_KEY_NOT_FOUND. Likewise, if the values
2030  * associated with @key cannot be interpreted as integers then
2031  * the return value is also undefined and @error is set to
2032  * #G_KEY_FILE_ERROR_INVALID_VALUE.
2033  *
2034  * Return value: the values associated with the key as a integer
2035  *
2036  * Since: 2.6
2037  **/
2038 gint *
2039 g_key_file_get_integer_list (GKeyFile     *key_file,
2040                              const gchar  *group_name,
2041                              const gchar  *key,
2042                              gsize        *length,
2043                              GError      **error)
2044 {
2045   GError *key_file_error = NULL;
2046   gchar **values;
2047   gint *int_values;
2048   gsize i, num_ints;
2049
2050   g_return_val_if_fail (key_file != NULL, NULL);
2051   g_return_val_if_fail (group_name != NULL, NULL);
2052   g_return_val_if_fail (key != NULL, NULL);
2053
2054   values = g_key_file_get_string_list (key_file, group_name, key,
2055                                        &num_ints, &key_file_error);
2056
2057   if (key_file_error)
2058     g_propagate_error (error, key_file_error);
2059
2060   if (!values)
2061     return NULL;
2062
2063   int_values = g_new0 (gint, num_ints);
2064
2065   for (i = 0; i < num_ints; i++)
2066     {
2067       int_values[i] = g_key_file_parse_value_as_integer (key_file,
2068                                                          values[i],
2069                                                          &key_file_error);
2070
2071       if (key_file_error)
2072         {
2073           g_propagate_error (error, key_file_error);
2074           g_strfreev (values);
2075           g_free (int_values);
2076
2077           return NULL;
2078         }
2079     }
2080   g_strfreev (values);
2081
2082   if (length)
2083     *length = num_ints;
2084
2085   return int_values;
2086 }
2087
2088 /**
2089  * g_key_file_set_integer_list:
2090  * @key_file: a #GKeyFile
2091  * @group_name: a group name
2092  * @key: a key
2093  * @list: an array of integer values
2094  * @length: number of integer values in @list
2095  *
2096  * Associates a list of integer values with @key under
2097  * @group_name.  If @key cannot be found then it is created.
2098  *
2099  * Since: 2.6
2100  **/
2101 void
2102 g_key_file_set_integer_list (GKeyFile     *key_file,
2103                              const gchar  *group_name,
2104                              const gchar  *key,
2105                              gint          list[],
2106                              gsize         length)
2107 {
2108   GString *values;
2109   gsize i;
2110
2111   g_return_if_fail (key_file != NULL);
2112   g_return_if_fail (group_name != NULL);
2113   g_return_if_fail (key != NULL);
2114   g_return_if_fail (list != NULL);
2115
2116   values = g_string_sized_new (length * 16);
2117   for (i = 0; i < length; i++)
2118     {
2119       gchar *value;
2120
2121       value = g_key_file_parse_integer_as_value (key_file, list[i]);
2122
2123       g_string_append (values, value);
2124       g_string_append_c (values, ';');
2125
2126       g_free (value);
2127     }
2128
2129   g_key_file_set_value (key_file, group_name, key, values->str);
2130   g_string_free (values, TRUE);
2131 }
2132
2133 static void
2134 g_key_file_set_key_comment (GKeyFile             *key_file,
2135                             const gchar          *group_name,
2136                             const gchar          *key,
2137                             const gchar          *comment,
2138                             GError              **error)
2139 {
2140   GKeyFileGroup *group;
2141   GKeyFileKeyValuePair *pair;
2142   GList *key_node, *comment_node, *tmp;
2143   
2144   group = g_key_file_lookup_group (key_file, group_name);
2145   if (!group)
2146     {
2147       g_set_error (error, G_KEY_FILE_ERROR,
2148                    G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
2149                    _("Key file does not have group '%s'"),
2150                    group_name);
2151
2152       return;
2153     }
2154
2155   /* First find the key the comments are supposed to be
2156    * associated with
2157    */
2158   key_node = g_key_file_lookup_key_value_pair_node (key_file, group, key);
2159
2160   if (key_node == NULL)
2161     {
2162       g_set_error (error, G_KEY_FILE_ERROR,
2163                    G_KEY_FILE_ERROR_KEY_NOT_FOUND,
2164                    _("Key file does not have key '%s' in group '%s'"),
2165                    key, group_name);
2166       return;
2167     }
2168
2169   /* Then find all the comments already associated with the
2170    * key and free them
2171    */
2172   tmp = key_node->next;
2173   while (tmp != NULL)
2174     {
2175       GKeyFileKeyValuePair *pair;
2176
2177       pair = (GKeyFileKeyValuePair *) tmp->data;
2178
2179       if (pair->key != NULL)
2180         break;
2181
2182       comment_node = tmp;
2183       tmp = tmp->next;
2184       g_key_file_remove_key_value_pair_node (key_file, group,
2185                                              comment_node); 
2186     }
2187
2188   if (comment == NULL)
2189     return;
2190
2191   /* Now we can add our new comment
2192    */
2193   pair = g_new0 (GKeyFileKeyValuePair, 1);
2194   
2195   pair->key = NULL;
2196   pair->value = g_key_file_parse_comment_as_value (key_file, comment);
2197   
2198   key_node = g_list_insert (key_node, pair, 1);
2199 }
2200
2201 static void
2202 g_key_file_set_group_comment (GKeyFile             *key_file,
2203                               const gchar          *group_name,
2204                               const gchar          *comment,
2205                               GError              **error)
2206 {
2207   GKeyFileGroup *group;
2208   
2209   group = g_key_file_lookup_group (key_file, group_name);
2210   if (!group)
2211     {
2212       g_set_error (error, G_KEY_FILE_ERROR,
2213                    G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
2214                    _("Key file does not have group '%s'"),
2215                    group_name);
2216
2217       return;
2218     }
2219
2220   /* First remove any existing comment
2221    */
2222   if (group->comment)
2223     {
2224       g_key_file_key_value_pair_free (group->comment);
2225       group->comment = NULL;
2226     }
2227
2228   if (comment == NULL)
2229     return;
2230
2231   /* Now we can add our new comment
2232    */
2233   group->comment = g_new0 (GKeyFileKeyValuePair, 1);
2234   
2235   group->comment->key = NULL;
2236   group->comment->value = g_key_file_parse_comment_as_value (key_file, comment);
2237 }
2238
2239 static void
2240 g_key_file_set_top_comment (GKeyFile             *key_file,
2241                             const gchar          *comment,
2242                             GError              **error)
2243 {
2244   GList *group_node;
2245   GKeyFileGroup *group;
2246   GKeyFileKeyValuePair *pair;
2247
2248   /* The last group in the list should be the top (comments only)
2249    * group in the file
2250    */
2251   g_assert (key_file->groups != NULL);
2252   group_node = g_list_last (key_file->groups);
2253   group = (GKeyFileGroup *) group_node->data;
2254   g_assert (group->name == NULL);
2255
2256   /* Note all keys must be comments at the top of
2257    * the file, so we can just free it all.
2258    */
2259   if (group->key_value_pairs != NULL)
2260     {
2261       g_list_foreach (group->key_value_pairs, 
2262                       (GFunc) g_key_file_key_value_pair_free, 
2263                       NULL);
2264       g_list_free (group->key_value_pairs);
2265       group->key_value_pairs = NULL;
2266     }
2267
2268   if (comment == NULL)
2269      return;
2270
2271   pair = g_new0 (GKeyFileKeyValuePair, 1);
2272   
2273   pair->key = NULL;
2274   pair->value = g_key_file_parse_comment_as_value (key_file, comment);
2275   
2276   group->key_value_pairs =
2277     g_list_prepend (group->key_value_pairs, pair);
2278 }
2279
2280 /**
2281  * g_key_file_set_comment:
2282  * @key_file: a #GKeyFile
2283  * @group_name: a group name
2284  * @key: a key
2285  * @comment: a comment
2286  * @error: return location for a #GError
2287  *
2288  * Places a comment above @key from @group_name.
2289  * @group_name. If @key is %NULL then @comment will
2290  * be written above @group_name.  If both @key
2291  * and @group_name are NULL, then @comment will
2292  * be written above the first group in the file.
2293  *
2294  * Since: 2.6
2295  **/
2296 void
2297 g_key_file_set_comment (GKeyFile             *key_file,
2298                         const gchar          *group_name,
2299                         const gchar          *key,
2300                         const gchar          *comment,
2301                         GError              **error)
2302 {
2303   g_return_if_fail (key_file != NULL);
2304
2305   if (group_name != NULL && key != NULL)
2306     g_key_file_set_key_comment (key_file, group_name, key, comment, error);
2307   else if (group_name != NULL)
2308     g_key_file_set_group_comment (key_file, group_name, comment, error);
2309   else
2310     g_key_file_set_top_comment (key_file, comment, error);
2311
2312   if (comment != NULL)
2313     key_file->approximate_size += strlen (comment);
2314 }
2315
2316 static gchar *
2317 g_key_file_get_key_comment (GKeyFile             *key_file,
2318                             const gchar          *group_name,
2319                             const gchar          *key,
2320                             GError              **error)
2321 {
2322   GKeyFileGroup *group;
2323   GList *key_node, *tmp;
2324   GString *string;
2325   gchar *comment;
2326
2327   group = g_key_file_lookup_group (key_file, group_name);
2328   if (!group)
2329     {
2330       g_set_error (error, G_KEY_FILE_ERROR,
2331                    G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
2332                    _("Key file does not have group '%s'"),
2333                    group_name);
2334
2335       return NULL;
2336     }
2337
2338   /* First find the key the comments are supposed to be
2339    * associated with
2340    */
2341   key_node = g_key_file_lookup_key_value_pair_node (key_file, group, key);
2342
2343   if (key_node == NULL)
2344     {
2345       g_set_error (error, G_KEY_FILE_ERROR,
2346                    G_KEY_FILE_ERROR_KEY_NOT_FOUND,
2347                    _("Key file does not have key '%s' in group '%s'"),
2348                    key, group_name);
2349       return NULL;
2350     }
2351
2352   string = NULL;
2353
2354   /* Then find all the comments already associated with the
2355    * key and concatentate them.
2356    */
2357   tmp = key_node->next;
2358   while (tmp != NULL)
2359     {
2360       GKeyFileKeyValuePair *pair;
2361
2362       pair = (GKeyFileKeyValuePair *) tmp->data;
2363
2364       if (pair->key != NULL)
2365         break;
2366       
2367       if (string == NULL)
2368         string = g_string_sized_new (512);
2369
2370       comment = g_key_file_parse_value_as_comment (key_file, pair->value);
2371       g_string_append (string, comment);
2372       g_free (comment);
2373
2374       tmp = tmp->next;
2375     }
2376
2377   if (string != NULL)
2378     {
2379       comment = string->str;
2380       g_string_free (string, FALSE);
2381     }
2382   else
2383     comment = NULL;
2384
2385   return comment;
2386 }
2387
2388 static gchar *
2389 g_key_file_get_group_comment (GKeyFile             *key_file,
2390                               const gchar          *group_name,
2391                               GError              **error)
2392 {
2393   GKeyFileGroup *group;
2394   
2395   group = g_key_file_lookup_group (key_file, group_name);
2396   if (!group)
2397     {
2398       g_set_error (error, G_KEY_FILE_ERROR,
2399                    G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
2400                    _("Key file does not have group '%s'"),
2401                    group_name);
2402
2403       return NULL;
2404     }
2405
2406   if (group->comment)
2407     return g_strdup (group->comment->value);
2408
2409   return NULL;
2410 }
2411
2412 static gchar *
2413 g_key_file_get_top_comment (GKeyFile             *key_file,
2414                             GError              **error)
2415 {
2416   GList *group_node, *tmp;
2417   GKeyFileGroup *group;
2418   GString *string;
2419   gchar *comment;
2420
2421   /* The last group in the list should be the top (comments only)
2422    * group in the file
2423    */
2424   g_assert (key_file->groups != NULL);
2425   group_node = g_list_last (key_file->groups);
2426   group = (GKeyFileGroup *) group_node->data;
2427   g_assert (group->name == NULL);
2428
2429   string = NULL;
2430
2431   /* Then find all the comments already associated with the
2432    * key and concatentate them.
2433    */
2434   tmp = group->key_value_pairs;
2435   while (tmp != NULL)
2436     {
2437       GKeyFileKeyValuePair *pair;
2438
2439       pair = (GKeyFileKeyValuePair *) tmp->data;
2440
2441       if (pair->key != NULL)
2442         break;
2443       
2444       if (string == NULL)
2445         string = g_string_sized_new (512);
2446
2447       comment = g_key_file_parse_value_as_comment (key_file, pair->value);
2448       g_string_append (string, comment);
2449       g_free (comment);
2450
2451       tmp = tmp->next;
2452     }
2453
2454   if (string != NULL)
2455     {
2456       comment = string->str;
2457       g_string_free (string, FALSE);
2458     }
2459   else
2460     comment = NULL;
2461
2462   return comment;
2463 }
2464
2465 /**
2466  * g_key_file_get_comment:
2467  * @key_file: a #GKeyFile
2468  * @group_name: a group name
2469  * @key: a key
2470  * @error: return location for a #GError
2471  *
2472  * Retreives a comment above @key from @group_name.
2473  * @group_name. If @key is %NULL then @comment will
2474  * be read from above @group_name.  If both @key
2475  * and @group_name are NULL, then @comment will
2476  * be read from above the first group in the file.
2477  *
2478  * Since: 2.6
2479  * Returns: a comment that should be freed with g_free()
2480  **/
2481 gchar * 
2482 g_key_file_get_comment (GKeyFile             *key_file,
2483                         const gchar          *group_name,
2484                         const gchar          *key,
2485                         GError              **error)
2486 {
2487   g_return_val_if_fail (key_file != NULL, NULL);
2488
2489   if (group_name != NULL && key != NULL)
2490     return g_key_file_get_key_comment (key_file, group_name, key, error);
2491   else if (group_name != NULL)
2492     return g_key_file_get_group_comment (key_file, group_name, error);
2493   else
2494     return g_key_file_get_top_comment (key_file, error);
2495 }
2496
2497 /**
2498  * g_key_file_remove_comment:
2499  * @key_file: a #GKeyFile
2500  * @group_name: a group name
2501  * @key: a key
2502  * @error: return location for a #GError
2503  *
2504  * Removes a comment above @key from @group_name.
2505  * @group_name. If @key is %NULL then @comment will
2506  * be written above @group_name.  If both @key
2507  * and @group_name are NULL, then @comment will
2508  * be written above the first group in the file.
2509  *
2510  * Since: 2.6
2511  **/
2512
2513 void
2514 g_key_file_remove_comment (GKeyFile             *key_file,
2515                            const gchar          *group_name,
2516                            const gchar          *key,
2517                            GError              **error)
2518 {
2519   g_return_if_fail (key_file != NULL);
2520
2521   if (group_name != NULL && key != NULL)
2522     g_key_file_set_key_comment (key_file, group_name, key, NULL, error);
2523   else if (group_name != NULL)
2524     g_key_file_set_group_comment (key_file, group_name, NULL, error);
2525   else
2526     g_key_file_set_top_comment (key_file, NULL, error);
2527 }
2528
2529 /**
2530  * g_key_file_has_group:
2531  * @key_file: a #GKeyFile
2532  * @group_name: a group name
2533  *
2534  * Looks whether the key file has the group @group_name.
2535  *
2536  * Return value: %TRUE if @group_name is a part of @key_file, %FALSE
2537  * otherwise.
2538  * Since: 2.6
2539  **/
2540 gboolean
2541 g_key_file_has_group (GKeyFile    *key_file,
2542                       const gchar *group_name)
2543 {
2544   GList *tmp;
2545   GKeyFileGroup *group;
2546
2547   g_return_val_if_fail (key_file != NULL, FALSE);
2548   g_return_val_if_fail (group_name != NULL, FALSE);
2549
2550   for (tmp = key_file->groups; tmp != NULL; tmp = tmp->next)
2551     {
2552       group = (GKeyFileGroup *) tmp->data;
2553       if (group && group->name && (strcmp (group->name, group_name) == 0))
2554         return TRUE;
2555     }
2556
2557   return FALSE;
2558 }
2559
2560 /**
2561  * g_key_file_has_key:
2562  * @key_file: a #GKeyFile
2563  * @group_name: a group name
2564  * @key: a key name
2565  * @error: return location for a #GError
2566  *
2567  * Looks whether the key file has the key @key in the group
2568  * @group_name.
2569  *
2570  * Return value: %TRUE if @key is a part of @group_name, %FALSE
2571  * otherwise.
2572  *
2573  * Since: 2.6
2574  **/
2575 gboolean
2576 g_key_file_has_key (GKeyFile     *key_file,
2577                     const gchar  *group_name,
2578                     const gchar  *key,
2579                     GError      **error)
2580 {
2581   GKeyFileKeyValuePair *pair;
2582   GKeyFileGroup *group;
2583
2584   g_return_val_if_fail (key_file != NULL, FALSE);
2585   g_return_val_if_fail (key != NULL, FALSE);
2586   g_return_val_if_fail (group_name != NULL, FALSE);
2587
2588   group = g_key_file_lookup_group (key_file, group_name);
2589
2590   if (!group)
2591     {
2592       g_set_error (error, G_KEY_FILE_ERROR,
2593                    G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
2594                    _("Key file does not have group '%s'"),
2595                    group_name);
2596
2597       return FALSE;
2598     }
2599
2600   pair = g_key_file_lookup_key_value_pair (key_file, group, key);
2601
2602   return pair != NULL;
2603 }
2604
2605 static void
2606 g_key_file_add_group (GKeyFile    *key_file,
2607                       const gchar *group_name)
2608 {
2609   GKeyFileGroup *group;
2610
2611   g_return_if_fail (key_file != NULL);
2612   g_return_if_fail (group_name != NULL);
2613   g_return_if_fail (g_key_file_lookup_group (key_file, group_name) == NULL);
2614
2615   group = g_new0 (GKeyFileGroup, 1);
2616   group->name = g_strdup (group_name);
2617   group->lookup_map = g_hash_table_new (g_str_hash, g_str_equal);
2618   key_file->groups = g_list_prepend (key_file->groups, group);
2619   key_file->approximate_size += strlen (group_name) + 3;
2620   key_file->current_group = group;
2621
2622   if (key_file->start_group_name == NULL)
2623     key_file->start_group_name = g_strdup (group_name);
2624 }
2625
2626 static void
2627 g_key_file_key_value_pair_free (GKeyFileKeyValuePair *pair)
2628 {
2629   if (pair != NULL)
2630     {
2631       g_free (pair->key);
2632       g_free (pair->value);
2633       g_free (pair);
2634     }
2635 }
2636
2637 /* Be careful not to call this function on a node with data in the
2638  * lookup map without removing it from the lookup map, first.
2639  *
2640  * Some current cases where this warning is not a concern are
2641  * when:
2642  *   - the node being removed is a comment node
2643  *   - the entire lookup map is getting destroyed soon after
2644  *     anyway.
2645  */ 
2646 static void
2647 g_key_file_remove_key_value_pair_node (GKeyFile      *key_file,
2648                                        GKeyFileGroup *group,
2649                                        GList         *pair_node)
2650 {
2651
2652   GKeyFileKeyValuePair *pair;
2653
2654   pair = (GKeyFileKeyValuePair *) pair_node->data;
2655
2656   group->key_value_pairs = g_list_remove_link (group->key_value_pairs, pair_node);
2657
2658   if (pair->key != NULL)
2659     key_file->approximate_size -= strlen (pair->key) + 1;
2660
2661   g_assert (pair->value != NULL);
2662   key_file->approximate_size -= strlen (pair->value);
2663
2664   g_key_file_key_value_pair_free (pair);
2665
2666   g_list_free_1 (pair_node);
2667 }
2668
2669 static void
2670 g_key_file_remove_group_node (GKeyFile *key_file,
2671                               GList    *group_node)
2672 {
2673   GKeyFileGroup *group;
2674   GList *tmp;
2675
2676   group = (GKeyFileGroup *) group_node->data;
2677
2678   /* If the current group gets deleted make the current group the first
2679    * group.
2680    */
2681   if (key_file->current_group == group)
2682     {
2683       /* groups should always contain at least the top comment group,
2684        * unless g_key_file_clear has been called
2685        */
2686       if (key_file->groups)
2687         key_file->current_group = (GKeyFileGroup *) key_file->groups->data;
2688       else
2689         key_file->current_group = NULL;
2690     }
2691
2692   key_file->groups = g_list_remove_link (key_file->groups, group_node);
2693
2694   if (group->name != NULL)
2695     key_file->approximate_size -= strlen (group->name) + 3;
2696
2697   tmp = group->key_value_pairs;
2698   while (tmp != NULL)
2699     {
2700       GList *pair_node;
2701
2702       pair_node = tmp;
2703       tmp = tmp->next;
2704       g_key_file_remove_key_value_pair_node (key_file, group, pair_node);
2705     }
2706
2707   g_assert (group->key_value_pairs == NULL);
2708
2709   if (group->lookup_map)
2710     {
2711       g_hash_table_destroy (group->lookup_map);
2712       group->lookup_map = NULL;
2713     }
2714
2715   g_free ((gchar *) group->name);
2716   g_free (group);
2717   g_list_free_1 (group_node);
2718 }
2719
2720 /**
2721  * g_key_file_remove_group:
2722  * @key_file: a #GKeyFile
2723  * @group_name: a group name
2724  * @error: return location for a #GError or %NULL
2725  *
2726  * Removes the specified group, @group_name, 
2727  * from the key file. 
2728  *
2729  * Since: 2.6
2730  **/
2731 void
2732 g_key_file_remove_group (GKeyFile     *key_file,
2733                          const gchar  *group_name,
2734                          GError      **error)
2735 {
2736   GList *group_node;
2737
2738   g_return_if_fail (key_file != NULL);
2739   g_return_if_fail (group_name != NULL);
2740
2741   group_node = g_key_file_lookup_group_node (key_file, group_name);
2742
2743   if (!group_node)
2744     g_set_error (error, G_KEY_FILE_ERROR,
2745                  G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
2746                  _("Key file does not have group '%s'"),
2747                  group_name);
2748
2749   g_key_file_remove_group_node (key_file, group_node);
2750 }
2751
2752 static void
2753 g_key_file_add_key (GKeyFile    *key_file,
2754                     const gchar *group_name,
2755                     const gchar *key,
2756                     const gchar *value)
2757 {
2758   GKeyFileGroup *group;
2759   GKeyFileKeyValuePair *pair;
2760
2761   group = g_key_file_lookup_group (key_file, group_name);
2762
2763   if (!group)
2764     {
2765       g_key_file_add_group (key_file, group_name);
2766       group = (GKeyFileGroup *) key_file->groups->data;
2767     }
2768
2769   pair = g_new0 (GKeyFileKeyValuePair, 1);
2770
2771   pair->key = g_strdup (key);
2772   pair->value = g_strdup (value);
2773
2774   g_hash_table_replace (group->lookup_map, pair->key, pair);
2775   group->key_value_pairs = g_list_prepend (group->key_value_pairs, pair);
2776   key_file->approximate_size += strlen (key) + strlen (value) + 2;
2777 }
2778
2779 /**
2780  * g_key_file_remove_key:
2781  * @key_file: a #GKeyFile
2782  * @group_name: a group name
2783  * @key: a key name to remove
2784  * @error: return location for a #GError or %NULL
2785  *
2786  * Removes @key in @group_name from the key file. 
2787  *
2788  * Since: 2.6
2789  **/
2790 void
2791 g_key_file_remove_key (GKeyFile     *key_file,
2792                        const gchar  *group_name,
2793                        const gchar  *key,
2794                        GError      **error)
2795 {
2796   GKeyFileGroup *group;
2797   GKeyFileKeyValuePair *pair;
2798
2799   g_return_if_fail (key_file != NULL);
2800   g_return_if_fail (group_name != NULL);
2801   g_return_if_fail (key != NULL);
2802
2803   pair = NULL;
2804
2805   if (group_name == NULL)
2806     group = key_file->current_group;
2807   else
2808     group = g_key_file_lookup_group (key_file, group_name);
2809
2810   if (!group)
2811     {
2812       g_set_error (error, G_KEY_FILE_ERROR,
2813                    G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
2814                    _("Key file does not have group '%s'"),
2815                    group_name);
2816       return;
2817     }
2818
2819   group->key_value_pairs = g_list_remove (group->key_value_pairs, key_file);
2820   pair = g_key_file_lookup_key_value_pair (key_file, group, key);
2821
2822   if (!pair)
2823     {
2824       g_set_error (error, G_KEY_FILE_ERROR,
2825                    G_KEY_FILE_ERROR_KEY_NOT_FOUND,
2826                    _("Key file does not have key '%s' in group '%s'"), key, group_name);
2827       return;
2828     }
2829
2830   g_hash_table_remove (group->lookup_map, pair->key);
2831
2832   key_file->approximate_size -= strlen (pair->key) + strlen (pair->value) + 2;
2833   g_key_file_key_value_pair_free (pair);
2834 }
2835
2836 static GList *
2837 g_key_file_lookup_group_node (GKeyFile    *key_file,
2838                               const gchar *group_name)
2839 {
2840   GKeyFileGroup *group;
2841   GList *tmp;
2842
2843   group = NULL;
2844   for (tmp = key_file->groups; tmp != NULL; tmp = tmp->next)
2845     {
2846       group = (GKeyFileGroup *) tmp->data;
2847
2848       if (group && group->name && strcmp (group->name, group_name) == 0)
2849         break;
2850
2851       group = NULL;
2852     }
2853
2854   return tmp;
2855 }
2856
2857 static GKeyFileGroup *
2858 g_key_file_lookup_group (GKeyFile    *key_file,
2859                          const gchar *group_name)
2860 {
2861   GList *group_node;
2862
2863   group_node = g_key_file_lookup_group_node (key_file, group_name);
2864
2865   if (group_node != NULL)
2866     return (GKeyFileGroup *) group_node->data; 
2867
2868   return NULL;
2869 }
2870
2871 static GList *
2872 g_key_file_lookup_key_value_pair_node (GKeyFile       *key_file,
2873                                        GKeyFileGroup  *group,
2874                                        const gchar    *key)
2875 {
2876   GList *key_node;
2877
2878   for (key_node = group->key_value_pairs;
2879        key_node != NULL;
2880        key_node = key_node->next)
2881     {
2882       GKeyFileKeyValuePair *pair;
2883
2884       pair = (GKeyFileKeyValuePair *) key_node->data; 
2885
2886       if (pair->key && strcmp (pair->key, key) == 0)
2887         break;
2888     }
2889
2890   return key_node;
2891 }
2892
2893 static GKeyFileKeyValuePair *
2894 g_key_file_lookup_key_value_pair (GKeyFile      *key_file,
2895                                   GKeyFileGroup *group,
2896                                   const gchar   *key)
2897 {
2898   return (GKeyFileKeyValuePair *) g_hash_table_lookup (group->lookup_map, key);
2899 }
2900
2901 /* Lines starting with # or consisting entirely of whitespace are merely
2902  * recorded, not parsed. This function assumes all leading whitespace
2903  * has been stripped.
2904  */
2905 static gboolean
2906 g_key_file_line_is_comment (const gchar *line)
2907 {
2908   return (*line == '#' || *line == '\0' || *line == '\n');
2909 }
2910
2911 /* A group in a key file is made up of a starting '[' followed by one
2912  * or more letters making up the group name followed by ']'.
2913  */
2914 static gboolean
2915 g_key_file_line_is_group (const gchar *line)
2916 {
2917   gchar *p;
2918
2919   p = (gchar *) line;
2920   if (*p != '[')
2921     return FALSE;
2922
2923   p = g_utf8_next_char (p);
2924
2925   if (!*p)
2926     return FALSE;
2927
2928   p = g_utf8_next_char (p);
2929
2930   /* Group name must be non-empty
2931    */
2932   if (*p == ']')
2933     return FALSE;
2934
2935   while (*p && *p != ']')
2936     p = g_utf8_next_char (p);
2937
2938   if (!*p)
2939     return FALSE;
2940
2941   return TRUE;
2942 }
2943
2944 static gboolean
2945 g_key_file_line_is_key_value_pair (const gchar *line)
2946 {
2947   gchar *p;
2948
2949   p = (gchar *) g_utf8_strchr (line, -1, '=');
2950
2951   if (!p)
2952     return FALSE;
2953
2954   /* Key must be non-empty
2955    */
2956   if (*p == line[0])
2957     return FALSE;
2958
2959   return TRUE;
2960 }
2961
2962 static gchar *
2963 g_key_file_parse_value_as_string (GKeyFile     *key_file,
2964                                   const gchar  *value,
2965                                   GSList      **pieces,
2966                                   GError      **error)
2967 {
2968   GError *parse_error = NULL;
2969   gchar *string_value, *p, *q0, *q;
2970
2971   string_value = g_new0 (gchar, strlen (value) + 1);
2972
2973   p = (gchar *) value;
2974   q0 = q = string_value;
2975   while (*p)
2976     {
2977       if (*p == '\\')
2978         {
2979           p++;
2980
2981           switch (*p)
2982             {
2983             case 's':
2984               *q = ' ';
2985               break;
2986
2987             case 'n':
2988               *q = '\n';
2989               break;
2990
2991             case 't':
2992               *q = '\t';
2993               break;
2994
2995             case 'r':
2996               *q = '\r';
2997               break;
2998
2999             case '\\':
3000               *q = '\\';
3001               break;
3002
3003             default:
3004               if (pieces && *p == key_file->list_separator)
3005                 *q = key_file->list_separator;
3006               else
3007                 {
3008                   *q++ = '\\';
3009                   *q = *p;
3010                   
3011                   if (parse_error == NULL)
3012                     {
3013                       gchar sequence[3];
3014                       
3015                       sequence[0] = '\\';
3016                       sequence[1] = *p;
3017                       sequence[2] = '\0';
3018                       
3019                       g_set_error (error, G_KEY_FILE_ERROR,
3020                                    G_KEY_FILE_ERROR_INVALID_VALUE,
3021                                    _("Key file contains invalid escape "
3022                                      "sequence '%s'"), sequence);
3023                     }
3024                 }
3025               break;
3026             }
3027         }
3028       else
3029         {
3030           *q = *p;
3031           if (pieces && (*p == key_file->list_separator))
3032             {
3033               *pieces = g_slist_prepend (*pieces, g_strndup (q0, q - q0));
3034               q0 = q + 1; 
3035             }
3036         }
3037
3038       q++;
3039       p++;
3040     }
3041
3042   if (p[-1] == '\\' && error == NULL)
3043     g_set_error (error, G_KEY_FILE_ERROR,
3044                  G_KEY_FILE_ERROR_INVALID_VALUE,
3045                  _("Key file contains escape character at end of line"));
3046
3047   *q = '\0';
3048   if (pieces)
3049   {
3050     if (q0 < q)
3051       *pieces = g_slist_prepend (*pieces, g_strndup (q0, q - q0));
3052     *pieces = g_slist_reverse (*pieces);
3053   }
3054
3055   return string_value;
3056 }
3057
3058 static gchar *
3059 g_key_file_parse_string_as_value (GKeyFile    *key_file,
3060                                   const gchar *string,
3061                                   gboolean     escape_separator)
3062 {
3063   gchar *value, *p, *q;
3064   gsize length;
3065
3066   length = strlen (string) + 1;
3067
3068   /* Worst case would be that every character needs to be escaped.
3069    * In other words every character turns to two characters
3070    */
3071   value = g_new0 (gchar, 2 * length);
3072
3073   p = (gchar *) string;
3074   q = value;
3075   while (p < (string + length - 1))
3076     {
3077       gchar escaped_character[3] = { '\\', 0, 0 };
3078
3079       switch (*p)
3080         {
3081         case ' ':
3082           escaped_character[1] = 's';
3083           strcpy (q, escaped_character);
3084           q += 2;
3085           break;
3086         case '\n':
3087           escaped_character[1] = 'n';
3088           strcpy (q, escaped_character);
3089           q += 2;
3090           break;
3091         case '\t':
3092           escaped_character[1] = 't';
3093           strcpy (q, escaped_character);
3094           q += 2;
3095           break;
3096         case '\r':
3097           escaped_character[1] = 'r';
3098           strcpy (q, escaped_character);
3099           q += 2;
3100           break;
3101         case '\\':
3102           escaped_character[1] = '\\';
3103           strcpy (q, escaped_character);
3104           q += 2;
3105           break;
3106         default:
3107           if (escape_separator && *p == key_file->list_separator)
3108             {
3109               escaped_character[1] = key_file->list_separator;
3110               strcpy (q, escaped_character);
3111               q += 2;
3112             }
3113           else 
3114             {
3115               *q = *p;
3116               q++;
3117             }
3118           break;
3119         }
3120       p++;
3121     }
3122   *q = '\0';
3123
3124   return value;
3125 }
3126
3127 static gint
3128 g_key_file_parse_value_as_integer (GKeyFile     *key_file,
3129                                    const gchar  *value,
3130                                    GError      **error)
3131 {
3132   gchar *end_of_valid_int;
3133   gint int_value = 0;
3134
3135   int_value = strtol (value, &end_of_valid_int, 0);
3136
3137   if (*end_of_valid_int != '\0')
3138     g_set_error (error, G_KEY_FILE_ERROR,
3139                  G_KEY_FILE_ERROR_INVALID_VALUE,
3140                  _("Value '%s' cannot be interpreted as a number."), value);
3141
3142   return int_value;
3143 }
3144
3145 static gchar *
3146 g_key_file_parse_integer_as_value (GKeyFile *key_file,
3147                                    gint      value)
3148
3149 {
3150   return g_strdup_printf ("%d", value);
3151 }
3152
3153 static gboolean
3154 g_key_file_parse_value_as_boolean (GKeyFile     *key_file,
3155                                    const gchar  *value,
3156                                    GError      **error)
3157 {
3158   if (value)
3159     {
3160       if (strcmp (value, "true") == 0 || strcmp (value, "1") == 0)
3161         return TRUE;
3162       else if (strcmp (value, "false") == 0 || strcmp (value, "0") == 0)
3163         return FALSE;
3164     }
3165
3166   g_set_error (error, G_KEY_FILE_ERROR,
3167                G_KEY_FILE_ERROR_INVALID_VALUE,
3168                _("Value '%s' cannot be interpreted as a boolean."), value);
3169
3170   return FALSE;
3171 }
3172
3173 static gchar *
3174 g_key_file_parse_boolean_as_value (GKeyFile *key_file,
3175                                    gboolean  value)
3176 {
3177   if (value)
3178     return g_strdup ("true");
3179   else
3180     return g_strdup ("false");
3181 }
3182
3183 static gchar *
3184 g_key_file_parse_value_as_comment (GKeyFile    *key_file,
3185                                    const gchar *value)
3186 {
3187   GString *string;
3188   gchar **lines, *comment;
3189   gsize i;
3190
3191   string = g_string_sized_new (512);
3192
3193   lines = g_strsplit (value, "\n", 0);
3194
3195   for (i = 0; lines[i] != NULL; i++)
3196     {
3197         if (lines[i][0] != '#')
3198            g_string_append_printf (string, "%s\n", lines[i]);
3199         else 
3200            g_string_append_printf (string, "%s\n", lines[i] + 1);
3201     }
3202   g_strfreev (lines);
3203
3204   comment = string->str;
3205
3206   g_string_free (string, FALSE);
3207
3208   return comment;
3209 }
3210
3211 static gchar *
3212 g_key_file_parse_comment_as_value (GKeyFile      *key_file,
3213                                    const gchar   *comment)
3214 {
3215   GString *string;
3216   gchar **lines, *value;
3217   gsize i;
3218
3219   string = g_string_sized_new (512);
3220
3221   lines = g_strsplit (comment, "\n", 0);
3222
3223   for (i = 0; lines[i] != NULL; i++)
3224     g_string_append_printf (string, "#%s%s", lines[i], 
3225                             lines[i + 1] == NULL? "" : "\n");
3226   g_strfreev (lines);
3227
3228   value = string->str;
3229
3230   g_string_free (string, FALSE);
3231
3232   return value;
3233 }
3234
3235