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