Index: gtk/gtk.symbols
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtk.symbols,v
retrieving revision 1.27
diff -p -u -2 -r1.27 gtk.symbols
--- gtk/gtk.symbols	15 Dec 2004 16:27:30 -0000	1.27
+++ gtk/gtk.symbols	31 Dec 2004 01:39:06 -0000
@@ -3010,2 +3010,5 @@ 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/gtkfilesystem.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkfilesystem.h,v
retrieving revision 1.26
diff -p -u -2 -r1.26 gtkfilesystem.h
--- gtk/gtkfilesystem.h	23 Nov 2004 20:02:15 -0000	1.26
+++ gtk/gtkfilesystem.h	31 Dec 2004 01:39:06 -0000
@@ -346,6 +346,14 @@ 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/gtkfilesystemwin32.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkfilesystemwin32.c,v
retrieving revision 1.25
diff -p -u -2 -r1.25 gtkfilesystemwin32.c
--- gtk/gtkfilesystemwin32.c	12 Dec 2004 22:22:36 -0000	1.25
+++ gtk/gtkfilesystemwin32.c	31 Dec 2004 01:39:07 -0000
@@ -42,13 +42,8 @@
 #include <direct.h>
 #include <io.h>
-#include <gdk/win32/gdkwin32.h> /* gdk_win32_hdc_get */
 #else
 #error "The implementation is win32 only."
 #endif /* G_OS_WIN32 */
 
-#ifndef G_IS_DIR_SEPARATOR
-#define G_IS_DIR_SEPARATOR(c) ((c) == G_DIR_SEPARATOR || (c) == '/')
-#endif
-
 typedef struct _GtkFileSystemWin32Class GtkFileSystemWin32Class;
 
@@ -183,4 +178,5 @@ static GtkFilePath *  filename_to_path  
 
 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 GtkFileInfo *  filename_get_info                      (const gchar              *filename,
@@ -191,6 +187,6 @@ static GtkFileInfo *  filename_get_info 
 struct _GtkFileSystemVolume
 {
-  gchar    *drive;
-  gboolean  is_mounted;
+  gchar *drive;
+  int drive_type;
 };
 
@@ -341,10 +337,6 @@ gtk_file_system_win32_list_volumes (GtkF
       {
 	GtkFileSystemVolume *vol = g_new0 (GtkFileSystemVolume, 1);
-	if (drive[0] == 'A' || drive[0] == 'B')
-	  vol->is_mounted = FALSE; /* skip floppy */
-	else
-	  vol->is_mounted = TRUE; /* handle other removable drives special, too? */
-
 	vol->drive = g_strdup (drive);
+	vol->drive_type = GetDriveType (drive);
 	list = g_slist_append (list, vol);
       }
@@ -360,13 +352,48 @@ gtk_file_system_win32_get_volume_for_pat
 {
   GtkFileSystemVolume *vol = g_new0 (GtkFileSystemVolume, 1);
-  gchar* p = g_strndup (gtk_file_path_get_string (path), 3);
+  const gchar *p;
 
-  g_return_val_if_fail (p != NULL, NULL);
+  g_return_val_if_fail (path != NULL, NULL);
 
-  /*FIXME: gtk_file_path_compare() is case sensitive, we are not*/
-  p[0] = g_ascii_toupper (p[0]);
-  vol->drive = p;
-  vol->is_mounted = (p[0] != 'A' && p[0] != 'B');
+  p = gtk_file_path_get_string (path);
 
+  if (!g_path_is_absolute (p))
+    {
+      if (g_ascii_isalpha (p[0]) && p[1] == ':')
+	vol->drive = g_strdup_printf ("%c:\\", p[0]);
+      else
+	vol->drive = g_strdup ("\\");
+      vol->drive_type = GetDriveType (vol->drive);
+    }
+  else
+    {
+      const gchar *q = g_path_skip_root (p);
+      vol->drive = g_strndup (p, q - p);
+      if (!G_IS_DIR_SEPARATOR (q[-1]))
+	{
+	  /* Make sure "drive" always ends in a slash */
+	  gchar *tem = vol->drive;
+	  vol->drive = g_strconcat (vol->drive, "\\", NULL);
+	  g_free (tem);
+	}
+      
+      if (filename_is_drive_root (vol->drive))
+	{
+	  vol->drive[0] = g_ascii_toupper (vol->drive[0]);
+	  vol->drive_type = GetDriveType (vol->drive);
+	}
+      else if (G_WIN32_HAVE_WIDECHAR_API ())
+	{
+	  wchar_t *wdrive = g_utf8_to_utf16 (vol->drive, -1, NULL, NULL, NULL);
+	  vol->drive_type = GetDriveTypeW (wdrive);
+	  g_free (wdrive);
+	}
+      else
+	{
+	  gchar *cpdrive = g_locale_from_utf8 (vol->drive, -1, NULL, NULL, NULL);
+	  vol->drive_type = GetDriveTypeA (cpdrive);
+	  g_free (cpdrive);
+	}
+    }
   return vol;
 }
@@ -392,28 +419,27 @@ gtk_file_system_win32_get_folder (GtkFil
     return g_object_ref (folder_win32);
 
-  if (!g_file_test (filename, G_FILE_TEST_IS_DIR))
+  if (!g_file_test (filename, G_FILE_TEST_EXISTS))
     {
       int save_errno = errno;
       gchar *display_filename = g_filename_display_name (filename);
+      g_set_error (error,
+		   GTK_FILE_SYSTEM_ERROR,
+		   GTK_FILE_SYSTEM_ERROR_NONEXISTENT,
+		   _("Error getting information for '%s': %s"),
+		   display_filename,
+		   g_strerror (save_errno));
+      g_free (display_filename);
+      return NULL;
+    }
+  if (!g_file_test (filename, G_FILE_TEST_IS_DIR))
+    {
+      gchar *display_filename = g_filename_display_name (filename);
 
-      /* If g_file_test() returned FALSE but not due to an error, it means
-       * that the filename is not a directory.
-       */
-      if (save_errno == 0)
-	/* ENOTDIR */
-	g_set_error (error,
-		     GTK_FILE_SYSTEM_ERROR,
-		     GTK_FILE_SYSTEM_ERROR_NOT_FOLDER,
-		     _("%s: %s"),
-		     display_filename,
-		     g_strerror (ENOTDIR));
-      else
-	g_set_error (error,
-		     GTK_FILE_SYSTEM_ERROR,
-		     GTK_FILE_SYSTEM_ERROR_NONEXISTENT,
-		     _("error getting information for '%s': %s"),
-		     display_filename,
-		     g_strerror (save_errno));
-
+      g_set_error (error,
+		   GTK_FILE_SYSTEM_ERROR,
+		   GTK_FILE_SYSTEM_ERROR_NOT_FOLDER,
+		   _("Error getting information for '%s': %s"),
+		   display_filename,
+		   g_strerror (ENOTDIR));
       g_free (display_filename);
       return NULL;
@@ -444,4 +470,5 @@ gtk_file_system_win32_create_folder (Gtk
   filename = filename_from_path (path);
   g_return_val_if_fail (filename != NULL, FALSE);
+  g_return_val_if_fail (g_path_is_absolute (filename), FALSE);
 
   result = g_mkdir (filename, 0777) == 0;
@@ -449,14 +476,15 @@ gtk_file_system_win32_create_folder (Gtk
   if (!result)
     {
+      int save_errno = errno;
       gchar *display_filename = g_filename_display_name (filename);
       g_set_error (error,
 		   GTK_FILE_SYSTEM_ERROR,
 		   GTK_FILE_SYSTEM_ERROR_NONEXISTENT,
-		   _("error creating directory '%s': %s"),
+		   _("Error creating directory '%s': %s"),
 		   display_filename,
-		   g_strerror (errno));
+		   g_strerror (save_errno));
       g_free (display_filename);
     }
-  else if (!filename_is_drive_root (filename))
+  else if (!filename_is_some_root (filename))
     {
       parent = g_path_get_dirname (filename);
@@ -502,5 +530,5 @@ gtk_file_system_win32_volume_get_is_moun
 					     GtkFileSystemVolume  *volume)
 {
-  return volume->is_mounted;
+  return TRUE;
 }
 
@@ -522,26 +550,31 @@ gtk_file_system_win32_volume_get_display
 {
   gchar *real_display_name;
-  gunichar2 *wdrive = g_utf8_to_utf16 (volume->drive, -1, NULL, NULL, NULL);
-  gunichar2  wname[80];
 
-  g_return_val_if_fail (wdrive != NULL, NULL);
+  g_return_val_if_fail (volume->drive != NULL, NULL);
 
-  if (GetVolumeInformationW (wdrive,
-			     wname, G_N_ELEMENTS(wname), 
-			     NULL, /* serial number */
-			     NULL, /* max. component length */
-			     NULL, /* fs flags */
-			     NULL, 0) /* fs type like FAT, NTFS */
-      && wname[0])
-    {
-      gchar *name = g_utf16_to_utf8 (wname, -1, NULL, NULL, NULL);
-      real_display_name = g_strconcat (name, " (", volume->drive, ")", NULL);
-      g_free (name);
+  if ((filename_is_drive_root (volume->drive) && volume->drive[0] >= 'C') ||
+      volume->drive_type != DRIVE_REMOVABLE)
+    {
+      gunichar2 *wdrive = g_utf8_to_utf16 (volume->drive, -1, NULL, NULL, NULL);
+      gunichar2 wname[80];
+      if (GetVolumeInformationW (wdrive,
+				 wname, G_N_ELEMENTS(wname), 
+				 NULL, /* serial number */
+				 NULL, /* max. component length */
+				 NULL, /* fs flags */
+				 NULL, 0) /* fs type like FAT, NTFS */ &&
+	  wname[0])
+	{
+	  gchar *name = g_utf16_to_utf8 (wname, -1, NULL, NULL, NULL);
+	  real_display_name = g_strconcat (name, " (", volume->drive, ")", NULL);
+	  g_free (name);
+	}
+      else
+	real_display_name = g_strdup (volume->drive);
+      g_free (wdrive);
     }
   else
     real_display_name = g_strdup (volume->drive);
 
-  g_free (wdrive);
-
   return real_display_name;
 }
@@ -555,26 +588,29 @@ gtk_file_system_win32_volume_render_icon
 {
   GtkIconSet *icon_set = NULL;
-  DWORD dt = GetDriveType (volume->drive);
 
-  switch (dt)
+  switch (volume->drive_type)
     {
-    case DRIVE_REMOVABLE :
+    case DRIVE_REMOVABLE:
       icon_set = gtk_style_lookup_icon_set (widget->style, GTK_STOCK_FLOPPY);
       break;
-    case DRIVE_CDROM :
+    case DRIVE_CDROM:
       icon_set = gtk_style_lookup_icon_set (widget->style, GTK_STOCK_CDROM);
       break;
-    case DRIVE_REMOTE :
+    case DRIVE_REMOTE:
       icon_set = gtk_style_lookup_icon_set (widget->style, GTK_STOCK_NETWORK);
       break;
-    case DRIVE_FIXED :
+    case DRIVE_FIXED:
       icon_set = gtk_style_lookup_icon_set (widget->style, GTK_STOCK_HARDDISK);
       break;
-    case DRIVE_RAMDISK :
-      /*FIXME: need a ram stock icon
-      gtk_file_info_set_icon_type (info, GTK_STOCK_OPEN);*/
+    case DRIVE_RAMDISK:
+#if 0
+      /*FIXME: need a ram stock icon?? */
+      gtk_file_info_set_icon_type (info, GTK_STOCK_RAMDISK);
       break;
+#endif
     default :
-      g_assert_not_reached ();
+      /* Use network icon as a guess */ 
+      icon_set = gtk_style_lookup_icon_set (widget->style, GTK_STOCK_NETWORK);
+      break;
     }
 
@@ -878,5 +914,5 @@ bookmarks_serialize (GSList  **bookmarks
 	      for (i = 0; lines[i] != NULL; i++)
 		{
-		  if (lines[i][0] && !g_slist_find_custom (list, lines[i], (GCompareFunc) strcmp))
+		  if (lines[i][0] && !g_slist_find_custom (list, lines[i], (GCompareFunc) _gtk_file_system_win32_path_compare))
 		    list = g_slist_append (list, g_strdup (lines[i]));
 		}
@@ -888,5 +924,5 @@ bookmarks_serialize (GSList  **bookmarks
       if (ok && (f = g_fopen (filename, "wb")) != NULL)
         {
-	  entry = g_slist_find_custom (list, uri, (GCompareFunc) strcmp);
+	  entry = g_slist_find_custom (list, uri, (GCompareFunc) _gtk_file_system_win32_path_compare);
 	  if (add)
 	    {
@@ -903,5 +939,5 @@ bookmarks_serialize (GSList  **bookmarks
 			       GTK_FILE_SYSTEM_ERROR,
 			       GTK_FILE_SYSTEM_ERROR_ALREADY_EXISTS,
-			       "%s already exists in the bookmarks list",
+			       "'%s' already exists in the bookmarks list",
 			       uri);
 		  ok = FALSE;
@@ -926,5 +962,5 @@ bookmarks_serialize (GSList  **bookmarks
 		       GTK_FILE_SYSTEM_ERROR,
 		       GTK_FILE_SYSTEM_ERROR_FAILED,
-		       _("Bookmark saving failed (%s)"),
+		       _("Bookmark saving failed: %s"),
 		       g_strerror (errno));
 	}
@@ -1099,4 +1135,7 @@ gtk_file_system_win32_render_icon (GtkFi
           icon_set = gtk_style_lookup_icon_set (widget->style, GTK_STOCK_CDROM);
           break;
+	case DRIVE_REMOTE :
+	  icon_set = gtk_style_lookup_icon_set (widget->style, GTK_STOCK_NETWORK);
+	  break;
         case DRIVE_FIXED :
           icon_set = gtk_style_lookup_icon_set (widget->style, GTK_STOCK_HARDDISK);
@@ -1106,8 +1145,13 @@ gtk_file_system_win32_render_icon (GtkFi
         }
     }
+  else if (filename_is_server_share (filename))
+    {
+      icon_set = gtk_style_lookup_icon_set (widget->style, GTK_STOCK_NETWORK);
+    }
   else if (g_file_test (filename, G_FILE_TEST_IS_DIR))
     {
       const gchar *home = g_get_home_dir ();
-      if (home != NULL && 0 == strcmp (home, filename))
+
+      if (home != NULL && 0 == _gtk_file_system_win32_path_compare (home, filename))
         icon_set = gtk_style_lookup_icon_set (widget->style, GTK_STOCK_HOME);
       else
@@ -1349,5 +1393,5 @@ filename_get_info (const gchar     *file
 {
   GtkFileInfo *info;
-#if 0 /* it's dead in GtkFileSystemUnix.c, too */
+#if 0 /* it's dead in gtkfilesystemunix.c, too */
   GtkFileIconType icon_type = GTK_FILE_ICON_REGULAR;
 #endif
@@ -1382,5 +1426,5 @@ filename_get_info (const gchar     *file
 		   GTK_FILE_SYSTEM_ERROR,
 		   GTK_FILE_SYSTEM_ERROR_NONEXISTENT,
-		   _("error getting information for '%s': %s"),
+		   _("Error getting information for '%s': %s"),
 		   display_filename,
 		   g_win32_error_message (GetLastError ()));
@@ -1428,5 +1472,5 @@ filename_get_info (const gchar     *file
    }
 
-#if 0 /* it's dead in GtkFileSystemUnix.c, too */
+#if 0 /* it's dead in gtkfilesystemunix.c, too */
   if (types & GTK_FILE_INFO_ICON)
     {
@@ -1439,5 +1483,5 @@ filename_get_info (const gchar     *file
 
   if ((types & GTK_FILE_INFO_MIME_TYPE)
-#if 0 /* it's dead in GtkFileSystemUnix.c, too */
+#if 0 /* it's dead in gtkfilesystemunix.c, too */
       || ((types & GTK_FILE_INFO_ICON) && icon_type == GTK_FILE_ICON_REGULAR)
 #endif
@@ -1493,5 +1537,44 @@ filename_is_drive_root (const char *file
   guint len = strlen (filename);
 
-  return (len == 3 && filename[1] == ':' && G_IS_DIR_SEPARATOR (filename[2]));
+  return (len == 3 &&
+	  g_ascii_isalpha (filename[0]) &&
+	  filename[1] == ':' &&
+	  G_IS_DIR_SEPARATOR (filename[2]));
+}
+
+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;
 }
 
@@ -1499,5 +1582,27 @@ static gboolean
 filename_is_some_root (const char *filename)
 {
-  return (G_IS_DIR_SEPARATOR (filename[0]) && filename[1] == '\0') ||
-         filename_is_drive_root (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;
+}
