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