+#ifndef G_OS_WIN32
+/* support for '.hidden' files */
+G_LOCK_DEFINE_STATIC (hidden_cache);
+static GHashTable *hidden_cache;
+
+static gboolean
+remove_from_hidden_cache (gpointer user_data)
+{
+ G_LOCK (hidden_cache);
+ g_hash_table_remove (hidden_cache, user_data);
+ G_UNLOCK (hidden_cache);
+
+ return FALSE;
+}
+
+static GHashTable *
+read_hidden_file (const gchar *dirname)
+{
+ gchar *contents = NULL;
+ gchar *filename;
+
+ filename = g_build_path ("/", dirname, ".hidden", NULL);
+ g_file_get_contents (filename, &contents, NULL, NULL);
+ g_free (filename);
+
+ if (contents != NULL)
+ {
+ GHashTable *table;
+ gchar **lines;
+ gint i;
+
+ table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+
+ lines = g_strsplit (contents, "\n", 0);
+ g_free (contents);
+
+ for (i = 0; lines[i]; i++)
+ /* hash table takes the individual strings... */
+ g_hash_table_add (table, lines[i]);
+
+ /* ... so we only free the container. */
+ g_free (lines);
+
+ return table;
+ }
+ else
+ return NULL;
+}
+
+static void
+maybe_unref_hash_table (gpointer data)
+{
+ if (data != NULL)
+ g_hash_table_unref (data);
+}
+
+static gboolean
+file_is_hidden (const gchar *path,
+ const gchar *basename)
+{
+ gboolean result;
+ gchar *dirname;
+ gpointer table;
+
+ dirname = g_path_get_dirname (path);
+
+ G_LOCK (hidden_cache);
+
+ if G_UNLIKELY (hidden_cache == NULL)
+ hidden_cache = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, maybe_unref_hash_table);
+
+ if (!g_hash_table_lookup_extended (hidden_cache, dirname,
+ NULL, &table))
+ {
+ gchar *mydirname;
+ GSource *remove_from_cache_source;
+
+ g_hash_table_insert (hidden_cache,
+ mydirname = g_strdup (dirname),
+ table = read_hidden_file (dirname));
+
+ remove_from_cache_source = g_timeout_source_new_seconds (5);
+ g_source_set_priority (remove_from_cache_source, G_PRIORITY_DEFAULT);
+ g_source_set_callback (remove_from_cache_source,
+ remove_from_hidden_cache,
+ mydirname,
+ NULL);
+ g_source_attach (remove_from_cache_source,
+ GLIB_PRIVATE_CALL (g_get_worker_context) ());
+ g_source_unref (remove_from_cache_source);
+ }
+
+ result = table != NULL && g_hash_table_contains (table, basename);
+
+ G_UNLOCK (hidden_cache);
+
+ g_free (dirname);
+
+ return result;
+}
+#endif /* !G_OS_WIN32 */
+
+void
+_g_local_file_info_get_nostat (GFileInfo *info,
+ const char *basename,
+ const char *path,
+ GFileAttributeMatcher *attribute_matcher)
+{
+ g_file_info_set_name (info, basename);
+
+ if (_g_file_attribute_matcher_matches_id (attribute_matcher,
+ G_FILE_ATTRIBUTE_ID_STANDARD_DISPLAY_NAME))
+ {
+ char *display_name = g_filename_display_basename (path);
+
+ /* look for U+FFFD REPLACEMENT CHARACTER */
+ if (strstr (display_name, "\357\277\275") != NULL)
+ {
+ char *p = display_name;
+ display_name = g_strconcat (display_name, _(" (invalid encoding)"), NULL);
+ g_free (p);
+ }
+ g_file_info_set_display_name (info, display_name);
+ g_free (display_name);
+ }
+
+ if (_g_file_attribute_matcher_matches_id (attribute_matcher,
+ G_FILE_ATTRIBUTE_ID_STANDARD_EDIT_NAME))
+ {
+ char *edit_name = g_filename_display_basename (path);
+ g_file_info_set_edit_name (info, edit_name);
+ g_free (edit_name);
+ }
+
+
+ if (_g_file_attribute_matcher_matches_id (attribute_matcher,
+ G_FILE_ATTRIBUTE_ID_STANDARD_COPY_NAME))
+ {
+ char *copy_name = g_filename_to_utf8 (basename, -1, NULL, NULL, NULL);
+ if (copy_name)
+ _g_file_info_set_attribute_string_by_id (info, G_FILE_ATTRIBUTE_ID_STANDARD_COPY_NAME, copy_name);
+ g_free (copy_name);
+ }
+}
+
+static const char *
+get_icon_name (const char *path,
+ const char *content_type,
+ gboolean use_symbolic,
+ gboolean *with_fallbacks_out)
+{
+ const char *name = NULL;
+ gboolean with_fallbacks = TRUE;
+
+ if (strcmp (path, g_get_home_dir ()) == 0)
+ {
+ name = use_symbolic ? "user-home-symbolic" : "user-home";
+ with_fallbacks = FALSE;
+ }
+ else if (strcmp (path, g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP)) == 0)
+ {
+ name = use_symbolic ? "user-desktop-symbolic" : "user-desktop";
+ with_fallbacks = FALSE;
+ }
+ else if (g_strcmp0 (path, g_get_user_special_dir (G_USER_DIRECTORY_DOCUMENTS)) == 0)
+ {
+ name = use_symbolic ? "folder-documents-symbolic" : "folder-documents";
+ }
+ else if (g_strcmp0 (path, g_get_user_special_dir (G_USER_DIRECTORY_DOWNLOAD)) == 0)
+ {
+ name = use_symbolic ? "folder-download-symbolic" : "folder-download";
+ }
+ else if (g_strcmp0 (path, g_get_user_special_dir (G_USER_DIRECTORY_MUSIC)) == 0)
+ {
+ name = use_symbolic ? "folder-music-symbolic" : "folder-music";
+ }
+ else if (g_strcmp0 (path, g_get_user_special_dir (G_USER_DIRECTORY_PICTURES)) == 0)
+ {
+ name = use_symbolic ? "folder-pictures-symbolic" : "folder-pictures";
+ }
+ else if (g_strcmp0 (path, g_get_user_special_dir (G_USER_DIRECTORY_PUBLIC_SHARE)) == 0)
+ {
+ name = use_symbolic ? "folder-publicshare-symbolic" : "folder-publicshare";
+ }
+ else if (g_strcmp0 (path, g_get_user_special_dir (G_USER_DIRECTORY_TEMPLATES)) == 0)
+ {
+ name = use_symbolic ? "folder-templates-symbolic" : "folder-templates";
+ }
+ else if (g_strcmp0 (path, g_get_user_special_dir (G_USER_DIRECTORY_VIDEOS)) == 0)
+ {
+ name = use_symbolic ? "folder-videos-symbolic" : "folder-videos";
+ }
+ else if (g_strcmp0 (content_type, "inode/directory") == 0)
+ {
+ name = use_symbolic ? "folder-symbolic" : "folder";
+ }
+ else
+ {
+ name = NULL;
+ }
+
+ if (with_fallbacks_out != NULL)
+ *with_fallbacks_out = with_fallbacks;
+
+ return name;
+}
+
+static GIcon *
+get_icon (const char *path,
+ const char *content_type,
+ gboolean use_symbolic)
+{
+ GIcon *icon = NULL;
+ const char *icon_name;
+ gboolean with_fallbacks;
+
+ icon_name = get_icon_name (path, content_type, use_symbolic, &with_fallbacks);
+ if (icon_name != NULL)
+ {
+ if (with_fallbacks)
+ icon = g_themed_icon_new_with_default_fallbacks (icon_name);
+ else
+ icon = g_themed_icon_new (icon_name);
+ }
+ else
+ {
+ if (use_symbolic)
+ icon = g_content_type_get_symbolic_icon (content_type);
+ else
+ icon = g_content_type_get_icon (content_type);
+ }
+
+ return icon;
+}
+