10
#include "desktop_file.h"
14
#define _(x) gettext ((x))
18
typedef struct _GnomeDesktopFileSection GnomeDesktopFileSection;
19
typedef struct _GnomeDesktopFileLine GnomeDesktopFileLine;
20
typedef struct _GnomeDesktopFileParser GnomeDesktopFileParser;
22
struct _GnomeDesktopFileSection {
23
GQuark section_name; /* 0 means just a comment block (before any section) */
25
GnomeDesktopFileLine *lines;
26
gint n_allocated_lines;
29
struct _GnomeDesktopFileLine {
30
GQuark key; /* 0 means comment or blank line in value */
35
struct _GnomeDesktopFile {
37
GnomeDesktopFileSection *sections;
38
gint n_allocated_sections;
40
GnomeDesktopFileEncoding encoding;
43
struct _GnomeDesktopFileParser {
50
#define VALID_KEY_CHAR 1
51
#define VALID_LOCALE_CHAR 2
53
/* 0 */ 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 ,
54
/* 16 */ 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 ,
55
/* 32 */ 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x3 , 0x2 , 0x0 ,
56
/* 48 */ 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 ,
57
/* 64 */ 0x2 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 ,
58
/* 80 */ 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x0 , 0x0 , 0x0 , 0x0 , 0x2 ,
59
/* 96 */ 0x0 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 ,
60
/* 112 */ 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 ,
61
/* 128 */ 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 ,
62
/* 144 */ 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 ,
63
/* 160 */ 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 ,
64
/* 176 */ 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 ,
65
/* 192 */ 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 ,
66
/* 208 */ 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 ,
67
/* 224 */ 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 ,
68
/* 240 */ 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0
71
static void report_error (GnomeDesktopFileParser *parser,
73
GnomeDesktopParseError error_code,
75
static GnomeDesktopFileSection *lookup_section (GnomeDesktopFile *df,
77
static GnomeDesktopFileLine * lookup_line (GnomeDesktopFile *df,
78
GnomeDesktopFileSection *section,
86
gnome_desktop_parse_error_quark (void)
90
quark = g_quark_from_static_string ("g_desktop_parse_error");
96
parser_free (GnomeDesktopFileParser *parser)
98
gnome_desktop_file_free (parser->df);
102
gnome_desktop_file_line_free (GnomeDesktopFileLine *line)
104
g_free (line->locale);
105
g_free (line->value);
109
gnome_desktop_file_section_free (GnomeDesktopFileSection *section)
113
for (i = 0; i < section->n_lines; i++)
114
gnome_desktop_file_line_free (§ion->lines[i]);
116
g_free (section->lines);
120
gnome_desktop_file_free (GnomeDesktopFile *df)
124
for (i = 0; i < df->n_sections; i++)
125
gnome_desktop_file_section_free (&df->sections[i]);
126
g_free (df->sections);
132
grow_lines_in_section (GnomeDesktopFileSection *section)
136
if (section->n_allocated_lines == 0)
139
new_n_lines = section->n_allocated_lines*2;
141
section->lines = g_realloc (section->lines,
142
sizeof (GnomeDesktopFileLine) * new_n_lines);
143
section->n_allocated_lines = new_n_lines;
147
grow_sections (GnomeDesktopFile *df)
151
if (df->n_allocated_sections == 0)
154
new_n_sections = df->n_allocated_sections*2;
156
df->sections = g_realloc (df->sections,
157
sizeof (GnomeDesktopFileSection) * new_n_sections);
158
df->n_allocated_sections = new_n_sections;
162
unescape_string (gchar *str, gint len)
168
/* len + 1 is enough, because unescaping never makes the
170
res = g_new (gchar, len + 1);
179
/* Found an embedded null */
188
/* Escape at end of string */
211
/* Invalid escape code */
226
escape_string (const gchar *str, gboolean escape_first_space)
233
/* len + 1 is enough, because unescaping never makes the
235
res = g_new (gchar, strlen (str)*2 + 1);
239
end = str + strlen (str);
245
if (escape_first_space && p == str)
283
static GnomeDesktopFileSection*
284
new_section (GnomeDesktopFile *df,
289
gboolean is_main = FALSE;
292
(strcmp (name, "Desktop Entry") == 0 ||
293
strcmp (name, "KDE Desktop Entry") == 0))
297
df->main_section >= 0)
300
GNOME_DESKTOP_PARSE_ERROR,
301
GNOME_DESKTOP_PARSE_ERROR_INVALID_SYNTAX,
302
"Two [Desktop Entry] or [KDE Desktop Entry] sections seen");
307
if (df->n_allocated_sections == df->n_sections)
310
if (df->n_sections == 1 &&
311
df->sections[0].section_name == 0 &&
312
df->sections[0].n_lines == 0)
315
g_warning ("non-initial NULL section\n");
317
/* The initial section was empty. Piggyback on it. */
318
df->sections[0].section_name = g_quark_from_string (name);
321
df->main_section = 0;
323
return &df->sections[0];
326
n = df->n_sections++;
329
df->main_section = n;
332
df->sections[n].section_name = g_quark_from_string (name);
334
df->sections[n].section_name = 0;
336
df->sections[n].n_lines = 0;
337
df->sections[n].lines = NULL;
338
df->sections[n].n_allocated_lines = 0;
340
grow_lines_in_section (&df->sections[n]);
342
return &df->sections[n];
345
static GnomeDesktopFileSection*
346
open_section (GnomeDesktopFileParser *parser,
350
GnomeDesktopFileSection *section;
352
section = new_section (parser->df, name, error);
356
parser->current_section = parser->df->n_sections - 1;
357
g_assert (&parser->df->sections[parser->current_section] == section);
362
static GnomeDesktopFileLine*
363
new_line_in_section (GnomeDesktopFileSection *section)
365
GnomeDesktopFileLine *line;
367
if (section->n_allocated_lines == section->n_lines)
368
grow_lines_in_section (section);
370
line = §ion->lines[section->n_lines++];
372
memset (line, 0, sizeof (GnomeDesktopFileLine));
377
static GnomeDesktopFileLine *
378
new_line (GnomeDesktopFileParser *parser)
380
GnomeDesktopFileSection *section;
382
section = &parser->df->sections[parser->current_section];
384
return new_line_in_section (section);
388
is_blank_line (GnomeDesktopFileParser *parser)
394
while (*p && *p != '\n')
396
if (!g_ascii_isspace (*p))
405
parse_comment_or_blank (GnomeDesktopFileParser *parser)
407
GnomeDesktopFileLine *line;
410
line_end = strchr (parser->line, '\n');
411
if (line_end == NULL)
412
line_end = parser->line + strlen (parser->line);
414
line = new_line (parser);
416
line->value = g_strndup (parser->line, line_end - parser->line);
418
if (*line_end == '\n')
420
else if (*line_end == '\0')
423
parser->line = line_end;
429
is_valid_section_name (const char *name)
431
/* 5. Group names may contain all ASCII characters except for control characters and '[' and ']'. */
435
if (!(g_ascii_isprint (*name) || *name == '\n' || *name == '\t'))
445
parse_section_start (GnomeDesktopFileParser *parser, GError **error)
450
line_end = strchr (parser->line, '\n');
451
if (line_end == NULL)
452
line_end = parser->line + strlen (parser->line);
454
if (line_end - parser->line <= 2 ||
457
report_error (parser, "Invalid syntax for section header", GNOME_DESKTOP_PARSE_ERROR_INVALID_SYNTAX, error);
458
parser_free (parser);
462
section_name = unescape_string (parser->line + 1, line_end - parser->line - 2);
464
if (section_name == NULL)
466
report_error (parser, "Invalid escaping in section name", GNOME_DESKTOP_PARSE_ERROR_INVALID_ESCAPES, error);
467
parser_free (parser);
471
if (!is_valid_section_name (section_name))
473
report_error (parser, "Invalid characters in section name", GNOME_DESKTOP_PARSE_ERROR_INVALID_CHARS, error);
474
parser_free (parser);
475
g_free (section_name);
479
if (open_section (parser, section_name, error) == NULL)
481
g_free (section_name);
485
if (*line_end == '\n')
487
else if (*line_end == '\0')
490
parser->line = line_end;
494
g_free (section_name);
500
parse_key_value (GnomeDesktopFileParser *parser, GError **error)
502
GnomeDesktopFileLine *line;
506
gchar *locale_start = NULL;
507
gchar *locale_end = NULL;
513
line_end = strchr (parser->line, '\n');
514
if (line_end == NULL)
515
line_end = parser->line + strlen (parser->line);
519
while (p < line_end &&
520
(valid[(guchar)*p] & VALID_KEY_CHAR))
524
if (key_start == key_end)
526
report_error (parser, "Empty key name", GNOME_DESKTOP_PARSE_ERROR_INVALID_SYNTAX, error);
527
parser_free (parser);
531
if (p < line_end && *p == '[')
535
while (p < line_end &&
536
(valid[(guchar)*p] & VALID_LOCALE_CHAR))
542
report_error (parser, "Unterminated locale specification in key", GNOME_DESKTOP_PARSE_ERROR_INVALID_SYNTAX, error);
543
parser_free (parser);
549
report_error (parser, "Invalid characters in locale name", GNOME_DESKTOP_PARSE_ERROR_INVALID_CHARS, error);
550
parser_free (parser);
554
if (locale_start == locale_end)
556
report_error (parser, "Empty locale name", GNOME_DESKTOP_PARSE_ERROR_INVALID_SYNTAX, error);
557
parser_free (parser);
563
/* Skip space before '=' */
564
while (p < line_end && *p == ' ')
567
if (p < line_end && *p != '=')
569
report_error (parser, "Invalid characters in key name", GNOME_DESKTOP_PARSE_ERROR_INVALID_CHARS, error);
570
parser_free (parser);
576
report_error (parser, "No '=' in key/value pair", GNOME_DESKTOP_PARSE_ERROR_INVALID_SYNTAX, error);
577
parser_free (parser);
584
/* Skip space after '=' */
585
while (p < line_end && *p == ' ')
590
value = unescape_string (value_start, line_end - value_start);
593
report_error (parser, "Invalid escaping in value", GNOME_DESKTOP_PARSE_ERROR_INVALID_ESCAPES, error);
594
parser_free (parser);
598
line = new_line (parser);
599
key = g_strndup (key_start, key_end - key_start);
600
line->key = g_quark_try_string (key);
602
line->key = g_quark_from_static_string (key);
606
line->locale = g_strndup (locale_start, locale_end - locale_start);
609
if (*line_end == '\n')
611
else if (*line_end == '\0')
614
parser->line = line_end;
622
report_error (GnomeDesktopFileParser *parser,
624
GnomeDesktopParseError error_code,
627
GnomeDesktopFileSection *section;
628
const gchar *section_name = NULL;
630
section = &parser->df->sections[parser->current_section];
632
if (section->section_name)
633
section_name = g_quark_to_string (section->section_name);
638
*error = g_error_new (GNOME_DESKTOP_PARSE_ERROR,
640
"Error in section %s at line %d: %s", section_name, parser->line_nr, message);
642
*error = g_error_new (GNOME_DESKTOP_PARSE_ERROR,
644
"Error at line %d: %s", parser->line_nr, message);
650
gnome_desktop_file_new_from_string (char *data,
653
GnomeDesktopFileParser parser;
654
GnomeDesktopFileLine *line;
656
parser.df = g_new0 (GnomeDesktopFile, 1);
657
parser.df->main_section = -1;
658
parser.current_section = -1;
664
/* Put any initial comments in a NULL segment */
665
open_section (&parser, NULL, NULL);
667
while (parser.line && *parser.line)
669
if (*parser.line == '[') {
670
if (!parse_section_start (&parser, error))
672
} else if (is_blank_line (&parser) ||
674
parse_comment_or_blank (&parser);
677
if (!parse_key_value (&parser, error))
682
if (parser.df->main_section >= 0)
684
line = lookup_line (parser.df,
685
&parser.df->sections[parser.df->main_section],
689
if (strcmp (line->value, "UTF-8") == 0)
690
parser.df->encoding = GNOME_DESKTOP_FILE_ENCODING_UTF8;
691
else if (strcmp (line->value, "Legacy-Mixed") == 0)
692
parser.df->encoding = GNOME_DESKTOP_FILE_ENCODING_LEGACY;
694
parser.df->encoding = GNOME_DESKTOP_FILE_ENCODING_UNKNOWN;
698
/* No encoding specified. We have to guess
699
* If the whole file validates as UTF-8 it's probably UTF-8.
700
* Otherwise we guess it's a Legacy-Mixed
702
if (g_utf8_validate (data, -1, NULL))
703
parser.df->encoding = GNOME_DESKTOP_FILE_ENCODING_UTF8;
705
parser.df->encoding = GNOME_DESKTOP_FILE_ENCODING_LEGACY;
710
parser.df->encoding = GNOME_DESKTOP_FILE_ENCODING_UNKNOWN;
715
GnomeDesktopFileEncoding
716
gnome_desktop_file_get_encoding (GnomeDesktopFile *df)
722
gnome_desktop_file_to_string (GnomeDesktopFile *df)
724
GnomeDesktopFileSection *section;
725
GnomeDesktopFileLine *line;
730
str = g_string_sized_new (800);
732
for (i = 0; i < df->n_sections; i ++)
734
section = &df->sections[i];
736
if (section->section_name)
738
g_string_append_c (str, '[');
739
s = escape_string (g_quark_to_string (section->section_name), FALSE);
740
g_string_append (str, s);
742
g_string_append (str, "]\n");
745
for (j = 0; j < section->n_lines; j++)
747
line = §ion->lines[j];
751
g_string_append (str, line->value);
752
g_string_append_c (str, '\n');
756
g_string_append (str, g_quark_to_string (line->key));
759
g_string_append_c (str, '[');
760
g_string_append (str, line->locale);
761
g_string_append_c (str, ']');
763
g_string_append_c (str, '=');
764
s = escape_string (line->value, TRUE);
765
g_string_append (str, s);
767
g_string_append_c (str, '\n');
772
return g_string_free (str, FALSE);
775
static GnomeDesktopFileSection *
776
lookup_section (GnomeDesktopFile *df,
777
const char *section_name)
779
GnomeDesktopFileSection *section;
780
GQuark section_quark;
783
if (section_name == NULL)
785
if (df->main_section < 0)
788
return &df->sections[df->main_section];
791
section_quark = g_quark_try_string (section_name);
792
if (section_quark == 0)
795
for (i = 0; i < df->n_sections; i ++)
797
section = &df->sections[i];
799
if (section->section_name == section_quark)
805
static GnomeDesktopFileLine *
806
lookup_line (GnomeDesktopFile *df,
807
GnomeDesktopFileSection *section,
811
GnomeDesktopFileLine *line;
815
key_quark = g_quark_try_string (keyname);
819
for (i = 0; i < section->n_lines; i++)
821
line = §ion->lines[i];
823
if (line->key == key_quark &&
824
((locale == NULL && line->locale == NULL) ||
825
(locale != NULL && line->locale != NULL && strcmp (locale, line->locale) == 0)))
833
gnome_desktop_file_get_raw (GnomeDesktopFile *df,
834
const char *section_name,
839
GnomeDesktopFileSection *section;
840
GnomeDesktopFileLine *line;
844
section = lookup_section (df, section_name);
848
line = lookup_line (df,
862
gnome_desktop_file_foreach_section (GnomeDesktopFile *df,
863
GnomeDesktopFileSectionFunc func,
866
GnomeDesktopFileSection *section;
869
for (i = 0; i < df->n_sections; i ++)
871
section = &df->sections[i];
873
(*func) (df, g_quark_to_string (section->section_name), user_data);
879
gnome_desktop_file_foreach_key (GnomeDesktopFile *df,
880
const char *section_name,
881
gboolean include_localized,
882
GnomeDesktopFileLineFunc func,
885
GnomeDesktopFileSection *section;
886
GnomeDesktopFileLine *line;
889
section = lookup_section (df, section_name);
893
for (i = 0; i < section->n_lines; i++)
895
line = §ion->lines[i];
897
(*func) (df, g_quark_to_string (line->key), line->locale, line->value, user_data);
904
gnome_desktop_file_rename_section (GnomeDesktopFile *df,
905
const char *old_name,
906
const char *new_name)
908
GnomeDesktopFileSection *section;
910
g_return_if_fail (new_name != NULL);
912
if (old_name == NULL &&
913
df->main_section < 0)
914
old_name = "Desktop Entry";
916
section = lookup_section (df, old_name);
920
section->section_name = g_quark_from_string (new_name);
924
gnome_desktop_file_has_section (GnomeDesktopFile *df,
927
GnomeDesktopFileSection *section;
929
g_return_val_if_fail (name != NULL, FALSE);
931
section = lookup_section (df, name);
933
return section != NULL;
937
gnome_desktop_file_load (const char *filename,
941
GnomeDesktopFile *df;
943
if (!g_file_get_contents (filename, &contents,
947
df = gnome_desktop_file_new_from_string (contents, error);
956
gnome_desktop_file_save (GnomeDesktopFile *df,
966
tmp_filename = g_strconcat (path, ".new-tmp", NULL);
968
f = fopen (tmp_filename, "w");
973
g_file_error_from_errno (errno),
974
_("Failed to open \"%s\": %s"),
975
tmp_filename, g_strerror (errno));
976
g_free (tmp_filename);
982
if (fchmod (fd, mode) < 0)
984
g_set_error (error, G_FILE_ERROR,
985
g_file_error_from_errno (errno),
986
_("Failed to set permissions %o on \"%s\": %s"),
987
mode, tmp_filename, g_strerror (errno));
990
unlink (tmp_filename);
991
g_free (tmp_filename);
996
str = gnome_desktop_file_to_string (df);
998
if (fputs (str, f) < 0)
1002
g_file_error_from_errno (errno),
1003
_("Failed to write to \"%s\": %s"),
1004
tmp_filename, g_strerror (errno));
1007
unlink (tmp_filename);
1009
g_free (tmp_filename);
1020
g_file_error_from_errno (errno),
1021
_("Failed to close \"%s\": %s"),
1022
tmp_filename, g_strerror (errno));
1024
unlink (tmp_filename);
1025
g_free (tmp_filename);
1030
if (rename (tmp_filename, path) < 0)
1034
g_file_error_from_errno (errno),
1035
_("Failed to rename \"%s\" to \"%s\": %s"),
1036
tmp_filename, path, g_strerror (errno));
1037
unlink (tmp_filename);
1038
g_free (tmp_filename);
1043
g_free (tmp_filename);
1048
/* Mask for components of locale spec. The ordering here is from
1049
* least significant to most significant
1053
COMPONENT_CODESET = 1 << 0,
1054
COMPONENT_TERRITORY = 1 << 1,
1055
COMPONENT_MODIFIER = 1 << 2
1058
/* Break an X/Open style locale specification into components
1061
explode_locale (const gchar *locale,
1067
const gchar *uscore_pos;
1068
const gchar *at_pos;
1069
const gchar *dot_pos;
1073
uscore_pos = strchr (locale, '_');
1074
dot_pos = strchr (uscore_pos ? uscore_pos : locale, '.');
1075
at_pos = strchr (dot_pos ? dot_pos : (uscore_pos ? uscore_pos : locale), '@');
1079
mask |= COMPONENT_MODIFIER;
1080
*modifier = g_strdup (at_pos);
1083
at_pos = locale + strlen (locale);
1087
mask |= COMPONENT_CODESET;
1088
*codeset = g_new (gchar, 1 + at_pos - dot_pos);
1089
strncpy (*codeset, dot_pos, at_pos - dot_pos);
1090
(*codeset)[at_pos - dot_pos] = '\0';
1097
mask |= COMPONENT_TERRITORY;
1098
*territory = g_new (gchar, 1 + dot_pos - uscore_pos);
1099
strncpy (*territory, uscore_pos, dot_pos - uscore_pos);
1100
(*territory)[dot_pos - uscore_pos] = '\0';
1103
uscore_pos = dot_pos;
1105
*language = g_new (gchar, 1 + uscore_pos - locale);
1106
strncpy (*language, locale, uscore_pos - locale);
1107
(*language)[uscore_pos - locale] = '\0';
1113
gnome_desktop_file_get_locale_string (GnomeDesktopFile *df,
1114
const char *section,
1115
const char *keyname,
1119
char *lang, *territory, *codeset, *modifier;
1121
char *with_territory;
1133
locale = setlocale (LC_MESSAGES, NULL);
1135
explode_locale (locale, &lang, &territory, &codeset, &modifier);
1138
with_territory = g_strconcat (lang, "_", territory, NULL);
1140
with_territory = NULL;
1142
if (with_territory == NULL ||
1143
!gnome_desktop_file_get_raw (df, section, keyname, with_territory, &raw))
1146
!gnome_desktop_file_get_raw (df, section, keyname, lang, &raw))
1148
gnome_desktop_file_get_raw (df, section, keyname, NULL, &raw);
1158
used_locale = with_territory;
1159
with_territory = NULL;
1166
g_free (with_territory);
1170
g_free (used_locale);
1174
if (gnome_desktop_file_get_encoding (df) == GNOME_DESKTOP_FILE_ENCODING_UTF8)
1176
g_free (used_locale);
1177
*val = g_strdup (raw);
1180
else if (gnome_desktop_file_get_encoding (df) == GNOME_DESKTOP_FILE_ENCODING_LEGACY)
1184
const char *encoding;
1186
encoding = desktop_file_get_encoding_for_locale (used_locale);
1192
g_free (used_locale);
1194
res = g_convert (raw, -1,
1203
g_printerr ("Error converting from UTF-8 to %s for key %s: %s\n",
1204
encoding, keyname, error->message);
1205
g_error_free (error);
1210
return *val != NULL;
1214
g_printerr ("Don't know encoding for desktop file field %s with locale \"%s\"\n",
1215
keyname, used_locale);
1216
g_free (used_locale);
1222
/* this is just ASCII, hopefully OK, though it's really a bit
1223
* broken to return it
1225
*val = g_strdup (raw);
1231
g_printerr ("Desktop file doesn't have its encoding marked, can't parse it.\n");
1232
g_free (used_locale);
1238
gnome_desktop_file_get_string (GnomeDesktopFile *df,
1239
const char *section,
1240
const char *keyname,
1247
if (!gnome_desktop_file_get_raw (df, section, keyname, NULL, &raw))
1250
*val = g_strdup (raw);
1256
gnome_desktop_file_get_strings (GnomeDesktopFile *df,
1257
const char *section,
1258
const char *keyname,
1272
if (!gnome_desktop_file_get_raw (df, section, keyname, locale, &raw))
1275
retval = g_strsplit (raw, ";", G_MAXINT);
1281
/* Drop the empty string g_strsplit leaves in the vector since
1282
* our list of strings ends in ";"
1291
g_strfreev (retval);
1300
gnome_desktop_file_set_raw (GnomeDesktopFile *df,
1301
const char *section_name,
1302
const char *keyname,
1306
GnomeDesktopFileSection *section;
1307
GnomeDesktopFileLine *line;
1310
if (section_name == NULL &&
1311
df->main_section < 0)
1312
section_name = "Desktop Entry";
1314
section = lookup_section (df, section_name);
1315
if (section == NULL)
1317
section = new_section (df, section_name, NULL);
1321
line = lookup_line (df,
1327
line = new_line_in_section (section);
1329
line->key = g_quark_from_string (keyname);
1330
g_free (line->value);
1331
g_free (line->locale);
1332
line->value = g_strdup (value);
1333
line->locale = g_strdup (locale);
1337
gnome_desktop_file_set_strings (GnomeDesktopFile *df,
1338
const char *section_name,
1339
const char *keyname,
1346
tmp = g_strjoinv (";", (char**)value);
1347
str = g_strconcat (tmp, ";", NULL);
1349
gnome_desktop_file_set_raw (df, section_name, keyname, locale, str);
1355
gnome_desktop_file_merge_string_into_list (GnomeDesktopFile *df,
1356
const char *section,
1357
const char *keyname,
1365
if (gnome_desktop_file_get_strings (df, section, keyname, locale,
1366
&values, &n_values))
1368
/* Look for a duplicate */
1375
while (i < n_values)
1377
if (strcmp (values[i], value) == 0)
1386
g_strfreev (values);
1389
return; /* nothing to do */
1392
gnome_desktop_file_get_raw (df, section, keyname, locale, &raw);
1395
/* Append to current list */
1401
/* handle broken file with no ';' after the list */
1402
if (len > 0 && raw[len-1] != ';')
1403
str = g_strconcat (raw, ";", value, ";", NULL);
1405
str = g_strconcat (raw, value, ";", NULL);
1408
str = g_strconcat (value, ";", NULL);
1410
gnome_desktop_file_set_raw (df, section, keyname, locale, str);
1416
gnome_desktop_file_remove_string_from_list (GnomeDesktopFile *df,
1417
const char *section,
1418
const char *keyname,
1425
if (gnome_desktop_file_get_strings (df, section, keyname, locale,
1426
&values, &n_values))
1434
while (i < n_values)
1436
if (values[i] == NULL)
1439
if (strcmp (values[i], value) == 0)
1450
while (i < n_values)
1453
if (values[i] == NULL)
1455
while (j < n_values && values[j] == NULL)
1460
values[i] = values[j];
1468
if (n_found == n_values)
1469
gnome_desktop_file_unset (df, section, keyname);
1470
else if (n_found > 0)
1471
gnome_desktop_file_set_strings (df, section, keyname, locale,
1472
(const char**) values);
1474
g_strfreev (values);
1480
/* #define VERIFY_CANONICAL_ENCODING_NAME */
1483
const char *encoding;
1484
const char *langs[N_LANG];
1485
} known_encodings[] = {
1486
{"ARMSCII-8", {"hy"}},
1487
{"BIG5", {"zh_TW"}},
1488
{"CP1251", {"be", "bg"}},
1489
{"EUC-CN", {"zh_CN"}},
1492
{"GEORGIAN-ACADEMY", {}},
1493
{"GEORGIAN-PS", {"ka"}},
1494
{"ISO-8859-1", {"br", "ca", "da", "de", "en", "es", "eu", "fi", "fr", "gl", "it", "nl", "no", "pt", "sv", "wa" }},
1495
{"ISO-8859-2", {"cs", "hr", "hu", "pl", "ro", "sk", "sl", "sq", "sr"}},
1496
{"ISO-8859-3", {"eo"}},
1497
{"ISO-8859-5", {"mk", "sp"}},
1498
{"ISO-8859-7", {"el"}},
1499
{"ISO-8859-9", {"tr"}},
1500
{"ISO-8859-13", {"lv", "lt", "mi"}},
1501
{"ISO-8859-14", {"ga", "cy"}},
1502
{"ISO-8859-15", {"et"}},
1505
{"TCVN-5712", {"vi"}},
1506
{"TIS-620", {"th"}},
1514
{"GB2312", "EUC-CN"},
1515
{"TCVN", "TCVN-5712" }
1519
aliases_equal (const char *enc1, const char *enc2)
1521
while (*enc1 && *enc2)
1523
while (*enc1 == '-' ||
1528
while (*enc2 == '-' ||
1533
if (g_ascii_tolower (*enc1) != g_ascii_tolower (*enc2))
1539
while (*enc1 == '-' ||
1544
while (*enc2 == '-' ||
1556
get_canonical_encoding (const char *encoding)
1559
for (i = 0; i < (int) G_N_ELEMENTS (enc_aliases); i++)
1561
if (aliases_equal (enc_aliases[i].alias, encoding))
1562
return enc_aliases[i].value;
1565
for (i = 0; i < (int) G_N_ELEMENTS (known_encodings); i++)
1567
if (aliases_equal (known_encodings[i].encoding, encoding))
1568
return known_encodings[i].encoding;
1575
lang_tag_matches (const char *l, const char *spec)
1579
if (strcmp (l, spec) == 0)
1582
l2 = strchr (l, '_');
1584
if (l2 && strchr (spec, '_') == NULL &&
1585
strncmp (l, spec, l2 - l) == 0)
1592
get_encoding_from_lang (const char *lang)
1596
for (i = 0; i < (int) G_N_ELEMENTS (known_encodings); i++)
1598
for (j = 0; j < N_LANG; j++)
1600
if (known_encodings[i].langs[j] && lang_tag_matches (lang, known_encodings[i].langs[j]))
1601
return known_encodings[i].encoding;
1608
desktop_file_get_encoding_for_locale (const char *locale)
1612
encoding = strchr(locale, '.');
1618
return get_canonical_encoding (encoding);
1621
return get_encoding_from_lang (locale);
1625
gnome_desktop_file_unset_internal (GnomeDesktopFile *df,
1626
const char *section_name,
1627
const char *keyname,
1629
gboolean all_locales)
1631
GnomeDesktopFileLine *line;
1632
GnomeDesktopFileSection *section;
1636
section = lookup_section (df, section_name);
1637
if (section == NULL)
1640
key_quark = g_quark_try_string (keyname);
1645
while (i < section->n_lines)
1647
line = §ion->lines[i];
1649
if (line->key == key_quark &&
1651
((locale == NULL && line->locale == NULL) ||
1652
(locale != NULL && line->locale != NULL && strcmp (locale, line->locale) == 0))))
1654
g_free (line->locale);
1655
g_free (line->value);
1657
if ((i+1) < section->n_lines)
1658
g_memmove (§ion->lines[i], §ion->lines[i+1],
1659
(section->n_lines - i - 1) * sizeof (section->lines[0]));
1661
section->n_lines -= 1;
1671
gnome_desktop_file_unset (GnomeDesktopFile *df,
1672
const char *section,
1673
const char *keyname)
1675
gnome_desktop_file_unset_internal (df, section, keyname, NULL, TRUE);
1679
gnome_desktop_file_unset_for_locale (GnomeDesktopFile *df,
1680
const char *section,
1681
const char *keyname,
1684
gnome_desktop_file_unset_internal (df, section, keyname, locale, FALSE);
1688
gnome_desktop_file_copy_key (GnomeDesktopFile *df,
1689
const char *section_name,
1690
const char *source_key,
1691
const char *dest_key)
1693
GnomeDesktopFileLine *line;
1694
GnomeDesktopFileSection *section;
1698
g_return_if_fail (source_key != NULL);
1699
g_return_if_fail (dest_key != NULL);
1700
g_return_if_fail (strcmp (source_key, dest_key) != 0);
1702
gnome_desktop_file_unset (df, section_name, dest_key);
1704
section = lookup_section (df, section_name);
1705
if (section == NULL)
1708
key_quark = g_quark_try_string (source_key);
1713
while (i < section->n_lines)
1715
line = §ion->lines[i];
1717
if (line->key == key_quark)
1719
/* Mmmm, modify the array we're iterating over...
1720
* should be safe as it just appends.
1723
gnome_desktop_file_set_raw (df, section_name, dest_key,
1724
line->locale, line->value);