Index: gtk/gtk.symbols
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtk.symbols,v
retrieving revision 1.28
diff -p -u -2 -r1.28 gtk.symbols
--- gtk/gtk.symbols	2 Jan 2005 23:15:21 -0000	1.28
+++ gtk/gtk.symbols	5 Jan 2005 13:44:56 -0000
@@ -930,4 +930,5 @@ gtk_file_system_create_folder
 gtk_file_system_error_quark
 gtk_file_system_filename_to_path
+gtk_file_system_get_desktop
 gtk_file_system_get_folder
 gtk_file_system_get_parent
@@ -939,4 +940,5 @@ gtk_file_system_list_volumes
 gtk_file_system_make_path
 gtk_file_system_parse
+gtk_file_system_path_compare
 gtk_file_system_path_is_local
 gtk_file_system_path_to_filename
@@ -3010,5 +3012,2 @@ gtk_window_unmaximize
 gtk_window_unstick
 gtk_wrap_mode_get_type G_GNUC_CONST
-#ifdef G_OS_WIN32
-_gtk_file_system_win32_path_compare
-#endif
Index: gtk/gtkfilechooserbutton.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkfilechooserbutton.c,v
retrieving revision 1.25
diff -p -u -2 -r1.25 gtkfilechooserbutton.c
--- gtk/gtkfilechooserbutton.c	3 Jan 2005 04:26:33 -0000	1.25
+++ gtk/gtkfilechooserbutton.c	5 Jan 2005 13:44:58 -0000
@@ -53,8 +53,4 @@
 #include "gtkfilechooserbutton.h"
 
-#ifdef G_OS_WIN32
-#include "gtkfilesystemwin32.h"
-#endif
-
 /* **************** *
  *  Private Macros  *
@@ -561,5 +557,5 @@ gtk_file_chooser_button_remove_shortcut_
 	  if (type == ROW_TYPE_SHORTCUT &&
 	      data &&
-	      gtk_file_path_compare (data, path) == 0)
+	      gtk_file_system_path_compare (priv->fs, (GtkFilePath *) data, path) == 0)
 	    {
 	      model_free_row_data (GTK_FILE_CHOOSER_BUTTON (chooser), &iter);
@@ -1277,5 +1273,4 @@ model_add_special (GtkFileChooserButton 
 {
   const gchar *homedir;
-  gchar *desktopdir = NULL;
   GtkListStore *store;
   GtkTreeIter iter;
@@ -1306,18 +1301,10 @@ model_add_special (GtkFileChooserButton 
       g_object_unref (pixbuf);
       button->priv->n_special++;
-
-#ifndef G_OS_WIN32
-      desktopdir = g_build_filename (homedir, DESKTOP_DISPLAY_NAME, NULL);
-#endif
     }
 
-#ifdef G_OS_WIN32
-  desktopdir = _gtk_file_system_win32_get_desktop ();
-#endif
+  path = gtk_file_system_get_desktop (button->priv->fs);
 
-  if (desktopdir)
+  if (path)
     {
-      path = gtk_file_system_filename_to_path (button->priv->fs, desktopdir);
-      g_free (desktopdir);
       pixbuf = gtk_file_system_render_icon (button->priv->fs, path,
 					    GTK_WIDGET (button),
@@ -1714,5 +1701,6 @@ update_combo_box (GtkFileChooserButton *
 	  row_found = (paths &&
 		       paths->data &&
-		       gtk_file_path_compare (data, paths->data) == 0);
+		       gtk_file_system_path_compare (priv->fs, (GtkFilePath *)data,
+						     (GtkFilePath *) paths->data) == 0);
 	  break;
 	case ROW_TYPE_VOLUME:
@@ -1723,5 +1711,6 @@ update_combo_box (GtkFileChooserButton *
 	    row_found = (paths &&
 			 paths->data &&
-			 gtk_file_path_compare (base_path, paths->data) == 0);
+			 gtk_file_system_path_compare (priv->fs, base_path,
+						       (GtkFilePath *) paths->data) == 0);
 	    gtk_file_path_free (base_path);
 	  }
@@ -1794,5 +1783,5 @@ update_label_and_image (GtkFileChooserBu
 
 	  base_path = gtk_file_system_volume_get_base_path (priv->fs, volume);
-	  if (base_path && gtk_file_path_compare (base_path, path) == 0)
+	  if (base_path && gtk_file_system_path_compare (priv->fs, base_path, path) == 0)
 	    {
 	      label_text = gtk_file_system_volume_get_display_name (priv->fs,
Index: gtk/gtkfilechooserdefault.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkfilechooserdefault.c,v
retrieving revision 1.235
diff -p -u -2 -r1.235 gtkfilechooserdefault.c
--- gtk/gtkfilechooserdefault.c	2 Jan 2005 23:15:21 -0000	1.235
+++ gtk/gtkfilechooserdefault.c	5 Jan 2005 13:45:02 -0000
@@ -1232,23 +1232,11 @@ shortcuts_append_home (GtkFileChooserDef
 }
 
-/* Appends the ~/Desktop directory to the shortcuts model */
+/* Appends the desktop directory to the shortcuts model */
 static void
 shortcuts_append_desktop (GtkFileChooserDefault *impl)
 {
-  char *name;
   GtkFilePath *path;
 
-#ifdef G_OS_WIN32
-  name = _gtk_file_system_win32_get_desktop ();
-#else
-  const char *home = g_get_home_dir ();
-  if (home == NULL)
-    return;
-
-  name = g_build_filename (home, "Desktop", NULL);
-#endif
-
-  path = gtk_file_system_filename_to_path (impl->file_system, name);
-  g_free (name);
+  path = gtk_file_system_get_desktop (impl->file_system);
 
   impl->has_desktop = shortcuts_insert_path (impl, -1, FALSE, NULL, path, _("Desktop"), FALSE, NULL);
@@ -1821,5 +1809,6 @@ shortcut_find_position (GtkFileChooserDe
 	      model_path = col_data;
 
-	      if (model_path && gtk_file_path_compare (model_path, path) == 0)
+	      if (model_path && gtk_file_system_path_compare (impl->file_system,
+							      model_path, path) == 0)
 		return i;
 	    }
@@ -4783,5 +4772,6 @@ get_paths_foreach (GtkTreeModel *model,
 
   if (!info->path_from_entry
-      || gtk_file_path_compare (info->path_from_entry, file_path) != 0)
+      || gtk_file_system_path_compare (info->impl->file_system,
+				       info->path_from_entry, file_path) != 0)
     info->result = g_slist_prepend (info->result, gtk_file_path_copy (file_path));
 }
@@ -5000,5 +4990,5 @@ gtk_file_chooser_default_remove_shortcut
 
       shortcut = col_data;
-      if (gtk_file_path_compare (shortcut, path) == 0)
+      if (gtk_file_system_path_compare (impl->file_system, shortcut, path) == 0)
 	{
 	  shortcuts_remove_rows (impl, pos + i, 1);
@@ -5423,5 +5413,5 @@ check_preview_change (GtkFileChooserDefa
   if (new_path != impl->preview_path &&
       !(new_path && impl->preview_path &&
-	gtk_file_path_compare (new_path, impl->preview_path) == 0))
+	gtk_file_system_path_compare (impl->file_system, new_path, impl->preview_path) == 0))
     {
       if (impl->preview_path)
Index: gtk/gtkfilechooserentry.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkfilechooserentry.c,v
retrieving revision 1.27
diff -p -u -2 -r1.27 gtkfilechooserentry.c
--- gtk/gtkfilechooserentry.c	19 Dec 2004 04:45:09 -0000	1.27
+++ gtk/gtkfilechooserentry.c	5 Jan 2005 13:45:02 -0000
@@ -29,4 +29,8 @@
 #include "gtkmain.h"
 
+#ifdef G_PLATFORM_WIN32
+#include "gtkfilesystemwin32.h"
+#endif
+
 typedef struct _GtkFileChooserEntryClass GtkFileChooserEntryClass;
 
@@ -318,5 +322,4 @@ completion_match_func (GtkEntryCompletio
     }
 
-
   norm_file_part = g_utf8_normalize (chooser_entry->file_part, -1, G_NORMALIZE_ALL);
   norm_name = g_utf8_normalize (name, -1, G_NORMALIZE_ALL);
@@ -327,9 +330,9 @@ completion_match_func (GtkEntryCompletio
 
     temp = norm_file_part;
-    norm_file_part = g_utf8_casefold (norm_file_part, -1);
+    norm_file_part = _gtk_file_system_win32_utf8_casefold (norm_file_part);
     g_free (temp);
 
     temp = norm_name;
-    norm_name = g_utf8_casefold (norm_name, -1);
+    norm_name = _gtk_file_system_win32_utf8_casefold (norm_name);
     g_free (temp);
   }
@@ -384,4 +387,35 @@ maybe_append_separator_to_path (GtkFileC
 }
 
+#ifdef G_PLATFORM_WIN32
+
+static gboolean
+str_has_prefix (const gchar *str,
+		const gchar *prefix)
+{
+  gchar *folded_str = _gtk_file_system_win32_utf8_casefold (str);
+  gchar *folded_prefix = _gtk_file_system_win32_utf8_casefold (prefix);
+  gboolean retval = g_str_has_prefix (folded_str, folded_prefix);
+
+  g_free (folded_str);
+  g_free (folded_prefix);
+  
+  return retval;
+}
+
+static gboolean
+is_same_char (gunichar a,
+	      gunichar b)
+{
+  return (_gtk_file_system_win32_casefold (a) == _gtk_file_system_win32_casefold (b));
+}
+
+#else
+
+#define str_has_prefix g_str_has_prefix
+
+#define is_same_char(a,b) ((a) == (b))
+
+#endif
+
 static gboolean
 check_completion_callback (GtkFileChooserEntry *chooser_entry)
@@ -406,5 +440,4 @@ check_completion_callback (GtkFileChoose
   valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (chooser_entry->completion_store),
 					 &iter);
-
   while (valid)
     {
@@ -418,5 +451,5 @@ check_completion_callback (GtkFileChoose
 			  -1);
 
-      if (g_str_has_prefix (display_name, chooser_entry->file_part))
+      if (str_has_prefix (display_name, chooser_entry->file_part))
 	{
 	  if (!common_prefix)
@@ -429,9 +462,11 @@ check_completion_callback (GtkFileChoose
 	      gchar *p = common_prefix;
 	      const gchar *q = display_name;
-		  
-	      while (*p && *p == *q)
+	      gunichar pc, qc;
+
+	      while (*p && (is_same_char ((pc = g_utf8_get_char (p)),
+					  (qc = g_utf8_get_char (q)))))
 		{
-		  p++;
-		  q++;
+		  p = g_utf8_next_char (p);
+		  q = g_utf8_next_char (q);
 		}
 		  
@@ -461,5 +496,5 @@ check_completion_callback (GtkFileChoose
     case GTK_FILE_CHOOSER_ACTION_SAVE:
     case GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER:
-      if (common_prefix && !g_str_has_suffix (common_prefix, "/"))
+      if (common_prefix && !g_str_has_suffix (common_prefix, G_DIR_SEPARATOR_S))
 	{
 	  g_free (common_prefix);
@@ -721,5 +756,8 @@ gtk_file_chooser_entry_maybe_update_dire
   if (chooser_entry->current_folder_path)
     {
-      if (gtk_file_path_compare (folder_path, chooser_entry->current_folder_path) != 0 || force_reload)
+      if (gtk_file_system_path_compare (chooser_entry->file_system,
+					folder_path,
+					chooser_entry->current_folder_path) != 0 ||
+	  force_reload)
 	{
 	  /* We changed our current directory.  We need to clear out the old
Index: gtk/gtkfilesystem.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkfilesystem.c,v
retrieving revision 1.39
diff -p -u -2 -r1.39 gtkfilesystem.c
--- gtk/gtkfilesystem.c	13 Sep 2004 16:00:00 -0000	1.39
+++ gtk/gtkfilesystem.c	5 Jan 2005 13:45:03 -0000
@@ -26,4 +26,8 @@
 #include "gtkmodules.h"
 
+#ifdef G_OS_WIN32
+#include "gtkfilesystemwin32.h"
+#endif
+
 #include <string.h>
 
@@ -773,4 +777,55 @@ gtk_file_system_list_bookmarks (GtkFileS
 }
 
+/**
+ * gtk_file_system_path_compare:
+ * @file_system: a #GtkFileSystem
+ * @path1: the first #GtkFilePath to compare
+ * @path2: the second #GtkFilePath
+ * 
+ * Compares two paths.
+ * 
+ * Return value: An integer, like strcmp.
+ *
+ * Since: 2.6.1
+ **/
+int
+gtk_file_system_path_compare (GtkFileSystem     *file_system,
+			      const GtkFilePath *path1,
+			      const GtkFilePath *path2)
+{
+  g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), 0);
+  g_return_val_if_fail (path1 != NULL, 0);
+  g_return_val_if_fail (path2 != NULL, 0);
+
+  if (GTK_FILE_SYSTEM_GET_IFACE (file_system)->path_compare)
+    return GTK_FILE_SYSTEM_GET_IFACE (file_system)->path_compare (file_system, path1, path2);
+  else
+    return strcmp (gtk_file_path_get_string (path1),
+		   gtk_file_path_get_string (path2));
+}
+
+/**
+ * gtk_file_system_get_desktop:
+ * @file_system: a #GtkFileSystem
+ * 
+ * Returns the path to the desktop directory for the current user.
+ * 
+ * Return value: A #GtkFilePath, or %NULL if the current user doesn't
+ * have any desktop directory, or if the file system doesn't support
+ * the concept.
+ *
+ * Since: 2.6.1
+ **/
+const GtkFilePath *
+gtk_file_system_get_desktop (GtkFileSystem *file_system)
+{
+  g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), 0);
+
+  if (GTK_FILE_SYSTEM_GET_IFACE (file_system)->get_desktop)
+    return GTK_FILE_SYSTEM_GET_IFACE (file_system)->get_desktop (file_system);
+  else
+    return NULL;
+}
+
 /*****************************************
  *             GtkFileFolder             *
@@ -928,9 +983,12 @@ gtk_file_path_get_type (void)
 }
 
-
 GSList *
 gtk_file_paths_sort (GSList *paths)
 {
+#ifdef G_OS_WIN32
+  return g_slist_sort (paths, (GCompareFunc)_gtk_file_system_win32_utf8_casefolded_cmp);
+#else
   return g_slist_sort (paths, (GCompareFunc)strcmp);
+#endif
 }
 
Index: gtk/gtkfilesystem.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkfilesystem.h,v
retrieving revision 1.27
diff -p -u -2 -r1.27 gtkfilesystem.h
--- gtk/gtkfilesystem.h	2 Jan 2005 23:15:21 -0000	1.27
+++ gtk/gtkfilesystem.h	5 Jan 2005 13:45:04 -0000
@@ -200,4 +200,9 @@ struct _GtkFileSystemIface
   void (*volumes_changed)   (GtkFileSystem *file_system);
   void (*bookmarks_changed) (GtkFileSystem *file_system);
+
+  int  (*path_compare) (GtkFileSystem     *file_system,
+			const GtkFilePath *path1,
+			const GtkFilePath *path2);
+  const GtkFilePath* (*get_desktop)  (GtkFileSystem *file_system);
 };
 
@@ -275,4 +280,9 @@ gboolean gtk_file_system_remove_bookmark
 GSList  *gtk_file_system_list_bookmarks  (GtkFileSystem     *file_system);
 
+int      gtk_file_system_path_compare    (GtkFileSystem     *file_system,
+					  const GtkFilePath *path1,
+					  const GtkFilePath *path2);
+
+const GtkFilePath *gtk_file_system_get_desktop (GtkFileSystem *file_system);
 
 /*
@@ -346,14 +356,6 @@ GType   gtk_file_path_get_type (void) G_
 
 #define gtk_file_path_copy(path)       gtk_file_path_new_dup (gtk_file_path_get_string(path))
-#ifdef G_OS_WIN32
-int _gtk_file_system_win32_path_compare (const gchar *path1,
-					 const gchar *path2);
-#define gtk_file_path_compare(path1,path2) \
-  _gtk_file_system_win32_path_compare (gtk_file_path_get_string (path1), \
-	                               gtk_file_path_get_string (path2))
-#else
 #define gtk_file_path_compare(path1,path2) strcmp (gtk_file_path_get_string (path1), \
 						   gtk_file_path_get_string (path2))
-#endif
 
 GSList *gtk_file_paths_sort (GSList *paths);
Index: gtk/gtkfilesystemmodel.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkfilesystemmodel.c,v
retrieving revision 1.33
diff -p -u -2 -r1.33 gtkfilesystemmodel.c
--- gtk/gtkfilesystemmodel.c	9 Aug 2004 16:59:52 -0000	1.33
+++ gtk/gtkfilesystemmodel.c	5 Jan 2005 13:45:05 -0000
@@ -1026,5 +1026,5 @@ find_child_node (GtkFileSystemModel *mod
       if (children->is_visible &&
 	  children->path &&
-	  gtk_file_path_compare (children->path, path) == 0)
+	  gtk_file_system_path_compare (model->file_system, children->path, path) == 0)
 	return children;
 
@@ -1046,5 +1046,5 @@ find_and_ref_path (GtkFileSystemModel  *
   GtkFileFolder *folder;
 
-  if (gtk_file_path_compare (path, model->root_path) == 0
+  if (gtk_file_system_path_compare (model->file_system, path, model->root_path) == 0
       || !gtk_file_system_get_parent (model->file_system, path, &parent_path, NULL))
     return NULL;
@@ -1554,5 +1554,7 @@ do_files_added (GtkFileSystemModel *mode
       
       while (children &&
-	     (!children->path || gtk_file_path_compare (children->path, file_path) < 0))
+	     (!children->path ||
+	      gtk_file_system_path_compare (model->file_system,
+					    children->path, file_path) < 0))
 	{
 	  prev = children;
@@ -1564,5 +1566,6 @@ do_files_added (GtkFileSystemModel *mode
   
       if (children &&
-	  children->path && gtk_file_path_compare (children->path, file_path) == 0)
+	  children->path && gtk_file_system_path_compare (model->file_system,
+							  children->path, file_path) == 0)
 	{
 	  /* Shouldn't happen */
@@ -1673,5 +1676,7 @@ do_files_changed (GtkFileSystemModel *mo
       
       while (children &&
-	     (!children->path || gtk_file_path_compare (children->path, file_path) < 0))
+	     (!children->path ||
+	      gtk_file_system_path_compare (model->file_system,
+					    children->path, file_path) < 0))
 	{
 	  prev = children;
@@ -1683,5 +1688,7 @@ do_files_changed (GtkFileSystemModel *mo
   
       if (children &&
-	  children->path && gtk_file_path_compare (children->path, file_path) == 0)
+	  children->path &&
+	  gtk_file_system_path_compare (model->file_system,
+					children->path, file_path) == 0)
 	{
 	  gtk_tree_model_row_changed (tree_model, path, &iter);
@@ -1750,5 +1757,7 @@ do_files_removed (GtkFileSystemModel *mo
       
       while (children &&
-	     (!children->path || gtk_file_path_compare (children->path, file_path) < 0))
+	     (!children->path ||
+	      gtk_file_system_path_compare (model->file_system,
+					    children->path, file_path) < 0))
 	{
 	  prev = children;
@@ -1760,5 +1769,7 @@ do_files_removed (GtkFileSystemModel *mo
   
       if (children &&
-	  children->path && gtk_file_path_compare (children->path, file_path) == 0)
+	  children->path &&
+	  gtk_file_system_path_compare (model->file_system,
+					children->path, file_path) == 0)
 	{
 	  FileModelNode *next = children->next;
Index: gtk/gtkfilesystemunix.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkfilesystemunix.c,v
retrieving revision 1.52
diff -p -u -2 -r1.52 gtkfilesystemunix.c
--- gtk/gtkfilesystemunix.c	30 Dec 2004 07:39:45 -0000	1.52
+++ gtk/gtkfilesystemunix.c	5 Jan 2005 13:45:05 -0000
@@ -196,4 +196,9 @@ static gboolean gtk_file_system_unix_rem
 static GSList * gtk_file_system_unix_list_bookmarks  (GtkFileSystem *file_system);
 
+static int   gtk_file_system_unix_path_compare  (GtkFileSystem     *file_system,
+						 const GtkFilePath *path1,
+						 const GtkFilePath *path2);
+static const GtkFilePath *gtk_file_system_unix_get_desktop (GtkFileSystem *file_system);
+
 static GType gtk_file_folder_unix_get_type   (void);
 static void  gtk_file_folder_unix_class_init (GtkFileFolderUnixClass *class);
@@ -311,4 +316,6 @@ gtk_file_system_unix_iface_init   (GtkFi
   iface->remove_bookmark = gtk_file_system_unix_remove_bookmark;
   iface->list_bookmarks = gtk_file_system_unix_list_bookmarks;
+  iface->path_compare = gtk_file_system_unix_path_compare;
+  iface->get_desktop = gtk_file_system_unix_get_desktop;
 }
 
@@ -1592,4 +1599,24 @@ gtk_file_system_unix_list_bookmarks (Gtk
   result = g_slist_reverse (result);
   return result;
+}
+
+static int
+gtk_file_system_unix_path_compare (GtkFileSystem     *file_system,
+				   const GtkFilePath *path1,
+				   const GtkFilePath *path2)
+{
+  return strcmp (gtk_file_path_get_string (path1),
+		 gtk_file_path_get_string (path2));
+}
+
+static const GtkFilePath *
+gtk_file_system_unix_get_desktop (GtkFileSystem *file_system)
+{
+  gchar *home = g_get_home_dir ();
+
+  if (!home)
+    return NULL;
+
+  return gtk_file_path_new_steal (g_build_filename (home, "Desktop", NULL));
 }
 
Index: gtk/gtkfilesystemwin32.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkfilesystemwin32.c,v
retrieving revision 1.26
diff -p -u -2 -r1.26 gtkfilesystemwin32.c
--- gtk/gtkfilesystemwin32.c	2 Jan 2005 23:15:21 -0000	1.26
+++ gtk/gtkfilesystemwin32.c	5 Jan 2005 13:45:07 -0000
@@ -20,4 +20,14 @@
  */
 
+/* Define this to use the default NTFS upcase table, generated by the
+ * code in Linux's /fs/ntfs/upcase.c
+ *
+ * Is it worth it to spend 128 KB on this table, when there still is
+ * no guarantee that it will be absolutely correct all the time, as
+ * the actual casefolding behaviour of a NTFS volume is specified in a
+ * per-volume table?
+ */
+/* #define USE_UPCASE_TABLE 1 */
+
 #include <config.h>
 #include "gtkalias.h"
@@ -164,4 +174,10 @@ static gboolean       gtk_file_system_wi
 							      GError                  **error);
 static GSList *       gtk_file_system_win32_list_bookmarks   (GtkFileSystem            *file_system);
+
+static int            gtk_file_system_win32_path_compare     (GtkFileSystem            *file_system,
+							      const GtkFilePath        *path1,
+							      const GtkFilePath        *path2);
+static const GtkFilePath *gtk_file_system_win32_get_desktop  (GtkFileSystem            *file_system);
+
 static GType          gtk_file_folder_win32_get_type         (void);
 static void           gtk_file_folder_win32_class_init       (GtkFileFolderWin32Class  *class);
@@ -283,4 +299,6 @@ gtk_file_system_win32_iface_init (GtkFil
   iface->remove_bookmark = gtk_file_system_win32_remove_bookmark;
   iface->list_bookmarks = gtk_file_system_win32_list_bookmarks;
+  iface->path_compare = gtk_file_system_win32_path_compare;
+  iface->get_desktop = gtk_file_system_win32_get_desktop;
 }
 
@@ -367,10 +385,4 @@ get_special_folder (int csidl)
 }
 
-gchar *
-_gtk_file_system_win32_get_desktop (void)
-{
-  return get_special_folder (CSIDL_DESKTOPDIRECTORY);
-}
-
 static GSList *
 gtk_file_system_win32_list_volumes (GtkFileSystem *file_system)
@@ -739,5 +751,5 @@ canonicalize_filename (gchar *filename)
 #endif
 
-  past_root = g_path_skip_root (filename);
+  past_root = (gchar *) g_path_skip_root (filename);
 
   q = p = past_root;
@@ -925,4 +937,121 @@ gtk_file_system_win32_filename_to_path (
 }
 
+/* The case-insensitivity of NTFS is defined in a per-volume table,
+ * stored in a hidden file called $UpCase. The table contains 65536
+ * shorts, i.e. it maps each Unicode character in the BMP into the
+ * corresponding uppercase one. (Remember, NTFS was designed when
+ * Unicode had just the BMP.) Thus, none of the fancy casefolding
+ * cases apply, and using g_utf8_casefold() is overkill and wrong.
+ *
+ * I don't know how much the $UpCase tables differ on NTFS volumes
+ * formatted by different Windows versions, or by users in different
+ * locales. Some experimentation would be welcome.
+ */
+
+#if USE_UPCASE_TABLE
+#include "ntfs-upcase-table.h"
+#endif
+
+int
+_gtk_file_system_win32_utf8_casefolded_cmp (const gchar *a,
+					    const gchar *b)
+{
+  int retval;
+  gunichar *p1 = g_utf8_to_ucs4_fast (a, -1, NULL), *q1 = p1;
+  gunichar *p2 = g_utf8_to_ucs4_fast (b, -1, NULL), *q2 = p2;
+
+  while (*q1 && *q2)
+    {
+      gunichar c1 = *q1, c2 = *q2;
+#if USE_UPCASE_TABLE
+      if (c1 < 0x10000)
+	c1 = default_upcase_table[c1];
+      if (c2 < 0x10000)
+	c2 = default_upcase_table[c2];
+#else
+      gunichar uc1, uc2;
+      if (c1 < 0x10000 &&
+	  g_unichar_islower (c1) &&
+	  c1 == g_unichar_tolower ((uc1 = g_unichar_toupper (c1))))
+	c1 = uc1;
+      if (c2 < 0x10000 &&
+	  g_unichar_islower (c2) &&
+	  c2 == g_unichar_tolower ((uc2 = g_unichar_toupper (c2))))
+	c2 = uc2;
+#endif
+      if (c1 < c2)
+	{
+	  retval = -1;
+	  break;
+	}
+      else if (c1 > c2)
+	{
+	  retval = 1;
+	  break;
+	}
+      q1++;
+      q2++;
+    }
+
+  if (!*q1 && !*q2)
+    retval = 0;
+  else if (!*q1)
+    retval = -1;
+  else if (!*q2)
+    retval = 1;
+
+  g_free (p1);
+  g_free (p2);
+
+  return retval;
+}
+
+gunichar
+_gtk_file_system_win32_casefold (gunichar c)
+{
+#if USE_UPCASE_TABLE
+  if (c < 0x10000)
+    return default_upcase_table[c];
+  else
+    return c;
+#else
+  gunichar uc;
+  if (c < 0x10000 &&
+      g_unichar_islower (c) &&
+      c == g_unichar_tolower ((uc = g_unichar_toupper (c))))
+    return uc;
+  else
+    return c;
+#endif
+}
+
+gchar *
+_gtk_file_system_win32_utf8_casefold (const gchar *s)
+{
+  gunichar *p = g_utf8_to_ucs4_fast (s, -1, NULL), *q = p;
+  gchar *retval;
+
+  while (*q)
+    {
+#if USE_UPCASE_TABLE
+      if (*q < 0x10000)
+	*q = default_upcase_table[*q];
+#else
+      gunichar uc;
+      if (*q < 0x10000 &&
+	  g_unichar_islower (*q) &&
+	  *q == g_unichar_tolower ((uc = g_unichar_toupper (*q))))
+	*q = uc;
+#endif
+      q++;
+    }
+
+  retval = g_ucs4_to_utf8 (p, -1, NULL, NULL, NULL);
+
+  g_free (p);
+
+  return retval;
+}
+
 static gboolean
 bookmarks_serialize (GSList  **bookmarks,
@@ -954,5 +1083,6 @@ bookmarks_serialize (GSList  **bookmarks
 	      for (i = 0; lines[i] != NULL; i++)
 		{
-		  if (lines[i][0] && !g_slist_find_custom (list, lines[i], (GCompareFunc) _gtk_file_system_win32_path_compare))
+		  if (lines[i][0] &&
+		      !g_slist_find_custom (list, lines[i], (GCompareFunc) _gtk_file_system_win32_utf8_casefolded_cmp))
 		    list = g_slist_append (list, g_strdup (lines[i]));
 		}
@@ -964,5 +1094,5 @@ bookmarks_serialize (GSList  **bookmarks
       if (ok && (f = g_fopen (filename, "wb")) != NULL)
         {
-	  entry = g_slist_find_custom (list, uri, (GCompareFunc) _gtk_file_system_win32_path_compare);
+	  entry = g_slist_find_custom (list, uri, (GCompareFunc) _gtk_file_system_win32_utf8_casefolded_cmp);
 	  if (add)
 	    {
@@ -1185,5 +1315,5 @@ win32_pseudo_mime_lookup (const char* na
   GtkIconSet *is = NULL;
   char *p = strrchr(name, '.');
-  char *extension = p ? g_utf8_casefold (p, -1) : g_strdup ("");
+  char *extension = p ? g_utf8_strdown (p, -1) : g_strdup ("");
   GdkPixbuf *pixbuf;
 
@@ -1237,5 +1367,5 @@ gtk_file_system_win32_render_icon (GtkFi
 {
   GtkIconSet *icon_set = NULL;
-  const char* filename = gtk_file_path_get_string (path);
+  const char *filename = gtk_file_path_get_string (path);
 
   /* handle drives with stock icons */
@@ -1274,5 +1404,8 @@ gtk_file_system_win32_render_icon (GtkFi
       const gchar *home = g_get_home_dir ();
 
-      if (home != NULL && 0 == _gtk_file_system_win32_path_compare (home, filename))
+      if (home != NULL &&
+	  gtk_file_system_path_compare (file_system,
+					gtk_file_path_new_steal (home),
+					gtk_file_path_new_steal (filename)) == 0)
         icon_set = gtk_style_lookup_icon_set (widget->style, GTK_STOCK_HOME);
       else
@@ -1285,8 +1418,10 @@ gtk_file_system_win32_render_icon (GtkFi
 
   if (!icon_set)
-    if (g_file_test (filename, G_FILE_TEST_IS_EXECUTABLE))
+    {
+      if (g_file_test (filename, G_FILE_TEST_IS_EXECUTABLE))
 	icon_set = gtk_style_lookup_icon_set (widget->style, GTK_STOCK_EXECUTE);
-    else
-      icon_set = gtk_style_lookup_icon_set (widget->style, GTK_STOCK_FILE);
+      else
+	icon_set = gtk_style_lookup_icon_set (widget->style, GTK_STOCK_FILE);
+    }
 
   // FIXME : I'd like to get from pixel_size (=20) back to
@@ -1351,4 +1486,24 @@ gtk_file_system_win32_list_bookmarks (Gt
 }
 
+static int
+gtk_file_system_win32_path_compare (GtkFileSystem     *file_system,
+				    const GtkFilePath *path1,
+				    const GtkFilePath *path2)
+{
+  const gchar *p1 = gtk_file_path_get_string (path1);
+  const gchar *p2 = gtk_file_path_get_string (path2);
+
+  g_return_val_if_fail (g_utf8_validate (p1, -1, NULL), 0);
+  g_return_val_if_fail (g_utf8_validate (p2, -1, NULL), 0);
+
+  return _gtk_file_system_win32_utf8_casefolded_cmp (p1, p2);
+}
+
+static const GtkFilePath *
+gtk_file_system_win32_get_desktop (GtkFileSystem *file_system)
+{
+  return gtk_file_path_new_steal (get_special_folder (CSIDL_DESKTOPDIRECTORY));
+}
+
 /*
  * GtkFileFolderWin32
@@ -1684,27 +1839,6 @@ static gboolean
 filename_is_some_root (const char *filename)
 {
-#if 0
-  return ((G_IS_DIR_SEPARATOR (filename[0]) && filename[1] == '\0') ||
-	  filename_is_server_share (filename) ||
-	  filename_is_drive_root (filename));
-#else
   return (g_path_is_absolute (filename) &&
 	  *(g_path_skip_root (filename)) == '\0');
-#endif
 }    
 
-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;
-}
Index: gtk/gtkfilesystemwin32.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkfilesystemwin32.h,v
retrieving revision 1.4
diff -p -u -2 -r1.4 gtkfilesystemwin32.h
--- gtk/gtkfilesystemwin32.h	2 Jan 2005 23:15:21 -0000	1.4
+++ gtk/gtkfilesystemwin32.h	5 Jan 2005 13:45:07 -0000
@@ -35,7 +35,9 @@ typedef struct _GtkFileSystemWin32      
 GtkFileSystem *gtk_file_system_win32_new      (void);
 GType          gtk_file_system_win32_get_type (void) G_GNUC_CONST;
-     
-gchar         *_gtk_file_system_win32_get_desktop (void);
 
+int            _gtk_file_system_win32_utf8_casefolded_cmp (const gchar *a,
+							   const gchar *b);
+gunichar       _gtk_file_system_win32_casefold            (gunichar c);
+gchar         *_gtk_file_system_win32_utf8_casefold       (const gchar *s);
 G_END_DECLS
 
Index: gtk/gtkpathbar.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkpathbar.c,v
retrieving revision 1.36
diff -p -u -2 -r1.36 gtkpathbar.c
--- gtk/gtkpathbar.c	20 Nov 2004 04:52:57 -0000	1.36
+++ gtk/gtkpathbar.c	5 Jan 2005 13:45:08 -0000
@@ -1057,11 +1057,11 @@ find_button_type (GtkPathBar  *path_bar,
 {
   if (path_bar->root_path != NULL &&
-      ! gtk_file_path_compare (path, path_bar->root_path))
+      ! gtk_file_system_path_compare (path_bar->file_system, path, path_bar->root_path))
     return ROOT_BUTTON;
   if (path_bar->home_path != NULL &&
-      ! gtk_file_path_compare (path, path_bar->home_path))
+      ! gtk_file_system_path_compare (path_bar->file_system, path, path_bar->home_path))
     return HOME_BUTTON;
   if (path_bar->desktop_path != NULL &&
-      ! gtk_file_path_compare (path, path_bar->desktop_path))
+      ! gtk_file_system_path_compare (path_bar->file_system, path, path_bar->desktop_path))
     return DESKTOP_BUTTON;
 
@@ -1192,5 +1192,5 @@ gtk_path_bar_check_parent_path (GtkPathB
 
       button_data = list->data;
-      if (! gtk_file_path_compare (file_path, button_data->path))
+      if (! gtk_file_system_path_compare (path_bar->file_system, file_path, button_data->path))
 	{
 	  current_path = list;
@@ -1352,5 +1352,4 @@ _gtk_path_bar_set_file_system (GtkPathBa
 {
   const char *home;
-  char *desktop;
 
   g_return_if_fail (GTK_IS_PATH_BAR (path_bar));
@@ -1364,10 +1363,5 @@ _gtk_path_bar_set_file_system (GtkPathBa
     {
       path_bar->home_path = gtk_file_system_filename_to_path (path_bar->file_system, home);
-      /* FIXME: Need file system backend specific way of getting the
-       * Desktop path.
-       */
-      desktop = g_build_filename (home, "Desktop", NULL);
-      path_bar->desktop_path = gtk_file_system_filename_to_path (path_bar->file_system, desktop);
-      g_free (desktop);
+      path_bar->desktop_path = gtk_file_system_get_desktop (path_bar->file_system);
     }
   else
@@ -1376,4 +1370,5 @@ _gtk_path_bar_set_file_system (GtkPathBa
       path_bar->desktop_path = NULL;
     }
+  /* FIXME: Need file system backend specific way of getting the root(s) */
   path_bar->root_path = gtk_file_system_filename_to_path (path_bar->file_system, "/");
 }
