static void
hash_lookup_defaults_func(gpointer key, gpointer value, gpointer user_data)
{
  MateConfEntry *entry = value;
  struct DefaultsLookupData* dld = user_data;
  MateConfSources *sources = dld->sources;
  const gchar** locales = dld->locales;
  
  if (mateconf_entry_get_value(entry) == NULL)
    {
      if (mateconf_entry_get_schema_name(entry) != NULL)
        {
          MateConfValue *val;


          val = mateconf_sources_query_value(sources,
                                          mateconf_entry_get_schema_name(entry),
                                          locales,
                                          TRUE,
                                          NULL,
                                          NULL,
                                          NULL,
                                          NULL);

          if (val != NULL &&
              val->type == MATECONF_VALUE_SCHEMA)
            {
              MateConfValue* defval;

              defval = mateconf_schema_steal_default_value (mateconf_value_get_schema(val));

              mateconf_entry_set_value_nocopy (entry, defval);
              mateconf_entry_set_is_default (entry, TRUE);
            }

          if (val)
            mateconf_value_free(val);
        }
    }
}
MateConfSchema *
mateconf_client_get_schema_for_key (MateConfClient *client, const char *key)
{
	MateConfEntry *entry;
	const char *schema_name;
	MateConfSchema *schema = NULL;

	entry = mateconf_client_get_entry (client, key, NULL, TRUE, NULL);
	schema_name = mateconf_entry_get_schema_name (entry);

	if (schema_name == NULL)
		goto out;

	schema = mateconf_client_get_schema (client, schema_name, NULL);

out:
	if (entry)
		mateconf_entry_free (entry);

	return schema;
}
GSList*       
mateconf_sources_all_entries   (MateConfSources* sources,
                             const gchar* dir,
                             const gchar** locales,
                             GError** err)
{
  GList* tmp;
  GHashTable* hash;
  GSList* flattened;
  gboolean first_pass = TRUE; /* as an optimization, don't bother
                                 doing hash lookups on first source
                              */
  struct DefaultsLookupData dld = { NULL, NULL };
  
  dld.sources = sources;
  dld.locales = locales;

  /* Empty MateConfSources, skip it */
  if (sources->sources == NULL)
    return NULL;

  hash = g_hash_table_new(g_str_hash, g_str_equal);

  tmp = sources->sources;

  while (tmp != NULL)
    {
      MateConfSource* src;
      GSList* pairs;
      GSList* iter;
      GError* error = NULL;
      
      src   = tmp->data;
      pairs = mateconf_source_all_entries(src, dir, locales, &error);
      iter  = pairs;
      
      /* On error, set error and bail */
      if (error != NULL)
        {
          g_hash_table_foreach(hash, hash_destroy_entries_func, NULL);
          
          g_hash_table_destroy(hash);
          
          if (err)
            {
              g_return_val_if_fail(*err == NULL, NULL);
              *err = error;
              return NULL;
            }
          else
            {
              g_error_free(error);
              return NULL;
            }
        }

      /* Iterate over the list of entries, stuffing them in the hash
         and setting their writability flag if they're new
      */
      
      while (iter != NULL)
        {
          MateConfEntry* pair = iter->data;
          MateConfEntry* previous;
          gchar *full;
          
          if (first_pass)
            previous = NULL; /* Can't possibly be there. */
          else
            previous = g_hash_table_lookup(hash, pair->key);
          
          if (previous != NULL)
            {
              if (mateconf_entry_get_value (previous) != NULL)
                /* Discard this latest one */
                ;
              else
                {
                  /* Save the new value, previously we had an entry but no value */
                  mateconf_entry_set_value_nocopy (previous,
                                                mateconf_entry_steal_value(pair));

                  /* As an efficiency hack, remember that
                   * entry->key is relative not absolute on the
                   * mateconfd side
                   */
                  full = mateconf_concat_dir_and_key (dir, previous->key);

                  mateconf_entry_set_is_writable (previous,
                                               key_is_writable (sources,
                                                                src,
                                                                full,
                                                                NULL));

                  g_free (full);
                }
              
              if (mateconf_entry_get_schema_name (previous) != NULL)
                /* Discard this latest one */
                ;
              else
                {
                  /* Save the new schema name, previously we had an entry but no schema name*/
                  if (mateconf_entry_get_schema_name (pair) != NULL)
                    {
                      mateconf_entry_set_schema_name (previous,
                                                   mateconf_entry_get_schema_name (pair));
                    }
                }

              mateconf_entry_free(pair);
            }
          else
            {
              /* Save */
              g_hash_table_insert(hash, pair->key, pair);
              
              /* As an efficiency hack, remember that
               * entry->key is relative not absolute on the
               * mateconfd side
               */
              full = mateconf_concat_dir_and_key (dir, pair->key);

              mateconf_entry_set_is_writable (pair,
                                           key_is_writable (sources,
                                                            src,
                                                            full,
                                                            NULL));
              
              g_free (full);
            }

          iter = g_slist_next(iter);
        }
      
      /* All pairs are either stored or destroyed. */
      g_slist_free(pairs);

      first_pass = FALSE;

      tmp = g_list_next(tmp);
    }

  flattened = NULL;

  g_hash_table_foreach(hash, hash_lookup_defaults_func, &dld);
  
  g_hash_table_foreach(hash, hash_listify_func, &flattened);

  g_hash_table_destroy(hash);
  
  return flattened;
}