986805f80829bb5de6198d5ced721dcbb20d92ce
[platform/upstream/glib.git] / glib / gkeyfile.c
1 /* gkeyfile.c - key file parser
2  *
3  *  Copyright 2004  Red Hat, Inc.  
4  *  Copyright 2009-2010  Collabora Ltd.
5  *  Copyright 2009  Nokia Corporation
6  *
7  * Written by Ray Strode <rstrode@redhat.com>
8  *            Matthias Clasen <mclasen@redhat.com>
9  *
10  * GLib is free software; you can redistribute it and/or modify it
11  * under the terms of the GNU Lesser General Public License as
12  * published by the Free Software Foundation; either version 2 of the
13  * License, or (at your option) any later version.
14  *
15  * GLib is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with GLib; see the file COPYING.LIB.  If not,
22  * see <http://www.gnu.org/licenses/>.
23  */
24
25 #include "config.h"
26
27 #include "gkeyfile.h"
28 #include "gutils.h"
29
30 #include <errno.h>
31 #include <fcntl.h>
32 #include <locale.h>
33 #include <string.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #ifdef G_OS_UNIX
39 #include <unistd.h>
40 #endif
41 #ifdef G_OS_WIN32
42 #include <io.h>
43
44 #undef fstat
45 #define fstat(a,b) _fstati64(a,b)
46 #undef stat
47 #define stat _stati64
48
49 #ifndef S_ISREG
50 #define S_ISREG(mode) ((mode)&_S_IFREG)
51 #endif
52
53 #endif  /* G_OS_WIN23 */
54
55 #include "gconvert.h"
56 #include "gdataset.h"
57 #include "gerror.h"
58 #include "gfileutils.h"
59 #include "ghash.h"
60 #include "glibintl.h"
61 #include "glist.h"
62 #include "gslist.h"
63 #include "gmem.h"
64 #include "gmessages.h"
65 #include "gstdio.h"
66 #include "gstring.h"
67 #include "gstrfuncs.h"
68 #include "gutils.h"
69
70
71 /**
72  * SECTION:keyfile
73  * @title: Key-value file parser
74  * @short_description: parses .ini-like config files
75  *
76  * #GKeyFile lets you parse, edit or create files containing groups of
77  * key-value pairs, which we call "key files" for lack of a better name.
78  * Several freedesktop.org specifications use key files now, e.g the
79  * [Desktop Entry Specification](http://freedesktop.org/Standards/desktop-entry-spec)
80  * and the
81  * [Icon Theme Specification](http://freedesktop.org/Standards/icon-theme-spec).
82  *
83  * The syntax of key files is described in detail in the
84  * [Desktop Entry Specification](http://freedesktop.org/Standards/desktop-entry-spec),
85  * here is a quick summary: Key files
86  * consists of groups of key-value pairs, interspersed with comments.
87  *
88  * |[
89  * # this is just an example
90  * # there can be comments before the first group
91  *
92  * [First Group]
93  *
94  * Name=Key File Example\tthis value shows\nescaping
95  *
96  * # localized strings are stored in multiple key-value pairs
97  * Welcome=Hello
98  * Welcome[de]=Hallo
99  * Welcome[fr_FR]=Bonjour
100  * Welcome[it]=Ciao
101  * Welcome[be@latin]=Hello
102  *
103  * [Another Group]
104  *
105  * Numbers=2;20;-200;0
106  *
107  * Booleans=true;false;true;true
108  * ]|
109  *
110  * Lines beginning with a '#' and blank lines are considered comments.
111  *
112  * Groups are started by a header line containing the group name enclosed
113  * in '[' and ']', and ended implicitly by the start of the next group or
114  * the end of the file. Each key-value pair must be contained in a group.
115  *
116  * Key-value pairs generally have the form `key=value`, with the
117  * exception of localized strings, which have the form
118  * `key[locale]=value`, with a locale identifier of the
119  * form `lang_COUNTRY\@MODIFIER` where `COUNTRY` and `MODIFIER`
120  * are optional.
121  * Space before and after the '=' character are ignored. Newline, tab,
122  * carriage return and backslash characters in value are escaped as \n,
123  * \t, \r, and \\, respectively. To preserve leading spaces in values,
124  * these can also be escaped as \s.
125  *
126  * Key files can store strings (possibly with localized variants), integers,
127  * booleans and lists of these. Lists are separated by a separator character,
128  * typically ';' or ','. To use the list separator character in a value in
129  * a list, it has to be escaped by prefixing it with a backslash.
130  *
131  * This syntax is obviously inspired by the .ini files commonly met
132  * on Windows, but there are some important differences:
133  *
134  * - .ini files use the ';' character to begin comments,
135  *   key files use the '#' character.
136  *
137  * - Key files do not allow for ungrouped keys meaning only
138  *   comments can precede the first group.
139  *
140  * - Key files are always encoded in UTF-8.
141  *
142  * - Key and Group names are case-sensitive. For example, a group called
143  *   [GROUP] is a different from [group].
144  *
145  * - .ini files don't have a strongly typed boolean entry type,
146  *    they only have GetProfileInt(). In key files, only
147  *    true and false (in lower case) are allowed.
148  *
149  * Note that in contrast to the
150  * [Desktop Entry Specification](http://freedesktop.org/Standards/desktop-entry-spec),
151  * groups in key files may contain the same
152  * key multiple times; the last entry wins. Key files may also contain
153  * multiple groups with the same name; they are merged together.
154  * Another difference is that keys and group names in key files are not
155  * restricted to ASCII characters.
156  */
157
158 /**
159  * G_KEY_FILE_ERROR:
160  *
161  * Error domain for key file parsing. Errors in this domain will
162  * be from the #GKeyFileError enumeration.
163  *
164  * See #GError for information on error domains.
165  */
166
167 /**
168  * GKeyFileError:
169  * @G_KEY_FILE_ERROR_UNKNOWN_ENCODING: the text being parsed was in
170  *     an unknown encoding
171  * @G_KEY_FILE_ERROR_PARSE: document was ill-formed
172  * @G_KEY_FILE_ERROR_NOT_FOUND: the file was not found
173  * @G_KEY_FILE_ERROR_KEY_NOT_FOUND: a requested key was not found
174  * @G_KEY_FILE_ERROR_GROUP_NOT_FOUND: a requested group was not found
175  * @G_KEY_FILE_ERROR_INVALID_VALUE: a value could not be parsed
176  *
177  * Error codes returned by key file parsing.
178  */
179
180 /**
181  * GKeyFileFlags:
182  * @G_KEY_FILE_NONE: No flags, default behaviour
183  * @G_KEY_FILE_KEEP_COMMENTS: Use this flag if you plan to write the
184  *     (possibly modified) contents of the key file back to a file;
185  *     otherwise all comments will be lost when the key file is
186  *     written back.
187  * @G_KEY_FILE_KEEP_TRANSLATIONS: Use this flag if you plan to write the
188  *     (possibly modified) contents of the key file back to a file;
189  *     otherwise only the translations for the current language will be
190  *     written back.
191  *
192  * Flags which influence the parsing.
193  */
194
195 /**
196  * G_KEY_FILE_DESKTOP_GROUP:
197  *
198  * The name of the main group of a desktop entry file, as defined in the
199  * [Desktop Entry Specification](http://freedesktop.org/Standards/desktop-entry-spec).
200  * Consult the specification for more
201  * details about the meanings of the keys below.
202  *
203  * Since: 2.14
204  */
205
206 /**
207  * G_KEY_FILE_DESKTOP_KEY_TYPE:
208  *
209  * A key under #G_KEY_FILE_DESKTOP_GROUP, whose value is a string
210  * giving the type of the desktop entry. Usually
211  * #G_KEY_FILE_DESKTOP_TYPE_APPLICATION,
212  * #G_KEY_FILE_DESKTOP_TYPE_LINK, or
213  * #G_KEY_FILE_DESKTOP_TYPE_DIRECTORY.
214  *
215  * Since: 2.14
216  */
217
218 /**
219  * G_KEY_FILE_DESKTOP_KEY_VERSION:
220  *
221  * A key under #G_KEY_FILE_DESKTOP_GROUP, whose value is a string
222  * giving the version of the Desktop Entry Specification used for
223  * the desktop entry file.
224  *
225  * Since: 2.14
226  */
227
228 /**
229  * G_KEY_FILE_DESKTOP_KEY_NAME:
230  *
231  * A key under #G_KEY_FILE_DESKTOP_GROUP, whose value is a localized
232  * string giving the specific name of the desktop entry.
233  *
234  * Since: 2.14
235  */
236
237 /**
238  * G_KEY_FILE_DESKTOP_KEY_GENERIC_NAME:
239  *
240  * A key under #G_KEY_FILE_DESKTOP_GROUP, whose value is a localized
241  * string giving the generic name of the desktop entry.
242  *
243  * Since: 2.14
244  */
245
246 /**
247  * G_KEY_FILE_DESKTOP_KEY_NO_DISPLAY:
248  *
249  * A key under #G_KEY_FILE_DESKTOP_GROUP, whose value is a boolean
250  * stating whether the desktop entry should be shown in menus.
251  *
252  * Since: 2.14
253  */
254
255 /**
256  * G_KEY_FILE_DESKTOP_KEY_COMMENT:
257  *
258  * A key under #G_KEY_FILE_DESKTOP_GROUP, whose value is a localized
259  * string giving the tooltip for the desktop entry.
260  *
261  * Since: 2.14
262  */
263
264 /**
265  * G_KEY_FILE_DESKTOP_KEY_ICON:
266  *
267  * A key under #G_KEY_FILE_DESKTOP_GROUP, whose value is a localized
268  * string giving the name of the icon to be displayed for the desktop
269  * entry.
270  *
271  * Since: 2.14
272  */
273
274 /**
275  * G_KEY_FILE_DESKTOP_KEY_HIDDEN:
276  *
277  * A key under #G_KEY_FILE_DESKTOP_GROUP, whose value is a boolean
278  * stating whether the desktop entry has been deleted by the user.
279  *
280  * Since: 2.14
281  */
282
283 /**
284  * G_KEY_FILE_DESKTOP_KEY_ONLY_SHOW_IN:
285  *
286  * A key under #G_KEY_FILE_DESKTOP_GROUP, whose value is a list of
287  * strings identifying the environments that should display the
288  * desktop entry.
289  *
290  * Since: 2.14
291  */
292
293 /**
294  * G_KEY_FILE_DESKTOP_KEY_NOT_SHOW_IN:
295  *
296  * A key under #G_KEY_FILE_DESKTOP_GROUP, whose value is a list of
297  * strings identifying the environments that should not display the
298  * desktop entry.
299  *
300  * Since: 2.14
301  */
302
303 /**
304  * G_KEY_FILE_DESKTOP_KEY_TRY_EXEC:
305  *
306  * A key under #G_KEY_FILE_DESKTOP_GROUP, whose value is a string
307  * giving the file name of a binary on disk used to determine if the
308  * program is actually installed. It is only valid for desktop entries
309  * with the `Application` type.
310  *
311  * Since: 2.14
312  */
313
314 /**
315  * G_KEY_FILE_DESKTOP_KEY_EXEC:
316  *
317  * A key under #G_KEY_FILE_DESKTOP_GROUP, whose value is a string
318  * giving the command line to execute. It is only valid for desktop
319  * entries with the `Application` type.
320  *
321  * Since: 2.14
322  */
323
324  /**
325   * G_KEY_FILE_DESKTOP_KEY_PATH:
326   *
327   * A key under #G_KEY_FILE_DESKTOP_GROUP, whose value is a string
328   * containing the working directory to run the program in. It is only
329   * valid for desktop entries with the `Application` type.
330   *
331   * Since: 2.14
332   */
333
334 /**
335  * G_KEY_FILE_DESKTOP_KEY_TERMINAL:
336  *
337  * A key under #G_KEY_FILE_DESKTOP_GROUP, whose value is a boolean
338  * stating whether the program should be run in a terminal window.
339  * It is only valid for desktop entries with the
340  * `Application` type.
341  *
342  * Since: 2.14
343  */
344
345 /**
346  * G_KEY_FILE_DESKTOP_KEY_MIME_TYPE:
347  *
348  * A key under #G_KEY_FILE_DESKTOP_GROUP, whose value is a list
349  * of strings giving the MIME types supported by this desktop entry.
350  *
351  * Since: 2.14
352  */
353
354 /**
355  * G_KEY_FILE_DESKTOP_KEY_CATEGORIES:
356  *
357  * A key under #G_KEY_FILE_DESKTOP_GROUP, whose value is a list
358  * of strings giving the categories in which the desktop entry
359  * should be shown in a menu.
360  *
361  * Since: 2.14
362  */
363
364 /**
365  * G_KEY_FILE_DESKTOP_KEY_STARTUP_NOTIFY:
366  *
367  * A key under #G_KEY_FILE_DESKTOP_GROUP, whose value is a boolean
368  * stating whether the application supports the
369  * [Startup Notification Protocol Specification](http://www.freedesktop.org/Standards/startup-notification-spec).
370  *
371  * Since: 2.14
372  */
373
374 /**
375  * G_KEY_FILE_DESKTOP_KEY_STARTUP_WM_CLASS:
376  *
377  * A key under #G_KEY_FILE_DESKTOP_GROUP, whose value is string
378  * identifying the WM class or name hint of a window that the application
379  * will create, which can be used to emulate Startup Notification with
380  * older applications.
381  *
382  * Since: 2.14
383  */
384
385 /**
386  * G_KEY_FILE_DESKTOP_KEY_URL :
387  *
388  * A key under #G_KEY_FILE_DESKTOP_GROUP, whose value is a string
389  * giving the URL to access. It is only valid for desktop entries
390  * with the `Link` type.
391  *
392  * Since: 2.14
393  */
394
395 /**
396  * G_KEY_FILE_DESKTOP_TYPE_APPLICATION:
397  *
398  * The value of the #G_KEY_FILE_DESKTOP_KEY_TYPE, key for desktop
399  * entries representing applications.
400  *
401  * Since: 2.14
402  */
403
404 /**
405  * G_KEY_FILE_DESKTOP_TYPE_LINK:
406  *
407  * The value of the #G_KEY_FILE_DESKTOP_KEY_TYPE, key for desktop
408  * entries representing links to documents.
409  *
410  * Since: 2.14
411  */
412
413 /**
414  * G_KEY_FILE_DESKTOP_TYPE_DIRECTORY:
415  *
416  * The value of the #G_KEY_FILE_DESKTOP_KEY_TYPE, key for desktop
417  * entries representing directories.
418  *
419  * Since: 2.14
420  */
421
422 typedef struct _GKeyFileGroup GKeyFileGroup;
423
424 /**
425  * GKeyFile:
426  *
427  * The GKeyFile struct contains only private data
428  * and should not be accessed directly.
429  */
430 struct _GKeyFile
431 {
432   GList *groups;
433   GHashTable *group_hash;
434
435   GKeyFileGroup *start_group;
436   GKeyFileGroup *current_group;
437
438   GString *parse_buffer; /* Holds up to one line of not-yet-parsed data */
439
440   gchar list_separator;
441
442   GKeyFileFlags flags;
443
444   gchar **locales;
445
446   volatile gint ref_count;
447 };
448
449 typedef struct _GKeyFileKeyValuePair GKeyFileKeyValuePair;
450
451 struct _GKeyFileGroup
452 {
453   const gchar *name;  /* NULL for above first group (which will be comments) */
454
455   GKeyFileKeyValuePair *comment; /* Special comment that is stuck to the top of a group */
456
457   GList *key_value_pairs;
458
459   /* Used in parallel with key_value_pairs for
460    * increased lookup performance
461    */
462   GHashTable *lookup_map;
463 };
464
465 struct _GKeyFileKeyValuePair
466 {
467   gchar *key;  /* NULL for comments */
468   gchar *value;
469 };
470
471 static gint                  find_file_in_data_dirs            (const gchar            *file,
472                                                                 const gchar           **data_dirs,
473                                                                 gchar                 **output_file,
474                                                                 GError                **error);
475 static gboolean              g_key_file_load_from_fd           (GKeyFile               *key_file,
476                                                                 gint                    fd,
477                                                                 GKeyFileFlags           flags,
478                                                                 GError                **error);
479 static GList                *g_key_file_lookup_group_node      (GKeyFile               *key_file,
480                                                                 const gchar            *group_name);
481 static GKeyFileGroup        *g_key_file_lookup_group           (GKeyFile               *key_file,
482                                                                 const gchar            *group_name);
483
484 static GList                *g_key_file_lookup_key_value_pair_node  (GKeyFile       *key_file,
485                                                                      GKeyFileGroup  *group,
486                                                                      const gchar    *key);
487 static GKeyFileKeyValuePair *g_key_file_lookup_key_value_pair       (GKeyFile       *key_file,
488                                                                      GKeyFileGroup  *group,
489                                                                      const gchar    *key);
490
491 static void                  g_key_file_remove_group_node          (GKeyFile      *key_file,
492                                                                     GList         *group_node);
493 static void                  g_key_file_remove_key_value_pair_node (GKeyFile      *key_file,
494                                                                     GKeyFileGroup *group,
495                                                                     GList         *pair_node);
496
497 static void                  g_key_file_add_key_value_pair     (GKeyFile               *key_file,
498                                                                 GKeyFileGroup          *group,
499                                                                 GKeyFileKeyValuePair   *pair);
500 static void                  g_key_file_add_key                (GKeyFile               *key_file,
501                                                                 GKeyFileGroup          *group,
502                                                                 const gchar            *key,
503                                                                 const gchar            *value);
504 static void                  g_key_file_add_group              (GKeyFile               *key_file,
505                                                                 const gchar            *group_name);
506 static gboolean              g_key_file_is_group_name          (const gchar *name);
507 static gboolean              g_key_file_is_key_name            (const gchar *name);
508 static void                  g_key_file_key_value_pair_free    (GKeyFileKeyValuePair   *pair);
509 static gboolean              g_key_file_line_is_comment        (const gchar            *line);
510 static gboolean              g_key_file_line_is_group          (const gchar            *line);
511 static gboolean              g_key_file_line_is_key_value_pair (const gchar            *line);
512 static gchar                *g_key_file_parse_value_as_string  (GKeyFile               *key_file,
513                                                                 const gchar            *value,
514                                                                 GSList                **separators,
515                                                                 GError                **error);
516 static gchar                *g_key_file_parse_string_as_value  (GKeyFile               *key_file,
517                                                                 const gchar            *string,
518                                                                 gboolean                escape_separator);
519 static gint                  g_key_file_parse_value_as_integer (GKeyFile               *key_file,
520                                                                 const gchar            *value,
521                                                                 GError                **error);
522 static gchar                *g_key_file_parse_integer_as_value (GKeyFile               *key_file,
523                                                                 gint                    value);
524 static gdouble               g_key_file_parse_value_as_double  (GKeyFile               *key_file,
525                                                                 const gchar            *value,
526                                                                 GError                **error);
527 static gboolean              g_key_file_parse_value_as_boolean (GKeyFile               *key_file,
528                                                                 const gchar            *value,
529                                                                 GError                **error);
530 static gchar                *g_key_file_parse_boolean_as_value (GKeyFile               *key_file,
531                                                                 gboolean                value);
532 static gchar                *g_key_file_parse_value_as_comment (GKeyFile               *key_file,
533                                                                 const gchar            *value);
534 static gchar                *g_key_file_parse_comment_as_value (GKeyFile               *key_file,
535                                                                 const gchar            *comment);
536 static void                  g_key_file_parse_key_value_pair   (GKeyFile               *key_file,
537                                                                 const gchar            *line,
538                                                                 gsize                   length,
539                                                                 GError                **error);
540 static void                  g_key_file_parse_comment          (GKeyFile               *key_file,
541                                                                 const gchar            *line,
542                                                                 gsize                   length,
543                                                                 GError                **error);
544 static void                  g_key_file_parse_group            (GKeyFile               *key_file,
545                                                                 const gchar            *line,
546                                                                 gsize                   length,
547                                                                 GError                **error);
548 static gchar                *key_get_locale                    (const gchar            *key);
549 static void                  g_key_file_parse_data             (GKeyFile               *key_file,
550                                                                 const gchar            *data,
551                                                                 gsize                   length,
552                                                                 GError                **error);
553 static void                  g_key_file_flush_parse_buffer     (GKeyFile               *key_file,
554                                                                 GError                **error);
555
556 G_DEFINE_QUARK (g-key-file-error-quark, g_key_file_error)
557
558 static void
559 g_key_file_init (GKeyFile *key_file)
560 {  
561   key_file->current_group = g_slice_new0 (GKeyFileGroup);
562   key_file->groups = g_list_prepend (NULL, key_file->current_group);
563   key_file->group_hash = g_hash_table_new (g_str_hash, g_str_equal);
564   key_file->start_group = NULL;
565   key_file->parse_buffer = g_string_sized_new (128);
566   key_file->list_separator = ';';
567   key_file->flags = 0;
568   key_file->locales = g_strdupv ((gchar **)g_get_language_names ());
569 }
570
571 static void
572 g_key_file_clear (GKeyFile *key_file)
573 {
574   GList *tmp, *group_node;
575
576   if (key_file->locales) 
577     {
578       g_strfreev (key_file->locales);
579       key_file->locales = NULL;
580     }
581
582   if (key_file->parse_buffer)
583     {
584       g_string_free (key_file->parse_buffer, TRUE);
585       key_file->parse_buffer = NULL;
586     }
587
588   tmp = key_file->groups;
589   while (tmp != NULL)
590     {
591       group_node = tmp;
592       tmp = tmp->next;
593       g_key_file_remove_group_node (key_file, group_node);
594     }
595
596   if (key_file->group_hash != NULL)
597     {
598       g_hash_table_destroy (key_file->group_hash);
599       key_file->group_hash = NULL;
600     }
601
602   g_warn_if_fail (key_file->groups == NULL);
603 }
604
605
606 /**
607  * g_key_file_new:
608  *
609  * Creates a new empty #GKeyFile object. Use
610  * g_key_file_load_from_file(), g_key_file_load_from_data(),
611  * g_key_file_load_from_dirs() or g_key_file_load_from_data_dirs() to
612  * read an existing key file.
613  *
614  * Return value: (transfer full): an empty #GKeyFile.
615  *
616  * Since: 2.6
617  **/
618 GKeyFile *
619 g_key_file_new (void)
620 {
621   GKeyFile *key_file;
622
623   key_file = g_slice_new0 (GKeyFile);
624   key_file->ref_count = 1;
625   g_key_file_init (key_file);
626
627   return key_file;
628 }
629
630 /**
631  * g_key_file_set_list_separator:
632  * @key_file: a #GKeyFile 
633  * @separator: the separator
634  *
635  * Sets the character which is used to separate
636  * values in lists. Typically ';' or ',' are used
637  * as separators. The default list separator is ';'.
638  *
639  * Since: 2.6
640  */
641 void
642 g_key_file_set_list_separator (GKeyFile *key_file,
643                                gchar     separator)
644 {
645   g_return_if_fail (key_file != NULL);
646
647   key_file->list_separator = separator;
648 }
649
650
651 /* Iterates through all the directories in *dirs trying to
652  * open file.  When it successfully locates and opens a file it
653  * returns the file descriptor to the open file.  It also
654  * outputs the absolute path of the file in output_file.
655  */
656 static gint
657 find_file_in_data_dirs (const gchar   *file,
658                         const gchar  **dirs,
659                         gchar        **output_file,
660                         GError       **error)
661 {
662   const gchar **data_dirs, *data_dir;
663   gchar *path;
664   gint fd;
665
666   path = NULL;
667   fd = -1;
668
669   if (dirs == NULL)
670     return fd;
671
672   data_dirs = dirs;
673
674   while (data_dirs && (data_dir = *data_dirs) && fd == -1)
675     {
676       gchar *candidate_file, *sub_dir;
677
678       candidate_file = (gchar *) file;
679       sub_dir = g_strdup ("");
680       while (candidate_file != NULL && fd == -1)
681         {
682           gchar *p;
683
684           path = g_build_filename (data_dir, sub_dir,
685                                    candidate_file, NULL);
686
687           fd = g_open (path, O_RDONLY, 0);
688
689           if (fd == -1)
690             {
691               g_free (path);
692               path = NULL;
693             }
694
695           candidate_file = strchr (candidate_file, '-');
696
697           if (candidate_file == NULL)
698             break;
699
700           candidate_file++;
701
702           g_free (sub_dir);
703           sub_dir = g_strndup (file, candidate_file - file - 1);
704
705           for (p = sub_dir; *p != '\0'; p++)
706             {
707               if (*p == '-')
708                 *p = G_DIR_SEPARATOR;
709             }
710         }
711       g_free (sub_dir);
712       data_dirs++;
713     }
714
715   if (fd == -1)
716     {
717       g_set_error_literal (error, G_KEY_FILE_ERROR,
718                            G_KEY_FILE_ERROR_NOT_FOUND,
719                            _("Valid key file could not be "
720                              "found in search dirs"));
721     }
722
723   if (output_file != NULL && fd > 0)
724     *output_file = g_strdup (path);
725
726   g_free (path);
727
728   return fd;
729 }
730
731 static gboolean
732 g_key_file_load_from_fd (GKeyFile       *key_file,
733                          gint            fd,
734                          GKeyFileFlags   flags,
735                          GError        **error)
736 {
737   GError *key_file_error = NULL;
738   gssize bytes_read;
739   struct stat stat_buf;
740   gchar read_buf[4096];
741   gchar list_separator;
742
743   if (fstat (fd, &stat_buf) < 0)
744     {
745       g_set_error_literal (error, G_FILE_ERROR,
746                            g_file_error_from_errno (errno),
747                            g_strerror (errno));
748       return FALSE;
749     }
750
751   if (!S_ISREG (stat_buf.st_mode))
752     {
753       g_set_error_literal (error, G_KEY_FILE_ERROR,
754                            G_KEY_FILE_ERROR_PARSE,
755                            _("Not a regular file"));
756       return FALSE;
757     }
758
759   list_separator = key_file->list_separator;
760   g_key_file_clear (key_file);
761   g_key_file_init (key_file);
762   key_file->list_separator = list_separator;
763   key_file->flags = flags;
764
765   do
766     {
767       bytes_read = read (fd, read_buf, 4096);
768
769       if (bytes_read == 0)  /* End of File */
770         break;
771
772       if (bytes_read < 0)
773         {
774           if (errno == EINTR || errno == EAGAIN)
775             continue;
776
777           g_set_error_literal (error, G_FILE_ERROR,
778                                g_file_error_from_errno (errno),
779                                g_strerror (errno));
780           return FALSE;
781         }
782
783       g_key_file_parse_data (key_file,
784                              read_buf, bytes_read,
785                              &key_file_error);
786     }
787   while (!key_file_error);
788
789   if (key_file_error)
790     {
791       g_propagate_error (error, key_file_error);
792       return FALSE;
793     }
794
795   g_key_file_flush_parse_buffer (key_file, &key_file_error);
796
797   if (key_file_error)
798     {
799       g_propagate_error (error, key_file_error);
800       return FALSE;
801     }
802
803   return TRUE;
804 }
805
806 /**
807  * g_key_file_load_from_file:
808  * @key_file: an empty #GKeyFile struct
809  * @file: (type filename): the path of a filename to load, in the GLib filename encoding
810  * @flags: flags from #GKeyFileFlags
811  * @error: return location for a #GError, or %NULL
812  *
813  * Loads a key file into an empty #GKeyFile structure.
814  * If the file could not be loaded then @error is set to
815  * either a #GFileError or #GKeyFileError.
816  *
817  * Return value: %TRUE if a key file could be loaded, %FALSE otherwise
818  *
819  * Since: 2.6
820  **/
821 gboolean
822 g_key_file_load_from_file (GKeyFile       *key_file,
823                            const gchar    *file,
824                            GKeyFileFlags   flags,
825                            GError        **error)
826 {
827   GError *key_file_error = NULL;
828   gint fd;
829
830   g_return_val_if_fail (key_file != NULL, FALSE);
831   g_return_val_if_fail (file != NULL, FALSE);
832
833   fd = g_open (file, O_RDONLY, 0);
834
835   if (fd == -1)
836     {
837       g_set_error_literal (error, G_FILE_ERROR,
838                            g_file_error_from_errno (errno),
839                            g_strerror (errno));
840       return FALSE;
841     }
842
843   g_key_file_load_from_fd (key_file, fd, flags, &key_file_error);
844   close (fd);
845
846   if (key_file_error)
847     {
848       g_propagate_error (error, key_file_error);
849       return FALSE;
850     }
851
852   return TRUE;
853 }
854
855 /**
856  * g_key_file_load_from_data:
857  * @key_file: an empty #GKeyFile struct
858  * @data: key file loaded in memory
859  * @length: the length of @data in bytes (or (gsize)-1 if data is nul-terminated)
860  * @flags: flags from #GKeyFileFlags
861  * @error: return location for a #GError, or %NULL
862  *
863  * Loads a key file from memory into an empty #GKeyFile structure.  
864  * If the object cannot be created then %error is set to a #GKeyFileError. 
865  *
866  * Return value: %TRUE if a key file could be loaded, %FALSE otherwise
867  *
868  * Since: 2.6
869  **/
870 gboolean
871 g_key_file_load_from_data (GKeyFile       *key_file,
872                            const gchar    *data,
873                            gsize           length,
874                            GKeyFileFlags   flags,
875                            GError        **error)
876 {
877   GError *key_file_error = NULL;
878   gchar list_separator;
879
880   g_return_val_if_fail (key_file != NULL, FALSE);
881   g_return_val_if_fail (data != NULL || length == 0, FALSE);
882
883   if (length == (gsize)-1)
884     length = strlen (data);
885
886   list_separator = key_file->list_separator;
887   g_key_file_clear (key_file);
888   g_key_file_init (key_file);
889   key_file->list_separator = list_separator;
890   key_file->flags = flags;
891
892   g_key_file_parse_data (key_file, data, length, &key_file_error);
893   
894   if (key_file_error)
895     {
896       g_propagate_error (error, key_file_error);
897       return FALSE;
898     }
899
900   g_key_file_flush_parse_buffer (key_file, &key_file_error);
901   
902   if (key_file_error)
903     {
904       g_propagate_error (error, key_file_error);
905       return FALSE;
906     }
907
908   return TRUE;
909 }
910
911 /**
912  * g_key_file_load_from_dirs:
913  * @key_file: an empty #GKeyFile struct
914  * @file: (type filename): a relative path to a filename to open and parse
915  * @search_dirs: (array zero-terminated=1) (element-type filename): %NULL-terminated array of directories to search
916  * @full_path: (out) (type filename) (allow-none): return location for a string containing the full path
917  *   of the file, or %NULL
918  * @flags: flags from #GKeyFileFlags
919  * @error: return location for a #GError, or %NULL
920  *
921  * This function looks for a key file named @file in the paths
922  * specified in @search_dirs, loads the file into @key_file and
923  * returns the file's full path in @full_path.  If the file could not
924  * be loaded then an %error is set to either a #GFileError or
925  * #GKeyFileError.
926  *
927  * Return value: %TRUE if a key file could be loaded, %FALSE otherwise
928  *
929  * Since: 2.14
930  **/
931 gboolean
932 g_key_file_load_from_dirs (GKeyFile       *key_file,
933                            const gchar    *file,
934                            const gchar   **search_dirs,
935                            gchar         **full_path,
936                            GKeyFileFlags   flags,
937                            GError        **error)
938 {
939   GError *key_file_error = NULL;
940   const gchar **data_dirs;
941   gchar *output_path;
942   gint fd;
943   gboolean found_file;
944
945   g_return_val_if_fail (key_file != NULL, FALSE);
946   g_return_val_if_fail (!g_path_is_absolute (file), FALSE);
947   g_return_val_if_fail (search_dirs != NULL, FALSE);
948
949   found_file = FALSE;
950   data_dirs = search_dirs;
951   output_path = NULL;
952   while (*data_dirs != NULL && !found_file)
953     {
954       g_free (output_path);
955
956       fd = find_file_in_data_dirs (file, data_dirs, &output_path,
957                                    &key_file_error);
958
959       if (fd == -1)
960         {
961           if (key_file_error)
962             g_propagate_error (error, key_file_error);
963           break;
964         }
965
966       found_file = g_key_file_load_from_fd (key_file, fd, flags,
967                                             &key_file_error);
968       close (fd);
969
970       if (key_file_error)
971         {
972           g_propagate_error (error, key_file_error);
973           break;
974         }
975     }
976
977   if (found_file && full_path)
978     *full_path = output_path;
979   else
980     g_free (output_path);
981
982   return found_file;
983 }
984
985 /**
986  * g_key_file_load_from_data_dirs:
987  * @key_file: an empty #GKeyFile struct
988  * @file: (type filename): a relative path to a filename to open and parse
989  * @full_path: (out) (type filename) (allow-none): return location for a string containing the full path
990  *   of the file, or %NULL
991  * @flags: flags from #GKeyFileFlags 
992  * @error: return location for a #GError, or %NULL
993  *
994  * This function looks for a key file named @file in the paths 
995  * returned from g_get_user_data_dir() and g_get_system_data_dirs(), 
996  * loads the file into @key_file and returns the file's full path in 
997  * @full_path.  If the file could not be loaded then an %error is
998  * set to either a #GFileError or #GKeyFileError.
999  *
1000  * Return value: %TRUE if a key file could be loaded, %FALSE othewise
1001  * Since: 2.6
1002  **/
1003 gboolean
1004 g_key_file_load_from_data_dirs (GKeyFile       *key_file,
1005                                 const gchar    *file,
1006                                 gchar         **full_path,
1007                                 GKeyFileFlags   flags,
1008                                 GError        **error)
1009 {
1010   gchar **all_data_dirs;
1011   const gchar * user_data_dir;
1012   const gchar * const * system_data_dirs;
1013   gsize i, j;
1014   gboolean found_file;
1015
1016   g_return_val_if_fail (key_file != NULL, FALSE);
1017   g_return_val_if_fail (!g_path_is_absolute (file), FALSE);
1018
1019   user_data_dir = g_get_user_data_dir ();
1020   system_data_dirs = g_get_system_data_dirs ();
1021   all_data_dirs = g_new (gchar *, g_strv_length ((gchar **)system_data_dirs) + 2);
1022
1023   i = 0;
1024   all_data_dirs[i++] = g_strdup (user_data_dir);
1025
1026   j = 0;
1027   while (system_data_dirs[j] != NULL)
1028     all_data_dirs[i++] = g_strdup (system_data_dirs[j++]);
1029   all_data_dirs[i] = NULL;
1030
1031   found_file = g_key_file_load_from_dirs (key_file,
1032                                           file,
1033                                           (const gchar **)all_data_dirs,
1034                                           full_path,
1035                                           flags,
1036                                           error);
1037
1038   g_strfreev (all_data_dirs);
1039
1040   return found_file;
1041 }
1042
1043 /**
1044  * g_key_file_ref: (skip)
1045  * @key_file: a #GKeyFile
1046  *
1047  * Increases the reference count of @key_file.
1048  *
1049  * Returns: the same @key_file.
1050  *
1051  * Since: 2.32
1052  **/
1053 GKeyFile *
1054 g_key_file_ref (GKeyFile *key_file)
1055 {
1056   g_return_val_if_fail (key_file != NULL, NULL);
1057
1058   g_atomic_int_inc (&key_file->ref_count);
1059
1060   return key_file;
1061 }
1062
1063 /**
1064  * g_key_file_free: (skip)
1065  * @key_file: a #GKeyFile
1066  *
1067  * Clears all keys and groups from @key_file, and decreases the
1068  * reference count by 1. If the reference count reaches zero,
1069  * frees the key file and all its allocated memory.
1070  *
1071  * Since: 2.6
1072  **/
1073 void
1074 g_key_file_free (GKeyFile *key_file)
1075 {
1076   g_return_if_fail (key_file != NULL);
1077
1078   g_key_file_clear (key_file);
1079   g_key_file_unref (key_file);
1080 }
1081
1082 /**
1083  * g_key_file_unref:
1084  * @key_file: a #GKeyFile
1085  *
1086  * Decreases the reference count of @key_file by 1. If the reference count
1087  * reaches zero, frees the key file and all its allocated memory.
1088  *
1089  * Since: 2.32
1090  **/
1091 void
1092 g_key_file_unref (GKeyFile *key_file)
1093 {
1094   g_return_if_fail (key_file != NULL);
1095
1096   if (g_atomic_int_dec_and_test (&key_file->ref_count))
1097     {
1098       g_key_file_clear (key_file);
1099       g_slice_free (GKeyFile, key_file);
1100     }
1101 }
1102
1103 /* If G_KEY_FILE_KEEP_TRANSLATIONS is not set, only returns
1104  * true for locales that match those in g_get_language_names().
1105  */
1106 static gboolean
1107 g_key_file_locale_is_interesting (GKeyFile    *key_file,
1108                                   const gchar *locale)
1109 {
1110   gsize i;
1111
1112   if (key_file->flags & G_KEY_FILE_KEEP_TRANSLATIONS)
1113     return TRUE;
1114
1115   for (i = 0; key_file->locales[i] != NULL; i++)
1116     {
1117       if (g_ascii_strcasecmp (key_file->locales[i], locale) == 0)
1118         return TRUE;
1119     }
1120
1121   return FALSE;
1122 }
1123
1124 static void
1125 g_key_file_parse_line (GKeyFile     *key_file,
1126                        const gchar  *line,
1127                        gsize         length,
1128                        GError      **error)
1129 {
1130   GError *parse_error = NULL;
1131   gchar *line_start;
1132
1133   g_return_if_fail (key_file != NULL);
1134   g_return_if_fail (line != NULL);
1135
1136   line_start = (gchar *) line;
1137   while (g_ascii_isspace (*line_start))
1138     line_start++;
1139
1140   if (g_key_file_line_is_comment (line_start))
1141     g_key_file_parse_comment (key_file, line, length, &parse_error);
1142   else if (g_key_file_line_is_group (line_start))
1143     g_key_file_parse_group (key_file, line_start,
1144                             length - (line_start - line),
1145                             &parse_error);
1146   else if (g_key_file_line_is_key_value_pair (line_start))
1147     g_key_file_parse_key_value_pair (key_file, line_start,
1148                                      length - (line_start - line),
1149                                      &parse_error);
1150   else
1151     {
1152       gchar *line_utf8 = _g_utf8_make_valid (line);
1153       g_set_error (error, G_KEY_FILE_ERROR,
1154                    G_KEY_FILE_ERROR_PARSE,
1155                    _("Key file contains line '%s' which is not "
1156                      "a key-value pair, group, or comment"),
1157                    line_utf8);
1158       g_free (line_utf8);
1159
1160       return;
1161     }
1162
1163   if (parse_error)
1164     g_propagate_error (error, parse_error);
1165 }
1166
1167 static void
1168 g_key_file_parse_comment (GKeyFile     *key_file,
1169                           const gchar  *line,
1170                           gsize         length,
1171                           GError      **error)
1172 {
1173   GKeyFileKeyValuePair *pair;
1174   
1175   if (!(key_file->flags & G_KEY_FILE_KEEP_COMMENTS))
1176     return;
1177   
1178   g_warn_if_fail (key_file->current_group != NULL);
1179
1180   pair = g_slice_new (GKeyFileKeyValuePair);
1181   pair->key = NULL;
1182   pair->value = g_strndup (line, length);
1183   
1184   key_file->current_group->key_value_pairs =
1185     g_list_prepend (key_file->current_group->key_value_pairs, pair);
1186 }
1187
1188 static void
1189 g_key_file_parse_group (GKeyFile     *key_file,
1190                         const gchar  *line,
1191                         gsize         length,
1192                         GError      **error)
1193 {
1194   gchar *group_name;
1195   const gchar *group_name_start, *group_name_end;
1196   
1197   /* advance past opening '['
1198    */
1199   group_name_start = line + 1;
1200   group_name_end = line + length - 1;
1201   
1202   while (*group_name_end != ']')
1203     group_name_end--;
1204
1205   group_name = g_strndup (group_name_start, 
1206                           group_name_end - group_name_start);
1207   
1208   if (!g_key_file_is_group_name (group_name))
1209     {
1210       g_set_error (error, G_KEY_FILE_ERROR,
1211                    G_KEY_FILE_ERROR_PARSE,
1212                    _("Invalid group name: %s"), group_name);
1213       g_free (group_name);
1214       return;
1215     }
1216
1217   g_key_file_add_group (key_file, group_name);
1218   g_free (group_name);
1219 }
1220
1221 static void
1222 g_key_file_parse_key_value_pair (GKeyFile     *key_file,
1223                                  const gchar  *line,
1224                                  gsize         length,
1225                                  GError      **error)
1226 {
1227   gchar *key, *value, *key_end, *value_start, *locale;
1228   gsize key_len, value_len;
1229
1230   if (key_file->current_group == NULL || key_file->current_group->name == NULL)
1231     {
1232       g_set_error_literal (error, G_KEY_FILE_ERROR,
1233                            G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
1234                            _("Key file does not start with a group"));
1235       return;
1236     }
1237
1238   key_end = value_start = strchr (line, '=');
1239
1240   g_warn_if_fail (key_end != NULL);
1241
1242   key_end--;
1243   value_start++;
1244
1245   /* Pull the key name from the line (chomping trailing whitespace)
1246    */
1247   while (g_ascii_isspace (*key_end))
1248     key_end--;
1249
1250   key_len = key_end - line + 2;
1251
1252   g_warn_if_fail (key_len <= length);
1253
1254   key = g_strndup (line, key_len - 1);
1255
1256   if (!g_key_file_is_key_name (key))
1257     {
1258       g_set_error (error, G_KEY_FILE_ERROR,
1259                    G_KEY_FILE_ERROR_PARSE,
1260                    _("Invalid key name: %s"), key);
1261       g_free (key);
1262       return; 
1263     }
1264
1265   /* Pull the value from the line (chugging leading whitespace)
1266    */
1267   while (g_ascii_isspace (*value_start))
1268     value_start++;
1269
1270   value_len = line + length - value_start + 1;
1271
1272   value = g_strndup (value_start, value_len);
1273
1274   g_warn_if_fail (key_file->start_group != NULL);
1275
1276   if (key_file->current_group
1277       && key_file->current_group->name
1278       && strcmp (key_file->start_group->name,
1279                  key_file->current_group->name) == 0
1280       && strcmp (key, "Encoding") == 0)
1281     {
1282       if (g_ascii_strcasecmp (value, "UTF-8") != 0)
1283         {
1284           gchar *value_utf8 = _g_utf8_make_valid (value);
1285           g_set_error (error, G_KEY_FILE_ERROR,
1286                        G_KEY_FILE_ERROR_UNKNOWN_ENCODING,
1287                        _("Key file contains unsupported "
1288                          "encoding '%s'"), value_utf8);
1289           g_free (value_utf8);
1290
1291           g_free (key);
1292           g_free (value);
1293           return;
1294         }
1295     }
1296
1297   /* Is this key a translation? If so, is it one that we care about?
1298    */
1299   locale = key_get_locale (key);
1300
1301   if (locale == NULL || g_key_file_locale_is_interesting (key_file, locale))
1302     {
1303       GKeyFileKeyValuePair *pair;
1304
1305       pair = g_slice_new (GKeyFileKeyValuePair);
1306       pair->key = key;
1307       pair->value = value;
1308
1309       g_key_file_add_key_value_pair (key_file, key_file->current_group, pair);
1310     }
1311   else
1312     {
1313       g_free (key);
1314       g_free (value);
1315     }
1316
1317   g_free (locale);
1318 }
1319
1320 static gchar *
1321 key_get_locale (const gchar *key)
1322 {
1323   gchar *locale;
1324
1325   locale = g_strrstr (key, "[");
1326
1327   if (locale && strlen (locale) <= 2)
1328     locale = NULL;
1329
1330   if (locale)
1331     locale = g_strndup (locale + 1, strlen (locale) - 2);
1332
1333   return locale;
1334 }
1335
1336 static void
1337 g_key_file_parse_data (GKeyFile     *key_file,
1338                        const gchar  *data,
1339                        gsize         length,
1340                        GError      **error)
1341 {
1342   GError *parse_error;
1343   gsize i;
1344
1345   g_return_if_fail (key_file != NULL);
1346   g_return_if_fail (data != NULL || length == 0);
1347
1348   parse_error = NULL;
1349
1350   i = 0;
1351   while (i < length)
1352     {
1353       if (data[i] == '\n')
1354         {
1355           if (key_file->parse_buffer->len > 0
1356               && (key_file->parse_buffer->str[key_file->parse_buffer->len - 1]
1357                   == '\r'))
1358             g_string_erase (key_file->parse_buffer,
1359                             key_file->parse_buffer->len - 1,
1360                             1);
1361             
1362           /* When a newline is encountered flush the parse buffer so that the
1363            * line can be parsed.  Note that completely blank lines won't show
1364            * up in the parse buffer, so they get parsed directly.
1365            */
1366           if (key_file->parse_buffer->len > 0)
1367             g_key_file_flush_parse_buffer (key_file, &parse_error);
1368           else
1369             g_key_file_parse_comment (key_file, "", 1, &parse_error);
1370
1371           if (parse_error)
1372             {
1373               g_propagate_error (error, parse_error);
1374               return;
1375             }
1376           i++;
1377         }
1378       else
1379         {
1380           const gchar *start_of_line;
1381           const gchar *end_of_line;
1382           gsize line_length;
1383
1384           start_of_line = data + i;
1385           end_of_line = memchr (start_of_line, '\n', length - i);
1386
1387           if (end_of_line == NULL)
1388             end_of_line = data + length;
1389
1390           line_length = end_of_line - start_of_line;
1391
1392           g_string_append_len (key_file->parse_buffer, start_of_line, line_length);
1393           i += line_length;
1394         }
1395     }
1396 }
1397
1398 static void
1399 g_key_file_flush_parse_buffer (GKeyFile  *key_file,
1400                                GError   **error)
1401 {
1402   GError *file_error = NULL;
1403
1404   g_return_if_fail (key_file != NULL);
1405
1406   file_error = NULL;
1407
1408   if (key_file->parse_buffer->len > 0)
1409     {
1410       g_key_file_parse_line (key_file, key_file->parse_buffer->str,
1411                              key_file->parse_buffer->len,
1412                              &file_error);
1413       g_string_erase (key_file->parse_buffer, 0, -1);
1414
1415       if (file_error)
1416         {
1417           g_propagate_error (error, file_error);
1418           return;
1419         }
1420     }
1421 }
1422
1423 /**
1424  * g_key_file_to_data:
1425  * @key_file: a #GKeyFile
1426  * @length: (out) (allow-none): return location for the length of the
1427  *   returned string, or %NULL
1428  * @error: return location for a #GError, or %NULL
1429  *
1430  * This function outputs @key_file as a string.  
1431  *
1432  * Note that this function never reports an error,
1433  * so it is safe to pass %NULL as @error.
1434  *
1435  * Return value: a newly allocated string holding
1436  *   the contents of the #GKeyFile 
1437  *
1438  * Since: 2.6
1439  **/
1440 gchar *
1441 g_key_file_to_data (GKeyFile  *key_file,
1442                     gsize     *length,
1443                     GError   **error)
1444 {
1445   GString *data_string;
1446   GList *group_node, *key_file_node;
1447
1448   g_return_val_if_fail (key_file != NULL, NULL);
1449
1450   data_string = g_string_new (NULL);
1451
1452   for (group_node = g_list_last (key_file->groups);
1453        group_node != NULL;
1454        group_node = group_node->prev)
1455     {
1456       GKeyFileGroup *group;
1457
1458       group = (GKeyFileGroup *) group_node->data;
1459
1460       /* separate groups by at least an empty line */
1461       if (data_string->len >= 2 &&
1462           data_string->str[data_string->len - 2] != '\n')
1463         g_string_append_c (data_string, '\n');
1464
1465       if (group->comment != NULL)
1466         g_string_append_printf (data_string, "%s\n", group->comment->value);
1467
1468       if (group->name != NULL)
1469         g_string_append_printf (data_string, "[%s]\n", group->name);
1470
1471       for (key_file_node = g_list_last (group->key_value_pairs);
1472            key_file_node != NULL;
1473            key_file_node = key_file_node->prev)
1474         {
1475           GKeyFileKeyValuePair *pair;
1476
1477           pair = (GKeyFileKeyValuePair *) key_file_node->data;
1478
1479           if (pair->key != NULL)
1480             g_string_append_printf (data_string, "%s=%s\n", pair->key, pair->value);
1481           else
1482             g_string_append_printf (data_string, "%s\n", pair->value);
1483         }
1484     }
1485
1486   if (length)
1487     *length = data_string->len;
1488
1489   return g_string_free (data_string, FALSE);
1490 }
1491
1492 /**
1493  * g_key_file_get_keys:
1494  * @key_file: a #GKeyFile
1495  * @group_name: a group name
1496  * @length: (out) (allow-none): return location for the number of keys returned, or %NULL
1497  * @error: return location for a #GError, or %NULL
1498  *
1499  * Returns all keys for the group name @group_name.  The array of
1500  * returned keys will be %NULL-terminated, so @length may
1501  * optionally be %NULL. In the event that the @group_name cannot
1502  * be found, %NULL is returned and @error is set to
1503  * #G_KEY_FILE_ERROR_GROUP_NOT_FOUND.
1504  *
1505  * Return value: (array zero-terminated=1) (transfer full): a newly-allocated %NULL-terminated array of strings.
1506  *     Use g_strfreev() to free it.
1507  *
1508  * Since: 2.6
1509  **/
1510 gchar **
1511 g_key_file_get_keys (GKeyFile     *key_file,
1512                      const gchar  *group_name,
1513                      gsize        *length,
1514                      GError      **error)
1515 {
1516   GKeyFileGroup *group;
1517   GList *tmp;
1518   gchar **keys;
1519   gsize i, num_keys;
1520   
1521   g_return_val_if_fail (key_file != NULL, NULL);
1522   g_return_val_if_fail (group_name != NULL, NULL);
1523   
1524   group = g_key_file_lookup_group (key_file, group_name);
1525   
1526   if (!group)
1527     {
1528       g_set_error (error, G_KEY_FILE_ERROR,
1529                    G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
1530                    _("Key file does not have group '%s'"),
1531                    group_name ? group_name : "(null)");
1532       return NULL;
1533     }
1534
1535   num_keys = 0;
1536   for (tmp = group->key_value_pairs; tmp; tmp = tmp->next)
1537     {
1538       GKeyFileKeyValuePair *pair;
1539
1540       pair = (GKeyFileKeyValuePair *) tmp->data;
1541
1542       if (pair->key)
1543         num_keys++;
1544     }
1545   
1546   keys = g_new (gchar *, num_keys + 1);
1547
1548   i = num_keys - 1;
1549   for (tmp = group->key_value_pairs; tmp; tmp = tmp->next)
1550     {
1551       GKeyFileKeyValuePair *pair;
1552
1553       pair = (GKeyFileKeyValuePair *) tmp->data;
1554
1555       if (pair->key)
1556         {
1557           keys[i] = g_strdup (pair->key);
1558           i--;
1559         }
1560     }
1561
1562   keys[num_keys] = NULL;
1563
1564   if (length)
1565     *length = num_keys;
1566
1567   return keys;
1568 }
1569
1570 /**
1571  * g_key_file_get_start_group:
1572  * @key_file: a #GKeyFile
1573  *
1574  * Returns the name of the start group of the file. 
1575  *
1576  * Return value: The start group of the key file.
1577  *
1578  * Since: 2.6
1579  **/
1580 gchar *
1581 g_key_file_get_start_group (GKeyFile *key_file)
1582 {
1583   g_return_val_if_fail (key_file != NULL, NULL);
1584
1585   if (key_file->start_group)
1586     return g_strdup (key_file->start_group->name);
1587
1588   return NULL;
1589 }
1590
1591 /**
1592  * g_key_file_get_groups:
1593  * @key_file: a #GKeyFile
1594  * @length: (out) (allow-none): return location for the number of returned groups, or %NULL
1595  *
1596  * Returns all groups in the key file loaded with @key_file.  
1597  * The array of returned groups will be %NULL-terminated, so 
1598  * @length may optionally be %NULL.
1599  *
1600  * Return value: (array zero-terminated=1) (transfer full): a newly-allocated %NULL-terminated array of strings.
1601  *   Use g_strfreev() to free it.
1602  * Since: 2.6
1603  **/
1604 gchar **
1605 g_key_file_get_groups (GKeyFile *key_file,
1606                        gsize    *length)
1607 {
1608   GList *group_node;
1609   gchar **groups;
1610   gsize i, num_groups;
1611
1612   g_return_val_if_fail (key_file != NULL, NULL);
1613
1614   num_groups = g_list_length (key_file->groups);
1615
1616   g_return_val_if_fail (num_groups > 0, NULL);
1617
1618   group_node = g_list_last (key_file->groups);
1619   
1620   g_return_val_if_fail (((GKeyFileGroup *) group_node->data)->name == NULL, NULL);
1621
1622   /* Only need num_groups instead of num_groups + 1
1623    * because the first group of the file (last in the
1624    * list) is always the comment group at the top,
1625    * which we skip
1626    */
1627   groups = g_new (gchar *, num_groups);
1628
1629
1630   i = 0;
1631   for (group_node = group_node->prev;
1632        group_node != NULL;
1633        group_node = group_node->prev)
1634     {
1635       GKeyFileGroup *group;
1636
1637       group = (GKeyFileGroup *) group_node->data;
1638
1639       g_warn_if_fail (group->name != NULL);
1640
1641       groups[i++] = g_strdup (group->name);
1642     }
1643   groups[i] = NULL;
1644
1645   if (length)
1646     *length = i;
1647
1648   return groups;
1649 }
1650
1651 /**
1652  * g_key_file_get_value:
1653  * @key_file: a #GKeyFile
1654  * @group_name: a group name
1655  * @key: a key
1656  * @error: return location for a #GError, or %NULL
1657  *
1658  * Returns the raw value associated with @key under @group_name. 
1659  * Use g_key_file_get_string() to retrieve an unescaped UTF-8 string. 
1660  *
1661  * In the event the key cannot be found, %NULL is returned and 
1662  * @error is set to #G_KEY_FILE_ERROR_KEY_NOT_FOUND.  In the 
1663  * event that the @group_name cannot be found, %NULL is returned 
1664  * and @error is set to #G_KEY_FILE_ERROR_GROUP_NOT_FOUND.
1665  *
1666  *
1667  * Return value: a newly allocated string or %NULL if the specified 
1668  *  key cannot be found.
1669  *
1670  * Since: 2.6
1671  **/
1672 gchar *
1673 g_key_file_get_value (GKeyFile     *key_file,
1674                       const gchar  *group_name,
1675                       const gchar  *key,
1676                       GError      **error)
1677 {
1678   GKeyFileGroup *group;
1679   GKeyFileKeyValuePair *pair;
1680   gchar *value = NULL;
1681
1682   g_return_val_if_fail (key_file != NULL, NULL);
1683   g_return_val_if_fail (group_name != NULL, NULL);
1684   g_return_val_if_fail (key != NULL, NULL);
1685   
1686   group = g_key_file_lookup_group (key_file, group_name);
1687
1688   if (!group)
1689     {
1690       g_set_error (error, G_KEY_FILE_ERROR,
1691                    G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
1692                    _("Key file does not have group '%s'"),
1693                    group_name ? group_name : "(null)");
1694       return NULL;
1695     }
1696
1697   pair = g_key_file_lookup_key_value_pair (key_file, group, key);
1698
1699   if (pair)
1700     value = g_strdup (pair->value);
1701   else
1702     g_set_error (error, G_KEY_FILE_ERROR,
1703                  G_KEY_FILE_ERROR_KEY_NOT_FOUND,
1704                  _("Key file does not have key '%s'"), key);
1705
1706   return value;
1707 }
1708
1709 /**
1710  * g_key_file_set_value:
1711  * @key_file: a #GKeyFile
1712  * @group_name: a group name
1713  * @key: a key
1714  * @value: a string
1715  *
1716  * Associates a new value with @key under @group_name.  
1717  *
1718  * If @key cannot be found then it is created. If @group_name cannot 
1719  * be found then it is created. To set an UTF-8 string which may contain 
1720  * characters that need escaping (such as newlines or spaces), use 
1721  * g_key_file_set_string().
1722  *
1723  * Since: 2.6
1724  **/
1725 void
1726 g_key_file_set_value (GKeyFile    *key_file,
1727                       const gchar *group_name,
1728                       const gchar *key,
1729                       const gchar *value)
1730 {
1731   GKeyFileGroup *group;
1732   GKeyFileKeyValuePair *pair;
1733
1734   g_return_if_fail (key_file != NULL);
1735   g_return_if_fail (g_key_file_is_group_name (group_name));
1736   g_return_if_fail (g_key_file_is_key_name (key));
1737   g_return_if_fail (value != NULL);
1738
1739   group = g_key_file_lookup_group (key_file, group_name);
1740
1741   if (!group)
1742     {
1743       g_key_file_add_group (key_file, group_name);
1744       group = (GKeyFileGroup *) key_file->groups->data;
1745
1746       g_key_file_add_key (key_file, group, key, value);
1747     }
1748   else
1749     {
1750       pair = g_key_file_lookup_key_value_pair (key_file, group, key);
1751
1752       if (!pair)
1753         g_key_file_add_key (key_file, group, key, value);
1754       else
1755         {
1756           g_free (pair->value);
1757           pair->value = g_strdup (value);
1758         }
1759     }
1760 }
1761
1762 /**
1763  * g_key_file_get_string:
1764  * @key_file: a #GKeyFile
1765  * @group_name: a group name
1766  * @key: a key
1767  * @error: return location for a #GError, or %NULL
1768  *
1769  * Returns the string value associated with @key under @group_name.
1770  * Unlike g_key_file_get_value(), this function handles escape sequences
1771  * like \s.
1772  *
1773  * In the event the key cannot be found, %NULL is returned and 
1774  * @error is set to #G_KEY_FILE_ERROR_KEY_NOT_FOUND.  In the 
1775  * event that the @group_name cannot be found, %NULL is returned 
1776  * and @error is set to #G_KEY_FILE_ERROR_GROUP_NOT_FOUND.
1777  *
1778  * Return value: a newly allocated string or %NULL if the specified 
1779  *   key cannot be found.
1780  *
1781  * Since: 2.6
1782  **/
1783 gchar *
1784 g_key_file_get_string (GKeyFile     *key_file,
1785                        const gchar  *group_name,
1786                        const gchar  *key,
1787                        GError      **error)
1788 {
1789   gchar *value, *string_value;
1790   GError *key_file_error;
1791
1792   g_return_val_if_fail (key_file != NULL, NULL);
1793   g_return_val_if_fail (group_name != NULL, NULL);
1794   g_return_val_if_fail (key != NULL, NULL);
1795
1796   key_file_error = NULL;
1797
1798   value = g_key_file_get_value (key_file, group_name, key, &key_file_error);
1799
1800   if (key_file_error)
1801     {
1802       g_propagate_error (error, key_file_error);
1803       return NULL;
1804     }
1805
1806   if (!g_utf8_validate (value, -1, NULL))
1807     {
1808       gchar *value_utf8 = _g_utf8_make_valid (value);
1809       g_set_error (error, G_KEY_FILE_ERROR,
1810                    G_KEY_FILE_ERROR_UNKNOWN_ENCODING,
1811                    _("Key file contains key '%s' with value '%s' "
1812                      "which is not UTF-8"), key, value_utf8);
1813       g_free (value_utf8);
1814       g_free (value);
1815
1816       return NULL;
1817     }
1818
1819   string_value = g_key_file_parse_value_as_string (key_file, value, NULL,
1820                                                    &key_file_error);
1821   g_free (value);
1822
1823   if (key_file_error)
1824     {
1825       if (g_error_matches (key_file_error,
1826                            G_KEY_FILE_ERROR,
1827                            G_KEY_FILE_ERROR_INVALID_VALUE))
1828         {
1829           g_set_error (error, G_KEY_FILE_ERROR,
1830                        G_KEY_FILE_ERROR_INVALID_VALUE,
1831                        _("Key file contains key '%s' "
1832                          "which has a value that cannot be interpreted."),
1833                        key);
1834           g_error_free (key_file_error);
1835         }
1836       else
1837         g_propagate_error (error, key_file_error);
1838     }
1839
1840   return string_value;
1841 }
1842
1843 /**
1844  * g_key_file_set_string:
1845  * @key_file: a #GKeyFile
1846  * @group_name: a group name
1847  * @key: a key
1848  * @string: a string
1849  *
1850  * Associates a new string value with @key under @group_name.  
1851  * If @key cannot be found then it is created.  
1852  * If @group_name cannot be found then it is created.
1853  * Unlike g_key_file_set_value(), this function handles characters
1854  * that need escaping, such as newlines.
1855  *
1856  * Since: 2.6
1857  **/
1858 void
1859 g_key_file_set_string (GKeyFile    *key_file,
1860                        const gchar *group_name,
1861                        const gchar *key,
1862                        const gchar *string)
1863 {
1864   gchar *value;
1865
1866   g_return_if_fail (key_file != NULL);
1867   g_return_if_fail (string != NULL);
1868
1869   value = g_key_file_parse_string_as_value (key_file, string, FALSE);
1870   g_key_file_set_value (key_file, group_name, key, value);
1871   g_free (value);
1872 }
1873
1874 /**
1875  * g_key_file_get_string_list:
1876  * @key_file: a #GKeyFile
1877  * @group_name: a group name
1878  * @key: a key
1879  * @length: (out) (allow-none): return location for the number of returned strings, or %NULL
1880  * @error: return location for a #GError, or %NULL
1881  *
1882  * Returns the values associated with @key under @group_name.
1883  *
1884  * In the event the key cannot be found, %NULL is returned and
1885  * @error is set to #G_KEY_FILE_ERROR_KEY_NOT_FOUND.  In the
1886  * event that the @group_name cannot be found, %NULL is returned
1887  * and @error is set to #G_KEY_FILE_ERROR_GROUP_NOT_FOUND.
1888  *
1889  * Return value: (array zero-terminated=1 length=length) (element-type utf8) (transfer full): 
1890  *  a %NULL-terminated string array or %NULL if the specified 
1891  *  key cannot be found. The array should be freed with g_strfreev().
1892  *
1893  * Since: 2.6
1894  **/
1895 gchar **
1896 g_key_file_get_string_list (GKeyFile     *key_file,
1897                             const gchar  *group_name,
1898                             const gchar  *key,
1899                             gsize        *length,
1900                             GError      **error)
1901 {
1902   GError *key_file_error = NULL;
1903   gchar *value, *string_value, **values;
1904   gint i, len;
1905   GSList *p, *pieces = NULL;
1906
1907   g_return_val_if_fail (key_file != NULL, NULL);
1908   g_return_val_if_fail (group_name != NULL, NULL);
1909   g_return_val_if_fail (key != NULL, NULL);
1910
1911   if (length)
1912     *length = 0;
1913
1914   value = g_key_file_get_value (key_file, group_name, key, &key_file_error);
1915
1916   if (key_file_error)
1917     {
1918       g_propagate_error (error, key_file_error);
1919       return NULL;
1920     }
1921
1922   if (!g_utf8_validate (value, -1, NULL))
1923     {
1924       gchar *value_utf8 = _g_utf8_make_valid (value);
1925       g_set_error (error, G_KEY_FILE_ERROR,
1926                    G_KEY_FILE_ERROR_UNKNOWN_ENCODING,
1927                    _("Key file contains key '%s' with value '%s' "
1928                      "which is not UTF-8"), key, value_utf8);
1929       g_free (value_utf8);
1930       g_free (value);
1931
1932       return NULL;
1933     }
1934
1935   string_value = g_key_file_parse_value_as_string (key_file, value, &pieces, &key_file_error);
1936   g_free (value);
1937   g_free (string_value);
1938
1939   if (key_file_error)
1940     {
1941       if (g_error_matches (key_file_error,
1942                            G_KEY_FILE_ERROR,
1943                            G_KEY_FILE_ERROR_INVALID_VALUE))
1944         {
1945           g_set_error (error, G_KEY_FILE_ERROR,
1946                        G_KEY_FILE_ERROR_INVALID_VALUE,
1947                        _("Key file contains key '%s' "
1948                          "which has a value that cannot be interpreted."),
1949                        key);
1950           g_error_free (key_file_error);
1951         }
1952       else
1953         g_propagate_error (error, key_file_error);
1954
1955       g_slist_free_full (pieces, g_free);
1956       return NULL;
1957     }
1958
1959   len = g_slist_length (pieces);
1960   values = g_new (gchar *, len + 1);
1961   for (p = pieces, i = 0; p; p = p->next)
1962     values[i++] = p->data;
1963   values[len] = NULL;
1964
1965   g_slist_free (pieces);
1966
1967   if (length)
1968     *length = len;
1969
1970   return values;
1971 }
1972
1973 /**
1974  * g_key_file_set_string_list:
1975  * @key_file: a #GKeyFile
1976  * @group_name: a group name
1977  * @key: a key
1978  * @list: (array zero-terminated=1 length=length) (element-type utf8): an array of string values
1979  * @length: number of string values in @list
1980  *
1981  * Associates a list of string values for @key under @group_name.
1982  * If @key cannot be found then it is created.
1983  * If @group_name cannot be found then it is created.
1984  *
1985  * Since: 2.6
1986  **/
1987 void
1988 g_key_file_set_string_list (GKeyFile            *key_file,
1989                             const gchar         *group_name,
1990                             const gchar         *key,
1991                             const gchar * const  list[],
1992                             gsize                length)
1993 {
1994   GString *value_list;
1995   gsize i;
1996
1997   g_return_if_fail (key_file != NULL);
1998   g_return_if_fail (list != NULL || length == 0);
1999
2000   value_list = g_string_sized_new (length * 128);
2001   for (i = 0; i < length && list[i] != NULL; i++)
2002     {
2003       gchar *value;
2004
2005       value = g_key_file_parse_string_as_value (key_file, list[i], TRUE);
2006       g_string_append (value_list, value);
2007       g_string_append_c (value_list, key_file->list_separator);
2008
2009       g_free (value);
2010     }
2011
2012   g_key_file_set_value (key_file, group_name, key, value_list->str);
2013   g_string_free (value_list, TRUE);
2014 }
2015
2016 /**
2017  * g_key_file_set_locale_string:
2018  * @key_file: a #GKeyFile
2019  * @group_name: a group name
2020  * @key: a key
2021  * @locale: a locale identifier
2022  * @string: a string
2023  *
2024  * Associates a string value for @key and @locale under @group_name.
2025  * If the translation for @key cannot be found then it is created.
2026  *
2027  * Since: 2.6
2028  **/
2029 void
2030 g_key_file_set_locale_string (GKeyFile     *key_file,
2031                               const gchar  *group_name,
2032                               const gchar  *key,
2033                               const gchar  *locale,
2034                               const gchar  *string)
2035 {
2036   gchar *full_key, *value;
2037
2038   g_return_if_fail (key_file != NULL);
2039   g_return_if_fail (key != NULL);
2040   g_return_if_fail (locale != NULL);
2041   g_return_if_fail (string != NULL);
2042
2043   value = g_key_file_parse_string_as_value (key_file, string, FALSE);
2044   full_key = g_strdup_printf ("%s[%s]", key, locale);
2045   g_key_file_set_value (key_file, group_name, full_key, value);
2046   g_free (full_key);
2047   g_free (value);
2048 }
2049
2050 /**
2051  * g_key_file_get_locale_string:
2052  * @key_file: a #GKeyFile
2053  * @group_name: a group name
2054  * @key: a key
2055  * @locale: (allow-none): a locale identifier or %NULL
2056  * @error: return location for a #GError, or %NULL
2057  *
2058  * Returns the value associated with @key under @group_name
2059  * translated in the given @locale if available.  If @locale is
2060  * %NULL then the current locale is assumed. 
2061  *
2062  * If @key cannot be found then %NULL is returned and @error is set 
2063  * to #G_KEY_FILE_ERROR_KEY_NOT_FOUND. If the value associated
2064  * with @key cannot be interpreted or no suitable translation can
2065  * be found then the untranslated value is returned.
2066  *
2067  * Return value: a newly allocated string or %NULL if the specified 
2068  *   key cannot be found.
2069  *
2070  * Since: 2.6
2071  **/
2072 gchar *
2073 g_key_file_get_locale_string (GKeyFile     *key_file,
2074                               const gchar  *group_name,
2075                               const gchar  *key,
2076                               const gchar  *locale,
2077                               GError      **error)
2078 {
2079   gchar *candidate_key, *translated_value;
2080   GError *key_file_error;
2081   gchar **languages;
2082   gboolean free_languages = FALSE;
2083   gint i;
2084
2085   g_return_val_if_fail (key_file != NULL, NULL);
2086   g_return_val_if_fail (group_name != NULL, NULL);
2087   g_return_val_if_fail (key != NULL, NULL);
2088
2089   candidate_key = NULL;
2090   translated_value = NULL;
2091   key_file_error = NULL;
2092
2093   if (locale)
2094     {
2095       languages = g_get_locale_variants (locale);
2096       free_languages = TRUE;
2097     }
2098   else
2099     {
2100       languages = (gchar **) g_get_language_names ();
2101       free_languages = FALSE;
2102     }
2103   
2104   for (i = 0; languages[i]; i++)
2105     {
2106       candidate_key = g_strdup_printf ("%s[%s]", key, languages[i]);
2107       
2108       translated_value = g_key_file_get_string (key_file,
2109                                                 group_name,
2110                                                 candidate_key, NULL);
2111       g_free (candidate_key);
2112
2113       if (translated_value)
2114         break;
2115
2116       g_free (translated_value);
2117       translated_value = NULL;
2118    }
2119
2120   /* Fallback to untranslated key
2121    */
2122   if (!translated_value)
2123     {
2124       translated_value = g_key_file_get_string (key_file, group_name, key,
2125                                                 &key_file_error);
2126       
2127       if (!translated_value)
2128         g_propagate_error (error, key_file_error);
2129     }
2130
2131   if (free_languages)
2132     g_strfreev (languages);
2133
2134   return translated_value;
2135 }
2136
2137 /**
2138  * g_key_file_get_locale_string_list:
2139  * @key_file: a #GKeyFile
2140  * @group_name: a group name
2141  * @key: a key
2142  * @locale: (allow-none): a locale identifier or %NULL
2143  * @length: (out) (allow-none): return location for the number of returned strings or %NULL
2144  * @error: return location for a #GError or %NULL
2145  *
2146  * Returns the values associated with @key under @group_name
2147  * translated in the given @locale if available.  If @locale is
2148  * %NULL then the current locale is assumed.
2149
2150  * If @key cannot be found then %NULL is returned and @error is set 
2151  * to #G_KEY_FILE_ERROR_KEY_NOT_FOUND. If the values associated
2152  * with @key cannot be interpreted or no suitable translations
2153  * can be found then the untranslated values are returned. The 
2154  * returned array is %NULL-terminated, so @length may optionally 
2155  * be %NULL.
2156  *
2157  * Return value: (array zero-terminated=1 length=length) (element-type utf8) (transfer full): a newly allocated %NULL-terminated string array
2158  *   or %NULL if the key isn't found. The string array should be freed
2159  *   with g_strfreev().
2160  *
2161  * Since: 2.6
2162  **/
2163 gchar **
2164 g_key_file_get_locale_string_list (GKeyFile     *key_file,
2165                                    const gchar  *group_name,
2166                                    const gchar  *key,
2167                                    const gchar  *locale,
2168                                    gsize        *length,
2169                                    GError      **error)
2170 {
2171   GError *key_file_error;
2172   gchar **values, *value;
2173   char list_separator[2];
2174   gsize len;
2175
2176   g_return_val_if_fail (key_file != NULL, NULL);
2177   g_return_val_if_fail (group_name != NULL, NULL);
2178   g_return_val_if_fail (key != NULL, NULL);
2179
2180   key_file_error = NULL;
2181
2182   value = g_key_file_get_locale_string (key_file, group_name, 
2183                                         key, locale,
2184                                         &key_file_error);
2185   
2186   if (key_file_error)
2187     g_propagate_error (error, key_file_error);
2188   
2189   if (!value)
2190     {
2191       if (length)
2192         *length = 0;
2193       return NULL;
2194     }
2195
2196   len = strlen (value);
2197   if (value[len - 1] == key_file->list_separator)
2198     value[len - 1] = '\0';
2199
2200   list_separator[0] = key_file->list_separator;
2201   list_separator[1] = '\0';
2202   values = g_strsplit (value, list_separator, 0);
2203
2204   g_free (value);
2205
2206   if (length)
2207     *length = g_strv_length (values);
2208
2209   return values;
2210 }
2211
2212 /**
2213  * g_key_file_set_locale_string_list:
2214  * @key_file: a #GKeyFile
2215  * @group_name: a group name
2216  * @key: a key
2217  * @locale: a locale identifier
2218  * @list: (array zero-terminated=1 length=length): a %NULL-terminated array of locale string values
2219  * @length: the length of @list
2220  *
2221  * Associates a list of string values for @key and @locale under
2222  * @group_name.  If the translation for @key cannot be found then
2223  * it is created. 
2224  *
2225  * Since: 2.6
2226  **/
2227 void
2228 g_key_file_set_locale_string_list (GKeyFile            *key_file,
2229                                    const gchar         *group_name,
2230                                    const gchar         *key,
2231                                    const gchar         *locale,
2232                                    const gchar * const  list[],
2233                                    gsize                length)
2234 {
2235   GString *value_list;
2236   gchar *full_key;
2237   gsize i;
2238
2239   g_return_if_fail (key_file != NULL);
2240   g_return_if_fail (key != NULL);
2241   g_return_if_fail (locale != NULL);
2242   g_return_if_fail (length != 0);
2243
2244   value_list = g_string_sized_new (length * 128);
2245   for (i = 0; i < length && list[i] != NULL; i++)
2246     {
2247       gchar *value;
2248       
2249       value = g_key_file_parse_string_as_value (key_file, list[i], TRUE);
2250       g_string_append (value_list, value);
2251       g_string_append_c (value_list, key_file->list_separator);
2252
2253       g_free (value);
2254     }
2255
2256   full_key = g_strdup_printf ("%s[%s]", key, locale);
2257   g_key_file_set_value (key_file, group_name, full_key, value_list->str);
2258   g_free (full_key);
2259   g_string_free (value_list, TRUE);
2260 }
2261
2262 /**
2263  * g_key_file_get_boolean:
2264  * @key_file: a #GKeyFile
2265  * @group_name: a group name
2266  * @key: a key
2267  * @error: return location for a #GError
2268  *
2269  * Returns the value associated with @key under @group_name as a
2270  * boolean. 
2271  *
2272  * If @key cannot be found then %FALSE is returned and @error is set
2273  * to #G_KEY_FILE_ERROR_KEY_NOT_FOUND. Likewise, if the value
2274  * associated with @key cannot be interpreted as a boolean then %FALSE
2275  * is returned and @error is set to #G_KEY_FILE_ERROR_INVALID_VALUE.
2276  *
2277  * Return value: the value associated with the key as a boolean, 
2278  *    or %FALSE if the key was not found or could not be parsed.
2279  *
2280  * Since: 2.6
2281  **/
2282 gboolean
2283 g_key_file_get_boolean (GKeyFile     *key_file,
2284                         const gchar  *group_name,
2285                         const gchar  *key,
2286                         GError      **error)
2287 {
2288   GError *key_file_error = NULL;
2289   gchar *value;
2290   gboolean bool_value;
2291
2292   g_return_val_if_fail (key_file != NULL, FALSE);
2293   g_return_val_if_fail (group_name != NULL, FALSE);
2294   g_return_val_if_fail (key != NULL, FALSE);
2295
2296   value = g_key_file_get_value (key_file, group_name, key, &key_file_error);
2297
2298   if (!value)
2299     {
2300       g_propagate_error (error, key_file_error);
2301       return FALSE;
2302     }
2303
2304   bool_value = g_key_file_parse_value_as_boolean (key_file, value,
2305                                                   &key_file_error);
2306   g_free (value);
2307
2308   if (key_file_error)
2309     {
2310       if (g_error_matches (key_file_error,
2311                            G_KEY_FILE_ERROR,
2312                            G_KEY_FILE_ERROR_INVALID_VALUE))
2313         {
2314           g_set_error (error, G_KEY_FILE_ERROR,
2315                        G_KEY_FILE_ERROR_INVALID_VALUE,
2316                        _("Key file contains key '%s' "
2317                          "which has a value that cannot be interpreted."),
2318                        key);
2319           g_error_free (key_file_error);
2320         }
2321       else
2322         g_propagate_error (error, key_file_error);
2323     }
2324
2325   return bool_value;
2326 }
2327
2328 /**
2329  * g_key_file_set_boolean:
2330  * @key_file: a #GKeyFile
2331  * @group_name: a group name
2332  * @key: a key
2333  * @value: %TRUE or %FALSE
2334  *
2335  * Associates a new boolean value with @key under @group_name.
2336  * If @key cannot be found then it is created. 
2337  *
2338  * Since: 2.6
2339  **/
2340 void
2341 g_key_file_set_boolean (GKeyFile    *key_file,
2342                         const gchar *group_name,
2343                         const gchar *key,
2344                         gboolean     value)
2345 {
2346   gchar *result;
2347
2348   g_return_if_fail (key_file != NULL);
2349
2350   result = g_key_file_parse_boolean_as_value (key_file, value);
2351   g_key_file_set_value (key_file, group_name, key, result);
2352   g_free (result);
2353 }
2354
2355 /**
2356  * g_key_file_get_boolean_list:
2357  * @key_file: a #GKeyFile
2358  * @group_name: a group name
2359  * @key: a key
2360  * @length: (out): the number of booleans returned
2361  * @error: return location for a #GError
2362  *
2363  * Returns the values associated with @key under @group_name as
2364  * booleans. 
2365  *
2366  * If @key cannot be found then %NULL is returned and @error is set to
2367  * #G_KEY_FILE_ERROR_KEY_NOT_FOUND. Likewise, if the values associated
2368  * with @key cannot be interpreted as booleans then %NULL is returned
2369  * and @error is set to #G_KEY_FILE_ERROR_INVALID_VALUE.
2370  *
2371  * Return value: (array length=length) (element-type gboolean) (transfer container):
2372  *    the values associated with the key as a list of booleans, or %NULL if the
2373  *    key was not found or could not be parsed. The returned list of booleans
2374  *    should be freed with g_free() when no longer needed.
2375  * 
2376  * Since: 2.6
2377  **/
2378 gboolean *
2379 g_key_file_get_boolean_list (GKeyFile     *key_file,
2380                              const gchar  *group_name,
2381                              const gchar  *key,
2382                              gsize        *length,
2383                              GError      **error)
2384 {
2385   GError *key_file_error;
2386   gchar **values;
2387   gboolean *bool_values;
2388   gsize i, num_bools;
2389
2390   g_return_val_if_fail (key_file != NULL, NULL);
2391   g_return_val_if_fail (group_name != NULL, NULL);
2392   g_return_val_if_fail (key != NULL, NULL);
2393
2394   if (length)
2395     *length = 0;
2396
2397   key_file_error = NULL;
2398
2399   values = g_key_file_get_string_list (key_file, group_name, key,
2400                                        &num_bools, &key_file_error);
2401
2402   if (key_file_error)
2403     g_propagate_error (error, key_file_error);
2404
2405   if (!values)
2406     return NULL;
2407
2408   bool_values = g_new (gboolean, num_bools);
2409
2410   for (i = 0; i < num_bools; i++)
2411     {
2412       bool_values[i] = g_key_file_parse_value_as_boolean (key_file,
2413                                                           values[i],
2414                                                           &key_file_error);
2415
2416       if (key_file_error)
2417         {
2418           g_propagate_error (error, key_file_error);
2419           g_strfreev (values);
2420           g_free (bool_values);
2421
2422           return NULL;
2423         }
2424     }
2425   g_strfreev (values);
2426
2427   if (length)
2428     *length = num_bools;
2429
2430   return bool_values;
2431 }
2432
2433 /**
2434  * g_key_file_set_boolean_list:
2435  * @key_file: a #GKeyFile
2436  * @group_name: a group name
2437  * @key: a key
2438  * @list: (array length=length): an array of boolean values
2439  * @length: length of @list
2440  *
2441  * Associates a list of boolean values with @key under @group_name.  
2442  * If @key cannot be found then it is created.
2443  * If @group_name is %NULL, the start_group is used.
2444  *
2445  * Since: 2.6
2446  **/
2447 void
2448 g_key_file_set_boolean_list (GKeyFile    *key_file,
2449                              const gchar *group_name,
2450                              const gchar *key,
2451                              gboolean     list[],
2452                              gsize        length)
2453 {
2454   GString *value_list;
2455   gsize i;
2456
2457   g_return_if_fail (key_file != NULL);
2458   g_return_if_fail (list != NULL);
2459
2460   value_list = g_string_sized_new (length * 8);
2461   for (i = 0; i < length; i++)
2462     {
2463       gchar *value;
2464
2465       value = g_key_file_parse_boolean_as_value (key_file, list[i]);
2466
2467       g_string_append (value_list, value);
2468       g_string_append_c (value_list, key_file->list_separator);
2469
2470       g_free (value);
2471     }
2472
2473   g_key_file_set_value (key_file, group_name, key, value_list->str);
2474   g_string_free (value_list, TRUE);
2475 }
2476
2477 /**
2478  * g_key_file_get_integer:
2479  * @key_file: a #GKeyFile
2480  * @group_name: a group name
2481  * @key: a key
2482  * @error: return location for a #GError
2483  *
2484  * Returns the value associated with @key under @group_name as an
2485  * integer. 
2486  *
2487  * If @key cannot be found then 0 is returned and @error is set to
2488  * #G_KEY_FILE_ERROR_KEY_NOT_FOUND. Likewise, if the value associated
2489  * with @key cannot be interpreted as an integer then 0 is returned
2490  * and @error is set to #G_KEY_FILE_ERROR_INVALID_VALUE.
2491  *
2492  * Return value: the value associated with the key as an integer, or
2493  *     0 if the key was not found or could not be parsed.
2494  *
2495  * Since: 2.6
2496  **/
2497 gint
2498 g_key_file_get_integer (GKeyFile     *key_file,
2499                         const gchar  *group_name,
2500                         const gchar  *key,
2501                         GError      **error)
2502 {
2503   GError *key_file_error;
2504   gchar *value;
2505   gint int_value;
2506
2507   g_return_val_if_fail (key_file != NULL, -1);
2508   g_return_val_if_fail (group_name != NULL, -1);
2509   g_return_val_if_fail (key != NULL, -1);
2510
2511   key_file_error = NULL;
2512
2513   value = g_key_file_get_value (key_file, group_name, key, &key_file_error);
2514
2515   if (key_file_error)
2516     {
2517       g_propagate_error (error, key_file_error);
2518       return 0;
2519     }
2520
2521   int_value = g_key_file_parse_value_as_integer (key_file, value,
2522                                                  &key_file_error);
2523   g_free (value);
2524
2525   if (key_file_error)
2526     {
2527       if (g_error_matches (key_file_error,
2528                            G_KEY_FILE_ERROR,
2529                            G_KEY_FILE_ERROR_INVALID_VALUE))
2530         {
2531           g_set_error (error, G_KEY_FILE_ERROR,
2532                        G_KEY_FILE_ERROR_INVALID_VALUE,
2533                        _("Key file contains key '%s' in group '%s' "
2534                          "which has a value that cannot be interpreted."),
2535                          key, group_name);
2536           g_error_free (key_file_error);
2537         }
2538       else
2539         g_propagate_error (error, key_file_error);
2540     }
2541
2542   return int_value;
2543 }
2544
2545 /**
2546  * g_key_file_set_integer:
2547  * @key_file: a #GKeyFile
2548  * @group_name: a group name
2549  * @key: a key
2550  * @value: an integer value
2551  *
2552  * Associates a new integer value with @key under @group_name.
2553  * If @key cannot be found then it is created.
2554  *
2555  * Since: 2.6
2556  **/
2557 void
2558 g_key_file_set_integer (GKeyFile    *key_file,
2559                         const gchar *group_name,
2560                         const gchar *key,
2561                         gint         value)
2562 {
2563   gchar *result;
2564
2565   g_return_if_fail (key_file != NULL);
2566
2567   result = g_key_file_parse_integer_as_value (key_file, value);
2568   g_key_file_set_value (key_file, group_name, key, result);
2569   g_free (result);
2570 }
2571
2572 /**
2573  * g_key_file_get_int64:
2574  * @key_file: a non-%NULL #GKeyFile
2575  * @group_name: a non-%NULL group name
2576  * @key: a non-%NULL key
2577  * @error: return location for a #GError
2578  *
2579  * Returns the value associated with @key under @group_name as a signed
2580  * 64-bit integer. This is similar to g_key_file_get_integer() but can return
2581  * 64-bit results without truncation.
2582  *
2583  * Returns: the value associated with the key as a signed 64-bit integer, or
2584  * 0 if the key was not found or could not be parsed.
2585  *
2586  * Since: 2.26
2587  */
2588 gint64
2589 g_key_file_get_int64 (GKeyFile     *key_file,
2590                       const gchar  *group_name,
2591                       const gchar  *key,
2592                       GError      **error)
2593 {
2594   gchar *s, *end;
2595   gint64 v;
2596
2597   g_return_val_if_fail (key_file != NULL, -1);
2598   g_return_val_if_fail (group_name != NULL, -1);
2599   g_return_val_if_fail (key != NULL, -1);
2600
2601   s = g_key_file_get_value (key_file, group_name, key, error);
2602
2603   if (s == NULL)
2604     return 0;
2605
2606   v = g_ascii_strtoll (s, &end, 10);
2607
2608   if (*s == '\0' || *end != '\0')
2609     {
2610       g_set_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_INVALID_VALUE,
2611                    _("Key '%s' in group '%s' has value '%s' "
2612                      "where %s was expected"),
2613                    key, group_name, s, "int64");
2614       g_free (s);
2615       return 0;
2616     }
2617
2618   g_free (s);
2619   return v;
2620 }
2621
2622 /**
2623  * g_key_file_set_int64:
2624  * @key_file: a #GKeyFile
2625  * @group_name: a group name
2626  * @key: a key
2627  * @value: an integer value
2628  *
2629  * Associates a new integer value with @key under @group_name.
2630  * If @key cannot be found then it is created.
2631  *
2632  * Since: 2.26
2633  **/
2634 void
2635 g_key_file_set_int64 (GKeyFile    *key_file,
2636                       const gchar *group_name,
2637                       const gchar *key,
2638                       gint64       value)
2639 {
2640   gchar *result;
2641
2642   g_return_if_fail (key_file != NULL);
2643
2644   result = g_strdup_printf ("%" G_GINT64_FORMAT, value);
2645   g_key_file_set_value (key_file, group_name, key, result);
2646   g_free (result);
2647 }
2648
2649 /**
2650  * g_key_file_get_uint64:
2651  * @key_file: a non-%NULL #GKeyFile
2652  * @group_name: a non-%NULL group name
2653  * @key: a non-%NULL key
2654  * @error: return location for a #GError
2655  *
2656  * Returns the value associated with @key under @group_name as an unsigned
2657  * 64-bit integer. This is similar to g_key_file_get_integer() but can return
2658  * large positive results without truncation.
2659  *
2660  * Returns: the value associated with the key as an unsigned 64-bit integer,
2661  * or 0 if the key was not found or could not be parsed.
2662  *
2663  * Since: 2.26
2664  */
2665 guint64
2666 g_key_file_get_uint64 (GKeyFile     *key_file,
2667                        const gchar  *group_name,
2668                        const gchar  *key,
2669                        GError      **error)
2670 {
2671   gchar *s, *end;
2672   guint64 v;
2673
2674   g_return_val_if_fail (key_file != NULL, -1);
2675   g_return_val_if_fail (group_name != NULL, -1);
2676   g_return_val_if_fail (key != NULL, -1);
2677
2678   s = g_key_file_get_value (key_file, group_name, key, error);
2679
2680   if (s == NULL)
2681     return 0;
2682
2683   v = g_ascii_strtoull (s, &end, 10);
2684
2685   if (*s == '\0' || *end != '\0')
2686     {
2687       g_set_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_INVALID_VALUE,
2688                    _("Key '%s' in group '%s' has value '%s' "
2689                      "where %s was expected"),
2690                    key, group_name, s, "uint64");
2691       g_free (s);
2692       return 0;
2693     }
2694
2695   g_free (s);
2696   return v;
2697 }
2698
2699 /**
2700  * g_key_file_set_uint64:
2701  * @key_file: a #GKeyFile
2702  * @group_name: a group name
2703  * @key: a key
2704  * @value: an integer value
2705  *
2706  * Associates a new integer value with @key under @group_name.
2707  * If @key cannot be found then it is created.
2708  *
2709  * Since: 2.26
2710  **/
2711 void
2712 g_key_file_set_uint64 (GKeyFile    *key_file,
2713                        const gchar *group_name,
2714                        const gchar *key,
2715                        guint64      value)
2716 {
2717   gchar *result;
2718
2719   g_return_if_fail (key_file != NULL);
2720
2721   result = g_strdup_printf ("%" G_GUINT64_FORMAT, value);
2722   g_key_file_set_value (key_file, group_name, key, result);
2723   g_free (result);
2724 }
2725
2726 /**
2727  * g_key_file_get_integer_list:
2728  * @key_file: a #GKeyFile
2729  * @group_name: a group name
2730  * @key: a key
2731  * @length: (out): the number of integers returned
2732  * @error: return location for a #GError
2733  *
2734  * Returns the values associated with @key under @group_name as
2735  * integers. 
2736  *
2737  * If @key cannot be found then %NULL is returned and @error is set to
2738  * #G_KEY_FILE_ERROR_KEY_NOT_FOUND. Likewise, if the values associated
2739  * with @key cannot be interpreted as integers then %NULL is returned
2740  * and @error is set to #G_KEY_FILE_ERROR_INVALID_VALUE.
2741  *
2742  * Return value: (array length=length) (element-type gint) (transfer container):
2743  *     the values associated with the key as a list of integers, or %NULL if
2744  *     the key was not found or could not be parsed. The returned list of
2745  *     integers should be freed with g_free() when no longer needed.
2746  *
2747  * Since: 2.6
2748  **/
2749 gint *
2750 g_key_file_get_integer_list (GKeyFile     *key_file,
2751                              const gchar  *group_name,
2752                              const gchar  *key,
2753                              gsize        *length,
2754                              GError      **error)
2755 {
2756   GError *key_file_error = NULL;
2757   gchar **values;
2758   gint *int_values;
2759   gsize i, num_ints;
2760
2761   g_return_val_if_fail (key_file != NULL, NULL);
2762   g_return_val_if_fail (group_name != NULL, NULL);
2763   g_return_val_if_fail (key != NULL, NULL);
2764
2765   if (length)
2766     *length = 0;
2767
2768   values = g_key_file_get_string_list (key_file, group_name, key,
2769                                        &num_ints, &key_file_error);
2770
2771   if (key_file_error)
2772     g_propagate_error (error, key_file_error);
2773
2774   if (!values)
2775     return NULL;
2776
2777   int_values = g_new (gint, num_ints);
2778
2779   for (i = 0; i < num_ints; i++)
2780     {
2781       int_values[i] = g_key_file_parse_value_as_integer (key_file,
2782                                                          values[i],
2783                                                          &key_file_error);
2784
2785       if (key_file_error)
2786         {
2787           g_propagate_error (error, key_file_error);
2788           g_strfreev (values);
2789           g_free (int_values);
2790
2791           return NULL;
2792         }
2793     }
2794   g_strfreev (values);
2795
2796   if (length)
2797     *length = num_ints;
2798
2799   return int_values;
2800 }
2801
2802 /**
2803  * g_key_file_set_integer_list:
2804  * @key_file: a #GKeyFile
2805  * @group_name: a group name
2806  * @key: a key
2807  * @list: (array length=length): an array of integer values
2808  * @length: number of integer values in @list
2809  *
2810  * Associates a list of integer values with @key under @group_name.  
2811  * If @key cannot be found then it is created.
2812  *
2813  * Since: 2.6
2814  **/
2815 void
2816 g_key_file_set_integer_list (GKeyFile    *key_file,
2817                              const gchar *group_name,
2818                              const gchar *key,
2819                              gint         list[],
2820                              gsize        length)
2821 {
2822   GString *values;
2823   gsize i;
2824
2825   g_return_if_fail (key_file != NULL);
2826   g_return_if_fail (list != NULL);
2827
2828   values = g_string_sized_new (length * 16);
2829   for (i = 0; i < length; i++)
2830     {
2831       gchar *value;
2832
2833       value = g_key_file_parse_integer_as_value (key_file, list[i]);
2834
2835       g_string_append (values, value);
2836       g_string_append_c (values, key_file->list_separator);
2837
2838       g_free (value);
2839     }
2840
2841   g_key_file_set_value (key_file, group_name, key, values->str);
2842   g_string_free (values, TRUE);
2843 }
2844
2845 /**
2846  * g_key_file_get_double:
2847  * @key_file: a #GKeyFile
2848  * @group_name: a group name
2849  * @key: a key
2850  * @error: return location for a #GError
2851  *
2852  * Returns the value associated with @key under @group_name as a
2853  * double. If @group_name is %NULL, the start_group is used.
2854  *
2855  * If @key cannot be found then 0.0 is returned and @error is set to
2856  * #G_KEY_FILE_ERROR_KEY_NOT_FOUND. Likewise, if the value associated
2857  * with @key cannot be interpreted as a double then 0.0 is returned
2858  * and @error is set to #G_KEY_FILE_ERROR_INVALID_VALUE.
2859  *
2860  * Return value: the value associated with the key as a double, or
2861  *     0.0 if the key was not found or could not be parsed.
2862  *
2863  * Since: 2.12
2864  **/
2865 gdouble
2866 g_key_file_get_double  (GKeyFile     *key_file,
2867                         const gchar  *group_name,
2868                         const gchar  *key,
2869                         GError      **error)
2870 {
2871   GError *key_file_error;
2872   gchar *value;
2873   gdouble double_value;
2874
2875   g_return_val_if_fail (key_file != NULL, -1);
2876   g_return_val_if_fail (group_name != NULL, -1);
2877   g_return_val_if_fail (key != NULL, -1);
2878
2879   key_file_error = NULL;
2880
2881   value = g_key_file_get_value (key_file, group_name, key, &key_file_error);
2882
2883   if (key_file_error)
2884     {
2885       g_propagate_error (error, key_file_error);
2886       return 0;
2887     }
2888
2889   double_value = g_key_file_parse_value_as_double (key_file, value,
2890                                                   &key_file_error);
2891   g_free (value);
2892
2893   if (key_file_error)
2894     {
2895       if (g_error_matches (key_file_error,
2896                            G_KEY_FILE_ERROR,
2897                            G_KEY_FILE_ERROR_INVALID_VALUE))
2898         {
2899           g_set_error (error, G_KEY_FILE_ERROR,
2900                        G_KEY_FILE_ERROR_INVALID_VALUE,
2901                        _("Key file contains key '%s' in group '%s' "
2902                          "which has a value that cannot be interpreted."),
2903                        key, group_name);
2904           g_error_free (key_file_error);
2905         }
2906       else
2907         g_propagate_error (error, key_file_error);
2908     }
2909
2910   return double_value;
2911 }
2912
2913 /**
2914  * g_key_file_set_double:
2915  * @key_file: a #GKeyFile
2916  * @group_name: a group name
2917  * @key: a key
2918  * @value: an double value
2919  *
2920  * Associates a new double value with @key under @group_name.
2921  * If @key cannot be found then it is created. 
2922  *
2923  * Since: 2.12
2924  **/
2925 void
2926 g_key_file_set_double  (GKeyFile    *key_file,
2927                         const gchar *group_name,
2928                         const gchar *key,
2929                         gdouble      value)
2930 {
2931   gchar result[G_ASCII_DTOSTR_BUF_SIZE];
2932
2933   g_return_if_fail (key_file != NULL);
2934
2935   g_ascii_dtostr (result, sizeof (result), value);
2936   g_key_file_set_value (key_file, group_name, key, result);
2937 }
2938
2939 /**
2940  * g_key_file_get_double_list:
2941  * @key_file: a #GKeyFile
2942  * @group_name: a group name
2943  * @key: a key
2944  * @length: (out): the number of doubles returned
2945  * @error: return location for a #GError
2946  *
2947  * Returns the values associated with @key under @group_name as
2948  * doubles. 
2949  *
2950  * If @key cannot be found then %NULL is returned and @error is set to
2951  * #G_KEY_FILE_ERROR_KEY_NOT_FOUND. Likewise, if the values associated
2952  * with @key cannot be interpreted as doubles then %NULL is returned
2953  * and @error is set to #G_KEY_FILE_ERROR_INVALID_VALUE.
2954  *
2955  * Return value: (array length=length) (element-type gdouble) (transfer container):
2956  *     the values associated with the key as a list of doubles, or %NULL if the
2957  *     key was not found or could not be parsed. The returned list of doubles
2958  *     should be freed with g_free() when no longer needed.
2959  *
2960  * Since: 2.12
2961  **/
2962 gdouble *
2963 g_key_file_get_double_list  (GKeyFile     *key_file,
2964                              const gchar  *group_name,
2965                              const gchar  *key,
2966                              gsize        *length,
2967                              GError      **error)
2968 {
2969   GError *key_file_error = NULL;
2970   gchar **values;
2971   gdouble *double_values;
2972   gsize i, num_doubles;
2973
2974   g_return_val_if_fail (key_file != NULL, NULL);
2975   g_return_val_if_fail (group_name != NULL, NULL);
2976   g_return_val_if_fail (key != NULL, NULL);
2977
2978   if (length)
2979     *length = 0;
2980
2981   values = g_key_file_get_string_list (key_file, group_name, key,
2982                                        &num_doubles, &key_file_error);
2983
2984   if (key_file_error)
2985     g_propagate_error (error, key_file_error);
2986
2987   if (!values)
2988     return NULL;
2989
2990   double_values = g_new (gdouble, num_doubles);
2991
2992   for (i = 0; i < num_doubles; i++)
2993     {
2994       double_values[i] = g_key_file_parse_value_as_double (key_file,
2995                                                            values[i],
2996                                                            &key_file_error);
2997
2998       if (key_file_error)
2999         {
3000           g_propagate_error (error, key_file_error);
3001           g_strfreev (values);
3002           g_free (double_values);
3003
3004           return NULL;
3005         }
3006     }
3007   g_strfreev (values);
3008
3009   if (length)
3010     *length = num_doubles;
3011
3012   return double_values;
3013 }
3014
3015 /**
3016  * g_key_file_set_double_list:
3017  * @key_file: a #GKeyFile
3018  * @group_name: a group name
3019  * @key: a key
3020  * @list: (array length=length): an array of double values
3021  * @length: number of double values in @list
3022  *
3023  * Associates a list of double values with @key under
3024  * @group_name.  If @key cannot be found then it is created.
3025  *
3026  * Since: 2.12
3027  **/
3028 void
3029 g_key_file_set_double_list (GKeyFile    *key_file,
3030                             const gchar *group_name,
3031                             const gchar *key,
3032                             gdouble      list[],
3033                             gsize        length)
3034 {
3035   GString *values;
3036   gsize i;
3037
3038   g_return_if_fail (key_file != NULL);
3039   g_return_if_fail (list != NULL);
3040
3041   values = g_string_sized_new (length * 16);
3042   for (i = 0; i < length; i++)
3043     {
3044       gchar result[G_ASCII_DTOSTR_BUF_SIZE];
3045
3046       g_ascii_dtostr( result, sizeof (result), list[i] );
3047
3048       g_string_append (values, result);
3049       g_string_append_c (values, key_file->list_separator);
3050     }
3051
3052   g_key_file_set_value (key_file, group_name, key, values->str);
3053   g_string_free (values, TRUE);
3054 }
3055
3056 static gboolean
3057 g_key_file_set_key_comment (GKeyFile     *key_file,
3058                             const gchar  *group_name,
3059                             const gchar  *key,
3060                             const gchar  *comment,
3061                             GError      **error)
3062 {
3063   GKeyFileGroup *group;
3064   GKeyFileKeyValuePair *pair;
3065   GList *key_node, *comment_node, *tmp;
3066   
3067   group = g_key_file_lookup_group (key_file, group_name);
3068   if (!group)
3069     {
3070       g_set_error (error, G_KEY_FILE_ERROR,
3071                    G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
3072                    _("Key file does not have group '%s'"),
3073                    group_name ? group_name : "(null)");
3074
3075       return FALSE;
3076     }
3077
3078   /* First find the key the comments are supposed to be
3079    * associated with
3080    */
3081   key_node = g_key_file_lookup_key_value_pair_node (key_file, group, key);
3082
3083   if (key_node == NULL)
3084     {
3085       g_set_error (error, G_KEY_FILE_ERROR,
3086                    G_KEY_FILE_ERROR_KEY_NOT_FOUND,
3087                    _("Key file does not have key '%s' in group '%s'"),
3088                    key, group->name);
3089       return FALSE;
3090     }
3091
3092   /* Then find all the comments already associated with the
3093    * key and free them
3094    */
3095   tmp = key_node->next;
3096   while (tmp != NULL)
3097     {
3098       pair = (GKeyFileKeyValuePair *) tmp->data;
3099
3100       if (pair->key != NULL)
3101         break;
3102
3103       comment_node = tmp;
3104       tmp = tmp->next;
3105       g_key_file_remove_key_value_pair_node (key_file, group,
3106                                              comment_node); 
3107     }
3108
3109   if (comment == NULL)
3110     return TRUE;
3111
3112   /* Now we can add our new comment
3113    */
3114   pair = g_slice_new (GKeyFileKeyValuePair);
3115   pair->key = NULL;
3116   pair->value = g_key_file_parse_comment_as_value (key_file, comment);
3117   
3118   key_node = g_list_insert (key_node, pair, 1);
3119
3120   return TRUE;
3121 }
3122
3123 static gboolean
3124 g_key_file_set_group_comment (GKeyFile     *key_file,
3125                               const gchar  *group_name,
3126                               const gchar  *comment,
3127                               GError      **error)
3128 {
3129   GKeyFileGroup *group;
3130   
3131   g_return_val_if_fail (g_key_file_is_group_name (group_name), FALSE);
3132
3133   group = g_key_file_lookup_group (key_file, group_name);
3134   if (!group)
3135     {
3136       g_set_error (error, G_KEY_FILE_ERROR,
3137                    G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
3138                    _("Key file does not have group '%s'"),
3139                    group_name ? group_name : "(null)");
3140
3141       return FALSE;
3142     }
3143
3144   /* First remove any existing comment
3145    */
3146   if (group->comment)
3147     {
3148       g_key_file_key_value_pair_free (group->comment);
3149       group->comment = NULL;
3150     }
3151
3152   if (comment == NULL)
3153     return TRUE;
3154
3155   /* Now we can add our new comment
3156    */
3157   group->comment = g_slice_new (GKeyFileKeyValuePair);
3158   group->comment->key = NULL;
3159   group->comment->value = g_key_file_parse_comment_as_value (key_file, comment);
3160
3161   return TRUE;
3162 }
3163
3164 static gboolean
3165 g_key_file_set_top_comment (GKeyFile     *key_file,
3166                             const gchar  *comment,
3167                             GError      **error)
3168 {
3169   GList *group_node;
3170   GKeyFileGroup *group;
3171   GKeyFileKeyValuePair *pair;
3172
3173   /* The last group in the list should be the top (comments only)
3174    * group in the file
3175    */
3176   g_warn_if_fail (key_file->groups != NULL);
3177   group_node = g_list_last (key_file->groups);
3178   group = (GKeyFileGroup *) group_node->data;
3179   g_warn_if_fail (group->name == NULL);
3180
3181   /* Note all keys must be comments at the top of
3182    * the file, so we can just free it all.
3183    */
3184   g_list_free_full (group->key_value_pairs, (GDestroyNotify) g_key_file_key_value_pair_free);
3185   group->key_value_pairs = NULL;
3186
3187   if (comment == NULL)
3188      return TRUE;
3189
3190   pair = g_slice_new (GKeyFileKeyValuePair);
3191   pair->key = NULL;
3192   pair->value = g_key_file_parse_comment_as_value (key_file, comment);
3193   
3194   group->key_value_pairs =
3195     g_list_prepend (group->key_value_pairs, pair);
3196
3197   return TRUE;
3198 }
3199
3200 /**
3201  * g_key_file_set_comment:
3202  * @key_file: a #GKeyFile
3203  * @group_name: (allow-none): a group name, or %NULL
3204  * @key: (allow-none): a key
3205  * @comment: a comment
3206  * @error: return location for a #GError
3207  *
3208  * Places a comment above @key from @group_name.
3209  * If @key is %NULL then @comment will be written above @group_name.  
3210  * If both @key and @group_name  are %NULL, then @comment will be 
3211  * written above the first group in the file.
3212  *
3213  * Returns: %TRUE if the comment was written, %FALSE otherwise
3214  *
3215  * Since: 2.6
3216  **/
3217 gboolean
3218 g_key_file_set_comment (GKeyFile     *key_file,
3219                         const gchar  *group_name,
3220                         const gchar  *key,
3221                         const gchar  *comment,
3222                         GError      **error)
3223 {
3224   g_return_val_if_fail (key_file != NULL, FALSE);
3225
3226   if (group_name != NULL && key != NULL) 
3227     {
3228       if (!g_key_file_set_key_comment (key_file, group_name, key, comment, error))
3229         return FALSE;
3230     } 
3231   else if (group_name != NULL) 
3232     {
3233       if (!g_key_file_set_group_comment (key_file, group_name, comment, error))
3234         return FALSE;
3235     } 
3236   else 
3237     {
3238       if (!g_key_file_set_top_comment (key_file, comment, error))
3239         return FALSE;
3240     }
3241
3242   return TRUE;
3243 }
3244
3245 static gchar *
3246 g_key_file_get_key_comment (GKeyFile     *key_file,
3247                             const gchar  *group_name,
3248                             const gchar  *key,
3249                             GError      **error)
3250 {
3251   GKeyFileGroup *group;
3252   GKeyFileKeyValuePair *pair;
3253   GList *key_node, *tmp;
3254   GString *string;
3255   gchar *comment;
3256
3257   g_return_val_if_fail (g_key_file_is_group_name (group_name), NULL);
3258
3259   group = g_key_file_lookup_group (key_file, group_name);
3260   if (!group)
3261     {
3262       g_set_error (error, G_KEY_FILE_ERROR,
3263                    G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
3264                    _("Key file does not have group '%s'"),
3265                    group_name ? group_name : "(null)");
3266
3267       return NULL;
3268     }
3269
3270   /* First find the key the comments are supposed to be
3271    * associated with
3272    */
3273   key_node = g_key_file_lookup_key_value_pair_node (key_file, group, key);
3274
3275   if (key_node == NULL)
3276     {
3277       g_set_error (error, G_KEY_FILE_ERROR,
3278                    G_KEY_FILE_ERROR_KEY_NOT_FOUND,
3279                    _("Key file does not have key '%s' in group '%s'"),
3280                    key, group->name);
3281       return NULL;
3282     }
3283
3284   string = NULL;
3285
3286   /* Then find all the comments already associated with the
3287    * key and concatentate them.
3288    */
3289   tmp = key_node->next;
3290   if (!key_node->next)
3291     return NULL;
3292
3293   pair = (GKeyFileKeyValuePair *) tmp->data;
3294   if (pair->key != NULL)
3295     return NULL;
3296
3297   while (tmp->next)
3298     {
3299       pair = (GKeyFileKeyValuePair *) tmp->next->data;
3300       
3301       if (pair->key != NULL)
3302         break;
3303
3304       tmp = tmp->next;
3305     }
3306
3307   while (tmp != key_node)
3308     {
3309       pair = (GKeyFileKeyValuePair *) tmp->data;
3310       
3311       if (string == NULL)
3312         string = g_string_sized_new (512);
3313       
3314       comment = g_key_file_parse_value_as_comment (key_file, pair->value);
3315       g_string_append (string, comment);
3316       g_free (comment);
3317       
3318       tmp = tmp->prev;
3319     }
3320
3321   if (string != NULL)
3322     {
3323       comment = string->str;
3324       g_string_free (string, FALSE);
3325     }
3326   else
3327     comment = NULL;
3328
3329   return comment;
3330 }
3331
3332 static gchar *
3333 get_group_comment (GKeyFile       *key_file,
3334                    GKeyFileGroup  *group,
3335                    GError        **error)
3336 {
3337   GString *string;
3338   GList *tmp;
3339   gchar *comment;
3340
3341   string = NULL;
3342
3343   tmp = group->key_value_pairs;
3344   while (tmp)
3345     {
3346       GKeyFileKeyValuePair *pair;
3347
3348       pair = (GKeyFileKeyValuePair *) tmp->data;
3349
3350       if (pair->key != NULL)
3351         {
3352           tmp = tmp->prev;
3353           break;
3354         }
3355
3356       if (tmp->next == NULL)
3357         break;
3358
3359       tmp = tmp->next;
3360     }
3361   
3362   while (tmp != NULL)
3363     {
3364       GKeyFileKeyValuePair *pair;
3365
3366       pair = (GKeyFileKeyValuePair *) tmp->data;
3367
3368       if (string == NULL)
3369         string = g_string_sized_new (512);
3370
3371       comment = g_key_file_parse_value_as_comment (key_file, pair->value);
3372       g_string_append (string, comment);
3373       g_free (comment);
3374
3375       tmp = tmp->prev;
3376     }
3377
3378   if (string != NULL)
3379     return g_string_free (string, FALSE);
3380
3381   return NULL;
3382 }
3383
3384 static gchar *
3385 g_key_file_get_group_comment (GKeyFile     *key_file,
3386                               const gchar  *group_name,
3387                               GError      **error)
3388 {
3389   GList *group_node;
3390   GKeyFileGroup *group;
3391   
3392   group = g_key_file_lookup_group (key_file, group_name);
3393   if (!group)
3394     {
3395       g_set_error (error, G_KEY_FILE_ERROR,
3396                    G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
3397                    _("Key file does not have group '%s'"),
3398                    group_name ? group_name : "(null)");
3399
3400       return NULL;
3401     }
3402
3403   if (group->comment)
3404     return g_strdup (group->comment->value);
3405   
3406   group_node = g_key_file_lookup_group_node (key_file, group_name);
3407   group_node = group_node->next;
3408   group = (GKeyFileGroup *)group_node->data;  
3409   return get_group_comment (key_file, group, error);
3410 }
3411
3412 static gchar *
3413 g_key_file_get_top_comment (GKeyFile  *key_file,
3414                             GError   **error)
3415 {
3416   GList *group_node;
3417   GKeyFileGroup *group;
3418
3419   /* The last group in the list should be the top (comments only)
3420    * group in the file
3421    */
3422   g_warn_if_fail (key_file->groups != NULL);
3423   group_node = g_list_last (key_file->groups);
3424   group = (GKeyFileGroup *) group_node->data;
3425   g_warn_if_fail (group->name == NULL);
3426
3427   return get_group_comment (key_file, group, error);
3428 }
3429
3430 /**
3431  * g_key_file_get_comment:
3432  * @key_file: a #GKeyFile
3433  * @group_name: (allow-none): a group name, or %NULL
3434  * @key: a key
3435  * @error: return location for a #GError
3436  *
3437  * Retrieves a comment above @key from @group_name.
3438  * If @key is %NULL then @comment will be read from above 
3439  * @group_name. If both @key and @group_name are %NULL, then 
3440  * @comment will be read from above the first group in the file.
3441  *
3442  * Returns: a comment that should be freed with g_free()
3443  *
3444  * Since: 2.6
3445  **/
3446 gchar * 
3447 g_key_file_get_comment (GKeyFile     *key_file,
3448                         const gchar  *group_name,
3449                         const gchar  *key,
3450                         GError      **error)
3451 {
3452   g_return_val_if_fail (key_file != NULL, NULL);
3453
3454   if (group_name != NULL && key != NULL)
3455     return g_key_file_get_key_comment (key_file, group_name, key, error);
3456   else if (group_name != NULL)
3457     return g_key_file_get_group_comment (key_file, group_name, error);
3458   else
3459     return g_key_file_get_top_comment (key_file, error);
3460 }
3461
3462 /**
3463  * g_key_file_remove_comment:
3464  * @key_file: a #GKeyFile
3465  * @group_name: (allow-none): a group name, or %NULL
3466  * @key: (allow-none): a key
3467  * @error: return location for a #GError
3468  *
3469  * Removes a comment above @key from @group_name.
3470  * If @key is %NULL then @comment will be removed above @group_name. 
3471  * If both @key and @group_name are %NULL, then @comment will
3472  * be removed above the first group in the file.
3473  *
3474  * Returns: %TRUE if the comment was removed, %FALSE otherwise
3475  *
3476  * Since: 2.6
3477  **/
3478
3479 gboolean
3480 g_key_file_remove_comment (GKeyFile     *key_file,
3481                            const gchar  *group_name,
3482                            const gchar  *key,
3483                            GError      **error)
3484 {
3485   g_return_val_if_fail (key_file != NULL, FALSE);
3486
3487   if (group_name != NULL && key != NULL)
3488     return g_key_file_set_key_comment (key_file, group_name, key, NULL, error);
3489   else if (group_name != NULL)
3490     return g_key_file_set_group_comment (key_file, group_name, NULL, error);
3491   else
3492     return g_key_file_set_top_comment (key_file, NULL, error);
3493 }
3494
3495 /**
3496  * g_key_file_has_group:
3497  * @key_file: a #GKeyFile
3498  * @group_name: a group name
3499  *
3500  * Looks whether the key file has the group @group_name.
3501  *
3502  * Return value: %TRUE if @group_name is a part of @key_file, %FALSE
3503  * otherwise.
3504  * Since: 2.6
3505  **/
3506 gboolean
3507 g_key_file_has_group (GKeyFile    *key_file,
3508                       const gchar *group_name)
3509 {
3510   g_return_val_if_fail (key_file != NULL, FALSE);
3511   g_return_val_if_fail (group_name != NULL, FALSE);
3512
3513   return g_key_file_lookup_group (key_file, group_name) != NULL;
3514 }
3515
3516 /* This code remains from a historical attempt to add a new public API
3517  * which respects the GError rules.
3518  */
3519 static gboolean
3520 g_key_file_has_key_full (GKeyFile     *key_file,
3521                          const gchar  *group_name,
3522                          const gchar  *key,
3523                          gboolean     *has_key,
3524                          GError      **error)
3525 {
3526   GKeyFileKeyValuePair *pair;
3527   GKeyFileGroup *group;
3528
3529   g_return_val_if_fail (key_file != NULL, FALSE);
3530   g_return_val_if_fail (group_name != NULL, FALSE);
3531   g_return_val_if_fail (key != NULL, FALSE);
3532
3533   group = g_key_file_lookup_group (key_file, group_name);
3534
3535   if (!group)
3536     {
3537       g_set_error (error, G_KEY_FILE_ERROR,
3538                    G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
3539                    _("Key file does not have group '%s'"),
3540                    group_name ? group_name : "(null)");
3541
3542       return FALSE;
3543     }
3544
3545   pair = g_key_file_lookup_key_value_pair (key_file, group, key);
3546
3547   if (has_key)
3548     *has_key = pair != NULL;
3549   return TRUE;
3550 }
3551
3552 /**
3553  * g_key_file_has_key: (skip)
3554  * @key_file: a #GKeyFile
3555  * @group_name: a group name
3556  * @key: a key name
3557  * @error: return location for a #GError
3558  *
3559  * Looks whether the key file has the key @key in the group
3560  * @group_name.
3561  *
3562  * Note that this function does not follow the rules for #GError strictly;
3563  * the return value both carries meaning and signals an error.  To use
3564  * this function, you must pass a #GError pointer in @error, and check
3565  * whether it is not %NULL to see if an error occurred.
3566  *
3567  * Language bindings should use g_key_file_get_value() to test whether
3568  * or not a key exists.
3569  *
3570  * Return value: %TRUE if @key is a part of @group_name, %FALSE otherwise
3571  *
3572  * Since: 2.6
3573  **/
3574 gboolean
3575 g_key_file_has_key (GKeyFile     *key_file,
3576                     const gchar  *group_name,
3577                     const gchar  *key,
3578                     GError      **error)
3579 {
3580   GError *temp_error = NULL;
3581   gboolean has_key;
3582
3583   if (g_key_file_has_key_full (key_file, group_name, key, &has_key, &temp_error))
3584     {
3585       return has_key;
3586     }
3587   else
3588     {
3589       g_propagate_error (error, temp_error);
3590       return FALSE;
3591     }
3592 }
3593
3594 static void
3595 g_key_file_add_group (GKeyFile    *key_file,
3596                       const gchar *group_name)
3597 {
3598   GKeyFileGroup *group;
3599
3600   g_return_if_fail (key_file != NULL);
3601   g_return_if_fail (g_key_file_is_group_name (group_name));
3602
3603   group = g_key_file_lookup_group (key_file, group_name);
3604   if (group != NULL)
3605     {
3606       key_file->current_group = group;
3607       return;
3608     }
3609
3610   group = g_slice_new0 (GKeyFileGroup);
3611   group->name = g_strdup (group_name);
3612   group->lookup_map = g_hash_table_new (g_str_hash, g_str_equal);
3613   key_file->groups = g_list_prepend (key_file->groups, group);
3614   key_file->current_group = group;
3615
3616   if (key_file->start_group == NULL)
3617     key_file->start_group = group;
3618
3619   g_hash_table_insert (key_file->group_hash, (gpointer)group->name, group);
3620 }
3621
3622 static void
3623 g_key_file_key_value_pair_free (GKeyFileKeyValuePair *pair)
3624 {
3625   if (pair != NULL)
3626     {
3627       g_free (pair->key);
3628       g_free (pair->value);
3629       g_slice_free (GKeyFileKeyValuePair, pair);
3630     }
3631 }
3632
3633 /* Be careful not to call this function on a node with data in the
3634  * lookup map without removing it from the lookup map, first.
3635  *
3636  * Some current cases where this warning is not a concern are
3637  * when:
3638  *   - the node being removed is a comment node
3639  *   - the entire lookup map is getting destroyed soon after
3640  *     anyway.
3641  */ 
3642 static void
3643 g_key_file_remove_key_value_pair_node (GKeyFile      *key_file,
3644                                        GKeyFileGroup *group,
3645                                        GList         *pair_node)
3646 {
3647
3648   GKeyFileKeyValuePair *pair;
3649
3650   pair = (GKeyFileKeyValuePair *) pair_node->data;
3651
3652   group->key_value_pairs = g_list_remove_link (group->key_value_pairs, pair_node);
3653
3654   g_warn_if_fail (pair->value != NULL);
3655
3656   g_key_file_key_value_pair_free (pair);
3657
3658   g_list_free_1 (pair_node);
3659 }
3660
3661 static void
3662 g_key_file_remove_group_node (GKeyFile *key_file,
3663                               GList    *group_node)
3664 {
3665   GKeyFileGroup *group;
3666   GList *tmp;
3667
3668   group = (GKeyFileGroup *) group_node->data;
3669
3670   if (group->name)
3671     g_hash_table_remove (key_file->group_hash, group->name);
3672
3673   /* If the current group gets deleted make the current group the last
3674    * added group.
3675    */
3676   if (key_file->current_group == group)
3677     {
3678       /* groups should always contain at least the top comment group,
3679        * unless g_key_file_clear has been called
3680        */
3681       if (key_file->groups)
3682         key_file->current_group = (GKeyFileGroup *) key_file->groups->data;
3683       else
3684         key_file->current_group = NULL;
3685     }
3686
3687   /* If the start group gets deleted make the start group the first
3688    * added group.
3689    */
3690   if (key_file->start_group == group)
3691     {
3692       tmp = g_list_last (key_file->groups);
3693       while (tmp != NULL)
3694         {
3695           if (tmp != group_node &&
3696               ((GKeyFileGroup *) tmp->data)->name != NULL)
3697             break;
3698
3699           tmp = tmp->prev;
3700         }
3701
3702       if (tmp)
3703         key_file->start_group = (GKeyFileGroup *) tmp->data;
3704       else
3705         key_file->start_group = NULL;
3706     }
3707
3708   key_file->groups = g_list_remove_link (key_file->groups, group_node);
3709
3710   tmp = group->key_value_pairs;
3711   while (tmp != NULL)
3712     {
3713       GList *pair_node;
3714
3715       pair_node = tmp;
3716       tmp = tmp->next;
3717       g_key_file_remove_key_value_pair_node (key_file, group, pair_node);
3718     }
3719
3720   g_warn_if_fail (group->key_value_pairs == NULL);
3721
3722   if (group->comment)
3723     {
3724       g_key_file_key_value_pair_free (group->comment);
3725       group->comment = NULL;
3726     }
3727
3728   if (group->lookup_map)
3729     {
3730       g_hash_table_destroy (group->lookup_map);
3731       group->lookup_map = NULL;
3732     }
3733
3734   g_free ((gchar *) group->name);
3735   g_slice_free (GKeyFileGroup, group);
3736   g_list_free_1 (group_node);
3737 }
3738
3739 /**
3740  * g_key_file_remove_group:
3741  * @key_file: a #GKeyFile
3742  * @group_name: a group name
3743  * @error: return location for a #GError or %NULL
3744  *
3745  * Removes the specified group, @group_name, 
3746  * from the key file. 
3747  *
3748  * Returns: %TRUE if the group was removed, %FALSE otherwise
3749  *
3750  * Since: 2.6
3751  **/
3752 gboolean
3753 g_key_file_remove_group (GKeyFile     *key_file,
3754                          const gchar  *group_name,
3755                          GError      **error)
3756 {
3757   GList *group_node;
3758
3759   g_return_val_if_fail (key_file != NULL, FALSE);
3760   g_return_val_if_fail (group_name != NULL, FALSE);
3761
3762   group_node = g_key_file_lookup_group_node (key_file, group_name);
3763
3764   if (!group_node)
3765     {
3766       g_set_error (error, G_KEY_FILE_ERROR,
3767                    G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
3768                    _("Key file does not have group '%s'"),
3769                    group_name);
3770       return FALSE;
3771     }
3772
3773   g_key_file_remove_group_node (key_file, group_node);
3774
3775   return TRUE;  
3776 }
3777
3778 static void
3779 g_key_file_add_key_value_pair (GKeyFile             *key_file,
3780                                GKeyFileGroup        *group,
3781                                GKeyFileKeyValuePair *pair)
3782 {
3783   g_hash_table_replace (group->lookup_map, pair->key, pair);
3784   group->key_value_pairs = g_list_prepend (group->key_value_pairs, pair);
3785 }
3786
3787 static void
3788 g_key_file_add_key (GKeyFile      *key_file,
3789                     GKeyFileGroup *group,
3790                     const gchar   *key,
3791                     const gchar   *value)
3792 {
3793   GKeyFileKeyValuePair *pair;
3794
3795   pair = g_slice_new (GKeyFileKeyValuePair);
3796   pair->key = g_strdup (key);
3797   pair->value = g_strdup (value);
3798
3799   g_key_file_add_key_value_pair (key_file, group, pair);
3800 }
3801
3802 /**
3803  * g_key_file_remove_key:
3804  * @key_file: a #GKeyFile
3805  * @group_name: a group name
3806  * @key: a key name to remove
3807  * @error: return location for a #GError or %NULL
3808  *
3809  * Removes @key in @group_name from the key file. 
3810  *
3811  * Returns: %TRUE if the key was removed, %FALSE otherwise
3812  *
3813  * Since: 2.6
3814  **/
3815 gboolean
3816 g_key_file_remove_key (GKeyFile     *key_file,
3817                        const gchar  *group_name,
3818                        const gchar  *key,
3819                        GError      **error)
3820 {
3821   GKeyFileGroup *group;
3822   GKeyFileKeyValuePair *pair;
3823
3824   g_return_val_if_fail (key_file != NULL, FALSE);
3825   g_return_val_if_fail (group_name != NULL, FALSE);
3826   g_return_val_if_fail (key != NULL, FALSE);
3827
3828   pair = NULL;
3829
3830   group = g_key_file_lookup_group (key_file, group_name);
3831   if (!group)
3832     {
3833       g_set_error (error, G_KEY_FILE_ERROR,
3834                    G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
3835                    _("Key file does not have group '%s'"),
3836                    group_name ? group_name : "(null)");
3837       return FALSE;
3838     }
3839
3840   pair = g_key_file_lookup_key_value_pair (key_file, group, key);
3841
3842   if (!pair)
3843     {
3844       g_set_error (error, G_KEY_FILE_ERROR,
3845                    G_KEY_FILE_ERROR_KEY_NOT_FOUND,
3846                    _("Key file does not have key '%s' in group '%s'"),
3847                    key, group->name);
3848       return FALSE;
3849     }
3850
3851   group->key_value_pairs = g_list_remove (group->key_value_pairs, pair);
3852   g_hash_table_remove (group->lookup_map, pair->key);
3853   g_key_file_key_value_pair_free (pair);
3854
3855   return TRUE;
3856 }
3857
3858 static GList *
3859 g_key_file_lookup_group_node (GKeyFile    *key_file,
3860                               const gchar *group_name)
3861 {
3862   GKeyFileGroup *group;
3863   GList *tmp;
3864
3865   for (tmp = key_file->groups; tmp != NULL; tmp = tmp->next)
3866     {
3867       group = (GKeyFileGroup *) tmp->data;
3868
3869       if (group && group->name && strcmp (group->name, group_name) == 0)
3870         break;
3871     }
3872
3873   return tmp;
3874 }
3875
3876 static GKeyFileGroup *
3877 g_key_file_lookup_group (GKeyFile    *key_file,
3878                          const gchar *group_name)
3879 {
3880   return (GKeyFileGroup *)g_hash_table_lookup (key_file->group_hash, group_name);
3881 }
3882
3883 static GList *
3884 g_key_file_lookup_key_value_pair_node (GKeyFile       *key_file,
3885                                        GKeyFileGroup  *group,
3886                                        const gchar    *key)
3887 {
3888   GList *key_node;
3889
3890   for (key_node = group->key_value_pairs;
3891        key_node != NULL;
3892        key_node = key_node->next)
3893     {
3894       GKeyFileKeyValuePair *pair;
3895
3896       pair = (GKeyFileKeyValuePair *) key_node->data; 
3897
3898       if (pair->key && strcmp (pair->key, key) == 0)
3899         break;
3900     }
3901
3902   return key_node;
3903 }
3904
3905 static GKeyFileKeyValuePair *
3906 g_key_file_lookup_key_value_pair (GKeyFile      *key_file,
3907                                   GKeyFileGroup *group,
3908                                   const gchar   *key)
3909 {
3910   return (GKeyFileKeyValuePair *) g_hash_table_lookup (group->lookup_map, key);
3911 }
3912
3913 /* Lines starting with # or consisting entirely of whitespace are merely
3914  * recorded, not parsed. This function assumes all leading whitespace
3915  * has been stripped.
3916  */
3917 static gboolean
3918 g_key_file_line_is_comment (const gchar *line)
3919 {
3920   return (*line == '#' || *line == '\0' || *line == '\n');
3921 }
3922
3923 static gboolean 
3924 g_key_file_is_group_name (const gchar *name)
3925 {
3926   gchar *p, *q;
3927
3928   if (name == NULL)
3929     return FALSE;
3930
3931   p = q = (gchar *) name;
3932   while (*q && *q != ']' && *q != '[' && !g_ascii_iscntrl (*q))
3933     q = g_utf8_find_next_char (q, NULL);
3934   
3935   if (*q != '\0' || q == p)
3936     return FALSE;
3937
3938   return TRUE;
3939 }
3940
3941 static gboolean
3942 g_key_file_is_key_name (const gchar *name)
3943 {
3944   gchar *p, *q;
3945
3946   if (name == NULL)
3947     return FALSE;
3948
3949   p = q = (gchar *) name;
3950   /* We accept a little more than the desktop entry spec says,
3951    * since gnome-vfs uses mime-types as keys in its cache.
3952    */
3953   while (*q && *q != '=' && *q != '[' && *q != ']')
3954     q = g_utf8_find_next_char (q, NULL);
3955   
3956   /* No empty keys, please */
3957   if (q == p)
3958     return FALSE;
3959
3960   /* We accept spaces in the middle of keys to not break
3961    * existing apps, but we don't tolerate initial or final
3962    * spaces, which would lead to silent corruption when
3963    * rereading the file.
3964    */
3965   if (*p == ' ' || q[-1] == ' ')
3966     return FALSE;
3967
3968   if (*q == '[')
3969     {
3970       q++;
3971       while (*q && (g_unichar_isalnum (g_utf8_get_char_validated (q, -1)) || *q == '-' || *q == '_' || *q == '.' || *q == '@'))
3972         q = g_utf8_find_next_char (q, NULL);
3973
3974       if (*q != ']')
3975         return FALSE;     
3976
3977       q++;
3978     }
3979
3980   if (*q != '\0')
3981     return FALSE;
3982
3983   return TRUE;
3984 }
3985
3986 /* A group in a key file is made up of a starting '[' followed by one
3987  * or more letters making up the group name followed by ']'.
3988  */
3989 static gboolean
3990 g_key_file_line_is_group (const gchar *line)
3991 {
3992   gchar *p;
3993
3994   p = (gchar *) line;
3995   if (*p != '[')
3996     return FALSE;
3997
3998   p++;
3999
4000   while (*p && *p != ']')
4001     p = g_utf8_find_next_char (p, NULL);
4002
4003   if (*p != ']')
4004     return FALSE;
4005  
4006   /* silently accept whitespace after the ] */
4007   p = g_utf8_find_next_char (p, NULL);
4008   while (*p == ' ' || *p == '\t')
4009     p = g_utf8_find_next_char (p, NULL);
4010      
4011   if (*p)
4012     return FALSE;
4013
4014   return TRUE;
4015 }
4016
4017 static gboolean
4018 g_key_file_line_is_key_value_pair (const gchar *line)
4019 {
4020   gchar *p;
4021
4022   p = (gchar *) g_utf8_strchr (line, -1, '=');
4023
4024   if (!p)
4025     return FALSE;
4026
4027   /* Key must be non-empty
4028    */
4029   if (*p == line[0])
4030     return FALSE;
4031
4032   return TRUE;
4033 }
4034
4035 static gchar *
4036 g_key_file_parse_value_as_string (GKeyFile     *key_file,
4037                                   const gchar  *value,
4038                                   GSList      **pieces,
4039                                   GError      **error)
4040 {
4041   gchar *string_value, *p, *q0, *q;
4042
4043   string_value = g_new (gchar, strlen (value) + 1);
4044
4045   p = (gchar *) value;
4046   q0 = q = string_value;
4047   while (*p)
4048     {
4049       if (*p == '\\')
4050         {
4051           p++;
4052
4053           switch (*p)
4054             {
4055             case 's':
4056               *q = ' ';
4057               break;
4058
4059             case 'n':
4060               *q = '\n';
4061               break;
4062
4063             case 't':
4064               *q = '\t';
4065               break;
4066
4067             case 'r':
4068               *q = '\r';
4069               break;
4070
4071             case '\\':
4072               *q = '\\';
4073               break;
4074
4075             case '\0':
4076               g_set_error_literal (error, G_KEY_FILE_ERROR,
4077                                    G_KEY_FILE_ERROR_INVALID_VALUE,
4078                                    _("Key file contains escape character "
4079                                      "at end of line"));
4080               break;
4081
4082             default:
4083               if (pieces && *p == key_file->list_separator)
4084                 *q = key_file->list_separator;
4085               else
4086                 {
4087                   *q++ = '\\';
4088                   *q = *p;
4089                   
4090                   if (*error == NULL)
4091                     {
4092                       gchar sequence[3];
4093                       
4094                       sequence[0] = '\\';
4095                       sequence[1] = *p;
4096                       sequence[2] = '\0';
4097                       
4098                       g_set_error (error, G_KEY_FILE_ERROR,
4099                                    G_KEY_FILE_ERROR_INVALID_VALUE,
4100                                    _("Key file contains invalid escape "
4101                                      "sequence '%s'"), sequence);
4102                     }
4103                 }
4104               break;
4105             }
4106         }
4107       else
4108         {
4109           *q = *p;
4110           if (pieces && (*p == key_file->list_separator))
4111             {
4112               *pieces = g_slist_prepend (*pieces, g_strndup (q0, q - q0));
4113               q0 = q + 1; 
4114             }
4115         }
4116
4117       if (*p == '\0')
4118         break;
4119
4120       q++;
4121       p++;
4122     }
4123
4124   *q = '\0';
4125   if (pieces)
4126   {
4127     if (q0 < q)
4128       *pieces = g_slist_prepend (*pieces, g_strndup (q0, q - q0));
4129     *pieces = g_slist_reverse (*pieces);
4130   }
4131
4132   return string_value;
4133 }
4134
4135 static gchar *
4136 g_key_file_parse_string_as_value (GKeyFile    *key_file,
4137                                   const gchar *string,
4138                                   gboolean     escape_separator)
4139 {
4140   gchar *value, *p, *q;
4141   gsize length;
4142   gboolean parsing_leading_space;
4143
4144   length = strlen (string) + 1;
4145
4146   /* Worst case would be that every character needs to be escaped.
4147    * In other words every character turns to two characters
4148    */
4149   value = g_new (gchar, 2 * length);
4150
4151   p = (gchar *) string;
4152   q = value;
4153   parsing_leading_space = TRUE;
4154   while (p < (string + length - 1))
4155     {
4156       gchar escaped_character[3] = { '\\', 0, 0 };
4157
4158       switch (*p)
4159         {
4160         case ' ':
4161           if (parsing_leading_space)
4162             {
4163               escaped_character[1] = 's';
4164               strcpy (q, escaped_character);
4165               q += 2;
4166             }
4167           else
4168             {
4169               *q = *p;
4170               q++;
4171             }
4172           break;
4173         case '\t':
4174           if (parsing_leading_space)
4175             {
4176               escaped_character[1] = 't';
4177               strcpy (q, escaped_character);
4178               q += 2;
4179             }
4180           else
4181             {
4182               *q = *p;
4183               q++;
4184             }
4185           break;
4186         case '\n':
4187           escaped_character[1] = 'n';
4188           strcpy (q, escaped_character);
4189           q += 2;
4190           break;
4191         case '\r':
4192           escaped_character[1] = 'r';
4193           strcpy (q, escaped_character);
4194           q += 2;
4195           break;
4196         case '\\':
4197           escaped_character[1] = '\\';
4198           strcpy (q, escaped_character);
4199           q += 2;
4200           parsing_leading_space = FALSE;
4201           break;
4202         default:
4203           if (escape_separator && *p == key_file->list_separator)
4204             {
4205               escaped_character[1] = key_file->list_separator;
4206               strcpy (q, escaped_character);
4207               q += 2;
4208               parsing_leading_space = TRUE;
4209             }
4210           else 
4211             {
4212               *q = *p;
4213               q++;
4214               parsing_leading_space = FALSE;
4215             }
4216           break;
4217         }
4218       p++;
4219     }
4220   *q = '\0';
4221
4222   return value;
4223 }
4224
4225 static gint
4226 g_key_file_parse_value_as_integer (GKeyFile     *key_file,
4227                                    const gchar  *value,
4228                                    GError      **error)
4229 {
4230   gchar *eof_int;
4231   glong long_value;
4232   gint int_value;
4233
4234   errno = 0;
4235   long_value = strtol (value, &eof_int, 10);
4236
4237   if (*value == '\0' || (*eof_int != '\0' && !g_ascii_isspace(*eof_int)))
4238     {
4239       gchar *value_utf8 = _g_utf8_make_valid (value);
4240       g_set_error (error, G_KEY_FILE_ERROR,
4241                    G_KEY_FILE_ERROR_INVALID_VALUE,
4242                    _("Value '%s' cannot be interpreted "
4243                      "as a number."), value_utf8);
4244       g_free (value_utf8);
4245
4246       return 0;
4247     }
4248
4249   int_value = long_value;
4250   if (int_value != long_value || errno == ERANGE)
4251     {
4252       gchar *value_utf8 = _g_utf8_make_valid (value);
4253       g_set_error (error,
4254                    G_KEY_FILE_ERROR, 
4255                    G_KEY_FILE_ERROR_INVALID_VALUE,
4256                    _("Integer value '%s' out of range"), 
4257                    value_utf8);
4258       g_free (value_utf8);
4259
4260       return 0;
4261     }
4262   
4263   return int_value;
4264 }
4265
4266 static gchar *
4267 g_key_file_parse_integer_as_value (GKeyFile *key_file,
4268                                    gint      value)
4269
4270 {
4271   return g_strdup_printf ("%d", value);
4272 }
4273
4274 static gdouble
4275 g_key_file_parse_value_as_double  (GKeyFile     *key_file,
4276                                    const gchar  *value,
4277                                    GError      **error)
4278 {
4279   gchar *end_of_valid_d;
4280   gdouble double_value = 0;
4281
4282   double_value = g_ascii_strtod (value, &end_of_valid_d);
4283
4284   if (*end_of_valid_d != '\0' || end_of_valid_d == value)
4285     {
4286       gchar *value_utf8 = _g_utf8_make_valid (value);
4287       g_set_error (error, G_KEY_FILE_ERROR,
4288                    G_KEY_FILE_ERROR_INVALID_VALUE,
4289                    _("Value '%s' cannot be interpreted "
4290                      "as a float number."), 
4291                    value_utf8);
4292       g_free (value_utf8);
4293     }
4294
4295   return double_value;
4296 }
4297
4298 static gboolean
4299 g_key_file_parse_value_as_boolean (GKeyFile     *key_file,
4300                                    const gchar  *value,
4301                                    GError      **error)
4302 {
4303   gchar *value_utf8;
4304
4305   if (strcmp (value, "true") == 0 || strcmp (value, "1") == 0)
4306     return TRUE;
4307   else if (strcmp (value, "false") == 0 || strcmp (value, "0") == 0)
4308     return FALSE;
4309
4310   value_utf8 = _g_utf8_make_valid (value);
4311   g_set_error (error, G_KEY_FILE_ERROR,
4312                G_KEY_FILE_ERROR_INVALID_VALUE,
4313                _("Value '%s' cannot be interpreted "
4314                  "as a boolean."), value_utf8);
4315   g_free (value_utf8);
4316
4317   return FALSE;
4318 }
4319
4320 static gchar *
4321 g_key_file_parse_boolean_as_value (GKeyFile *key_file,
4322                                    gboolean  value)
4323 {
4324   if (value)
4325     return g_strdup ("true");
4326   else
4327     return g_strdup ("false");
4328 }
4329
4330 static gchar *
4331 g_key_file_parse_value_as_comment (GKeyFile    *key_file,
4332                                    const gchar *value)
4333 {
4334   GString *string;
4335   gchar **lines;
4336   gsize i;
4337
4338   string = g_string_sized_new (512);
4339
4340   lines = g_strsplit (value, "\n", 0);
4341
4342   for (i = 0; lines[i] != NULL; i++)
4343     {
4344         if (lines[i][0] != '#')
4345            g_string_append_printf (string, "%s\n", lines[i]);
4346         else 
4347            g_string_append_printf (string, "%s\n", lines[i] + 1);
4348     }
4349   g_strfreev (lines);
4350
4351   return g_string_free (string, FALSE);
4352 }
4353
4354 static gchar *
4355 g_key_file_parse_comment_as_value (GKeyFile      *key_file,
4356                                    const gchar   *comment)
4357 {
4358   GString *string;
4359   gchar **lines;
4360   gsize i;
4361
4362   string = g_string_sized_new (512);
4363
4364   lines = g_strsplit (comment, "\n", 0);
4365
4366   for (i = 0; lines[i] != NULL; i++)
4367     g_string_append_printf (string, "#%s%s", lines[i], 
4368                             lines[i + 1] == NULL? "" : "\n");
4369   g_strfreev (lines);
4370
4371   return g_string_free (string, FALSE);
4372 }
4373
4374 /**
4375  * g_key_file_save_to_file:
4376  * @key_file: a #GKeyFile
4377  * @filename: the name of the file to write to
4378  * @error: a pointer to a %NULL #GError, or %NULL
4379  *
4380  * Writes the contents of @key_file to @filename using
4381  * g_file_set_contents().
4382  *
4383  * This function can fail for any of the reasons that
4384  * g_file_set_contents() may fail.
4385  *
4386  * Returns: %TRUE if successful, else %FALSE with @error set
4387  *
4388  * Since: 2.40
4389  */
4390 gboolean
4391 g_key_file_save_to_file (GKeyFile     *key_file,
4392                          const gchar  *filename,
4393                          GError      **error)
4394 {
4395   gchar *contents;
4396   gboolean success;
4397   gsize length;
4398
4399   g_return_val_if_fail (key_file != NULL, FALSE);
4400   g_return_val_if_fail (filename != NULL, FALSE);
4401   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
4402
4403   contents = g_key_file_to_data (key_file, &length, NULL);
4404   g_assert (contents != NULL);
4405
4406   success = g_file_set_contents (filename, contents, length, error);
4407   g_free (contents);
4408
4409   return success;
4410 }