summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog45
-rw-r--r--ChangeLog.pre-2-1045
-rw-r--r--gtk/gtkfilesystem.c4
-rw-r--r--gtk/gtkfilesystemwin32.c357
4 files changed, 279 insertions, 172 deletions
diff --git a/ChangeLog b/ChangeLog
index 7542d4bd87..3f27d86306 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,8 +1,51 @@
2006-08-23 Tor Lillqvist <tml@novell.com>
+ * gtk/gtkfilesystemwin32.c: Remove dead code. Reduce spurious
+ differences between this file and gtkfilesystemunix.c so that it
+ is easier to compare them and check if differences are
+ intentional. I will later factor out the common functions and code
+ snippets from these two files.
+
+2006-08-23 Tor Lillqvist <tml@novell.com>
+
+ Fix several problems with the file chooser on Windows, for
+ instance prevent duplicated directory entries from appearing.
+
+ * gtk/gtkfilesystem.c (gtk_file_paths_sort): Use
+ _gtk_file_system_win32_path_compare() on Windows for casefolded
+ sorting.
+
+ * gtk/gtkfilesystemwin32.c (casefolded_hash, casefolded_equal):
+ case-independent hash and equality functions. Scan the UTF-8
+ strings gunichar by gunichar, and ignore special casing rules, to
+ more closely match NTFS behaviour.
+ (gtk_file_system_win32_init): Use casefolded_hash() and
+ casefolded_equal() for the folder hash table.
+ (remove_trailing_slash): Don't remove the slash of a drive or
+ share root.
+ (get_mime_type_for_file): Take also a WIN32_FILE_ATTRIBUTE_DATA as
+ argument, and use that to recognize directories. Don't call
+ g_file_test() to check for executables, just look at the file name
+ extension directly.
+ (gtk_file_system_win32_make_path): Check illegal chars in file
+ name, like in gtkfilesystemunix.c.
+ (create_file_info): Drop unused basename parameter. Call
+ g_filename_display_name() directly for roots, as
+ g_filename_display_basename() mishandles those.
+ (gtk_file_folder_win32_get_info): Skip sanity check for now, as it
+ fails for server share roots. Construct basename only in the if
+ branch that uses it.
+ (fill_in_names): Use casefolded_hash() and casefolded_equal() for
+ the folder's stat_info hash table, too.
+ (_gtk_file_system_win32_path_compare): Scan the strings gunichar
+ by gunichar and ignore special casing here, too, instead of using
+ g_utf8_casefold(). Match slash and backslash.
+
+2006-08-23 Tor Lillqvist <tml@novell.com>
+
* gdk/x11/gdkwindow-x11.c (gdk_window_shape_combine_mask)
(gdk_window_input_shape_combine_mask)
- gdk_window_shape_combine_region)
+ (gdk_window_shape_combine_region)
(gdk_window_input_shape_combine_region): Add Win32 detail to doc
comments.
diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10
index 7542d4bd87..3f27d86306 100644
--- a/ChangeLog.pre-2-10
+++ b/ChangeLog.pre-2-10
@@ -1,8 +1,51 @@
2006-08-23 Tor Lillqvist <tml@novell.com>
+ * gtk/gtkfilesystemwin32.c: Remove dead code. Reduce spurious
+ differences between this file and gtkfilesystemunix.c so that it
+ is easier to compare them and check if differences are
+ intentional. I will later factor out the common functions and code
+ snippets from these two files.
+
+2006-08-23 Tor Lillqvist <tml@novell.com>
+
+ Fix several problems with the file chooser on Windows, for
+ instance prevent duplicated directory entries from appearing.
+
+ * gtk/gtkfilesystem.c (gtk_file_paths_sort): Use
+ _gtk_file_system_win32_path_compare() on Windows for casefolded
+ sorting.
+
+ * gtk/gtkfilesystemwin32.c (casefolded_hash, casefolded_equal):
+ case-independent hash and equality functions. Scan the UTF-8
+ strings gunichar by gunichar, and ignore special casing rules, to
+ more closely match NTFS behaviour.
+ (gtk_file_system_win32_init): Use casefolded_hash() and
+ casefolded_equal() for the folder hash table.
+ (remove_trailing_slash): Don't remove the slash of a drive or
+ share root.
+ (get_mime_type_for_file): Take also a WIN32_FILE_ATTRIBUTE_DATA as
+ argument, and use that to recognize directories. Don't call
+ g_file_test() to check for executables, just look at the file name
+ extension directly.
+ (gtk_file_system_win32_make_path): Check illegal chars in file
+ name, like in gtkfilesystemunix.c.
+ (create_file_info): Drop unused basename parameter. Call
+ g_filename_display_name() directly for roots, as
+ g_filename_display_basename() mishandles those.
+ (gtk_file_folder_win32_get_info): Skip sanity check for now, as it
+ fails for server share roots. Construct basename only in the if
+ branch that uses it.
+ (fill_in_names): Use casefolded_hash() and casefolded_equal() for
+ the folder's stat_info hash table, too.
+ (_gtk_file_system_win32_path_compare): Scan the strings gunichar
+ by gunichar and ignore special casing here, too, instead of using
+ g_utf8_casefold(). Match slash and backslash.
+
+2006-08-23 Tor Lillqvist <tml@novell.com>
+
* gdk/x11/gdkwindow-x11.c (gdk_window_shape_combine_mask)
(gdk_window_input_shape_combine_mask)
- gdk_window_shape_combine_region)
+ (gdk_window_shape_combine_region)
(gdk_window_input_shape_combine_region): Add Win32 detail to doc
comments.
diff --git a/gtk/gtkfilesystem.c b/gtk/gtkfilesystem.c
index 493960239d..7e10039871 100644
--- a/gtk/gtkfilesystem.c
+++ b/gtk/gtkfilesystem.c
@@ -1183,7 +1183,11 @@ gtk_file_path_get_type (void)
GSList *
gtk_file_paths_sort (GSList *paths)
{
+#ifndef G_OS_WIN32
return g_slist_sort (paths, (GCompareFunc)strcmp);
+#else
+ return g_slist_sort (paths, (GCompareFunc)_gtk_file_system_win32_path_compare);
+#endif
}
/**
diff --git a/gtk/gtkfilesystemwin32.c b/gtk/gtkfilesystemwin32.c
index 71325e3188..05166909cf 100644
--- a/gtk/gtkfilesystemwin32.c
+++ b/gtk/gtkfilesystemwin32.c
@@ -122,30 +122,28 @@ static const GtkFileInfoType STAT_NEEDED_MASK = (GTK_FILE_INFO_IS_FOLDER |
GTK_FILE_INFO_SIZE |
GTK_FILE_INFO_ICON);
-static void gtk_file_system_win32_iface_init (GtkFileSystemIface *iface);
-static void gtk_file_system_win32_finalize (GObject *object);
+static void gtk_file_system_win32_iface_init (GtkFileSystemIface *iface);
+static void gtk_file_system_win32_finalize (GObject *object);
-static GSList * gtk_file_system_win32_list_volumes (GtkFileSystem *file_system);
+static GSList * gtk_file_system_win32_list_volumes (GtkFileSystem *file_system);
static GtkFileSystemVolume *gtk_file_system_win32_get_volume_for_path (GtkFileSystem *file_system,
const GtkFilePath *path);
-static GtkFileSystemHandle *gtk_file_system_win32_get_folder (GtkFileSystem *file_system,
- const GtkFilePath *path,
- GtkFileInfoType types,
+static GtkFileSystemHandle *gtk_file_system_win32_get_folder (GtkFileSystem *file_system,
+ const GtkFilePath *path,
+ GtkFileInfoType types,
GtkFileSystemGetFolderCallback callback,
gpointer data);
-
static GtkFileSystemHandle *gtk_file_system_win32_get_info (GtkFileSystem *file_system,
const GtkFilePath *path,
GtkFileInfoType types,
GtkFileSystemGetInfoCallback callback,
gpointer data);
-
-static GtkFileSystemHandle *gtk_file_system_win32_create_folder (GtkFileSystem *file_system,
- const GtkFilePath *path,
+static GtkFileSystemHandle *gtk_file_system_win32_create_folder (GtkFileSystem *file_system,
+ const GtkFilePath *path,
GtkFileSystemCreateFolderCallback callback,
gpointer data);
-static void gtk_file_system_win32_cancel_operation (GtkFileSystemHandle *handle);
+static void gtk_file_system_win32_cancel_operation (GtkFileSystemHandle *handle);
static void gtk_file_system_win32_volume_free (GtkFileSystem *file_system,
GtkFileSystemVolume *volume);
@@ -163,85 +161,84 @@ static gchar * gtk_file_system_win32_volume_get_icon_name (GtkFileSystem
GtkFileSystemVolume *volume,
GError **error);
-static gboolean gtk_file_system_win32_get_parent (GtkFileSystem *file_system,
- const GtkFilePath *path,
- GtkFilePath **parent,
- GError **error);
-static GtkFilePath * gtk_file_system_win32_make_path (GtkFileSystem *file_system,
- const GtkFilePath *base_path,
- const gchar *display_name,
- GError **error);
-static gboolean gtk_file_system_win32_parse (GtkFileSystem *file_system,
- const GtkFilePath *base_path,
- const gchar *str,
- GtkFilePath **folder,
- gchar **file_part,
- GError **error);
-static gchar * gtk_file_system_win32_path_to_uri (GtkFileSystem *file_system,
- const GtkFilePath *path);
-static gchar * gtk_file_system_win32_path_to_filename (GtkFileSystem *file_system,
- const GtkFilePath *path);
-static GtkFilePath * gtk_file_system_win32_uri_to_path (GtkFileSystem *file_system,
- const gchar *uri);
-static GtkFilePath * gtk_file_system_win32_filename_to_path (GtkFileSystem *file_system,
- const gchar *filename);
-
-static gboolean gtk_file_system_win32_insert_bookmark (GtkFileSystem *file_system,
- const GtkFilePath *path,
+static gboolean gtk_file_system_win32_get_parent (GtkFileSystem *file_system,
+ const GtkFilePath *path,
+ GtkFilePath **parent,
+ GError **error);
+static GtkFilePath * gtk_file_system_win32_make_path (GtkFileSystem *file_system,
+ const GtkFilePath *base_path,
+ const gchar *display_name,
+ GError **error);
+static gboolean gtk_file_system_win32_parse (GtkFileSystem *file_system,
+ const GtkFilePath *base_path,
+ const gchar *str,
+ GtkFilePath **folder,
+ gchar **file_part,
+ GError **error);
+
+static gchar * gtk_file_system_win32_path_to_uri (GtkFileSystem *file_system,
+ const GtkFilePath *path);
+static gchar * gtk_file_system_win32_path_to_filename (GtkFileSystem *file_system,
+ const GtkFilePath *path);
+static GtkFilePath *gtk_file_system_win32_uri_to_path (GtkFileSystem *file_system,
+ const gchar *uri);
+static GtkFilePath *gtk_file_system_win32_filename_to_path (GtkFileSystem *file_system,
+ const gchar *filename);
+
+
+static gboolean gtk_file_system_win32_insert_bookmark (GtkFileSystem *file_system,
+ const GtkFilePath *path,
gint position,
- GError **error);
-static gboolean gtk_file_system_win32_remove_bookmark (GtkFileSystem *file_system,
- const GtkFilePath *path,
- GError **error);
-static GSList *gtk_file_system_win32_list_bookmarks (GtkFileSystem *file_system);
-static gchar *gtk_file_system_win32_get_bookmark_label (GtkFileSystem *file_system,
- const GtkFilePath *path);
+ GError **error);
+static gboolean gtk_file_system_win32_remove_bookmark (GtkFileSystem *file_system,
+ const GtkFilePath *path,
+ GError **error);
+static GSList * gtk_file_system_win32_list_bookmarks (GtkFileSystem *file_system);
+static gchar * gtk_file_system_win32_get_bookmark_label (GtkFileSystem *file_system,
+ const GtkFilePath *path);
static void gtk_file_system_win32_set_bookmark_label (GtkFileSystem *file_system,
const GtkFilePath *path,
const gchar *label);
-static void gtk_file_folder_win32_iface_init (GtkFileFolderIface *iface);
-static void gtk_file_folder_win32_finalize (GObject *object);
-static GtkFileInfo *gtk_file_folder_win32_get_info (GtkFileFolder *folder,
- const GtkFilePath *path,
- GError **error);
-static gboolean gtk_file_folder_win32_list_children (GtkFileFolder *folder,
- GSList **children,
- GError **error);
+static void gtk_file_folder_win32_iface_init (GtkFileFolderIface *iface);
+static void gtk_file_folder_win32_finalize (GObject *object);
+
+static GtkFileInfo *gtk_file_folder_win32_get_info (GtkFileFolder *folder,
+ const GtkFilePath *path,
+ GError **error);
+static gboolean gtk_file_folder_win32_list_children (GtkFileFolder *folder,
+ GSList **children,
+ GError **error);
static gboolean gtk_file_folder_win32_is_finished_loading (GtkFileFolder *folder);
-static GtkFilePath * filename_to_path (const gchar *filename);
+static GtkFilePath *filename_to_path (const gchar *filename);
-static gboolean filename_is_root (const char *filename);
+static gboolean filename_is_root (const char *filename);
-static gboolean filename_is_drive_root (const char *filename);
-static gboolean filename_is_server_share (const char *filename);
-static gboolean filename_is_some_root (const char *filename);
+static gboolean filename_is_drive_root (const char *filename);
+static gboolean filename_is_some_root (const char *filename);
-static gboolean stat_with_error (const char *filename,
- WIN32_FILE_ATTRIBUTE_DATA *wfad,
- GError **error);
-static GtkFileInfo *create_file_info (GtkFileFolderWin32 *folder_win32,
- const char *filename,
- const char *basename,
- GtkFileInfoType types,
- WIN32_FILE_ATTRIBUTE_DATA *wfad,
- const char *mime_type);
+static gboolean stat_with_error (const char *filename,
+ WIN32_FILE_ATTRIBUTE_DATA *wfad,
+ GError **error);
+static GtkFileInfo *create_file_info (GtkFileFolderWin32 *folder_win32,
+ const char *filename,
+ GtkFileInfoType types,
+ WIN32_FILE_ATTRIBUTE_DATA *wfad,
+ const char *mime_type);
static gboolean fill_in_names (GtkFileFolderWin32 *folder_win32,
GError **error);
static void fill_in_stats (GtkFileFolderWin32 *folder_win32);
static void fill_in_mime_type (GtkFileFolderWin32 *folder_win32);
-static gboolean cb_fill_in_stats (gpointer key,
- gpointer value,
- gpointer user_data);
-static gboolean cb_fill_in_mime_type (gpointer key,
- gpointer value,
- gpointer user_data);
-
-static char *get_parent_dir (const char *filename);
+static gboolean cb_fill_in_stats (gpointer key,
+ gpointer value,
+ gpointer user_data);
+static gboolean cb_fill_in_mime_type (gpointer key,
+ gpointer value,
+ gpointer user_data);
/* some info kept together for volumes */
struct _GtkFileSystemVolume
@@ -255,14 +252,14 @@ struct _GtkFileSystemVolume
*/
G_DEFINE_TYPE_WITH_CODE (GtkFileSystemWin32, gtk_file_system_win32, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (GTK_TYPE_FILE_SYSTEM,
- gtk_file_system_win32_iface_init));
+ gtk_file_system_win32_iface_init))
/*
* GtkFileFolderWin32
*/
G_DEFINE_TYPE_WITH_CODE (GtkFileFolderWin32, _gtk_file_folder_win32, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (GTK_TYPE_FILE_FOLDER,
- gtk_file_folder_win32_iface_init));
+ gtk_file_folder_win32_iface_init))
/**
* gtk_file_system_win32_new:
@@ -329,15 +326,36 @@ check_volumes (gpointer data)
return TRUE;
}
+static guint
+casefolded_hash (gconstpointer v)
+{
+ const gchar *p = (const gchar *) v;
+ guint32 h = 0;
+
+ while (*p)
+ {
+ h = (h << 5) - h + g_unichar_toupper (g_utf8_get_char (p));
+ p = g_utf8_next_char (p);
+ }
+
+ return h;
+}
+
+static gboolean casefolded_equal (gconstpointer v1,
+ gconstpointer v2)
+{
+ return (_gtk_file_system_win32_path_compare ((const gchar *) v1, (const gchar *) v2) == 0);
+}
+
static void
gtk_file_system_win32_init (GtkFileSystemWin32 *system_win32)
{
+ system_win32->folder_hash = g_hash_table_new (casefolded_hash, casefolded_equal);
+
/* Set up an idle handler for volume changes. Once a second should
* be enough.
*/
system_win32->timeout = g_timeout_add_full (0, 1000, check_volumes, system_win32, NULL);
-
- system_win32->folder_hash = g_hash_table_new (g_str_hash, g_str_equal);
}
static void
@@ -464,11 +482,15 @@ gtk_file_system_win32_get_volume_for_path (GtkFileSystem *file_system,
static char *
remove_trailing_slash (const char *filename)
{
- int len;
+ int root_len, len;
len = strlen (filename);
- if (len > 1 && filename[len - 1] == '/')
+ if (g_path_is_absolute (filename))
+ root_len = g_path_skip_root (filename) - filename;
+ else
+ root_len = 1;
+ if (len > root_len && G_IS_DIR_SEPARATOR (filename[len - 1]))
return g_strndup (filename, len - 1);
else
return g_memdup (filename, len + 1);
@@ -766,19 +788,25 @@ create_handle (GtkFileSystem *file_system)
}
static char *
-get_mime_type_for_file (const char *filename)
+get_mime_type_for_file (const char *filename,
+ const WIN32_FILE_ATTRIBUTE_DATA *wfad)
{
const char *extension;
HKEY key = NULL;
DWORD type, nbytes = 0;
char *value = NULL;
- if (g_file_test (filename, G_FILE_TEST_IS_EXECUTABLE))
- return g_strdup ("application/x-executable");
+ if (wfad->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ return g_strdup ("x-directory/normal");
extension = strrchr (filename, '.');
if (extension != NULL &&
+ (stricmp (extension, ".exe") == 0 ||
+ stricmp (extension, ".com") == 0))
+ return g_strdup ("application/x-executable");
+
+ if (extension != NULL &&
extension[1] != '\0' &&
RegOpenKeyEx (HKEY_CLASSES_ROOT, extension, 0,
KEY_QUERY_VALUE, &key) == ERROR_SUCCESS &&
@@ -811,7 +839,6 @@ gtk_file_system_win32_get_info (GtkFileSystem *file_system,
GtkFileSystemHandle *handle;
const char *filename;
GtkFileInfo *info;
- gchar *basename;
WIN32_FILE_ATTRIBUTE_DATA wfad;
const char *mime_type;
@@ -830,14 +857,11 @@ gtk_file_system_win32_get_info (GtkFileSystem *file_system,
}
if ((types & GTK_FILE_INFO_MIME_TYPE) != 0)
- mime_type = get_mime_type_for_file (filename);
+ mime_type = get_mime_type_for_file (filename, &wfad);
else
mime_type = NULL;
- basename = g_path_get_basename (filename);
-
- info = create_file_info (NULL, filename, basename, types, &wfad, mime_type);
- g_free (basename);
+ info = create_file_info (NULL, filename, types, &wfad, mime_type);
g_object_ref (handle);
queue_get_info_callback (callback, handle, info, NULL, data);
@@ -1068,6 +1092,7 @@ gtk_file_system_win32_create_folder (GtkFileSystem *file_syst
g_signal_emit_by_name (folder_win32, "files-added", paths);
g_slist_free (paths);
}
+
g_free(parent);
}
}
@@ -1185,18 +1210,6 @@ get_icon_type_from_stat (WIN32_FILE_ATTRIBUTE_DATA *wfad)
return ICON_REGULAR;
}
-static IconType
-get_icon_type (const char *filename,
- GError **error)
-{
- WIN32_FILE_ATTRIBUTE_DATA wfad;
-
- if (!stat_with_error (filename, &wfad, error))
- return ICON_NONE;
-
- return get_icon_type_from_stat (&wfad);
-}
-
/* Renders a fallback icon from the stock system */
static const gchar *
get_fallback_icon_name (IconType icon_type)
@@ -1232,6 +1245,8 @@ gtk_file_system_win32_volume_get_icon_name (GtkFileSystem *file_system,
return g_strdup ("gnome-dev-harddisk");
}
+#if 0 /* Unused, see below */
+
static char *
get_parent_dir (const char *filename)
{
@@ -1255,6 +1270,8 @@ get_parent_dir (const char *filename)
return g_path_get_dirname (filename);
}
+#endif
+
static gboolean
gtk_file_system_win32_get_parent (GtkFileSystem *file_system,
const GtkFilePath *path,
@@ -1292,11 +1309,24 @@ gtk_file_system_win32_make_path (GtkFileSystem *file_system,
const char *base_filename;
gchar *full_filename;
GtkFilePath *result;
+ char *p;
base_filename = gtk_file_path_get_string (base_path);
g_return_val_if_fail (base_filename != NULL, NULL);
g_return_val_if_fail (g_path_is_absolute (base_filename), NULL);
+ if ((p = strpbrk (display_name, "<>\"/\\|")))
+ {
+ g_set_error (error,
+ GTK_FILE_SYSTEM_ERROR,
+ GTK_FILE_SYSTEM_ERROR_BAD_FILENAME,
+ _("The name \"%s\" is not valid because it contains the character \"%c\". "
+ "Please use a different name."),
+ display_name,
+ *p);
+ return NULL;
+ }
+
full_filename = g_build_filename (base_filename, display_name, NULL);
result = filename_to_path (full_filename);
g_free (full_filename);
@@ -1495,7 +1525,7 @@ static GtkFilePath *
gtk_file_system_win32_uri_to_path (GtkFileSystem *file_system,
const gchar *uri)
{
- GtkFilePath *path = NULL;
+ GtkFilePath *path;
gchar *filename = g_filename_from_uri (uri, NULL, NULL);
#if DEBUGGING_OUTPUT
@@ -1507,6 +1537,8 @@ gtk_file_system_win32_uri_to_path (GtkFileSystem *file_system,
path = filename_to_path (filename);
g_free (filename);
}
+ else
+ path = NULL;
return path;
}
@@ -1518,6 +1550,10 @@ gtk_file_system_win32_filename_to_path (GtkFileSystem *file_system,
return filename_to_path (filename);
}
+#if 0
+
+/* These are unused currently, hmm */
+
static GdkPixbuf*
extract_icon (const char* filename)
{
@@ -1629,6 +1665,8 @@ win32_pseudo_mime_lookup (const char* name)
return is;
}
+#endif
+
/* Returns the name of the icon to be used for a path which is known to be a
* directory. This can vary for Home, Desktop, etc.
*/
@@ -1694,12 +1732,10 @@ get_icon_type_from_path (GtkFileFolderWin32 *folder_win32,
}
}
- if (wfad)
- return get_icon_type_from_stat (wfad);
+ icon_type = get_icon_type_from_stat (wfad);
- icon_type = get_icon_type (filename, NULL);
if (icon_type == ICON_REGULAR)
- *mime_type = get_mime_type_for_file (filename);
+ *mime_type = get_mime_type_for_file (filename, wfad);
return icon_type;
}
@@ -2287,7 +2323,6 @@ stat_with_error (const char *filename,
static GtkFileInfo *
create_file_info (GtkFileFolderWin32 *folder_win32,
const char *filename,
- const char *basename,
GtkFileInfoType types,
WIN32_FILE_ATTRIBUTE_DATA *wfad,
const char *mime_type)
@@ -2298,7 +2333,13 @@ create_file_info (GtkFileFolderWin32 *folder_win32,
if (types & GTK_FILE_INFO_DISPLAY_NAME)
{
- gchar *display_name = g_filename_display_basename (filename);
+ gchar *display_name;
+
+ if (filename_is_root (filename))
+ display_name = g_filename_display_name (filename);
+ else
+ display_name = g_filename_display_basename (filename);
+
gtk_file_info_set_display_name (info, display_name);
g_free (display_name);
}
@@ -2384,7 +2425,7 @@ create_stat_info_entry_and_emit_add (GtkFileFolderWin32 *folder_win32,
entry->wfad = *wfad;
if ((folder_win32->types & GTK_FILE_INFO_MIME_TYPE) != 0)
- entry->mime_type = get_mime_type_for_file (filename);
+ entry->mime_type = get_mime_type_for_file (filename, wfad);
g_hash_table_insert (folder_win32->stat_info,
g_strdup (basename),
@@ -2406,7 +2447,6 @@ gtk_file_folder_win32_get_info (GtkFileFolder *folder,
{
GtkFileFolderWin32 *folder_win32 = GTK_FILE_FOLDER_WIN32 (folder);
GtkFileInfo *info;
- gchar *dirname, *basename;
const char *filename;
GtkFileInfoType types;
WIN32_FILE_ATTRIBUTE_DATA wfad;
@@ -2425,18 +2465,29 @@ gtk_file_folder_win32_get_info (GtkFileFolder *folder,
g_return_val_if_fail (filename != NULL, NULL);
g_return_val_if_fail (g_path_is_absolute (filename), NULL);
- dirname = get_parent_dir (filename);
- g_return_val_if_fail (strcmp (dirname, folder_win32->filename) == 0, NULL);
- g_free (dirname);
+#if 0
+ /* Skip this sanity check, as it fails for server share roots, where
+ * dirname gets set to \\server\share\ and folder_win32->filename is
+ * \\server\share. Also, should we do a casefolded comparison here,
+ * too, anyway?
+ */
+ {
+ gchar *dirname = get_parent_dir (filename);
+ g_return_val_if_fail (strcmp (dirname, folder_win32->filename) == 0, NULL);
+ g_free (dirname);
+ }
+#endif
- basename = g_path_get_basename (filename);
types = folder_win32->types;
if (folder_win32->have_stat)
{
struct stat_info_entry *entry;
+ gchar *basename;
g_assert (folder_win32->stat_info != NULL);
+
+ basename = g_path_get_basename (filename);
entry = g_hash_table_lookup (folder_win32->stat_info, basename);
if (!entry)
@@ -2449,26 +2500,23 @@ gtk_file_folder_win32_get_info (GtkFileFolder *folder,
entry = create_stat_info_entry_and_emit_add (folder_win32, filename, basename, &wfad);
}
-
- info = create_file_info (folder_win32, filename, basename, types, &entry->wfad, entry->mime_type);
g_free (basename);
+
+ info = create_file_info (folder_win32, filename, types, &entry->wfad, entry->mime_type);
return info;
}
else
{
if (!stat_with_error (filename, &wfad, error))
- {
- g_free (basename);
- return NULL;
- }
+ return NULL;
if ((types & GTK_FILE_INFO_MIME_TYPE) != 0)
- mime_type = get_mime_type_for_file (filename);
+ mime_type = get_mime_type_for_file (filename, &wfad);
else
mime_type = NULL;
- info = create_file_info (folder_win32, filename, basename, types, &wfad, mime_type);
- g_free (basename);
+ info = create_file_info (folder_win32, filename, types, &wfad, mime_type);
+
return info;
}
}
@@ -2531,7 +2579,7 @@ fill_in_names (GtkFileFolderWin32 *folder_win32, GError **error)
if (!dir)
return FALSE;
- folder_win32->stat_info = g_hash_table_new_full (g_str_hash, g_str_equal,
+ folder_win32->stat_info = g_hash_table_new_full (casefolded_hash, casefolded_equal,
(GDestroyNotify) g_free,
(GDestroyNotify) free_stat_info_entry);
@@ -2607,7 +2655,7 @@ cb_fill_in_mime_type (gpointer key, gpointer value, gpointer user_data)
GtkFileFolderWin32 *folder_win32 = user_data;
char *fullname = g_build_filename (folder_win32->filename, basename, NULL);
- entry->mime_type = get_mime_type_for_file (fullname);
+ entry->mime_type = get_mime_type_for_file (fullname, &entry->wfad);
g_free (fullname);
@@ -2664,42 +2712,6 @@ filename_is_drive_root (const char *filename)
}
static gboolean
-filename_is_server_share (const char *filename)
-{
- /* Check if filename is of the form \\server\share or \\server\share\ */
-
- const char *p, *q, *r;
-
- if (!(G_IS_DIR_SEPARATOR (filename[0]) &&
- filename[1] == filename[0]))
- return FALSE;
-
- p = strchr (filename + 2, '\\');
- q = strchr (filename + 2, '/');
-
- if (p == NULL || (q != NULL && q < p))
- p = q;
-
- if (p == NULL)
- return FALSE;
-
- if (!p[1] || G_IS_DIR_SEPARATOR (p[1]))
- return FALSE;
-
- q = strchr (p + 1, '\\');
- r = strchr (p + 1, '/');
-
- if (q == NULL || (r != NULL && r < q))
- q = r;
-
- if (q == NULL ||
- q[1] == '\0')
- return TRUE;
-
- return FALSE;
-}
-
-static gboolean
filename_is_some_root (const char *filename)
{
return (g_path_is_absolute (filename) &&
@@ -2710,16 +2722,21 @@ int
_gtk_file_system_win32_path_compare (const gchar *path1,
const gchar *path2)
{
- int retval;
- gchar *folded_path1 = g_utf8_casefold (path1, -1);
- gchar *folded_path2 = g_utf8_casefold (path2, -1);
-
- retval = strcmp (folded_path1, folded_path2);
-
- g_free (folded_path1);
- g_free (folded_path2);
-
- return retval;
+ while (*path1 && *path2)
+ {
+ gunichar c1 = g_utf8_get_char (path1);
+ gunichar c2 = g_utf8_get_char (path2);
+ if (c1 == c2 ||
+ (G_IS_DIR_SEPARATOR (c1) && G_IS_DIR_SEPARATOR (c1)) ||
+ g_unichar_toupper (c1) == g_unichar_toupper (c2))
+ {
+ path1 = g_utf8_next_char (path1);
+ path2 = g_utf8_next_char (path2);
+ }
+ else
+ break;
+ }
+ return *path1 - *path2;
}
#define __GTK_FILE_SYSTEM_WIN32_C__