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