d77a1ae1678baa835f5701e9422f1c5d87125e2d
[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   gssize 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 = 0;
1023   for (tmp = group->key_value_pairs; tmp; tmp = tmp->next)
1024     {
1025       GKeyFileKeyValuePair *pair;
1026
1027       pair = (GKeyFileKeyValuePair *) tmp->data;
1028
1029       if (pair->key)
1030         num_keys++;
1031     }
1032   
1033   keys = g_new0 (gchar *, num_keys + 1);
1034
1035   i = num_keys - 1;
1036   for (tmp = group->key_value_pairs; tmp; tmp = tmp->next)
1037     {
1038       GKeyFileKeyValuePair *pair;
1039
1040       pair = (GKeyFileKeyValuePair *) tmp->data;
1041
1042       if (pair->key)
1043         {
1044           keys[i] = g_strdup (pair->key);
1045           i--;
1046         }
1047     }
1048
1049   keys[num_keys] = NULL;
1050
1051   if (length)
1052     *length = num_keys;
1053
1054   return keys;
1055 }
1056
1057 /**
1058  * g_key_file_get_start_group:
1059  * @key_file: a #GKeyFile
1060  *
1061  * Returns the name of the start group of the file. 
1062  *
1063  * Return value: The start group of the key file.
1064  *
1065  * Since: 2.6
1066  **/
1067 gchar *
1068 g_key_file_get_start_group (GKeyFile *key_file)
1069 {
1070   g_return_val_if_fail (key_file != NULL, NULL);
1071
1072   if (key_file->start_group)
1073     return g_strdup (key_file->start_group->name);
1074
1075   return NULL;
1076 }
1077
1078 /**
1079  * g_key_file_get_groups:
1080  * @key_file: a #GKeyFile
1081  * @length: return location for the number of returned groups, or %NULL
1082  *
1083  * Returns all groups in the key file loaded with @key_file.  The
1084  * array of returned groups will be %NULL-terminated, so @length may
1085  * optionally be %NULL.
1086  *
1087  * Return value: a newly-allocated %NULL-terminated array of strings. 
1088  *   Use g_strfreev() to free it.
1089  * Since: 2.6
1090  **/
1091 gchar **
1092 g_key_file_get_groups (GKeyFile *key_file,
1093                        gsize    *length)
1094 {
1095   GList *group_node;
1096   gchar **groups;
1097   gsize i, num_groups;
1098
1099   g_return_val_if_fail (key_file != NULL, NULL);
1100
1101   num_groups = g_list_length (key_file->groups);
1102
1103   g_assert (num_groups > 0);
1104
1105   /* Only need num_groups instead of num_groups + 1
1106    * because the first group of the file (last in the
1107    * list) is always the comment group at the top,
1108    * which we skip
1109    */
1110   groups = (gchar **) g_new0 (gchar **, num_groups);
1111
1112   group_node = g_list_last (key_file->groups);
1113   
1114   g_assert (((GKeyFileGroup *) group_node->data)->name == NULL);
1115
1116   i = 0;
1117   for (group_node = group_node->prev;
1118        group_node != NULL;
1119        group_node = group_node->prev)
1120     {
1121       GKeyFileGroup *group;
1122
1123       group = (GKeyFileGroup *) group_node->data;
1124
1125       g_assert (group->name != NULL);
1126
1127       groups[i++] = g_strdup (group->name);
1128     }
1129   groups[i] = NULL;
1130
1131   if (length)
1132     *length = i;
1133
1134   return groups;
1135 }
1136
1137 /**
1138  * g_key_file_get_value:
1139  * @key_file: a #GKeyFile
1140  * @group_name: a group name
1141  * @key: a key
1142  * @error: return location for a #GError, or %NULL
1143  *
1144  * Returns the value associated with @key under @group_name.  
1145  *
1146  * In the event the key cannot be found, %NULL is returned and 
1147  * @error is set to #G_KEY_FILE_ERROR_KEY_NOT_FOUND.  In the 
1148  * event that the @group_name cannot be found, %NULL is returned 
1149  * and @error is set to #G_KEY_FILE_ERROR_GROUP_NOT_FOUND.
1150  *
1151  * Return value: a newly allocated string or %NULL if the specified 
1152  *  key cannot be found.
1153  *
1154  * Since: 2.6
1155  **/
1156 gchar *
1157 g_key_file_get_value (GKeyFile     *key_file,
1158                       const gchar  *group_name,
1159                       const gchar  *key,
1160                       GError      **error)
1161 {
1162   GKeyFileGroup *group;
1163   GKeyFileKeyValuePair *pair;
1164   gchar *value = NULL;
1165
1166   g_return_val_if_fail (key_file != NULL, NULL);
1167   g_return_val_if_fail (group_name != NULL, NULL);
1168   g_return_val_if_fail (key != NULL, NULL);
1169   
1170   group = g_key_file_lookup_group (key_file, group_name);
1171
1172   if (!group)
1173     {
1174       g_set_error (error, G_KEY_FILE_ERROR,
1175                    G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
1176                    _("Key file does not have group '%s'"),
1177                    group_name ? group_name : "(null)");
1178       return NULL;
1179     }
1180
1181   pair = g_key_file_lookup_key_value_pair (key_file, group, key);
1182
1183   if (pair)
1184     value = g_strdup (pair->value);
1185   else
1186     g_set_error (error, G_KEY_FILE_ERROR,
1187                  G_KEY_FILE_ERROR_KEY_NOT_FOUND,
1188                  _("Key file does not have key '%s'"), key);
1189
1190   return value;
1191 }
1192
1193 /**
1194  * g_key_file_set_value:
1195  * @key_file: a #GKeyFile
1196  * @group_name: a group name
1197  * @key: a key
1198  * @value: a string
1199  *
1200  * Associates a new value with @key under @group_name.  If @key
1201  * cannot be found then it is created. If @group_name cannot be
1202  * found then it is created.
1203  *
1204  * Since: 2.6
1205  **/
1206 void
1207 g_key_file_set_value (GKeyFile    *key_file,
1208                       const gchar *group_name,
1209                       const gchar *key,
1210                       const gchar *value)
1211 {
1212   GKeyFileGroup *group;
1213   GKeyFileKeyValuePair *pair;
1214
1215   g_return_if_fail (key_file != NULL);
1216   g_return_if_fail (group_name != NULL);
1217   g_return_if_fail (key != NULL);
1218   g_return_if_fail (value != NULL);
1219
1220   group = g_key_file_lookup_group (key_file, group_name);
1221
1222   if (!group)
1223     {
1224       g_key_file_add_group (key_file, group_name);
1225       group = (GKeyFileGroup *) key_file->groups->data;
1226
1227       g_key_file_add_key (key_file, group, key, value);
1228     }
1229   else
1230     {
1231       pair = g_key_file_lookup_key_value_pair (key_file, group, key);
1232
1233       if (!pair)
1234         g_key_file_add_key (key_file, group, key, value);
1235       else
1236         {
1237           g_free (pair->value);
1238           pair->value = g_strdup (value);
1239         }
1240     }
1241 }
1242
1243 /**
1244  * g_key_file_get_string:
1245  * @key_file: a #GKeyFile
1246  * @group_name: a group name
1247  * @key: a key
1248  * @error: return location for a #GError, or %NULL
1249  *
1250  * Returns the value associated with @key under @group_name.  
1251  *
1252  * In the event the key cannot be found, %NULL is returned and 
1253  * @error is set to #G_KEY_FILE_ERROR_KEY_NOT_FOUND.  In the 
1254  * event that the @group_name cannot be found, %NULL is returned 
1255  * and @error is set to #G_KEY_FILE_ERROR_GROUP_NOT_FOUND.
1256  *
1257  * Return value: a newly allocated string or %NULL if the specified 
1258  *   key cannot be found.
1259  *
1260  * Since: 2.6
1261  **/
1262 gchar *
1263 g_key_file_get_string (GKeyFile     *key_file,
1264                        const gchar  *group_name,
1265                        const gchar  *key,
1266                        GError      **error)
1267 {
1268   gchar *value, *string_value;
1269   GError *key_file_error;
1270
1271   g_return_val_if_fail (key_file != NULL, NULL);
1272   g_return_val_if_fail (group_name != NULL, NULL);
1273   g_return_val_if_fail (key != NULL, NULL);
1274
1275   key_file_error = NULL;
1276
1277   value = g_key_file_get_value (key_file, group_name, key, &key_file_error);
1278
1279   if (key_file_error)
1280     {
1281       g_propagate_error (error, key_file_error);
1282       return NULL;
1283     }
1284
1285   if (!g_utf8_validate (value, -1, NULL))
1286     {
1287       g_set_error (error, G_KEY_FILE_ERROR,
1288                    G_KEY_FILE_ERROR_UNKNOWN_ENCODING,
1289                    _("Key file contains key '%s' with value '%s' "
1290                      "which is not UTF-8"), key, value);
1291       g_free (value);
1292       return NULL;
1293     }
1294
1295   string_value = g_key_file_parse_value_as_string (key_file, value, NULL,
1296                                                    &key_file_error);
1297   g_free (value);
1298
1299   if (key_file_error)
1300     {
1301       if (g_error_matches (key_file_error,
1302                            G_KEY_FILE_ERROR,
1303                            G_KEY_FILE_ERROR_INVALID_VALUE))
1304         {
1305           g_set_error (error, G_KEY_FILE_ERROR,
1306                        G_KEY_FILE_ERROR_INVALID_VALUE,
1307                        _("Key file contains key '%s' "
1308                          "which has value that cannot be interpreted."),
1309                        key);
1310           g_error_free (key_file_error);
1311         }
1312       else
1313         g_propagate_error (error, key_file_error);
1314     }
1315
1316   return string_value;
1317 }
1318
1319 /**
1320  * g_key_file_set_string:
1321  * @key_file: a #GKeyFile
1322  * @group_name: a group name
1323  * @key: a key
1324  * @string: a string
1325  *
1326  * Associates a new string value with @key under @group_name.  If
1327  * @key cannot be found then it is created.  If @group_name
1328  * cannot be found then it is created.
1329  *
1330  * Since: 2.6
1331  **/
1332 void
1333 g_key_file_set_string (GKeyFile    *key_file,
1334                        const gchar *group_name,
1335                        const gchar *key,
1336                        const gchar *string)
1337 {
1338   gchar *value;
1339
1340   g_return_if_fail (key_file != NULL);
1341   g_return_if_fail (group_name != NULL);
1342   g_return_if_fail (key != NULL);
1343   g_return_if_fail (string != NULL);
1344
1345   value = g_key_file_parse_string_as_value (key_file, string, FALSE);
1346   g_key_file_set_value (key_file, group_name, key, value);
1347   g_free (value);
1348 }
1349
1350 /**
1351  * g_key_file_get_string_list:
1352  * @key_file: a #GKeyFile
1353  * @group_name: a group name
1354  * @key: a key
1355  * @length: return location for the number of returned strings, or %NULL
1356  * @error: return location for a #GError, or %NULL
1357  *
1358  * Returns the values associated with @key under @group_name.
1359  *
1360  * In the event the key cannot be found, %NULL is returned and
1361  * @error is set to #G_KEY_FILE_ERROR_KEY_NOT_FOUND.  In the
1362  * event that the @group_name cannot be found, %NULL is returned
1363  * and @error is set to #G_KEY_FILE_ERROR_GROUP_NOT_FOUND.
1364  *
1365  * Return value: a %NULL-terminated string array or %NULL if the specified 
1366  *   key cannot be found. The array should be freed with g_strfreev().
1367  *
1368  * Since: 2.6
1369  **/
1370 gchar **
1371 g_key_file_get_string_list (GKeyFile     *key_file,
1372                             const gchar  *group_name,
1373                             const gchar  *key,
1374                             gsize        *length,
1375                             GError      **error)
1376 {
1377   GError *key_file_error = NULL;
1378   gchar *value, *string_value, **values;
1379   gint i, len;
1380   GSList *p, *pieces = NULL;
1381
1382   g_return_val_if_fail (key_file != NULL, NULL);
1383   g_return_val_if_fail (group_name != NULL, NULL);
1384   g_return_val_if_fail (key != NULL, NULL);
1385
1386   value = g_key_file_get_value (key_file, group_name, key, &key_file_error);
1387
1388   if (key_file_error)
1389     {
1390       g_propagate_error (error, key_file_error);
1391       return NULL;
1392     }
1393
1394   if (!g_utf8_validate (value, -1, NULL))
1395     {
1396       g_set_error (error, G_KEY_FILE_ERROR,
1397                    G_KEY_FILE_ERROR_UNKNOWN_ENCODING,
1398                    _("Key file contains key '%s' with value '%s' "
1399                      "which is not UTF-8"), key, value);
1400       g_free (value);
1401       return NULL;
1402     }
1403
1404   string_value = g_key_file_parse_value_as_string (key_file, value, &pieces, &key_file_error);
1405   g_free (value);
1406   g_free (string_value);
1407
1408   if (key_file_error)
1409     {
1410       if (g_error_matches (key_file_error,
1411                            G_KEY_FILE_ERROR,
1412                            G_KEY_FILE_ERROR_INVALID_VALUE))
1413         {
1414           g_set_error (error, G_KEY_FILE_ERROR,
1415                        G_KEY_FILE_ERROR_INVALID_VALUE,
1416                        _("Key file contains key '%s' "
1417                          "which has value that cannot be interpreted."),
1418                        key);
1419           g_error_free (key_file_error);
1420         }
1421       else
1422         g_propagate_error (error, key_file_error);
1423     }
1424
1425   len = g_slist_length (pieces);
1426   values = g_new0 (gchar *, len + 1); 
1427   for (p = pieces, i = 0; p; p = p->next)
1428     values[i++] = p->data;
1429   values[len] = NULL;
1430
1431   g_slist_free (pieces);
1432
1433   if (length)
1434     *length = len;
1435
1436   return values;
1437 }
1438
1439 /**
1440  * g_key_file_set_string_list:
1441  * @key_file: a #GKeyFile
1442  * @group_name: a group name
1443  * @key: a key
1444  * @list: an array of locale string values
1445  * @length: number of locale string values in @list
1446  *
1447  * Associates a list of string values for @key under @group_name.
1448  * If @key cannot be found then it is created.  If @group_name 
1449  * cannot be found then it is created.
1450  *
1451  * Since: 2.6
1452  **/
1453 void
1454 g_key_file_set_string_list (GKeyFile            *key_file,
1455                             const gchar         *group_name,
1456                             const gchar         *key,
1457                             const gchar * const  list[],
1458                             gsize                length)
1459 {
1460   GString *value_list;
1461   gsize i;
1462
1463   g_return_if_fail (key_file != NULL);
1464   g_return_if_fail (group_name != NULL);
1465   g_return_if_fail (key != NULL);
1466   g_return_if_fail (list != NULL);
1467
1468   value_list = g_string_sized_new (length * 128);
1469   for (i = 0; list[i] != NULL && i < length; i++)
1470     {
1471       gchar *value;
1472
1473       value = g_key_file_parse_string_as_value (key_file, list[i], TRUE);
1474       g_string_append (value_list, value);
1475       g_string_append_c (value_list, key_file->list_separator);
1476
1477       g_free (value);
1478     }
1479
1480   g_key_file_set_value (key_file, group_name, key, value_list->str);
1481   g_string_free (value_list, TRUE);
1482 }
1483
1484 /**
1485  * g_key_file_set_locale_string:
1486  * @key_file: a #GKeyFile
1487  * @group_name: a group name
1488  * @key: a key
1489  * @locale: a locale
1490  * @string: a string
1491  *
1492  * Associates a string value for @key and @locale under
1493  * @group_name.  If the translation for @key cannot be found 
1494  * then it is created.
1495  *
1496  * Since: 2.6
1497  **/
1498 void
1499 g_key_file_set_locale_string (GKeyFile     *key_file,
1500                               const gchar  *group_name,
1501                               const gchar  *key,
1502                               const gchar  *locale,
1503                               const gchar  *string)
1504 {
1505   gchar *full_key, *value;
1506
1507   g_return_if_fail (key_file != NULL);
1508   g_return_if_fail (group_name != NULL);
1509   g_return_if_fail (key != NULL);
1510   g_return_if_fail (locale != NULL);
1511   g_return_if_fail (string != NULL);
1512
1513   value = g_key_file_parse_string_as_value (key_file, string, FALSE);
1514   full_key = g_strdup_printf ("%s[%s]", key, locale);
1515   g_key_file_set_value (key_file, group_name, full_key, value);
1516   g_free (full_key);
1517   g_free (value);
1518 }
1519
1520 extern GSList *_g_compute_locale_variants (const gchar *locale);
1521
1522 /**
1523  * g_key_file_get_locale_string:
1524  * @key_file: a #GKeyFile
1525  * @group_name: a group name
1526  * @key: a key
1527  * @locale: a locale or %NULL
1528  * @error: return location for a #GError, or %NULL
1529  *
1530  * Returns the value associated with @key under @group_name
1531  * translated in the given @locale if available.  If @locale is
1532  * %NULL then the current locale is assumed. 
1533  *
1534  * If @key cannot be found then %NULL is returned and @error is set to
1535  * #G_KEY_FILE_ERROR_KEY_NOT_FOUND. If the value associated
1536  * with @key cannot be interpreted or no suitable translation can
1537  * be found then the untranslated value is returned.
1538  *
1539  * Return value: a newly allocated string or %NULL if the specified 
1540  *   key cannot be found.
1541  *
1542  * Since: 2.6
1543  **/
1544 gchar *
1545 g_key_file_get_locale_string (GKeyFile     *key_file,
1546                               const gchar  *group_name,
1547                               const gchar  *key,
1548                               const gchar  *locale,
1549                               GError      **error)
1550 {
1551   gchar *candidate_key, *translated_value;
1552   GError *key_file_error;
1553   gchar **languages;
1554   gboolean free_languages = FALSE;
1555   gint i;
1556
1557   g_return_val_if_fail (key_file != NULL, NULL);
1558   g_return_val_if_fail (group_name != NULL, NULL);
1559   g_return_val_if_fail (key != NULL, NULL);
1560
1561   candidate_key = NULL;
1562   translated_value = NULL;
1563   key_file_error = NULL;
1564
1565   if (locale)
1566     {
1567       GSList *l, *list;
1568
1569       list = _g_compute_locale_variants (locale);
1570
1571       languages = g_new0 (gchar *, g_slist_length (list) + 1);
1572       for (l = list, i = 0; l; l = l->next, i++)
1573         languages[i] = l->data;
1574       languages[i] = NULL;
1575
1576       g_slist_free (list);
1577       free_languages = TRUE;
1578     }
1579   else
1580     {
1581       languages = (gchar **) g_get_language_names ();
1582       free_languages = FALSE;
1583     }
1584   
1585   for (i = 0; languages[i]; i++)
1586     {
1587       candidate_key = g_strdup_printf ("%s[%s]", key, languages[i]);
1588       
1589       translated_value = g_key_file_get_string (key_file,
1590                                                 group_name,
1591                                                 candidate_key, NULL);
1592       g_free (candidate_key);
1593
1594       if (translated_value && g_utf8_validate (translated_value, -1, NULL))
1595         break;
1596
1597       g_free (translated_value);
1598       translated_value = NULL;
1599    }
1600
1601   /* Fallback to untranslated key
1602    */
1603   if (!translated_value)
1604     {
1605       translated_value = g_key_file_get_string (key_file, group_name, key,
1606                                                 &key_file_error);
1607       
1608       if (!translated_value)
1609         g_propagate_error (error, key_file_error);
1610     }
1611
1612   if (free_languages)
1613     g_strfreev (languages);
1614
1615   return translated_value;
1616 }
1617
1618 /** 
1619  * g_key_file_get_locale_string_list: 
1620  * @key_file: a #GKeyFile
1621  * @group_name: a group name
1622  * @key: a key
1623  * @locale: a locale
1624  * @length: return location for the number of returned strings or %NULL
1625  * @error: return location for a #GError or %NULL
1626  *
1627  * Returns the values associated with @key under @group_name
1628  * translated in the given @locale if available.  If @locale is
1629  * %NULL then the current locale is assumed.
1630
1631  * If @key cannot be found then %NULL is returned and @error is set to
1632  * #G_KEY_FILE_ERROR_KEY_NOT_FOUND. If the values associated
1633  * with @key cannot be interpreted or no suitable translations
1634  * can be found then the untranslated values are returned.
1635  * The returned array is %NULL-terminated, so @length may optionally be %NULL.
1636  *
1637  * Return value: a newly allocated %NULL-terminated string array
1638  *   or %NULL if the key isn't found. The string array should be freed
1639  *   with g_strfreev().
1640  *
1641  * Since: 2.6
1642  **/
1643 gchar **
1644 g_key_file_get_locale_string_list (GKeyFile     *key_file,
1645                                    const gchar  *group_name,
1646                                    const gchar  *key,
1647                                    const gchar  *locale,
1648                                    gsize        *length,
1649                                    GError      **error)
1650 {
1651   GError *key_file_error;
1652   gchar **values, *value;
1653
1654   g_return_val_if_fail (key_file != NULL, NULL);
1655   g_return_val_if_fail (group_name != NULL, NULL);
1656   g_return_val_if_fail (key != NULL, NULL);
1657
1658   key_file_error = NULL;
1659
1660   value = g_key_file_get_locale_string (key_file, group_name, 
1661                                         key, locale,
1662                                         &key_file_error);
1663   
1664   if (key_file_error)
1665     g_propagate_error (error, key_file_error);
1666   
1667   if (!value)
1668     return NULL;
1669
1670   if (value[strlen (value) - 1] == ';')
1671     value[strlen (value) - 1] = '\0';
1672
1673   values = g_strsplit (value, ";", 0);
1674
1675   g_free (value);
1676
1677   if (length)
1678     *length = g_strv_length (values);
1679
1680   return values;
1681 }
1682
1683 /**
1684  * g_key_file_set_locale_string_list:
1685  * @key_file: a #GKeyFile
1686  * @group_name: a group name
1687  * @key: a key
1688  * @locale: a locale
1689  * @list: a %NULL-terminated array of locale string values
1690  * @length: the length of @list
1691  *
1692  * Associates a list of string values for @key and @locale under
1693  * @group_name.  If the translation for @key cannot be found then
1694  * it is created. 
1695  *
1696  * Since: 2.6
1697  **/
1698 void
1699 g_key_file_set_locale_string_list (GKeyFile            *key_file,
1700                                    const gchar         *group_name,
1701                                    const gchar         *key,
1702                                    const gchar         *locale,
1703                                    const gchar * const  list[],
1704                                    gsize                length)
1705 {
1706   GString *value_list;
1707   gchar *full_key;
1708   gsize i;
1709
1710   g_return_if_fail (key_file != NULL);
1711   g_return_if_fail (group_name != NULL);
1712   g_return_if_fail (key != NULL);
1713   g_return_if_fail (locale != NULL);
1714   g_return_if_fail (length != 0);
1715
1716   value_list = g_string_sized_new (length * 128);
1717   for (i = 0; list[i] != NULL && i < length; i++)
1718     {
1719       gchar *value;
1720       
1721       value = g_key_file_parse_string_as_value (key_file, list[i], TRUE);
1722       
1723       g_string_append (value_list, value);
1724       g_string_append_c (value_list, ';');
1725
1726       g_free (value);
1727     }
1728
1729   full_key = g_strdup_printf ("%s[%s]", key, locale);
1730   g_key_file_set_value (key_file, group_name, full_key, value_list->str);
1731   g_free (full_key);
1732   g_string_free (value_list, TRUE);
1733 }
1734
1735 /**
1736  * g_key_file_get_boolean:
1737  * @key_file: a #GKeyFile
1738  * @group_name: a group name
1739  * @key: a key
1740  * @error: return location for a #GError
1741  *
1742  * Returns the value associated with @key under @group_name as a
1743  * boolean. 
1744  *
1745  * If @key cannot be found then the return value is undefined and
1746  * @error is set to #G_KEY_FILE_ERROR_KEY_NOT_FOUND. Likewise, if
1747  * the value associated with @key cannot be interpreted as a boolean
1748  * then the return value is also undefined and @error is set to
1749  * #G_KEY_FILE_ERROR_INVALID_VALUE.
1750  *
1751  * Return value: the value associated with the key as a boolean
1752  * Since: 2.6
1753  **/
1754 gboolean
1755 g_key_file_get_boolean (GKeyFile     *key_file,
1756                         const gchar  *group_name,
1757                         const gchar  *key,
1758                         GError      **error)
1759 {
1760   GError *key_file_error = NULL;
1761   gchar *value;
1762   gboolean bool_value;
1763
1764   g_return_val_if_fail (key_file != NULL, FALSE);
1765   g_return_val_if_fail (group_name != NULL, FALSE);
1766   g_return_val_if_fail (key != NULL, FALSE);
1767
1768   value = g_key_file_get_value (key_file, group_name, key, &key_file_error);
1769
1770   if (!value)
1771     {
1772       g_propagate_error (error, key_file_error);
1773       return FALSE;
1774     }
1775
1776   bool_value = g_key_file_parse_value_as_boolean (key_file, value,
1777                                                   &key_file_error);
1778   g_free (value);
1779
1780   if (key_file_error)
1781     {
1782       if (g_error_matches (key_file_error,
1783                            G_KEY_FILE_ERROR,
1784                            G_KEY_FILE_ERROR_INVALID_VALUE))
1785         {
1786           g_set_error (error, G_KEY_FILE_ERROR,
1787                        G_KEY_FILE_ERROR_INVALID_VALUE,
1788                        _("Key file contains key '%s' "
1789                          "which has value that cannot be interpreted."),
1790                        key);
1791           g_error_free (key_file_error);
1792         }
1793       else
1794         g_propagate_error (error, key_file_error);
1795     }
1796
1797   return bool_value;
1798 }
1799
1800 /**
1801  * g_key_file_set_boolean:
1802  * @key_file: a #GKeyFile
1803  * @group_name: a group name
1804  * @key: a key
1805  * @value: %TRUE or %FALSE
1806  *
1807  * Associates a new boolean value with @key under @group_name.
1808  * If @key cannot be found then it is created. 
1809  *
1810  * Since: 2.6
1811  **/
1812 void
1813 g_key_file_set_boolean (GKeyFile    *key_file,
1814                         const gchar *group_name,
1815                         const gchar *key,
1816                         gboolean     value)
1817 {
1818   gchar *result;
1819
1820   g_return_if_fail (key_file != NULL);
1821   g_return_if_fail (group_name != NULL);
1822   g_return_if_fail (key != NULL);
1823
1824   result = g_key_file_parse_boolean_as_value (key_file, value);
1825   g_key_file_set_value (key_file, group_name, key, result);
1826   g_free (result);
1827 }
1828
1829 /**
1830  * g_key_file_get_boolean_list:
1831  * @key_file: a #GKeyFile
1832  * @group_name: a group name
1833  * @key: a key
1834  * @length: the number of booleans returned
1835  * @error: return location for a #GError
1836  *
1837  * Returns the values associated with @key under @group_name as
1838  * booleans. If @group_name is %NULL, the start_group is used.
1839  *
1840  * If @key cannot be found then the return value is undefined and
1841  * @error is set to #G_KEY_FILE_ERROR_KEY_NOT_FOUND. Likewise, if
1842  * the values associated with @key cannot be interpreted as booleans
1843  * then the return value is also undefined and @error is set to
1844  * #G_KEY_FILE_ERROR_INVALID_VALUE.
1845  *
1846  * Return value: the values associated with the key as a boolean
1847  * 
1848  * Since: 2.6
1849  **/
1850 gboolean *
1851 g_key_file_get_boolean_list (GKeyFile     *key_file,
1852                              const gchar  *group_name,
1853                              const gchar  *key,
1854                              gsize        *length,
1855                              GError      **error)
1856 {
1857   GError *key_file_error;
1858   gchar **values;
1859   gboolean *bool_values;
1860   gsize i, num_bools;
1861
1862   g_return_val_if_fail (key_file != NULL, NULL);
1863   g_return_val_if_fail (group_name != NULL, NULL);
1864   g_return_val_if_fail (key != NULL, NULL);
1865
1866   key_file_error = NULL;
1867
1868   values = g_key_file_get_string_list (key_file, group_name, key,
1869                                        &num_bools, &key_file_error);
1870
1871   if (key_file_error)
1872     g_propagate_error (error, key_file_error);
1873
1874   if (!values)
1875     return NULL;
1876
1877   bool_values = g_new0 (gboolean, num_bools);
1878
1879   for (i = 0; i < num_bools; i++)
1880     {
1881       bool_values[i] = g_key_file_parse_value_as_boolean (key_file,
1882                                                           values[i],
1883                                                           &key_file_error);
1884
1885       if (key_file_error)
1886         {
1887           g_propagate_error (error, key_file_error);
1888           g_strfreev (values);
1889           g_free (bool_values);
1890
1891           return NULL;
1892         }
1893     }
1894   g_strfreev (values);
1895
1896   if (length)
1897     *length = num_bools;
1898
1899   return bool_values;
1900 }
1901
1902 /**
1903  * g_key_file_set_boolean_list:
1904  * @key_file: a #GKeyFile
1905  * @group_name: a group name
1906  * @key: a key
1907  * @list: an array of boolean values
1908  * @length: length of @list
1909  *
1910  * Associates a list of boolean values with @key under
1911  * @group_name.  If @key cannot be found then it is created.
1912  * If @group_name is %NULL, the start_group is used.
1913  *
1914  * Since: 2.6
1915  **/
1916 void
1917 g_key_file_set_boolean_list (GKeyFile    *key_file,
1918                              const gchar *group_name,
1919                              const gchar *key,
1920                              gboolean     list[],
1921                              gsize        length)
1922 {
1923   GString *value_list;
1924   gsize i;
1925
1926   g_return_if_fail (key_file != NULL);
1927   g_return_if_fail (group_name != NULL);
1928   g_return_if_fail (key != NULL);
1929   g_return_if_fail (list != NULL);
1930
1931   value_list = g_string_sized_new (length * 8);
1932   for (i = 0; i < length; i++)
1933     {
1934       gchar *value;
1935
1936       value = g_key_file_parse_boolean_as_value (key_file, list[i]);
1937
1938       g_string_append (value_list, value);
1939       g_string_append_c (value_list, key_file->list_separator);
1940
1941       g_free (value);
1942     }
1943
1944   g_key_file_set_value (key_file, group_name, key, value_list->str);
1945   g_string_free (value_list, TRUE);
1946 }
1947
1948 /**
1949  * g_key_file_get_integer:
1950  * @key_file: a #GKeyFile
1951  * @group_name: a group name
1952  * @key: a key
1953  * @error: return location for a #GError
1954  *
1955  * Returns the value associated with @key under @group_name as an
1956  * integer. If @group_name is %NULL, the start_group is used.
1957  *
1958  * If @key cannot be found then the return value is undefined and
1959  * @error is set to #G_KEY_FILE_ERROR_KEY_NOT_FOUND. Likewise, if
1960  * the value associated with @key cannot be interpreted as an integer
1961  * then the return value is also undefined and @error is set to
1962  * #G_KEY_FILE_ERROR_INVALID_VALUE.
1963  *
1964  * Return value: the value associated with the key as an integer.
1965  *
1966  * Since: 2.6
1967  **/
1968 gint
1969 g_key_file_get_integer (GKeyFile     *key_file,
1970                         const gchar  *group_name,
1971                         const gchar  *key,
1972                         GError      **error)
1973 {
1974   GError *key_file_error;
1975   gchar *value;
1976   gint int_value;
1977
1978   g_return_val_if_fail (key_file != NULL, -1);
1979   g_return_val_if_fail (group_name != NULL, -1);
1980   g_return_val_if_fail (key != NULL, -1);
1981
1982   key_file_error = NULL;
1983
1984   value = g_key_file_get_value (key_file, group_name, key, &key_file_error);
1985
1986   if (key_file_error)
1987     {
1988       g_propagate_error (error, key_file_error);
1989       return 0;
1990     }
1991
1992   int_value = g_key_file_parse_value_as_integer (key_file, value,
1993                                                  &key_file_error);
1994   g_free (value);
1995
1996   if (key_file_error)
1997     {
1998       if (g_error_matches (key_file_error,
1999                            G_KEY_FILE_ERROR,
2000                            G_KEY_FILE_ERROR_INVALID_VALUE))
2001         {
2002           g_set_error (error, G_KEY_FILE_ERROR,
2003                        G_KEY_FILE_ERROR_INVALID_VALUE,
2004                        _("Key file contains key '%s' in group '%s' "
2005                          "which has value that cannot be interpreted."), key, 
2006                        group_name);
2007           g_error_free (key_file_error);
2008         }
2009       else
2010         g_propagate_error (error, key_file_error);
2011     }
2012
2013   return int_value;
2014 }
2015
2016 /**
2017  * g_key_file_set_integer:
2018  * @key_file: a #GKeyFile
2019  * @group_name: a group name
2020  * @key: a key
2021  * @value: an integer value
2022  *
2023  * Associates a new integer value with @key under @group_name.
2024  * If @key cannot be found then it is created.
2025  *
2026  * Since: 2.6
2027  **/
2028 void
2029 g_key_file_set_integer (GKeyFile    *key_file,
2030                         const gchar *group_name,
2031                         const gchar *key,
2032                         gint         value)
2033 {
2034   gchar *result;
2035
2036   g_return_if_fail (key_file != NULL);
2037   g_return_if_fail (group_name != NULL);
2038   g_return_if_fail (key != NULL);
2039
2040   result = g_key_file_parse_integer_as_value (key_file, value);
2041   g_key_file_set_value (key_file, group_name, key, result);
2042   g_free (result);
2043 }
2044
2045 /**
2046  * g_key_file_get_integer_list:
2047  * @key_file: a #GKeyFile
2048  * @group_name: a group name
2049  * @key: a key
2050  * @length: the number of integers returned
2051  * @error: return location for a #GError
2052  *
2053  * Returns the values associated with @key under @group_name as
2054  * integers. 
2055  *
2056  * If @key cannot be found then the return value is undefined and
2057  * @error is set to #G_KEY_FILE_ERROR_KEY_NOT_FOUND. Likewise, if
2058  * the values associated with @key cannot be interpreted as integers
2059  * then the return value is also undefined and @error is set to
2060  * #G_KEY_FILE_ERROR_INVALID_VALUE.
2061  *
2062  * Return value: the values associated with the key as a integer
2063  *
2064  * Since: 2.6
2065  **/
2066 gint *
2067 g_key_file_get_integer_list (GKeyFile     *key_file,
2068                              const gchar  *group_name,
2069                              const gchar  *key,
2070                              gsize        *length,
2071                              GError      **error)
2072 {
2073   GError *key_file_error = NULL;
2074   gchar **values;
2075   gint *int_values;
2076   gsize i, num_ints;
2077
2078   g_return_val_if_fail (key_file != NULL, NULL);
2079   g_return_val_if_fail (group_name != NULL, NULL);
2080   g_return_val_if_fail (key != NULL, NULL);
2081
2082   values = g_key_file_get_string_list (key_file, group_name, key,
2083                                        &num_ints, &key_file_error);
2084
2085   if (key_file_error)
2086     g_propagate_error (error, key_file_error);
2087
2088   if (!values)
2089     return NULL;
2090
2091   int_values = g_new0 (gint, num_ints);
2092
2093   for (i = 0; i < num_ints; i++)
2094     {
2095       int_values[i] = g_key_file_parse_value_as_integer (key_file,
2096                                                          values[i],
2097                                                          &key_file_error);
2098
2099       if (key_file_error)
2100         {
2101           g_propagate_error (error, key_file_error);
2102           g_strfreev (values);
2103           g_free (int_values);
2104
2105           return NULL;
2106         }
2107     }
2108   g_strfreev (values);
2109
2110   if (length)
2111     *length = num_ints;
2112
2113   return int_values;
2114 }
2115
2116 /**
2117  * g_key_file_set_integer_list:
2118  * @key_file: a #GKeyFile
2119  * @group_name: a group name
2120  * @key: a key
2121  * @list: an array of integer values
2122  * @length: number of integer values in @list
2123  *
2124  * Associates a list of integer values with @key under
2125  * @group_name.  If @key cannot be found then it is created.
2126  *
2127  * Since: 2.6
2128  **/
2129 void
2130 g_key_file_set_integer_list (GKeyFile     *key_file,
2131                              const gchar  *group_name,
2132                              const gchar  *key,
2133                              gint          list[],
2134                              gsize         length)
2135 {
2136   GString *values;
2137   gsize i;
2138
2139   g_return_if_fail (key_file != NULL);
2140   g_return_if_fail (group_name != NULL);
2141   g_return_if_fail (key != NULL);
2142   g_return_if_fail (list != NULL);
2143
2144   values = g_string_sized_new (length * 16);
2145   for (i = 0; i < length; i++)
2146     {
2147       gchar *value;
2148
2149       value = g_key_file_parse_integer_as_value (key_file, list[i]);
2150
2151       g_string_append (values, value);
2152       g_string_append_c (values, ';');
2153
2154       g_free (value);
2155     }
2156
2157   g_key_file_set_value (key_file, group_name, key, values->str);
2158   g_string_free (values, TRUE);
2159 }
2160
2161 static void
2162 g_key_file_set_key_comment (GKeyFile             *key_file,
2163                             const gchar          *group_name,
2164                             const gchar          *key,
2165                             const gchar          *comment,
2166                             GError              **error)
2167 {
2168   GKeyFileGroup *group;
2169   GKeyFileKeyValuePair *pair;
2170   GList *key_node, *comment_node, *tmp;
2171   
2172   group = g_key_file_lookup_group (key_file, group_name);
2173   if (!group)
2174     {
2175       g_set_error (error, G_KEY_FILE_ERROR,
2176                    G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
2177                    _("Key file does not have group '%s'"),
2178                    group_name ? group_name : "(null)");
2179
2180       return;
2181     }
2182
2183   /* First find the key the comments are supposed to be
2184    * associated with
2185    */
2186   key_node = g_key_file_lookup_key_value_pair_node (key_file, group, key);
2187
2188   if (key_node == NULL)
2189     {
2190       g_set_error (error, G_KEY_FILE_ERROR,
2191                    G_KEY_FILE_ERROR_KEY_NOT_FOUND,
2192                    _("Key file does not have key '%s' in group '%s'"),
2193                    key, group->name);
2194       return;
2195     }
2196
2197   /* Then find all the comments already associated with the
2198    * key and free them
2199    */
2200   tmp = key_node->next;
2201   while (tmp != NULL)
2202     {
2203       GKeyFileKeyValuePair *pair;
2204
2205       pair = (GKeyFileKeyValuePair *) tmp->data;
2206
2207       if (pair->key != NULL)
2208         break;
2209
2210       comment_node = tmp;
2211       tmp = tmp->next;
2212       g_key_file_remove_key_value_pair_node (key_file, group,
2213                                              comment_node); 
2214     }
2215
2216   if (comment == NULL)
2217     return;
2218
2219   /* Now we can add our new comment
2220    */
2221   pair = g_new0 (GKeyFileKeyValuePair, 1);
2222   
2223   pair->key = NULL;
2224   pair->value = g_key_file_parse_comment_as_value (key_file, comment);
2225   
2226   key_node = g_list_insert (key_node, pair, 1);
2227 }
2228
2229 static void
2230 g_key_file_set_group_comment (GKeyFile             *key_file,
2231                               const gchar          *group_name,
2232                               const gchar          *comment,
2233                               GError              **error)
2234 {
2235   GKeyFileGroup *group;
2236   
2237   group = g_key_file_lookup_group (key_file, group_name);
2238   if (!group)
2239     {
2240       g_set_error (error, G_KEY_FILE_ERROR,
2241                    G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
2242                    _("Key file does not have group '%s'"),
2243                    group_name ? group_name : "(null)");
2244
2245       return;
2246     }
2247
2248   /* First remove any existing comment
2249    */
2250   if (group->comment)
2251     {
2252       g_key_file_key_value_pair_free (group->comment);
2253       group->comment = NULL;
2254     }
2255
2256   if (comment == NULL)
2257     return;
2258
2259   /* Now we can add our new comment
2260    */
2261   group->comment = g_new0 (GKeyFileKeyValuePair, 1);
2262   
2263   group->comment->key = NULL;
2264   group->comment->value = g_key_file_parse_comment_as_value (key_file, comment);
2265 }
2266
2267 static void
2268 g_key_file_set_top_comment (GKeyFile             *key_file,
2269                             const gchar          *comment,
2270                             GError              **error)
2271 {
2272   GList *group_node;
2273   GKeyFileGroup *group;
2274   GKeyFileKeyValuePair *pair;
2275
2276   /* The last group in the list should be the top (comments only)
2277    * group in the file
2278    */
2279   g_assert (key_file->groups != NULL);
2280   group_node = g_list_last (key_file->groups);
2281   group = (GKeyFileGroup *) group_node->data;
2282   g_assert (group->name == NULL);
2283
2284   /* Note all keys must be comments at the top of
2285    * the file, so we can just free it all.
2286    */
2287   if (group->key_value_pairs != NULL)
2288     {
2289       g_list_foreach (group->key_value_pairs, 
2290                       (GFunc) g_key_file_key_value_pair_free, 
2291                       NULL);
2292       g_list_free (group->key_value_pairs);
2293       group->key_value_pairs = NULL;
2294     }
2295
2296   if (comment == NULL)
2297      return;
2298
2299   pair = g_new0 (GKeyFileKeyValuePair, 1);
2300   
2301   pair->key = NULL;
2302   pair->value = g_key_file_parse_comment_as_value (key_file, comment);
2303   
2304   group->key_value_pairs =
2305     g_list_prepend (group->key_value_pairs, pair);
2306 }
2307
2308 /**
2309  * g_key_file_set_comment:
2310  * @key_file: a #GKeyFile
2311  * @group_name: a group name, or %NULL
2312  * @key: a key
2313  * @comment: a comment
2314  * @error: return location for a #GError
2315  *
2316  * Places a comment above @key from @group_name.
2317  * @group_name. If @key is %NULL then @comment will
2318  * be written above @group_name.  If both @key
2319  * and @group_name are NULL, then @comment will
2320  * be written above the first group in the file.
2321  *
2322  * Since: 2.6
2323  **/
2324 void
2325 g_key_file_set_comment (GKeyFile             *key_file,
2326                         const gchar          *group_name,
2327                         const gchar          *key,
2328                         const gchar          *comment,
2329                         GError              **error)
2330 {
2331   g_return_if_fail (key_file != NULL);
2332
2333   if (group_name != NULL && key != NULL)
2334     g_key_file_set_key_comment (key_file, group_name, key, comment, error);
2335   else if (group_name != NULL)
2336     g_key_file_set_group_comment (key_file, group_name, comment, error);
2337   else
2338     g_key_file_set_top_comment (key_file, comment, error);
2339
2340   if (comment != NULL)
2341     key_file->approximate_size += strlen (comment);
2342 }
2343
2344 static gchar *
2345 g_key_file_get_key_comment (GKeyFile             *key_file,
2346                             const gchar          *group_name,
2347                             const gchar          *key,
2348                             GError              **error)
2349 {
2350   GKeyFileGroup *group;
2351   GKeyFileKeyValuePair *pair;
2352   GList *key_node, *tmp;
2353   GString *string;
2354   gchar *comment;
2355
2356   group = g_key_file_lookup_group (key_file, group_name);
2357   if (!group)
2358     {
2359       g_set_error (error, G_KEY_FILE_ERROR,
2360                    G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
2361                    _("Key file does not have group '%s'"),
2362                    group_name ? group_name : "(null)");
2363
2364       return NULL;
2365     }
2366
2367   /* First find the key the comments are supposed to be
2368    * associated with
2369    */
2370   key_node = g_key_file_lookup_key_value_pair_node (key_file, group, key);
2371
2372   if (key_node == NULL)
2373     {
2374       g_set_error (error, G_KEY_FILE_ERROR,
2375                    G_KEY_FILE_ERROR_KEY_NOT_FOUND,
2376                    _("Key file does not have key '%s' in group '%s'"),
2377                    key, group->name);
2378       return NULL;
2379     }
2380
2381   string = NULL;
2382
2383   /* Then find all the comments already associated with the
2384    * key and concatentate them.
2385    */
2386   tmp = key_node->next;
2387   if (!key_node->next)
2388     return NULL;
2389
2390   pair = (GKeyFileKeyValuePair *) tmp->data;
2391   if (pair->key != NULL)
2392     return NULL;
2393
2394   while (tmp->next)
2395     {
2396       pair = (GKeyFileKeyValuePair *) tmp->next->data;
2397       
2398       if (pair->key != NULL)
2399         break;
2400
2401       tmp = tmp->next;
2402     }
2403
2404   while (tmp != key_node)
2405     {
2406       GKeyFileKeyValuePair *pair;
2407       
2408       pair = (GKeyFileKeyValuePair *) tmp->data;
2409       
2410       if (string == NULL)
2411         string = g_string_sized_new (512);
2412       
2413       comment = g_key_file_parse_value_as_comment (key_file, pair->value);
2414       g_string_append (string, comment);
2415       g_free (comment);
2416       
2417       tmp = tmp->prev;
2418     }
2419
2420   if (string != NULL)
2421     {
2422       comment = string->str;
2423       g_string_free (string, FALSE);
2424     }
2425   else
2426     comment = NULL;
2427
2428   return comment;
2429 }
2430
2431 static gchar *
2432 get_group_comment (GKeyFile       *key_file,
2433                    GKeyFileGroup  *group,
2434                    GError        **error)
2435 {
2436   GString *string;
2437   GList *tmp;
2438   gchar *comment;
2439
2440   string = NULL;
2441
2442   tmp = group->key_value_pairs;
2443   while (tmp)
2444     {
2445       GKeyFileKeyValuePair *pair;
2446
2447       pair = (GKeyFileKeyValuePair *) tmp->data;
2448
2449       if (pair->key != NULL)
2450         {
2451           tmp = tmp->prev;
2452           break;
2453         }
2454
2455       if (tmp->next == NULL)
2456         break;
2457
2458       tmp = tmp->next;
2459     }
2460   
2461   while (tmp != NULL)
2462     {
2463       GKeyFileKeyValuePair *pair;
2464
2465       pair = (GKeyFileKeyValuePair *) tmp->data;
2466
2467       if (string == NULL)
2468         string = g_string_sized_new (512);
2469
2470       comment = g_key_file_parse_value_as_comment (key_file, pair->value);
2471       g_string_append (string, comment);
2472       g_free (comment);
2473
2474       tmp = tmp->prev;
2475     }
2476
2477   if (string != NULL)
2478     return g_string_free (string, FALSE);
2479
2480   return NULL;
2481 }
2482
2483 static gchar *
2484 g_key_file_get_group_comment (GKeyFile             *key_file,
2485                               const gchar          *group_name,
2486                               GError              **error)
2487 {
2488   GList *group_node;
2489   GKeyFileGroup *group;
2490   
2491   group_node = g_key_file_lookup_group_node (key_file, group_name);
2492   group = (GKeyFileGroup *)group_node->data;
2493   if (!group)
2494     {
2495       g_set_error (error, G_KEY_FILE_ERROR,
2496                    G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
2497                    _("Key file does not have group '%s'"),
2498                    group_name ? group_name : "(null)");
2499
2500       return NULL;
2501     }
2502
2503   if (group->comment)
2504     return g_strdup (group->comment->value);
2505   
2506   group_node = group_node->next;
2507   group = (GKeyFileGroup *)group_node->data;  
2508   return get_group_comment (key_file, group, error);
2509 }
2510
2511 static gchar *
2512 g_key_file_get_top_comment (GKeyFile             *key_file,
2513                             GError              **error)
2514 {
2515   GList *group_node;
2516   GKeyFileGroup *group;
2517
2518   /* The last group in the list should be the top (comments only)
2519    * group in the file
2520    */
2521   g_assert (key_file->groups != NULL);
2522   group_node = g_list_last (key_file->groups);
2523   group = (GKeyFileGroup *) group_node->data;
2524   g_assert (group->name == NULL);
2525
2526   return get_group_comment (key_file, group, error);
2527 }
2528
2529 /**
2530  * g_key_file_get_comment:
2531  * @key_file: a #GKeyFile
2532  * @group_name: a group name, or %NULL
2533  * @key: a key
2534  * @error: return location for a #GError
2535  *
2536  * Retrieves a comment above @key from @group_name.
2537  * @group_name. If @key is %NULL then @comment will
2538  * be read from above @group_name.  If both @key
2539  * and @group_name are NULL, then @comment will
2540  * be read from above the first group in the file.
2541  *
2542  * Returns: a comment that should be freed with g_free()
2543  *
2544  * Since: 2.6
2545  **/
2546 gchar * 
2547 g_key_file_get_comment (GKeyFile             *key_file,
2548                         const gchar          *group_name,
2549                         const gchar          *key,
2550                         GError              **error)
2551 {
2552   g_return_val_if_fail (key_file != NULL, NULL);
2553
2554   if (group_name != NULL && key != NULL)
2555     return g_key_file_get_key_comment (key_file, group_name, key, error);
2556   else if (group_name != NULL)
2557     return g_key_file_get_group_comment (key_file, group_name, error);
2558   else
2559     return g_key_file_get_top_comment (key_file, error);
2560 }
2561
2562 /**
2563  * g_key_file_remove_comment:
2564  * @key_file: a #GKeyFile
2565  * @group_name: a group name, or %NULL
2566  * @key: a key
2567  * @error: return location for a #GError
2568  *
2569  * Removes a comment above @key from @group_name.
2570  * @group_name. If @key is %NULL then @comment will
2571  * be written above @group_name.  If both @key
2572  * and @group_name are NULL, then @comment will
2573  * be written above the first group in the file.
2574  *
2575  * Since: 2.6
2576  **/
2577
2578 void
2579 g_key_file_remove_comment (GKeyFile             *key_file,
2580                            const gchar          *group_name,
2581                            const gchar          *key,
2582                            GError              **error)
2583 {
2584   g_return_if_fail (key_file != NULL);
2585
2586   if (group_name != NULL && key != NULL)
2587     g_key_file_set_key_comment (key_file, group_name, key, NULL, error);
2588   else if (group_name != NULL)
2589     g_key_file_set_group_comment (key_file, group_name, NULL, error);
2590   else
2591     g_key_file_set_top_comment (key_file, NULL, error);
2592 }
2593
2594 /**
2595  * g_key_file_has_group:
2596  * @key_file: a #GKeyFile
2597  * @group_name: a group name
2598  *
2599  * Looks whether the key file has the group @group_name.
2600  *
2601  * Return value: %TRUE if @group_name is a part of @key_file, %FALSE
2602  * otherwise.
2603  * Since: 2.6
2604  **/
2605 gboolean
2606 g_key_file_has_group (GKeyFile    *key_file,
2607                       const gchar *group_name)
2608 {
2609   g_return_val_if_fail (key_file != NULL, FALSE);
2610   g_return_val_if_fail (group_name != NULL, FALSE);
2611
2612   return g_key_file_lookup_group_node (key_file, group_name) != NULL;
2613 }
2614
2615 /**
2616  * g_key_file_has_key:
2617  * @key_file: a #GKeyFile
2618  * @group_name: a group name
2619  * @key: a key name
2620  * @error: return location for a #GError
2621  *
2622  * Looks whether the key file has the key @key in the group
2623  * @group_name. 
2624  *
2625  * Return value: %TRUE if @key is a part of @group_name, %FALSE
2626  * otherwise.
2627  *
2628  * Since: 2.6
2629  **/
2630 gboolean
2631 g_key_file_has_key (GKeyFile     *key_file,
2632                     const gchar  *group_name,
2633                     const gchar  *key,
2634                     GError      **error)
2635 {
2636   GKeyFileKeyValuePair *pair;
2637   GKeyFileGroup *group;
2638
2639   g_return_val_if_fail (key_file != NULL, FALSE);
2640   g_return_val_if_fail (group_name != NULL, FALSE);
2641   g_return_val_if_fail (key != NULL, FALSE);
2642
2643   group = g_key_file_lookup_group (key_file, group_name);
2644
2645   if (!group)
2646     {
2647       g_set_error (error, G_KEY_FILE_ERROR,
2648                    G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
2649                    _("Key file does not have group '%s'"),
2650                    group_name ? group_name : "(null)");
2651
2652       return FALSE;
2653     }
2654
2655   pair = g_key_file_lookup_key_value_pair (key_file, group, key);
2656
2657   return pair != NULL;
2658 }
2659
2660 static void
2661 g_key_file_add_group (GKeyFile    *key_file,
2662                       const gchar *group_name)
2663 {
2664   GKeyFileGroup *group;
2665
2666   g_return_if_fail (key_file != NULL);
2667   g_return_if_fail (group_name != NULL);
2668   g_return_if_fail (g_key_file_lookup_group_node (key_file, group_name) == NULL);
2669
2670   group = g_new0 (GKeyFileGroup, 1);
2671   group->name = g_strdup (group_name);
2672   group->lookup_map = g_hash_table_new (g_str_hash, g_str_equal);
2673   key_file->groups = g_list_prepend (key_file->groups, group);
2674   key_file->approximate_size += strlen (group_name) + 3;
2675   key_file->current_group = group;
2676
2677   if (key_file->start_group == NULL)
2678     key_file->start_group = group;
2679 }
2680
2681 static void
2682 g_key_file_key_value_pair_free (GKeyFileKeyValuePair *pair)
2683 {
2684   if (pair != NULL)
2685     {
2686       g_free (pair->key);
2687       g_free (pair->value);
2688       g_free (pair);
2689     }
2690 }
2691
2692 /* Be careful not to call this function on a node with data in the
2693  * lookup map without removing it from the lookup map, first.
2694  *
2695  * Some current cases where this warning is not a concern are
2696  * when:
2697  *   - the node being removed is a comment node
2698  *   - the entire lookup map is getting destroyed soon after
2699  *     anyway.
2700  */ 
2701 static void
2702 g_key_file_remove_key_value_pair_node (GKeyFile      *key_file,
2703                                        GKeyFileGroup *group,
2704                                        GList         *pair_node)
2705 {
2706
2707   GKeyFileKeyValuePair *pair;
2708
2709   pair = (GKeyFileKeyValuePair *) pair_node->data;
2710
2711   group->key_value_pairs = g_list_remove_link (group->key_value_pairs, pair_node);
2712
2713   if (pair->key != NULL)
2714     key_file->approximate_size -= strlen (pair->key) + 1;
2715
2716   g_assert (pair->value != NULL);
2717   key_file->approximate_size -= strlen (pair->value);
2718
2719   g_key_file_key_value_pair_free (pair);
2720
2721   g_list_free_1 (pair_node);
2722 }
2723
2724 static void
2725 g_key_file_remove_group_node (GKeyFile *key_file,
2726                               GList    *group_node)
2727 {
2728   GKeyFileGroup *group;
2729   GList *tmp;
2730
2731   group = (GKeyFileGroup *) group_node->data;
2732
2733   /* If the current group gets deleted make the current group the last
2734    * added group.
2735    */
2736   if (key_file->current_group == group)
2737     {
2738       /* groups should always contain at least the top comment group,
2739        * unless g_key_file_clear has been called
2740        */
2741       if (key_file->groups)
2742         key_file->current_group = (GKeyFileGroup *) key_file->groups->data;
2743       else
2744         key_file->current_group = NULL;
2745     }
2746
2747   /* If the start group gets deleted make the start group the first
2748    * added group.
2749    */
2750   if (key_file->start_group == group)
2751     {
2752       tmp = g_list_last (key_file->groups);
2753       while (tmp != NULL)
2754         {
2755           if (tmp != group_node &&
2756               ((GKeyFileGroup *) tmp->data)->name != NULL)
2757             break;
2758
2759           tmp = tmp->prev;
2760         }
2761
2762       if (tmp)
2763         key_file->start_group = (GKeyFileGroup *) tmp->data;
2764       else
2765         key_file->start_group = NULL;
2766     }
2767
2768   key_file->groups = g_list_remove_link (key_file->groups, group_node);
2769
2770   if (group->name != NULL)
2771     key_file->approximate_size -= strlen (group->name) + 3;
2772
2773   tmp = group->key_value_pairs;
2774   while (tmp != NULL)
2775     {
2776       GList *pair_node;
2777
2778       pair_node = tmp;
2779       tmp = tmp->next;
2780       g_key_file_remove_key_value_pair_node (key_file, group, pair_node);
2781     }
2782
2783   g_assert (group->key_value_pairs == NULL);
2784
2785   if (group->lookup_map)
2786     {
2787       g_hash_table_destroy (group->lookup_map);
2788       group->lookup_map = NULL;
2789     }
2790
2791   g_free ((gchar *) group->name);
2792   g_free (group);
2793   g_list_free_1 (group_node);
2794 }
2795
2796 /**
2797  * g_key_file_remove_group:
2798  * @key_file: a #GKeyFile
2799  * @group_name: a group name
2800  * @error: return location for a #GError or %NULL
2801  *
2802  * Removes the specified group, @group_name, 
2803  * from the key file. 
2804  *
2805  * Since: 2.6
2806  **/
2807 void
2808 g_key_file_remove_group (GKeyFile     *key_file,
2809                          const gchar  *group_name,
2810                          GError      **error)
2811 {
2812   GList *group_node;
2813
2814   g_return_if_fail (key_file != NULL);
2815   g_return_if_fail (group_name != NULL);
2816
2817   group_node = g_key_file_lookup_group_node (key_file, group_name);
2818
2819   if (!group_node)
2820     {
2821       g_set_error (error, G_KEY_FILE_ERROR,
2822                    G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
2823                    _("Key file does not have group '%s'"),
2824                    group_name);
2825       return;
2826     }
2827
2828     g_key_file_remove_group_node (key_file, group_node);
2829 }
2830
2831 static void
2832 g_key_file_add_key (GKeyFile      *key_file,
2833                     GKeyFileGroup *group,
2834                     const gchar   *key,
2835                     const gchar   *value)
2836 {
2837   GKeyFileKeyValuePair *pair;
2838
2839   pair = g_new0 (GKeyFileKeyValuePair, 1);
2840
2841   pair->key = g_strdup (key);
2842   pair->value = g_strdup (value);
2843
2844   g_hash_table_replace (group->lookup_map, pair->key, pair);
2845   group->key_value_pairs = g_list_prepend (group->key_value_pairs, pair);
2846   key_file->approximate_size += strlen (key) + strlen (value) + 2;
2847 }
2848
2849 /**
2850  * g_key_file_remove_key:
2851  * @key_file: a #GKeyFile
2852  * @group_name: a group name
2853  * @key: a key name to remove
2854  * @error: return location for a #GError or %NULL
2855  *
2856  * Removes @key in @group_name from the key file. 
2857  *
2858  * Since: 2.6
2859  **/
2860 void
2861 g_key_file_remove_key (GKeyFile     *key_file,
2862                        const gchar  *group_name,
2863                        const gchar  *key,
2864                        GError      **error)
2865 {
2866   GKeyFileGroup *group;
2867   GKeyFileKeyValuePair *pair;
2868
2869   g_return_if_fail (key_file != NULL);
2870   g_return_if_fail (group_name != NULL);
2871   g_return_if_fail (key != NULL);
2872
2873   pair = NULL;
2874
2875   group = g_key_file_lookup_group (key_file, group_name);
2876   if (!group)
2877     {
2878       g_set_error (error, G_KEY_FILE_ERROR,
2879                    G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
2880                    _("Key file does not have group '%s'"),
2881                    group_name ? group_name : "(null)");
2882       return;
2883     }
2884
2885   pair = g_key_file_lookup_key_value_pair (key_file, group, key);
2886
2887   if (!pair)
2888     {
2889       g_set_error (error, G_KEY_FILE_ERROR,
2890                    G_KEY_FILE_ERROR_KEY_NOT_FOUND,
2891                    _("Key file does not have key '%s' in group '%s'"),
2892                    key, group->name);
2893       return;
2894     }
2895
2896   key_file->approximate_size -= strlen (pair->key) + strlen (pair->value) + 2;
2897
2898   group->key_value_pairs = g_list_remove (group->key_value_pairs, pair);
2899   g_hash_table_remove (group->lookup_map, pair->key);  
2900   g_key_file_key_value_pair_free (pair);
2901 }
2902
2903 static GList *
2904 g_key_file_lookup_group_node (GKeyFile    *key_file,
2905                               const gchar *group_name)
2906 {
2907   GKeyFileGroup *group;
2908   GList *tmp;
2909
2910   group = NULL;
2911   for (tmp = key_file->groups; tmp != NULL; tmp = tmp->next)
2912     {
2913       group = (GKeyFileGroup *) tmp->data;
2914
2915       if (group && group->name && strcmp (group->name, group_name) == 0)
2916         break;
2917
2918       group = NULL;
2919     }
2920
2921   return tmp;
2922 }
2923
2924 static GKeyFileGroup *
2925 g_key_file_lookup_group (GKeyFile    *key_file,
2926                          const gchar *group_name)
2927 {
2928   GList *group_node;
2929
2930   group_node = g_key_file_lookup_group_node (key_file, group_name);
2931
2932   if (group_node != NULL)
2933     return (GKeyFileGroup *) group_node->data; 
2934
2935   return NULL;
2936 }
2937
2938 static GList *
2939 g_key_file_lookup_key_value_pair_node (GKeyFile       *key_file,
2940                                        GKeyFileGroup  *group,
2941                                        const gchar    *key)
2942 {
2943   GList *key_node;
2944
2945   for (key_node = group->key_value_pairs;
2946        key_node != NULL;
2947        key_node = key_node->next)
2948     {
2949       GKeyFileKeyValuePair *pair;
2950
2951       pair = (GKeyFileKeyValuePair *) key_node->data; 
2952
2953       if (pair->key && strcmp (pair->key, key) == 0)
2954         break;
2955     }
2956
2957   return key_node;
2958 }
2959
2960 static GKeyFileKeyValuePair *
2961 g_key_file_lookup_key_value_pair (GKeyFile      *key_file,
2962                                   GKeyFileGroup *group,
2963                                   const gchar   *key)
2964 {
2965   return (GKeyFileKeyValuePair *) g_hash_table_lookup (group->lookup_map, key);
2966 }
2967
2968 /* Lines starting with # or consisting entirely of whitespace are merely
2969  * recorded, not parsed. This function assumes all leading whitespace
2970  * has been stripped.
2971  */
2972 static gboolean
2973 g_key_file_line_is_comment (const gchar *line)
2974 {
2975   return (*line == '#' || *line == '\0' || *line == '\n');
2976 }
2977
2978 /* A group in a key file is made up of a starting '[' followed by one
2979  * or more letters making up the group name followed by ']'.
2980  */
2981 static gboolean
2982 g_key_file_line_is_group (const gchar *line)
2983 {
2984   gchar *p;
2985
2986   p = (gchar *) line;
2987   if (*p != '[')
2988     return FALSE;
2989
2990   p = g_utf8_next_char (p);
2991
2992   /* Group name must be non-empty
2993    */
2994   if (!*p || *p == ']')
2995     return FALSE;
2996
2997   while (*p && *p != ']')
2998     p = g_utf8_next_char (p);
2999
3000   if (!*p)
3001     return FALSE;
3002
3003   return TRUE;
3004 }
3005
3006 static gboolean
3007 g_key_file_line_is_key_value_pair (const gchar *line)
3008 {
3009   gchar *p;
3010
3011   p = (gchar *) g_utf8_strchr (line, -1, '=');
3012
3013   if (!p)
3014     return FALSE;
3015
3016   /* Key must be non-empty
3017    */
3018   if (*p == line[0])
3019     return FALSE;
3020
3021   return TRUE;
3022 }
3023
3024 static gchar *
3025 g_key_file_parse_value_as_string (GKeyFile     *key_file,
3026                                   const gchar  *value,
3027                                   GSList      **pieces,
3028                                   GError      **error)
3029 {
3030   gchar *string_value, *p, *q0, *q;
3031
3032   string_value = g_new0 (gchar, strlen (value) + 1);
3033
3034   p = (gchar *) value;
3035   q0 = q = string_value;
3036   while (*p)
3037     {
3038       if (*p == '\\')
3039         {
3040           p++;
3041
3042           switch (*p)
3043             {
3044             case 's':
3045               *q = ' ';
3046               break;
3047
3048             case 'n':
3049               *q = '\n';
3050               break;
3051
3052             case 't':
3053               *q = '\t';
3054               break;
3055
3056             case 'r':
3057               *q = '\r';
3058               break;
3059
3060             case '\\':
3061               *q = '\\';
3062               break;
3063
3064             case '\0':
3065               g_set_error (error, G_KEY_FILE_ERROR,
3066                            G_KEY_FILE_ERROR_INVALID_VALUE,
3067                            _("Key file contains escape character "
3068                              "at end of line"));
3069               break;
3070
3071             default:
3072               if (pieces && *p == key_file->list_separator)
3073                 *q = key_file->list_separator;
3074               else
3075                 {
3076                   *q++ = '\\';
3077                   *q = *p;
3078                   
3079                   if (*error == NULL)
3080                     {
3081                       gchar sequence[3];
3082                       
3083                       sequence[0] = '\\';
3084                       sequence[1] = *p;
3085                       sequence[2] = '\0';
3086                       
3087                       g_set_error (error, G_KEY_FILE_ERROR,
3088                                    G_KEY_FILE_ERROR_INVALID_VALUE,
3089                                    _("Key file contains invalid escape "
3090                                      "sequence '%s'"), sequence);
3091                     }
3092                 }
3093               break;
3094             }
3095         }
3096       else
3097         {
3098           *q = *p;
3099           if (pieces && (*p == key_file->list_separator))
3100             {
3101               *pieces = g_slist_prepend (*pieces, g_strndup (q0, q - q0));
3102               q0 = q + 1; 
3103             }
3104         }
3105
3106       if (*p == '\0')
3107         break;
3108
3109       q++;
3110       p++;
3111     }
3112
3113   *q = '\0';
3114   if (pieces)
3115   {
3116     if (q0 < q)
3117       *pieces = g_slist_prepend (*pieces, g_strndup (q0, q - q0));
3118     *pieces = g_slist_reverse (*pieces);
3119   }
3120
3121   return string_value;
3122 }
3123
3124 static gchar *
3125 g_key_file_parse_string_as_value (GKeyFile    *key_file,
3126                                   const gchar *string,
3127                                   gboolean     escape_separator)
3128 {
3129   gchar *value, *p, *q;
3130   gsize length;
3131   gboolean parsing_leading_space;
3132
3133   length = strlen (string) + 1;
3134
3135   /* Worst case would be that every character needs to be escaped.
3136    * In other words every character turns to two characters
3137    */
3138   value = g_new0 (gchar, 2 * length);
3139
3140   p = (gchar *) string;
3141   q = value;
3142   parsing_leading_space = TRUE;
3143   while (p < (string + length - 1))
3144     {
3145       gchar escaped_character[3] = { '\\', 0, 0 };
3146
3147       switch (*p)
3148         {
3149         case ' ':
3150           if (parsing_leading_space)
3151             {
3152               escaped_character[1] = 's';
3153               strcpy (q, escaped_character);
3154               q += 2;
3155             }
3156           else
3157             {
3158               *q = *p;
3159               q++;
3160             }
3161           break;
3162         case '\t':
3163           if (parsing_leading_space)
3164             {
3165               escaped_character[1] = 't';
3166               strcpy (q, escaped_character);
3167               q += 2;
3168             }
3169           else
3170             {
3171               *q = *p;
3172               q++;
3173             }
3174           break;
3175         case '\n':
3176           escaped_character[1] = 'n';
3177           strcpy (q, escaped_character);
3178           q += 2;
3179           break;
3180         case '\r':
3181           escaped_character[1] = 'r';
3182           strcpy (q, escaped_character);
3183           q += 2;
3184           break;
3185         case '\\':
3186           escaped_character[1] = '\\';
3187           strcpy (q, escaped_character);
3188           q += 2;
3189           parsing_leading_space = FALSE;
3190           break;
3191         default:
3192           if (escape_separator && *p == key_file->list_separator)
3193             {
3194               escaped_character[1] = key_file->list_separator;
3195               strcpy (q, escaped_character);
3196               q += 2;
3197               parsing_leading_space = TRUE;
3198             }
3199           else 
3200             {
3201               *q = *p;
3202               q++;
3203               parsing_leading_space = FALSE;
3204             }
3205           break;
3206         }
3207       p++;
3208     }
3209   *q = '\0';
3210
3211   return value;
3212 }
3213
3214 static gint
3215 g_key_file_parse_value_as_integer (GKeyFile     *key_file,
3216                                    const gchar  *value,
3217                                    GError      **error)
3218 {
3219   gchar *end_of_valid_int;
3220   glong long_value;
3221   gint int_value;
3222
3223   errno = 0;
3224   long_value = strtol (value, &end_of_valid_int, 10);
3225
3226   if (*value == '\0' || *end_of_valid_int != '\0')
3227     {
3228       g_set_error (error, G_KEY_FILE_ERROR,
3229                    G_KEY_FILE_ERROR_INVALID_VALUE,
3230                    _("Value '%s' cannot be interpreted as a number."), value);
3231       return 0;
3232     }
3233
3234   int_value = long_value;
3235   if (int_value != long_value || errno == ERANGE)
3236     {
3237       g_set_error (error,
3238                    G_KEY_FILE_ERROR, 
3239                    G_KEY_FILE_ERROR_INVALID_VALUE,
3240                    _("Integer value '%s' out of range"), value);
3241       return 0;
3242     }
3243   
3244   return int_value;
3245 }
3246
3247 static gchar *
3248 g_key_file_parse_integer_as_value (GKeyFile *key_file,
3249                                    gint      value)
3250
3251 {
3252   return g_strdup_printf ("%d", value);
3253 }
3254
3255 static gboolean
3256 g_key_file_parse_value_as_boolean (GKeyFile     *key_file,
3257                                    const gchar  *value,
3258                                    GError      **error)
3259 {
3260   if (value)
3261     {
3262       if (strcmp (value, "true") == 0 || strcmp (value, "1") == 0)
3263         return TRUE;
3264       else if (strcmp (value, "false") == 0 || strcmp (value, "0") == 0)
3265         return FALSE;
3266     }
3267
3268   g_set_error (error, G_KEY_FILE_ERROR,
3269                G_KEY_FILE_ERROR_INVALID_VALUE,
3270                _("Value '%s' cannot be interpreted as a boolean."), value);
3271
3272   return FALSE;
3273 }
3274
3275 static gchar *
3276 g_key_file_parse_boolean_as_value (GKeyFile *key_file,
3277                                    gboolean  value)
3278 {
3279   if (value)
3280     return g_strdup ("true");
3281   else
3282     return g_strdup ("false");
3283 }
3284
3285 static gchar *
3286 g_key_file_parse_value_as_comment (GKeyFile    *key_file,
3287                                    const gchar *value)
3288 {
3289   GString *string;
3290   gchar **lines, *comment;
3291   gsize i;
3292
3293   string = g_string_sized_new (512);
3294
3295   lines = g_strsplit (value, "\n", 0);
3296
3297   for (i = 0; lines[i] != NULL; i++)
3298     {
3299         if (lines[i][0] != '#')
3300            g_string_append_printf (string, "%s\n", lines[i]);
3301         else 
3302            g_string_append_printf (string, "%s\n", lines[i] + 1);
3303     }
3304   g_strfreev (lines);
3305
3306   comment = string->str;
3307
3308   g_string_free (string, FALSE);
3309
3310   return comment;
3311 }
3312
3313 static gchar *
3314 g_key_file_parse_comment_as_value (GKeyFile      *key_file,
3315                                    const gchar   *comment)
3316 {
3317   GString *string;
3318   gchar **lines, *value;
3319   gsize i;
3320
3321   string = g_string_sized_new (512);
3322
3323   lines = g_strsplit (comment, "\n", 0);
3324
3325   for (i = 0; lines[i] != NULL; i++)
3326     g_string_append_printf (string, "#%s%s", lines[i], 
3327                             lines[i + 1] == NULL? "" : "\n");
3328   g_strfreev (lines);
3329
3330   value = string->str;
3331
3332   g_string_free (string, FALSE);
3333
3334   return value;
3335 }
3336
3337 #define __G_KEY_FILE_C__
3338 #include "galiasdef.c"