summaryrefslogtreecommitdiff
path: root/backends
diff options
context:
space:
mode:
authorMark McLoughlin <mark@skynet.ie>2005-12-11 15:38:08 +0000
committerMark McLoughlin <markmc@src.gnome.org>2005-12-11 15:38:08 +0000
commitf4c43bff55658daafa2646bbaaa2ff0dca0c64f8 (patch)
tree048fbc470aec0adebee66b39a1bb13e297bff356 /backends
parent43eb1135ee9e1f184148c0261367f7ef22b44485 (diff)
downloadgconf-f4c43bff55658daafa2646bbaaa2ff0dca0c64f8.tar.gz
re-work the logic for finding the best schema for the given locales.
2005-12-11 Mark McLoughlin <mark@skynet.ie> * backends/markup-tree.c: (markup_entry_get_value): re-work the logic for finding the best schema for the given locales. 2005-12-11 Mark McLoughlin <mark@skynet.ie> * backends/markup-tree.c: - Introduce the concept of a "subtree root" - a point in the tree where we save a subtree in a merged file. - When loading a subtree (%gconf-tree.xml), take note of any available translations (%gconf-tree-$(locale).xml) - When getting/setting/unsetting a schema, ensure that the appropriate translations are loaded - When parsing a translations file, allow for missing attributes and elements and read the translations of descriptions - When syncing a subtree, write out all translations of descriptions which are currently cached in memory to separate files. * backends/gconf-merge-tree.c: (merge_tree): update for markup_dir_build_file_path() change
Diffstat (limited to 'backends')
-rw-r--r--backends/gconf-merge-tree.c2
-rw-r--r--backends/markup-tree.c1282
2 files changed, 984 insertions, 300 deletions
diff --git a/backends/gconf-merge-tree.c b/backends/gconf-merge-tree.c
index abad0b4a..1f5fc965 100644
--- a/backends/gconf-merge-tree.c
+++ b/backends/gconf-merge-tree.c
@@ -91,7 +91,7 @@ merge_tree (const char *root_dir)
{
char *markup_file;
- markup_file = markup_dir_build_file_path (tree->root, TRUE);
+ markup_file = markup_dir_build_file_path (tree->root, TRUE, NULL);
fprintf (stderr, _("Error saving GConf tree to '%s': %s\n"),
markup_file,
error->message);
diff --git a/backends/markup-tree.c b/backends/markup-tree.c
index 6d0c49c0..1f6908b5 100644
--- a/backends/markup-tree.c
+++ b/backends/markup-tree.c
@@ -1,5 +1,6 @@
/* GConf
* Copyright (C) 2002 Red Hat Inc.
+ * Copyright (C) 2005 Mark McLoughlin
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -64,20 +65,23 @@ static gboolean markup_dir_sync (MarkupDir *dir);
static char* markup_dir_build_path (MarkupDir *dir,
gboolean filesystem_path,
gboolean with_data_file,
- gboolean subtree_data_file);
+ gboolean subtree_data_file,
+ const char *locale);
static void markup_dir_set_entries_need_save (MarkupDir *dir);
+static void markup_dir_setup_as_subtree_root (MarkupDir *dir);
static MarkupEntry* markup_entry_new (MarkupDir *dir,
const char *name);
static void markup_entry_free (MarkupEntry *entry);
-static void parse_tree (MarkupDir *root,
- gboolean parse_subtree,
- GError **err);
-static void save_tree (MarkupDir *root,
- gboolean save_as_subtree,
- guint file_mode,
- GError **err);
+static void parse_tree (MarkupDir *root,
+ gboolean parse_subtree,
+ const char *locale,
+ GError **err);
+static void save_tree (MarkupDir *root,
+ gboolean save_as_subtree,
+ guint file_mode,
+ GError **err);
struct _MarkupTree
@@ -166,11 +170,15 @@ struct _MarkupDir
{
MarkupTree *tree;
MarkupDir *parent;
+ MarkupDir *subtree_root;
char *name;
GSList *entries;
GSList *subdirs;
+ /* Available %gconf-tree-$(locale).xml files */
+ GHashTable *available_local_descs;
+
/* Have read the existing XML file */
guint entries_loaded : 1;
/* Need to rewrite the XML file since we changed
@@ -192,6 +200,15 @@ struct _MarkupDir
/* Save to %gconf-tree.xml when syncing */
guint save_as_subtree : 1;
+
+ /* We've loaded all locales in @available_local_descs */
+ guint all_local_descs_loaded : 1;
+
+ /* This is a temporary directory used only during parsing */
+ guint is_parser_dummy : 1;
+
+ /* Temporary flag used only when writing */
+ guint is_dir_empty : 1;
};
static MarkupDir*
@@ -209,8 +226,13 @@ markup_dir_new (MarkupTree *tree,
if (parent)
{
+ dir->subtree_root = parent->subtree_root;
parent->subdirs = g_slist_prepend (parent->subdirs, dir);
}
+ else
+ {
+ markup_dir_setup_as_subtree_root (dir);
+ }
return dir;
}
@@ -220,6 +242,12 @@ markup_dir_free (MarkupDir *dir)
{
GSList *tmp;
+ if (dir->available_local_descs != NULL)
+ {
+ g_hash_table_destroy (dir->available_local_descs);
+ dir->available_local_descs = NULL;
+ }
+
tmp = dir->entries;
while (tmp)
{
@@ -259,17 +287,18 @@ markup_dir_queue_sync (MarkupDir *dir)
}
static inline char *
-markup_dir_build_file_path (MarkupDir *dir,
- gboolean subtree_data_file)
+markup_dir_build_file_path (MarkupDir *dir,
+ gboolean subtree_data_file,
+ const char *locale)
{
- return markup_dir_build_path (dir, TRUE, TRUE, subtree_data_file);
+ return markup_dir_build_path (dir, TRUE, TRUE, subtree_data_file, locale);
}
static inline char *
markup_dir_build_dir_path (MarkupDir *dir,
gboolean filesystem_path)
{
- return markup_dir_build_path (dir, filesystem_path, FALSE, FALSE);
+ return markup_dir_build_path (dir, filesystem_path, FALSE, FALSE, NULL);
}
static MarkupDir*
@@ -367,6 +396,90 @@ markup_tree_sync (MarkupTree *tree,
return TRUE;
}
+static void
+markup_dir_setup_as_subtree_root (MarkupDir *dir)
+{
+ if (dir->subtree_root != dir)
+ {
+ dir->subtree_root = dir;
+
+ dir->available_local_descs = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ g_free,
+ NULL);
+ dir->all_local_descs_loaded = TRUE;
+ }
+}
+
+static void
+markup_dir_list_available_local_descs (MarkupDir *dir)
+{
+#define LOCALE_FILE_PREFIX "%gconf-tree-"
+#define LOCALE_FILE_SUFFIX ".xml"
+#define LOCALE_FILE_PREFIX_LEN (sizeof (LOCALE_FILE_PREFIX) - 1)
+#define LOCALE_FILE_SUFFIX_LEN (sizeof (LOCALE_FILE_SUFFIX) - 1)
+
+ GDir *dp;
+ char *dir_path;
+ const char *dent;
+
+ dir_path = markup_dir_build_dir_path (dir, TRUE);
+
+ if ((dp = g_dir_open (dir_path, 0, NULL)) == NULL)
+ {
+ /* This is debug-only since it usually happens when creating a
+ * new directory
+ */
+ gconf_log (GCL_DEBUG,
+ "Could not open directory \"%s\": %s\n",
+ dir_path, g_strerror (errno));
+ g_free (dir_path);
+ return;
+ }
+
+ g_assert (dir->available_local_descs != NULL);
+ g_assert (g_hash_table_size (dir->available_local_descs) == 0);
+
+ while ((dent = g_dir_read_name (dp)) != NULL)
+ {
+ gsize dent_len;
+ char *locale;
+
+ dent_len = strlen (dent);
+
+ if (dent_len <= LOCALE_FILE_PREFIX_LEN + LOCALE_FILE_SUFFIX_LEN)
+ continue;
+
+ if (strncmp (dent, LOCALE_FILE_PREFIX, LOCALE_FILE_PREFIX_LEN) != 0)
+ continue;
+
+ if (strcmp (dent + dent_len - LOCALE_FILE_SUFFIX_LEN, LOCALE_FILE_SUFFIX) != 0)
+ continue;
+
+ locale = g_strndup (dent + LOCALE_FILE_PREFIX_LEN,
+ dent_len - LOCALE_FILE_PREFIX_LEN - LOCALE_FILE_SUFFIX_LEN);
+
+ g_hash_table_replace (dir->available_local_descs,
+ locale,
+ GINT_TO_POINTER (FALSE));
+ }
+
+ if (g_hash_table_size (dir->available_local_descs) != 0)
+ dir->all_local_descs_loaded = FALSE;
+
+ /* if this fails, we really can't do a thing about it
+ * and it's not a meaningful error
+ */
+ g_dir_close (dp);
+
+ g_free (dir_path);
+
+#undef LOCALE_FILE_SUFFIX_LEN
+#undef LOCALE_FILE_PREFIX_LEN
+#undef LOCALE_FILE_SUFFIX
+#undef LOCALE_FILE_PREFIX
+}
+
static gboolean
load_subtree (MarkupDir *dir)
{
@@ -375,7 +488,7 @@ load_subtree (MarkupDir *dir)
GError *tmp_err = NULL;
char *markup_file;
- markup_file = markup_dir_build_file_path (dir, TRUE);
+ markup_file = markup_dir_build_file_path (dir, TRUE, NULL);
if (!gconf_file_exists (markup_file))
{
g_free (markup_file);
@@ -386,7 +499,10 @@ load_subtree (MarkupDir *dir)
dir->entries_loaded = TRUE;
dir->save_as_subtree = TRUE;
- parse_tree (dir, TRUE, &tmp_err);
+ markup_dir_setup_as_subtree_root (dir);
+ markup_dir_list_available_local_descs (dir);
+
+ parse_tree (dir, TRUE, NULL, &tmp_err);
if (tmp_err)
{
/* note that tmp_err may be a G_MARKUP_ERROR while only
@@ -428,7 +544,7 @@ load_entries (MarkupDir *dir)
{
GError *tmp_err = NULL;
- parse_tree (dir, FALSE, &tmp_err);
+ parse_tree (dir, FALSE, NULL, &tmp_err);
if (tmp_err)
{
char *markup_file;
@@ -441,7 +557,7 @@ load_entries (MarkupDir *dir)
/* this message is debug-only because it usually happens
* when creating a new directory
*/
- markup_file = markup_dir_build_file_path (dir, FALSE);
+ markup_file = markup_dir_build_file_path (dir, FALSE, NULL);
gconf_log (GCL_DEBUG,
"Failed to load file \"%s\": %s",
markup_file, tmp_err->message);
@@ -828,7 +944,9 @@ delete_useless_subdirs (MarkupDir *dir)
char *fs_filename;
fs_dirname = markup_dir_build_dir_path (subdir, TRUE);
- fs_filename = markup_dir_build_file_path (subdir, subdir->save_as_subtree);
+ fs_filename = markup_dir_build_file_path (subdir,
+ subdir->save_as_subtree,
+ NULL);
if (g_unlink (fs_filename) < 0)
{
@@ -975,8 +1093,8 @@ markup_dir_sync (MarkupDir *dir)
clean_old_local_schemas_recurse (dir, dir->save_as_subtree);
fs_dirname = markup_dir_build_dir_path (dir, TRUE);
- fs_filename = markup_dir_build_file_path (dir, FALSE);
- fs_subtree = markup_dir_build_file_path (dir, TRUE);
+ fs_filename = markup_dir_build_file_path (dir, FALSE, NULL);
+ fs_subtree = markup_dir_build_file_path (dir, TRUE, NULL);
/* For a dir to be loaded as a subdir, it must have a
* %gconf.xml file, even if it has no entries in that
@@ -1116,7 +1234,8 @@ static char*
markup_dir_build_path (MarkupDir *dir,
gboolean filesystem_path,
gboolean with_data_file,
- gboolean subtree_data_file)
+ gboolean subtree_data_file,
+ const char *locale)
{
GString *name;
GSList *components;
@@ -1152,7 +1271,19 @@ markup_dir_build_path (MarkupDir *dir,
g_slist_free (components);
if (with_data_file)
- g_string_append (name, !subtree_data_file ? "/%gconf.xml" : "/%gconf-tree.xml");
+ {
+ if (locale == NULL)
+ {
+ g_string_append (name,
+ subtree_data_file ? "/%gconf-tree.xml" : "/%gconf.xml");
+ }
+ else
+ {
+ g_assert (subtree_data_file);
+
+ g_string_append_printf (name, "/%%gconf-tree-%s.xml", locale);
+ }
+ }
return g_string_free (name, FALSE);
}
@@ -1195,6 +1326,106 @@ markup_entry_free (MarkupEntry *entry)
g_free (entry);
}
+static void
+load_schema_descs_for_locale (MarkupDir *dir,
+ const char *locale)
+{
+ GError *error;
+
+ error = NULL;
+ parse_tree (dir, TRUE, locale, &error);
+ if (error != NULL)
+ {
+ char *markup_file;
+
+ markup_file = markup_dir_build_file_path (dir, TRUE, locale);
+
+ gconf_log (GCL_ERR,
+ _("Failed to load file \"%s\": %s"),
+ markup_file,
+ error->message);
+
+ g_free (markup_file);
+ g_error_free (error);
+ }
+
+ g_hash_table_replace (dir->available_local_descs,
+ g_strdup (locale),
+ GINT_TO_POINTER (TRUE));
+}
+
+static void
+load_schema_descs_foreach (const char *locale,
+ gpointer value,
+ MarkupDir *dir)
+{
+ if (value != NULL)
+ return; /* already loaded */
+
+ load_schema_descs_for_locale (dir, locale);
+}
+
+static gboolean
+find_unloaded_locale (const char *locale,
+ gpointer value,
+ gboolean *any_unloaded)
+{
+ if (value != NULL)
+ return FALSE;
+
+ *any_unloaded = TRUE;
+
+ return TRUE;
+}
+
+static void
+ensure_schema_descs_loaded (MarkupEntry *entry,
+ const char *locale)
+{
+ MarkupDir *subtree_root;
+
+ subtree_root = entry->dir->subtree_root;
+
+ if (subtree_root->all_local_descs_loaded)
+ return;
+
+ if (locale == NULL)
+ {
+ g_hash_table_foreach (subtree_root->available_local_descs,
+ (GHFunc) load_schema_descs_foreach,
+ subtree_root);
+
+ subtree_root->all_local_descs_loaded = TRUE;
+
+ return;
+ }
+ else
+ {
+ gpointer value;
+ gboolean any_unloaded;
+
+ value = NULL;
+ if (!g_hash_table_lookup_extended (subtree_root->available_local_descs,
+ locale,
+ NULL,
+ &value))
+ return; /* locale isn't available */
+
+ if (value != NULL)
+ return; /* already loaded */
+
+ load_schema_descs_for_locale (subtree_root, locale);
+
+ any_unloaded = FALSE;
+ g_hash_table_find (subtree_root->available_local_descs,
+ (GHRFunc) find_unloaded_locale,
+ &any_unloaded);
+
+ if (!any_unloaded)
+ subtree_root->all_local_descs_loaded = TRUE;
+ }
+}
+
void
markup_entry_set_value (MarkupEntry *entry,
const GConfValue *value)
@@ -1247,6 +1478,8 @@ markup_entry_set_value (MarkupEntry *entry,
if (locale == NULL)
locale = "C";
+ ensure_schema_descs_loaded (entry, locale);
+
local_schema = NULL;
tmp = entry->local_schemas;
while (tmp != NULL)
@@ -1361,6 +1594,8 @@ markup_entry_unset_value (MarkupEntry *entry,
gconf_value_free (entry->value);
entry->value = NULL;
+ ensure_schema_descs_loaded (entry, NULL);
+
g_slist_foreach (entry->local_schemas,
(GFunc) local_schema_info_free,
NULL);
@@ -1374,6 +1609,8 @@ markup_entry_unset_value (MarkupEntry *entry,
/* Just blow away any matching local schema */
GSList *tmp;
+ ensure_schema_descs_loaded (entry, locale);
+
tmp = entry->local_schemas;
while (tmp != NULL)
{
@@ -1454,14 +1691,11 @@ markup_entry_get_value (MarkupEntry *entry,
{
GConfValue *retval;
GConfSchema *schema;
- int n_locales;
static const char *fallback_locales[2] = {
"C", NULL
};
- LocalSchemaInfo **local_schemas;
LocalSchemaInfo *best;
LocalSchemaInfo *c_local_schema;
- GSList *tmp;
int i;
retval = gconf_value_copy (entry->value);
@@ -1473,49 +1707,47 @@ markup_entry_get_value (MarkupEntry *entry,
if (locales == NULL || locales[0] == NULL)
locales = fallback_locales;
- n_locales = 0;
- while (locales[n_locales])
- ++n_locales;
-
- local_schemas = g_new0 (LocalSchemaInfo*, n_locales);
+ best = NULL;
c_local_schema = NULL;
- tmp = entry->local_schemas;
- while (tmp != NULL)
+ i = 0;
+ while (locales[i] != NULL)
{
- LocalSchemaInfo *lsi = tmp->data;
+ GSList *tmp;
- if (strcmp (lsi->locale, "C") == 0)
- c_local_schema = lsi;
+ ensure_schema_descs_loaded (entry, locales[i]);
- i = 0;
- while (locales[i])
+ tmp = entry->local_schemas;
+ while (tmp != NULL)
{
- if (strcmp (locales[i], lsi->locale) == 0)
+ LocalSchemaInfo *lsi = tmp->data;
+
+ if (c_local_schema == NULL &&
+ strcmp (lsi->locale, "C") == 0)
{
- local_schemas[i] = lsi;
- break;
+ c_local_schema = lsi;
+ if (best != NULL)
+ break;
}
- ++i;
+
+ if (best == NULL &&
+ strcmp (locales[i], lsi->locale) == 0)
+ {
+ best = lsi;
+ if (c_local_schema != NULL)
+ break;
+ }
+
+ tmp = tmp->next;
}
/* Quit as soon as we have the best possible locale */
- if (local_schemas[0] != NULL && c_local_schema != NULL)
+ if (best != NULL && c_local_schema != NULL)
break;
- tmp = tmp->next;
- }
-
- i = 0;
- best = local_schemas[i];
- while (best == NULL && i < n_locales)
- {
- best = local_schemas[i];
++i;
}
- g_free (local_schemas);
-
/* If we found localized info, add it to the return value,
* fall back to C locale if we can
*/
@@ -1644,7 +1876,10 @@ typedef struct
/* Collected while parsing a schema entry */
GSList *local_schemas;
+ char *locale;
+
guint allow_subdirs : 1;
+ guint parsing_local_descs : 1;
} ParseInfo;
static void set_error (GError **err,
@@ -1705,9 +1940,10 @@ set_error (GError **err,
}
static void
-parse_info_init (ParseInfo *info,
- MarkupDir *root,
- gboolean allow_subdirs)
+parse_info_init (ParseInfo *info,
+ MarkupDir *root,
+ gboolean allow_subdirs,
+ const char *locale)
{
info->states = g_slist_prepend (NULL, GINT_TO_POINTER (STATE_START));
@@ -1720,7 +1956,10 @@ parse_info_init (ParseInfo *info,
info->local_schemas = NULL;
+ info->locale = g_strdup (locale);
+
info->allow_subdirs = allow_subdirs != FALSE;
+ info->parsing_local_descs = info->locale != NULL;
dir_stack_push (info, root);
}
@@ -1728,6 +1967,8 @@ parse_info_init (ParseInfo *info,
static void
parse_info_free (ParseInfo *info)
{
+ g_free (info->locale);
+
g_slist_free (info->dir_stack);
/* Don't free current_entry - always owned by tree */
@@ -2393,102 +2634,152 @@ parse_entry_element (GMarkupParseContext *context,
ParseInfo *info,
GError **error)
{
- const char *name;
- const char *muser;
- const char *mtime;
- const char *schema;
- const char *type;
- const char *dummy1, *dummy2, *dummy3, *dummy4;
- const char *dummy5, *dummy6, *dummy7;
- GConfValue *value;
- GError *tmp_err;
-
+ MarkupEntry *entry;
+
g_return_if_fail (peek_state (info) == STATE_GCONF || peek_state (info) == STATE_DIR);
g_return_if_fail (ELEMENT_IS ("entry"));
g_return_if_fail (info->current_entry == NULL);
push_state (info, STATE_ENTRY);
- name = NULL;
- muser = NULL;
- mtime = NULL;
- schema = NULL;
- type = NULL;
-
- if (!locate_attributes (context, element_name, attribute_names, attribute_values,
- error,
- "name", &name,
- "muser", &muser,
- "mtime", &mtime,
- "schema", &schema,
- "type", &type,
+ if (!info->parsing_local_descs)
+ {
+ const char *name;
+ const char *muser;
+ const char *mtime;
+ const char *schema;
+ const char *type;
+ const char *dummy1, *dummy2, *dummy3, *dummy4;
+ const char *dummy5, *dummy6, *dummy7;
+ GConfValue *value;
+ GError *tmp_err;
+
+ name = NULL;
+ muser = NULL;
+ mtime = NULL;
+ schema = NULL;
+ type = NULL;
+
+ if (!locate_attributes (context, element_name, attribute_names, attribute_values,
+ error,
+ "name", &name,
+ "muser", &muser,
+ "mtime", &mtime,
+ "schema", &schema,
+ "type", &type,
- /* These are allowed but we don't use them until
- * parse_value_element
- */
- "value", &dummy1,
- "stype", &dummy2,
- "ltype", &dummy3,
- "list_type", &dummy4,
- "car_type", &dummy5,
- "cdr_type", &dummy6,
- "owner", &dummy7,
- NULL))
- return;
+ /* These are allowed but we don't use them until
+ * parse_value_element
+ */
+ "value", &dummy1,
+ "stype", &dummy2,
+ "ltype", &dummy3,
+ "list_type", &dummy4,
+ "car_type", &dummy5,
+ "cdr_type", &dummy6,
+ "owner", &dummy7,
+ NULL))
+ return;
- if (name == NULL)
- {
- set_error (error, context, GCONF_ERROR_PARSE_ERROR,
- _("No \"%s\" attribute on element <%s>"),
- "name", element_name);
- return;
- }
+ if (name == NULL)
+ {
+ set_error (error, context, GCONF_ERROR_PARSE_ERROR,
+ _("No \"%s\" attribute on element <%s>"),
+ "name", element_name);
+ return;
+ }
- /* Entries can exist just for the schema name,
- * lacking a value element. But if the entry has a type
- * attribute, it's supposed to have a value.
- */
- value = NULL;
- tmp_err = NULL;
- parse_value_element (context, element_name, attribute_names,
- attribute_values, &value,
- &tmp_err);
+ /* Entries can exist just for the schema name,
+ * lacking a value element. But if the entry has a type
+ * attribute, it's supposed to have a value.
+ */
+ value = NULL;
+ tmp_err = NULL;
+ parse_value_element (context, element_name, attribute_names,
+ attribute_values, &value,
+ &tmp_err);
- if (tmp_err)
- {
- if (type != NULL)
+ if (tmp_err)
{
- g_propagate_error (error, tmp_err);
- return;
+ if (type != NULL)
+ {
+ g_propagate_error (error, tmp_err);
+ return;
+ }
+ else
+ g_error_free (tmp_err);
}
- else
- g_error_free (tmp_err);
- }
- info->current_entry = markup_entry_new (dir_stack_peek (info), name);
- if (value != NULL)
- {
- info->current_entry->value = value;
- value_stack_push (info, value, FALSE); /* FALSE since current_entry owns it */
- }
+ entry = markup_entry_new (dir_stack_peek (info), name);
+ if (value != NULL)
+ {
+ entry->value = value;
+ value_stack_push (info, value, FALSE); /* FALSE since entry owns it */
+ }
- if (muser)
- markup_entry_set_mod_user (info->current_entry, muser);
+ if (muser)
+ markup_entry_set_mod_user (entry, muser);
- if (mtime)
- {
- GTime vmtime;
+ if (mtime)
+ {
+ GTime vmtime;
- vmtime = gconf_string_to_gulong (mtime);
+ vmtime = gconf_string_to_gulong (mtime);
- markup_entry_set_mod_time (info->current_entry, vmtime);
+ markup_entry_set_mod_time (entry, vmtime);
+ }
+
+ /* don't use markup_entry_set_schema_name because it would
+ * mess up the modtime
+ */
+ if (schema)
+ entry->schema_name = g_strdup (schema);
}
+ else
+ {
+ MarkupDir *dir;
+ GSList *tmp;
+ const char *name;
+
+ name = NULL;
- /* don't use markup_entry_set_schema_name because it would
- * mess up the modtime
- */
- if (schema)
- info->current_entry->schema_name = g_strdup (schema);
+ if (!locate_attributes (context, element_name, attribute_names, attribute_values,
+ error,
+ "name", &name,
+ NULL))
+ return;
+
+ if (name == NULL)
+ {
+ set_error (error, context, GCONF_ERROR_PARSE_ERROR,
+ _("No \"%s\" attribute on element <%s>"),
+ "name", element_name);
+ return;
+ }
+
+ dir = dir_stack_peek (info);
+
+ entry = NULL;
+
+ tmp = dir->entries;
+ while (tmp != NULL)
+ {
+ entry = tmp->data;
+
+ if (strcmp (entry->name, name) == 0)
+ break;
+ else
+ entry = NULL;
+
+ tmp = tmp->next;
+ }
+
+ /* Note: entry can be NULL here, in which case we'll discard
+ * the LocalSchemaInfo once we've finished parsing this entry
+ */
+ }
+
+ info->current_entry = entry;
}
static void
@@ -2499,7 +2790,8 @@ parse_dir_element (GMarkupParseContext *context,
ParseInfo *info,
GError **error)
{
- MarkupDir *dir;
+ MarkupDir *parent;
+ MarkupDir *dir;
const char *name;
g_return_if_fail (peek_state (info) == STATE_GCONF || peek_state (info) == STATE_DIR);
@@ -2508,7 +2800,7 @@ parse_dir_element (GMarkupParseContext *context,
push_state (info, STATE_DIR);
name = NULL;
-
+
if (!locate_attributes (context, element_name, attribute_names, attribute_values,
error,
"name", &name,
@@ -2523,11 +2815,46 @@ parse_dir_element (GMarkupParseContext *context,
return;
}
- dir = markup_dir_new (info->root->tree, dir_stack_peek (info), name);
+ dir = NULL;
+ parent = dir_stack_peek (info);
- dir->not_in_filesystem = TRUE;
- dir->entries_loaded = TRUE;
- dir->subdirs_loaded = TRUE;
+ if (!info->parsing_local_descs)
+ {
+ dir = markup_dir_new (info->root->tree, parent, name);
+
+ dir->not_in_filesystem = TRUE;
+ dir->entries_loaded = TRUE;
+ dir->subdirs_loaded = TRUE;
+ }
+ else
+ {
+ GSList *tmp;
+
+ tmp = parent->subdirs;
+ while (tmp != NULL)
+ {
+ dir = tmp->data;
+
+ if (strcmp (dir->name, name) == 0)
+ break;
+ else
+ dir = NULL;
+
+ tmp = tmp->next;
+ }
+
+ if (dir == NULL)
+ {
+ dir = markup_dir_new (info->root->tree, parent, name);
+
+ /* This is a dummy directory which will be deleted when
+ * we've finised parsing the contents of this element.
+ */
+ dir->is_parser_dummy = TRUE;
+ }
+ }
+
+ g_assert (dir != NULL);
dir_stack_push (info, dir);
}
@@ -2546,7 +2873,7 @@ parse_local_schema_child_element (GMarkupParseContext *context,
local_schema = info->local_schemas->data;
- if (ELEMENT_IS ("default"))
+ if (ELEMENT_IS ("default") && !info->parsing_local_descs)
{
GConfValue *value;
@@ -2602,12 +2929,13 @@ parse_local_schema_element (GMarkupParseContext *context,
const char *locale;
const char *short_desc;
LocalSchemaInfo *local_schema;
- GConfValue *value;
g_return_if_fail (ELEMENT_IS ("local_schema"));
- value = value_stack_peek (info);
- if (value == NULL || value->type != GCONF_VALUE_SCHEMA)
+ if (!info->parsing_local_descs &&
+ (info->current_entry == NULL ||
+ info->current_entry->value == NULL ||
+ info->current_entry->value->type != GCONF_VALUE_SCHEMA))
{
set_error (error, context, GCONF_ERROR_PARSE_ERROR,
_("<%s> provided but current element does not have type %s"),
@@ -2620,19 +2948,32 @@ parse_local_schema_element (GMarkupParseContext *context,
locale = NULL;
short_desc = NULL;
- if (!locate_attributes (context, element_name, attribute_names, attribute_values,
- error,
- "locale", &locale,
- "short_desc", &short_desc,
- NULL))
- return;
+ if (!info->parsing_local_descs)
+ {
+ if (!locate_attributes (context, element_name, attribute_names, attribute_values,
+ error,
+ "locale", &locale,
+ "short_desc", &short_desc,
+ NULL))
+ return;
- if (locale == NULL)
+ if (locale == NULL)
+ {
+ set_error (error, context, GCONF_ERROR_PARSE_ERROR,
+ _("No \"%s\" attribute on element <%s>"),
+ "locale", element_name);
+ return;
+ }
+ }
+ else
{
- set_error (error, context, GCONF_ERROR_PARSE_ERROR,
- _("No \"%s\" attribute on element <%s>"),
- "locale", element_name);
- return;
+ if (!locate_attributes (context, element_name, attribute_names, attribute_values,
+ error,
+ "short_desc", &short_desc,
+ NULL))
+ return;
+
+ locale = info->locale;
}
local_schema = local_schema_info_new ();
@@ -2773,20 +3114,23 @@ parse_value_child_element (GMarkupParseContext *context,
current_state = peek_state (info);
- if (current_state == STATE_ENTRY &&
- info->current_entry->value == NULL)
- {
- set_error (error, context, GCONF_ERROR_PARSE_ERROR,
- _("<%s> provided but parent <entry> does not have a value"),
- element_name);
- return;
- }
- else if (current_state == STATE_ENTRY)
+ if (!info->parsing_local_descs)
{
- g_assert (info->current_entry->value == value_stack_peek (info));
+ if (current_state == STATE_ENTRY &&
+ info->current_entry->value == NULL)
+ {
+ set_error (error, context, GCONF_ERROR_PARSE_ERROR,
+ _("<%s> provided but parent <entry> does not have a value"),
+ element_name);
+ return;
+ }
+ else if (current_state == STATE_ENTRY)
+ {
+ g_assert (info->current_entry->value == value_stack_peek (info));
+ }
}
- if (ELEMENT_IS ("stringvalue"))
+ if (ELEMENT_IS ("stringvalue") && !info->parsing_local_descs)
{
GConfValue *value;
@@ -2830,8 +3174,9 @@ parse_value_child_element (GMarkupParseContext *context,
break;
}
}
- else if (ELEMENT_IS ("car") ||
- ELEMENT_IS ("cdr"))
+ else if ((ELEMENT_IS ("car") ||
+ ELEMENT_IS ("cdr")) &&
+ !info->parsing_local_descs)
{
switch (current_state)
{
@@ -2853,7 +3198,7 @@ parse_value_child_element (GMarkupParseContext *context,
break;
}
}
- else if (ELEMENT_IS ("li"))
+ else if (ELEMENT_IS ("li") && !info->parsing_local_descs)
{
switch (current_state)
{
@@ -2977,14 +3322,69 @@ end_element_handler (GMarkupParseContext *context,
break;
case STATE_ENTRY:
- g_assert (info->current_entry);
- g_assert (info->current_entry->local_schemas == NULL);
+ if (!info->parsing_local_descs)
+ {
+ g_assert (info->current_entry);
+ g_assert (info->current_entry->local_schemas == NULL);
- info->current_entry->local_schemas = g_slist_reverse (info->local_schemas);
- info->local_schemas = NULL;
+ info->current_entry->local_schemas = g_slist_reverse (info->local_schemas);
+ info->local_schemas = NULL;
- if (info->current_entry->value != NULL)
- value_stack_pop (info);
+ if (info->current_entry->value != NULL)
+ value_stack_pop (info);
+ }
+ else if (info->local_schemas != NULL)
+ {
+ LocalSchemaInfo *local_schema;
+
+ g_assert (g_slist_length (info->local_schemas) == 1);
+
+ local_schema = info->local_schemas->data;
+
+ g_slist_free (info->local_schemas);
+ info->local_schemas = NULL;
+
+ if (info->current_entry != NULL &&
+ info->current_entry->value != NULL &&
+ info->current_entry->value->type == GCONF_VALUE_SCHEMA)
+ {
+ GSList *tmp;
+
+ tmp = info->current_entry->local_schemas;
+ while (tmp != NULL)
+ {
+ LocalSchemaInfo *lsi = tmp->data;
+
+ if (strcmp (local_schema->locale, lsi->locale) == 0)
+ {
+ g_free (lsi->short_desc);
+ lsi->short_desc = local_schema->short_desc;
+ local_schema->short_desc = NULL;
+
+ g_free (lsi->long_desc);
+ lsi->long_desc = local_schema->short_desc;
+ local_schema->long_desc = NULL;
+
+ local_schema_info_free (local_schema);
+
+ break;
+ }
+
+ tmp = tmp->next;
+ }
+
+ if (tmp == NULL)
+ {
+ info->current_entry->local_schemas =
+ g_slist_append (info->current_entry->local_schemas,
+ local_schema);
+ }
+ }
+ else
+ {
+ local_schema_info_free (local_schema);
+ }
+ }
info->current_entry = NULL;
@@ -3022,8 +3422,17 @@ end_element_handler (GMarkupParseContext *context,
MarkupDir *dir;
dir = dir_stack_pop (info);
- dir->entries = g_slist_reverse (dir->entries);
- dir->subdirs = g_slist_reverse (dir->subdirs);
+
+ if (!info->parsing_local_descs)
+ {
+ dir->entries = g_slist_reverse (dir->entries);
+ dir->subdirs = g_slist_reverse (dir->subdirs);
+ }
+ else if (dir->is_parser_dummy)
+ {
+ dir->parent->subdirs = g_slist_remove (dir->parent->subdirs, dir);
+ markup_dir_free (dir);
+ }
pop_state (info);
}
@@ -3129,9 +3538,10 @@ text_handler (GMarkupParseContext *context,
}
static void
-parse_tree (MarkupDir *root,
- gboolean parse_subtree,
- GError **err)
+parse_tree (MarkupDir *root,
+ gboolean parse_subtree,
+ const char *locale,
+ GError **err)
{
GMarkupParseContext *context;
GError *error;
@@ -3139,9 +3549,12 @@ parse_tree (MarkupDir *root,
char *filename;
FILE *f;
- filename = markup_dir_build_file_path (root, parse_subtree);
+ if (!parse_subtree)
+ g_assert (locale == NULL);
+
+ filename = markup_dir_build_file_path (root, parse_subtree, locale);
- parse_info_init (&info, root, parse_subtree);
+ parse_info_init (&info, root, parse_subtree, locale);
error = NULL;
@@ -3223,16 +3636,18 @@ static gboolean write_pair_children (GConfValue *value,
FILE *f,
int indent);
static gboolean write_schema_children (GConfValue *value,
- GSList *local_schemas,
FILE *f,
- int indent);
+ int indent,
+ GSList *local_schemas,
+ gboolean save_as_subtree);
static gboolean
-write_value_element (GConfValue *value,
- GSList *local_schemas,
- const char *closing_element,
- FILE *f,
- int indent)
+write_value_element (GConfValue *value,
+ const char *closing_element,
+ FILE *f,
+ int indent,
+ GSList *local_schemas,
+ gboolean save_as_subtree)
{
char *whitespace;
@@ -3379,17 +3794,21 @@ write_value_element (GConfValue *value,
break;
case GCONF_VALUE_LIST:
- if (!write_list_children (value, f, indent))
+ if (!write_list_children (value, f, indent + INDENT_SPACES))
return FALSE;
break;
case GCONF_VALUE_PAIR:
- if (!write_pair_children (value, f, indent))
+ if (!write_pair_children (value, f, indent + INDENT_SPACES))
return FALSE;
break;
case GCONF_VALUE_SCHEMA:
- if (!write_schema_children (value, local_schemas, f, indent))
+ if (!write_schema_children (value,
+ f,
+ indent + INDENT_SPACES,
+ local_schemas,
+ save_as_subtree))
return FALSE;
break;
@@ -3433,7 +3852,7 @@ write_list_children (GConfValue *value,
if (fputs ("<li", f) < 0)
goto out;
- if (!write_value_element (li, NULL, "li", f, indent))
+ if (!write_value_element (li, "li", f, indent, NULL, FALSE))
goto out;
tmp = tmp->next;
@@ -3469,7 +3888,7 @@ write_pair_children (GConfValue *value,
if (fputs ("<car", f) < 0)
goto out;
- if (!write_value_element (child, NULL, "car", f, indent))
+ if (!write_value_element (child, "car", f, indent, NULL, FALSE))
goto out;
}
@@ -3483,7 +3902,7 @@ write_pair_children (GConfValue *value,
if (fputs ("<cdr", f) < 0)
goto out;
- if (!write_value_element (child, NULL, "cdr", f, indent))
+ if (!write_value_element (child, "cdr", f, indent, NULL, FALSE))
goto out;
}
@@ -3497,34 +3916,32 @@ write_pair_children (GConfValue *value,
}
static gboolean
-write_schema_children (GConfValue *value,
- GSList *local_schemas,
- FILE *f,
- int indent)
+write_local_schema_info (LocalSchemaInfo *local_schema,
+ FILE *f,
+ int indent,
+ gboolean is_locale_file,
+ gboolean write_descs)
{
- /* Here we write each local_schema, in turn a local_schema can
- * contain <default> and <longdesc> and have locale and short_desc
- * attributes
- */
- GSList *tmp;
gboolean retval;
char *whitespace1, *whitespace2;
+ char *s;
+
+ if (!write_descs && local_schema->default_value == NULL)
+ return TRUE;
+
+ retval = FALSE;
whitespace1 = g_strnfill (indent, ' ');
whitespace2 = g_strnfill (indent + INDENT_SPACES, ' ');
-
- tmp = local_schemas;
- while (tmp != NULL)
- {
- LocalSchemaInfo *local_schema = tmp->data;
- char *s;
- if (fputs (whitespace1, f) < 0)
- goto out;
+ if (fputs (whitespace1, f) < 0)
+ goto out;
- if (fputs ("<local_schema", f) < 0)
- goto out;
-
+ if (fputs ("<local_schema", f) < 0)
+ goto out;
+
+ if (!is_locale_file)
+ {
g_assert (local_schema->locale);
s = g_markup_escape_text (local_schema->locale, -1);
@@ -3532,69 +3949,70 @@ write_schema_children (GConfValue *value,
if (fprintf (f, " locale=\"%s\"", s) < 0)
{
g_free (s);
- goto out;
+ goto out;
}
g_free (s);
+ }
- if (local_schema->short_desc)
- {
- s = g_markup_escape_text (local_schema->short_desc, -1);
+ if (write_descs && local_schema->short_desc)
+ {
+ s = g_markup_escape_text (local_schema->short_desc, -1);
- if (fprintf (f, " short_desc=\"%s\"", s) < 0)
- {
- g_free (s);
- goto out;
- }
-
+ if (fprintf (f, " short_desc=\"%s\"", s) < 0)
+ {
g_free (s);
+ goto out;
}
+
+ g_free (s);
+ }
- if (fputs (">\n", f) < 0)
- goto out;
-
- if (local_schema->default_value)
- {
- if (fputs (whitespace2, f) < 0)
- goto out;
-
- if (fputs ("<default", f) < 0)
- goto out;
+ if (fputs (">\n", f) < 0)
+ goto out;
- if (!write_value_element (local_schema->default_value, NULL,
- "default", f,
- indent + INDENT_SPACES))
- goto out;
- }
+ if (!is_locale_file && local_schema->default_value)
+ {
+ if (fputs (whitespace2, f) < 0)
+ goto out;
+
+ if (fputs ("<default", f) < 0)
+ goto out;
+
+ if (!write_value_element (local_schema->default_value,
+ "default",
+ f,
+ indent + INDENT_SPACES,
+ NULL,
+ FALSE))
+ goto out;
+ }
- if (local_schema->long_desc)
- {
- if (fprintf (f, "%s<longdesc>", whitespace2) < 0)
- goto out;
+ if (write_descs && local_schema->long_desc)
+ {
+ if (fprintf (f, "%s<longdesc>", whitespace2) < 0)
+ goto out;
- s = g_markup_escape_text (local_schema->long_desc, -1);
-
- if (fputs (s, f) < 0)
- {
- g_free (s);
- goto out;
- }
+ s = g_markup_escape_text (local_schema->long_desc, -1);
+ if (fputs (s, f) < 0)
+ {
g_free (s);
-
- if (fputs ("</longdesc>\n", f) < 0)
- goto out;
+ goto out;
}
+
+ g_free (s);
- if (fputs (whitespace1, f) < 0)
- goto out;
+ if (fputs ("</longdesc>\n", f) < 0)
+ goto out;
+ }
- if (fputs ("</local_schema>\n", f) < 0)
- goto out;
+ if (fputs (whitespace1, f) < 0)
+ goto out;
+
+ if (fputs ("</local_schema>\n", f) < 0)
+ goto out;
- tmp = tmp->next;
- }
-
retval = TRUE;
out:
@@ -3602,50 +4020,176 @@ write_schema_children (GConfValue *value,
g_free (whitespace1);
g_free (whitespace2);
+ return retval;
+}
+
+static gboolean
+write_schema_children (GConfValue *value,
+ FILE *f,
+ int indent,
+ GSList *local_schemas,
+ gboolean save_as_subtree)
+{
+ /* Here we write each local_schema, in turn a local_schema can
+ * contain <default> and <longdesc> and have locale and short_desc
+ * attributes
+ */
+ GSList *tmp;
+
+ tmp = local_schemas;
+ while (tmp != NULL)
+ {
+ LocalSchemaInfo *local_schema = tmp->data;
+ gboolean write_descs;
+
+ write_descs = TRUE;
+
+ if (save_as_subtree &&
+ strcmp (local_schema->locale, "C") != 0)
+ write_descs = FALSE;
+
+ if (!write_local_schema_info (local_schema,
+ f,
+ indent,
+ FALSE,
+ write_descs))
+ return FALSE;
+
+ tmp = tmp->next;
+ }
+
return TRUE;
}
+static void
+get_non_c_desc_locales (MarkupEntry *entry,
+ GHashTable *non_c_desc_locales)
+{
+ GSList *tmp;
+
+ tmp = entry->local_schemas;
+ while (tmp != NULL)
+ {
+ LocalSchemaInfo *local_schema = tmp->data;
+
+ if (strcmp (local_schema->locale, "C") != 0 &&
+ local_schema->short_desc != NULL &&
+ local_schema->long_desc != NULL)
+ {
+ g_hash_table_replace (non_c_desc_locales,
+ (char *) local_schema->locale,
+ GINT_TO_POINTER (TRUE));
+ }
+
+ tmp = tmp->next;
+ }
+}
+
+static LocalSchemaInfo *
+get_local_schema_info (MarkupEntry *entry,
+ const char *locale)
+{
+ GSList *tmp;
+
+ tmp = entry->local_schemas;
+ while (tmp != NULL)
+ {
+ LocalSchemaInfo *local_schema = tmp->data;
+
+ if (strcmp (local_schema->locale, locale) == 0)
+ {
+ return local_schema;
+ }
+
+ tmp = tmp->next;
+ }
+
+ return NULL;
+}
+
static gboolean
write_entry (MarkupEntry *entry,
FILE *f,
- int indent)
+ int indent,
+ gboolean save_as_subtree,
+ const char *locale,
+ GHashTable *other_locales)
{
- gboolean retval = FALSE;
- char *whitespace;
+ LocalSchemaInfo *local_schema_info;
+ gboolean retval;
+ char *whitespace;
- whitespace = g_strnfill (indent, ' ');
+ retval = FALSE;
+ local_schema_info = NULL;
- if (fprintf (f, "%s<entry", whitespace) < 0)
- goto out;
+ if (save_as_subtree)
+ {
+ if (locale == NULL)
+ {
+ g_assert (other_locales != NULL);
+ get_non_c_desc_locales (entry, other_locales);
+ }
+ else
+ {
+ if ((local_schema_info = get_local_schema_info (entry, locale)) == NULL)
+ return TRUE;
+ }
+ }
+
+ whitespace = g_strnfill (indent, ' ');
g_assert (entry->name != NULL);
- if (fprintf (f, " name=\"%s\" mtime=\"%lu\"",
- entry->name,
- (unsigned long) entry->mod_time) < 0)
+ if (fprintf (f, "%s<entry name=\"%s\"", whitespace, entry->name) < 0)
goto out;
-
- if (entry->schema_name)
- {
- if (fprintf (f, " schema=\"%s\"", entry->schema_name) < 0)
- goto out;
- }
- if (entry->mod_user)
+ if (local_schema_info == NULL)
{
- if (fprintf (f, " muser=\"%s\"", entry->mod_user) < 0)
+ if (fprintf (f, " mtime=\"%lu\"", (unsigned long) entry->mod_time) < 0)
goto out;
- }
+
+ if (entry->schema_name)
+ {
+ if (fprintf (f, " schema=\"%s\"", entry->schema_name) < 0)
+ goto out;
+ }
- if (entry->value != NULL)
- {
- if (!write_value_element (entry->value, entry->local_schemas, "entry", f, indent))
- goto out;
- }
+ if (entry->mod_user)
+ {
+ if (fprintf (f, " muser=\"%s\"", entry->mod_user) < 0)
+ goto out;
+ }
+
+ if (entry->value != NULL)
+ {
+ if (!write_value_element (entry->value,
+ "entry",
+ f,
+ indent,
+ entry->local_schemas,
+ save_as_subtree))
+ goto out;
+ }
+ else
+ {
+ if (fputs ("/>\n", f) < 0)
+ goto out;
+ }
+ }
else
{
- if (fputs ("/>\n", f) < 0)
- goto out;
+ if (fputs (">\n", f) < 0)
+ goto out;
+
+ if (!write_local_schema_info (local_schema_info,
+ f,
+ indent + INDENT_SPACES,
+ TRUE,
+ TRUE))
+ goto out;
+
+ if (fprintf (f, "%s</entry>\n", whitespace) < 0)
+ goto out;
}
retval = TRUE;
@@ -3658,9 +4202,12 @@ write_entry (MarkupEntry *entry,
}
static gboolean
-write_dir (MarkupDir *dir,
- FILE *f,
- int indent)
+write_dir (MarkupDir *dir,
+ FILE *f,
+ int indent,
+ gboolean save_as_subtree,
+ const char *locale,
+ GHashTable *other_locales)
{
GSList *tmp;
gboolean retval = FALSE;
@@ -3668,10 +4215,7 @@ write_dir (MarkupDir *dir,
dir->not_in_filesystem = TRUE;
- /* This dir will be deleted from the
- * MarkupTree after syncing anyway ...
- */
- if (!dir->entries && !dir->subdirs)
+ if (save_as_subtree && locale != NULL && dir->is_dir_empty)
return TRUE;
whitespace = g_strnfill (indent, ' ');
@@ -3686,7 +4230,12 @@ write_dir (MarkupDir *dir,
{
MarkupEntry *entry = tmp->data;
- if (!write_entry (entry, f, indent + INDENT_SPACES))
+ if (!write_entry (entry,
+ f,
+ indent + INDENT_SPACES,
+ save_as_subtree,
+ locale,
+ other_locales))
goto out;
tmp = tmp->next;
@@ -3697,7 +4246,12 @@ write_dir (MarkupDir *dir,
{
MarkupDir *subdir = tmp->data;
- if (!write_dir (subdir, f, indent + INDENT_SPACES))
+ if (!write_dir (subdir,
+ f,
+ indent + INDENT_SPACES,
+ save_as_subtree,
+ locale,
+ other_locales))
goto out;
tmp = tmp->next;
@@ -3715,11 +4269,49 @@ write_dir (MarkupDir *dir,
return retval;
}
+static gboolean
+init_is_dir_empty_flags (MarkupDir *dir,
+ const char *locale)
+{
+ GSList *tmp;
+
+ dir->is_dir_empty = TRUE;
+
+ tmp = dir->entries;
+ while (tmp != NULL)
+ {
+ MarkupEntry *entry = tmp->data;
+
+ if (get_local_schema_info (entry, locale) != NULL)
+ {
+ dir->is_dir_empty = FALSE;
+ break;
+ }
+
+ tmp = tmp->next;
+ }
+
+ tmp = dir->subdirs;
+ while (tmp != NULL)
+ {
+ MarkupDir *subdir = tmp->data;
+
+ if (!init_is_dir_empty_flags (subdir, locale))
+ dir->is_dir_empty = FALSE;
+
+ tmp = tmp->next;
+ }
+
+ return dir->is_dir_empty;
+}
+
static void
-save_tree (MarkupDir *dir,
- gboolean save_as_subtree,
- guint file_mode,
- GError **err)
+save_tree_with_locale (MarkupDir *dir,
+ gboolean save_as_subtree,
+ const char *locale,
+ GHashTable *other_locales,
+ guint file_mode,
+ GError **err)
{
/* We save to a secondary file then copy over, to handle
* out-of-disk-space robustly
@@ -3741,7 +4333,7 @@ save_tree (MarkupDir *dir,
new_fd = -1;
f = NULL;
- filename = markup_dir_build_file_path (dir, save_as_subtree);
+ filename = markup_dir_build_file_path (dir, save_as_subtree, locale);
new_filename = g_strconcat (filename, ".new", NULL);
#ifdef G_OS_WIN32
@@ -3795,7 +4387,12 @@ save_tree (MarkupDir *dir,
{
MarkupEntry *entry = tmp->data;
- if (!write_entry (entry, f, INDENT_SPACES))
+ if (!write_entry (entry,
+ f,
+ INDENT_SPACES,
+ save_as_subtree,
+ locale,
+ other_locales))
{
write_failed = TRUE;
goto done_writing;
@@ -3806,12 +4403,20 @@ save_tree (MarkupDir *dir,
if (save_as_subtree)
{
+ if (locale != NULL)
+ init_is_dir_empty_flags (dir, locale);
+
tmp = dir->subdirs;
while (tmp != NULL)
{
MarkupDir *dir = tmp->data;
- if (!write_dir (dir, f, INDENT_SPACES))
+ if (!write_dir (dir,
+ f,
+ INDENT_SPACES,
+ save_as_subtree,
+ locale,
+ other_locales))
{
write_failed = TRUE;
goto done_writing;
@@ -3891,6 +4496,85 @@ save_tree (MarkupDir *dir,
fclose (f);
}
+typedef struct
+{
+ MarkupDir *dir;
+ guint file_mode;
+ GError *first_error;
+} OtherLocalesForeachData;
+
+static void
+other_locales_foreach (const char *locale,
+ gpointer dummy,
+ OtherLocalesForeachData *data)
+{
+ GError *error;
+
+ error = NULL;
+ save_tree_with_locale (data->dir,
+ TRUE,
+ locale,
+ NULL,
+ data->file_mode,
+ &error);
+ if (error != NULL)
+ {
+ if (data->first_error != NULL)
+ data->first_error = error;
+ else
+ g_error_free (error);
+ }
+}
+
+static void
+save_tree (MarkupDir *dir,
+ gboolean save_as_subtree,
+ guint file_mode,
+ GError **err)
+{
+ if (!save_as_subtree)
+ {
+ save_tree_with_locale (dir, FALSE, NULL, NULL, file_mode, err);
+ }
+ else
+ {
+ OtherLocalesForeachData other_locales_foreach_data;
+ GHashTable *other_locales;
+
+ /* First save %gconf-tree.xml with all values and C locale
+ * schema descriptions; then save schema descriptions for
+ * all other locales in %gconf-tree-$(locale).xml
+ */
+
+ other_locales = g_hash_table_new (g_str_hash, g_str_equal);
+
+ save_tree_with_locale (dir,
+ TRUE,
+ NULL,
+ other_locales,
+ file_mode,
+ err);
+
+ other_locales_foreach_data.dir = dir;
+ other_locales_foreach_data.file_mode = file_mode;
+ other_locales_foreach_data.first_error = NULL;
+
+ g_hash_table_foreach (other_locales,
+ (GHFunc) other_locales_foreach,
+ &other_locales_foreach_data);
+
+ if (other_locales_foreach_data.first_error != NULL)
+ {
+ if (err != NULL && *err == NULL)
+ *err = other_locales_foreach_data.first_error;
+ else
+ g_error_free (other_locales_foreach_data.first_error);
+ }
+
+ g_hash_table_destroy (other_locales);
+ }
+}
+
/*
* Local schema
*/