]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkfilesel.c
Move signal and property documentation inline, fix a problem with the
[~andy/gtk] / gtk / gtkfilesel.c
index 90e8e2b467d5b1ae163b09e805cb58d9d9f42a65..3bbd6d380f6a87cb48081a630954d9e4614ce1f7 100644 (file)
@@ -24,7 +24,7 @@
  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
  */
 
-#include "config.h"
+#include <config.h>
 
 #include <stdio.h>
 #include <sys/types.h>
@@ -43,6 +43,7 @@
 #endif
 
 #include <glib.h>              /* Include early to get G_OS_WIN32 etc */
+#include <glib/gstdio.h>
 
 #if defined(G_PLATFORM_WIN32)
 #include <ctype.h>
@@ -50,9 +51,6 @@
 #include <windows.h>
 #undef STRICT
 #endif /* G_PLATFORM_WIN32 */
-#ifdef G_OS_WIN32
-#include <winsock.h>           /* For gethostname */
-#endif
 
 #include "gdk/gdkkeysyms.h"
 #include "gtkbutton.h"
 #include "gtkvbox.h"
 #include "gtkmenu.h"
 #include "gtkmenuitem.h"
-#include "gtkoptionmenu.h"
 #include "gtkdialog.h"
 #include "gtkmessagedialog.h"
 #include "gtkdnd.h"
 #include "gtkeventbox.h"
 
+#undef GTK_DISABLE_DEPRECATED
+#include "gtkoptionmenu.h"
+
 #define WANT_HPANED 1
 #include "gtkhpaned.h"
 
+#include "gtkalias.h"
+
 #ifdef G_OS_WIN32
 #include <direct.h>
 #include <io.h>
-#define mkdir(p,m) _mkdir(p)
 #ifndef S_ISDIR
 #define S_ISDIR(mode) ((mode)&_S_IFDIR)
 #endif
@@ -370,7 +371,6 @@ static gint compare_cmpl_dir(const void* a, const void* b);
 static void update_cmpl(PossibleCompletion* poss,
                        CompletionState* cmpl_state);
 
-static void gtk_file_selection_class_init    (GtkFileSelectionClass *klass);
 static void gtk_file_selection_set_property  (GObject         *object,
                                              guint            prop_id,
                                              const GValue    *value,
@@ -379,7 +379,6 @@ static void gtk_file_selection_get_property  (GObject         *object,
                                              guint            prop_id,
                                              GValue          *value,
                                              GParamSpec      *pspec);
-static void gtk_file_selection_init          (GtkFileSelection      *filesel);
 static void gtk_file_selection_finalize      (GObject               *object);
 static void gtk_file_selection_destroy       (GtkObject             *object);
 static void gtk_file_selection_map           (GtkWidget             *widget);
@@ -464,8 +463,6 @@ compare_sys_filenames (const gchar *a,
 
 #endif
 
-static GtkWindowClass *parent_class = NULL;
-
 /* Saves errno when something cmpl does fails. */
 static gint cmpl_errno;
 
@@ -505,33 +502,7 @@ translate_win32_path (GtkFileSelection *filesel)
 }
 #endif
 
-GType
-gtk_file_selection_get_type (void)
-{
-  static GType file_selection_type = 0;
-
-  if (!file_selection_type)
-    {
-      static const GTypeInfo filesel_info =
-      {
-       sizeof (GtkFileSelectionClass),
-       NULL,           /* base_init */
-       NULL,           /* base_finalize */
-       (GClassInitFunc) gtk_file_selection_class_init,
-       NULL,           /* class_finalize */
-       NULL,           /* class_data */
-       sizeof (GtkFileSelection),
-       0,              /* n_preallocs */
-       (GInstanceInitFunc) gtk_file_selection_init,
-      };
-
-      file_selection_type =
-       g_type_register_static (GTK_TYPE_DIALOG, "GtkFileSelection",
-                               &filesel_info, 0);
-    }
-
-  return file_selection_type;
-}
+G_DEFINE_TYPE (GtkFileSelection, gtk_file_selection, GTK_TYPE_DIALOG)
 
 static void
 gtk_file_selection_class_init (GtkFileSelectionClass *class)
@@ -544,8 +515,6 @@ gtk_file_selection_class_init (GtkFileSelectionClass *class)
   object_class = (GtkObjectClass*) class;
   widget_class = (GtkWidgetClass*) class;
 
-  parent_class = g_type_class_peek_parent (class);
-
   gobject_class->finalize = gtk_file_selection_finalize;
   gobject_class->set_property = gtk_file_selection_set_property;
   gobject_class->get_property = gtk_file_selection_get_property;
@@ -553,26 +522,24 @@ gtk_file_selection_class_init (GtkFileSelectionClass *class)
   g_object_class_install_property (gobject_class,
                                    PROP_FILENAME,
                                    g_param_spec_string ("filename",
-                                                        _("Filename"),
-                                                        _("The currently selected filename"),
+                                                        P_("Filename"),
+                                                        P_("The currently selected filename"),
                                                         NULL,
-                                                        G_PARAM_READABLE | G_PARAM_WRITABLE));
+                                                        GTK_PARAM_READWRITE));
   g_object_class_install_property (gobject_class,
                                   PROP_SHOW_FILEOPS,
-                                  g_param_spec_boolean ("show_fileops",
-                                                        _("Show file operations"),
-                                                        _("Whether buttons for creating/manipulating files should be displayed"),
+                                  g_param_spec_boolean ("show-fileops",
+                                                        P_("Show file operations"),
+                                                        P_("Whether buttons for creating/manipulating files should be displayed"),
                                                         FALSE,
-                                                        G_PARAM_READABLE |
-                                                        G_PARAM_WRITABLE));
+                                                        GTK_PARAM_READWRITE));
   g_object_class_install_property (gobject_class,
                                   PROP_SELECT_MULTIPLE,
-                                  g_param_spec_boolean ("select_multiple",
-                                                        _("Select multiple"),
-                                                        _("Whether to allow multiple files to be selected"),
+                                  g_param_spec_boolean ("select-multiple",
+                                                        P_("Select Multiple"),
+                                                        P_("Whether to allow multiple files to be selected"),
                                                         FALSE,
-                                                        G_PARAM_READABLE |
-                                                        G_PARAM_WRITABLE));
+                                                        GTK_PARAM_READWRITE));
   object_class->destroy = gtk_file_selection_destroy;
   widget_class->map = gtk_file_selection_map;
 }
@@ -653,7 +620,6 @@ gtk_file_selection_init (GtkFileSelection *filesel)
   GtkWidget *entry_vbox;
   GtkWidget *label;
   GtkWidget *list_hbox, *list_container;
-  GtkWidget *confirm_area;
   GtkWidget *pulldown_hbox;
   GtkWidget *scrolled_win;
   GtkWidget *eventbox;
@@ -797,7 +763,6 @@ gtk_file_selection_init (GtkFileSelection *filesel)
   gtk_widget_show (filesel->action_area);
   
   /*  The OK/Cancel button area */
-  confirm_area = dialog->action_area;
 
   /*  The Cancel button  */
   filesel->cancel_button = gtk_dialog_add_button (dialog,
@@ -807,7 +772,12 @@ gtk_file_selection_init (GtkFileSelection *filesel)
   filesel->ok_button = gtk_dialog_add_button (dialog,
                                               GTK_STOCK_OK,
                                               GTK_RESPONSE_OK);
-  
+
+  gtk_dialog_set_alternative_button_order (dialog,
+                                          GTK_RESPONSE_OK,
+                                          GTK_RESPONSE_CANCEL,
+                                          -1);
+
   gtk_widget_grab_default (filesel->ok_button);
 
   /*  The selection entry widget  */
@@ -932,8 +902,7 @@ filenames_dropped (GtkWidget        *widget,
   char *uri = NULL;
   char *filename = NULL;
   char *hostname;
-  char this_hostname[257];
-  int res;
+  const char *this_hostname;
   GError *error = NULL;
        
   if (!selection_data->data)
@@ -955,11 +924,10 @@ filenames_dropped (GtkWidget        *widget,
       return;
     }
 
-  res = gethostname (this_hostname, 256);
-  this_hostname[256] = 0;
+  this_hostname = g_get_host_name ();
   
   if ((hostname == NULL) ||
-      (res == 0 && strcmp (hostname, this_hostname) == 0) ||
+      (strcmp (hostname, this_hostname) == 0) ||
       (strcmp (hostname, "localhost") == 0))
     gtk_file_selection_set_filename (GTK_FILE_SELECTION (widget),
                                     filename);
@@ -982,7 +950,7 @@ filenames_dropped (GtkWidget        *widget,
                                         "Are you sure that you want to select it?"), filename_utf8, hostname);
       g_free (filename_utf8);
 
-      g_object_set_data_full (G_OBJECT (dialog), "gtk-fs-dnd-filename", g_strdup (filename), g_free);
+      g_object_set_data_full (G_OBJECT (dialog), I_("gtk-fs-dnd-filename"), g_strdup (filename), g_free);
       
       g_signal_connect_data (dialog, "response",
                             (GCallback) dnd_really_drop, 
@@ -1015,8 +983,7 @@ filenames_drag_get (GtkWidget        *widget,
 {
   const gchar *file;
   gchar *uri_list;
-  char hostname[256];
-  int res;
+  const char *hostname;
   GError *error;
 
   file = gtk_file_selection_get_filename (filesel);
@@ -1025,10 +992,10 @@ filenames_drag_get (GtkWidget        *widget,
     {
       if (info == TARGET_URILIST)
        {
-         res = gethostname (hostname, 256);
+         hostname = g_get_host_name ();
          
          error = NULL;
-         uri_list = g_filename_to_uri (file, (!res)?hostname:NULL, &error);
+         uri_list = g_filename_to_uri (file, hostname, &error);
          if (!uri_list)
            {
              g_warning ("Error getting filename: %s\n",
@@ -1059,7 +1026,7 @@ file_selection_setup_dnd (GtkFileSelection *filesel)
   static const GtkTargetEntry drop_types[] = {
     { "text/uri-list", 0, TARGET_URILIST}
   };
-  static gint n_drop_types = sizeof(drop_types)/sizeof(drop_types[0]);
+  static const gint n_drop_types = sizeof(drop_types)/sizeof(drop_types[0]);
   static const GtkTargetEntry drag_types[] = {
     { "text/uri-list", 0, TARGET_URILIST},
     { "UTF8_STRING", 0, TARGET_UTF8_STRING },
@@ -1067,7 +1034,7 @@ file_selection_setup_dnd (GtkFileSelection *filesel)
     { "TEXT",   0, 0 }, 
     { "COMPOUND_TEXT", 0, 0 }
   };
-  static gint n_drag_types = sizeof(drag_types)/sizeof(drag_types[0]);
+  static const gint n_drag_types = sizeof(drag_types)/sizeof(drag_types[0]);
 
   gtk_drag_dest_set (GTK_WIDGET (filesel),
                     GTK_DEST_DEFAULT_ALL,
@@ -1142,7 +1109,7 @@ gtk_file_selection_show_fileop_buttons (GtkFileSelection *filesel)
   
   gtk_file_selection_update_fileops (filesel);
   
-  g_object_notify (G_OBJECT (filesel), "show_fileops");
+  g_object_notify (G_OBJECT (filesel), "show-fileops");
 }
 
 void       
@@ -1167,7 +1134,7 @@ gtk_file_selection_hide_fileop_buttons (GtkFileSelection *filesel)
       gtk_widget_destroy (filesel->fileop_c_dir);
       filesel->fileop_c_dir = NULL;
     }
-  g_object_notify (G_OBJECT (filesel), "show_fileops");
+  g_object_notify (G_OBJECT (filesel), "show-fileops");
 }
 
 
@@ -1185,7 +1152,7 @@ gtk_file_selection_hide_fileop_buttons (GtkFileSelection *filesel)
  * working directory and an empty filename, @filename must have a trailing
  * directory separator.
  *
- * The encoding of @filename is the on-disk encoding, which
+ * The encoding of @filename is preferred GLib file name encoding, which
  * may not be UTF-8. See g_filename_from_utf8().
  **/
 void
@@ -1230,11 +1197,10 @@ gtk_file_selection_set_filename (GtkFileSelection *filesel,
  * gtk_file_selection_get_filename:
  * @filesel: a #GtkFileSelection
  * 
- * This function returns the selected filename in the on-disk encoding
- * (see g_filename_from_utf8()), which may or may not be the same as that
- * used by GTK+ (UTF-8). To convert to UTF-8, call g_filename_to_utf8().
- * The returned string points to a statically allocated buffer and
- * should be copied if you plan to keep it around.
+ * This function returns the selected filename in the GLib file name
+ * encoding. To convert to UTF-8, call g_filename_to_utf8(). The
+ * returned string points to a statically allocated buffer and should
+ * be copied if you plan to keep it around.
  *
  * If no file is selected then the selected directory path is returned.
  * 
@@ -1244,7 +1210,7 @@ G_CONST_RETURN gchar*
 gtk_file_selection_get_filename (GtkFileSelection *filesel)
 {
   static const gchar nothing[2] = "";
-  static gchar something[MAXPATHLEN*2];
+  static GString *something;
   char *sys_filename;
   const char *text;
 
@@ -1261,9 +1227,13 @@ gtk_file_selection_get_filename (GtkFileSelection *filesel)
       g_free (fullname);
       if (!sys_filename)
        return nothing;
-      strncpy (something, sys_filename, sizeof (something));
+      if (!something)
+        something = g_string_new (sys_filename);
+      else
+        g_string_assign (something, sys_filename);
       g_free (sys_filename);
-      return something;
+
+      return something->str;
     }
 
   return nothing;
@@ -1330,7 +1300,7 @@ gtk_file_selection_destroy (GtkObject *object)
       filesel->last_selected = NULL;
     }
 
-  GTK_OBJECT_CLASS (parent_class)->destroy (object);
+  GTK_OBJECT_CLASS (gtk_file_selection_parent_class)->destroy (object);
 }
 
 static void
@@ -1341,7 +1311,7 @@ gtk_file_selection_map (GtkWidget *widget)
   /* Refresh the contents */
   gtk_file_selection_populate (filesel, "", FALSE, FALSE);
   
-  GTK_WIDGET_CLASS (parent_class)->map (widget);
+  GTK_WIDGET_CLASS (gtk_file_selection_parent_class)->map (widget);
 }
 
 static void
@@ -1351,7 +1321,7 @@ gtk_file_selection_finalize (GObject *object)
 
   g_free (filesel->fileop_file);
 
-  G_OBJECT_CLASS (parent_class)->finalize (object);
+  G_OBJECT_CLASS (gtk_file_selection_parent_class)->finalize (object);
 }
 
 /* Begin file operations callbacks */
@@ -1368,7 +1338,7 @@ gtk_file_selection_fileop_error (GtkFileSelection *fs,
   dialog = gtk_message_dialog_new (GTK_WINDOW (fs),
                                   GTK_DIALOG_DESTROY_WITH_PARENT,
                                   GTK_MESSAGE_ERROR,
-                                  GTK_BUTTONS_CLOSE,
+                                  GTK_BUTTONS_OK,
                                   "%s", error_message);
 
   /* yes, we free it */
@@ -1435,17 +1405,17 @@ gtk_file_selection_create_dir_confirmed (GtkWidget *widget,
       if (g_error_matches (error, G_CONVERT_ERROR, G_CONVERT_ERROR_ILLEGAL_SEQUENCE))
        buf = g_strdup_printf (_("The folder name \"%s\" contains symbols that are not allowed in filenames"), dirname);
       else
-       buf = g_strdup_printf (_("Error creating folder \"%s\": %s\n%s"), dirname, error->message,
-                              _("You probably used symbols not allowed in filenames."));
+       buf = g_strdup_printf (_("Error creating folder '%s': %s"), 
+                              dirname, error->message);
       gtk_file_selection_fileop_error (fs, buf);
       g_error_free (error);
       goto out;
     }
 
-  if (mkdir (sys_full_path, 0755) < 0) 
+  if (g_mkdir (sys_full_path, 0777) < 0)
     {
-      buf = g_strdup_printf (_("Error creating folder \"%s\": %s\n"), dirname,
-                            g_strerror (errno));
+      buf = g_strdup_printf (_("Error creating folder '%s': %s"), 
+                            dirname, g_strerror (errno));
       gtk_file_selection_fileop_error (fs, buf);
     }
 
@@ -1563,18 +1533,17 @@ gtk_file_selection_delete_file_response (GtkDialog *dialog,
        buf = g_strdup_printf (_("The filename \"%s\" contains symbols that are not allowed in filenames"),
                               fs->fileop_file);
       else
-       buf = g_strdup_printf (_("Error deleting file \"%s\": %s\n%s"),
-                              fs->fileop_file, error->message,
-                              _("It probably contains symbols not allowed in filenames."));
+       buf = g_strdup_printf (_("Error deleting file '%s': %s"),
+                              fs->fileop_file, error->message);
       
       gtk_file_selection_fileop_error (fs, buf);
       g_error_free (error);
       goto out;
     }
 
-  if (unlink (sys_full_path) < 0) 
+  if (g_unlink (sys_full_path) < 0) 
     {
-      buf = g_strdup_printf (_("Error deleting file \"%s\": %s"),
+      buf = g_strdup_printf (_("Error deleting file '%s': %s"),
                             fs->fileop_file, g_strerror (errno));
       gtk_file_selection_fileop_error (fs, buf);
     }
@@ -1617,7 +1586,7 @@ gtk_file_selection_delete_file (GtkWidget *widget,
                             GTK_WINDOW (fs)->modal ? GTK_DIALOG_MODAL : 0,
                             GTK_MESSAGE_QUESTION,
                             GTK_BUTTONS_NONE,
-                            _("Really delete file \"%s\" ?"), filename);
+                            _("Really delete file \"%s\"?"), filename);
 
   g_signal_connect (dialog, "destroy",
                    G_CALLBACK (gtk_file_selection_fileop_destroy),
@@ -1668,11 +1637,10 @@ gtk_file_selection_rename_file_confirmed (GtkWidget *widget,
   if (error)
     {
       if (g_error_matches (error, G_CONVERT_ERROR, G_CONVERT_ERROR_ILLEGAL_SEQUENCE))
-       buf = g_strdup_printf (_("The file name \"%s\" contains symbols that are not allowed in filenames"), new_filename);
+       buf = g_strdup_printf (_("The filename \"%s\" contains symbols that are not allowed in filenames"), new_filename);
       else
-       buf = g_strdup_printf (_("Error renaming file to \"%s\": %s\n%s"),
-                              new_filename, error->message,
-                              _("You probably used symbols not allowed in filenames."));
+       buf = g_strdup_printf (_("Error renaming file to \"%s\": %s"),
+                              new_filename, error->message);
       gtk_file_selection_fileop_error (fs, buf);
       g_error_free (error);
       goto out1;
@@ -1682,17 +1650,16 @@ gtk_file_selection_rename_file_confirmed (GtkWidget *widget,
   if (error)
     {
       if (g_error_matches (error, G_CONVERT_ERROR, G_CONVERT_ERROR_ILLEGAL_SEQUENCE))
-       buf = g_strdup_printf (_("The file name \"%s\" contains symbols that are not allowed in filenames"), old_filename);
+       buf = g_strdup_printf (_("The filename \"%s\" contains symbols that are not allowed in filenames"), old_filename);
       else
-       buf = g_strdup_printf (_("Error renaming file \"%s\": %s\n%s"),
-                              old_filename, error->message,
-                              _("It probably contains symbols not allowed in filenames."));
+       buf = g_strdup_printf (_("Error renaming file \"%s\": %s"),
+                              old_filename, error->message);
       gtk_file_selection_fileop_error (fs, buf);
       g_error_free (error);
       goto out2;
     }
   
-  if (rename (sys_old_filename, sys_new_filename) < 0) 
+  if (g_rename (sys_old_filename, sys_new_filename) < 0) 
     {
       buf = g_strdup_printf (_("Error renaming file \"%s\" to \"%s\": %s"),
                             sys_old_filename, sys_new_filename,
@@ -2419,8 +2386,7 @@ gtk_file_selection_file_changed (GtkTreeSelection *selection,
 
   if (index != -1)
     {
-      if (fs->last_selected != NULL)
-       g_free (fs->last_selected);
+      g_free (fs->last_selected);
 
       fs->last_selected = g_strdup (g_ptr_array_index (new_names, index));
       filename = get_real_filename (fs->last_selected, FALSE);
@@ -2447,12 +2413,10 @@ maybe_clear_entry:
  *
  * Retrieves the list of file selections the user has made in the dialog box.
  * This function is intended for use when the user can select multiple files
- * in the file list. The first file in the list is equivalent to what
- * gtk_file_selection_get_filename() would return.
+ * in the file list. 
  *
- * The filenames are in the encoding of g_filename_from_utf8(), which may or 
- * may not be the same as that used by GTK+ (UTF-8). To convert to UTF-8, call
- * g_filename_to_utf8() on each string.
+ * The filenames are in the GLib file name encoding. To convert to
+ * UTF-8, call g_filename_to_utf8() on each string.
  *
  * Return value: a newly-allocated %NULL-terminated array of strings. Use
  * g_strfreev() to free it.
@@ -2491,6 +2455,15 @@ gtk_file_selection_get_selections (GtkFileSelection *filesel)
     {
       dirname = g_path_get_dirname (filename);
 
+      if ((names->len >= 1) && 
+         (strcmp (gtk_entry_get_text (GTK_ENTRY (filesel->selection_entry)), "") == 0))
+       { /* multiple files are selected and last selection was removed via ctrl click */
+         g_free (dirname);
+         dirname = g_strdup (filename); /* as gtk_file_selection_get_filename returns dir 
+                                           if no file is selected */
+         unselected_entry = FALSE;
+       }
+
       for (i = 0; i < names->len; i++)
        {
          buf = g_filename_from_utf8 (g_ptr_array_index (names, i), -1,
@@ -2656,13 +2629,14 @@ cmpl_init_state (void)
 {
   gchar *utf8_cwd;
   CompletionState *new_state;
+  gint tries = 0;
 
   new_state = g_new (CompletionState, 1);
 
   utf8_cwd = get_current_dir_utf8 ();
 
 tryagain:
-
+  tries++;
   new_state->reference_dir = NULL;
   new_state->completion_dir = NULL;
   new_state->active_completion_dir = NULL;
@@ -2682,7 +2656,8 @@ tryagain:
     {
       /* Directories changing from underneath us, grumble */
       strcpy (utf8_cwd, G_DIR_SEPARATOR_S);
-      goto tryagain;
+      if (tries < 2)
+       goto tryagain;
     }
 
   g_free (utf8_cwd);
@@ -2725,14 +2700,10 @@ cmpl_free_state (CompletionState* cmpl_state)
   cmpl_free_dir_list (cmpl_state->directory_storage);
   cmpl_free_dir_sent_list (cmpl_state->directory_sent_storage);
 
-  if (cmpl_state->user_dir_name_buffer)
-    g_free (cmpl_state->user_dir_name_buffer);
-  if (cmpl_state->user_directories)
-    g_free (cmpl_state->user_directories);
-  if (cmpl_state->the_completion.text)
-    g_free (cmpl_state->the_completion.text);
-  if (cmpl_state->updated_text)
-    g_free (cmpl_state->updated_text);
+  g_free (cmpl_state->user_dir_name_buffer);
+  g_free (cmpl_state->user_directories);
+  g_free (cmpl_state->the_completion.text);
+  g_free (cmpl_state->updated_text);
 
   g_free (cmpl_state);
 }
@@ -3040,7 +3011,7 @@ open_user_dir (const gchar     *text_to_complete,
 
 #endif
 
-/* open a directory relative the the current relative directory */
+/* open a directory relative to the current relative directory */
 static CompletionDir*
 open_relative_dir (gchar           *dir_name,
                   CompletionDir   *dir,
@@ -3133,8 +3104,8 @@ open_new_dir (gchar       *dir_name,
          || !g_utf8_validate (sent->entries[n_entries].entry_name, -1, NULL))
        {
          gchar *escaped_str = g_strescape (dirent, NULL);
-         g_message (_("The filename \"%s\" couldn't be converted to UTF-8 "
-                      "(try setting the environment variable G_BROKEN_FILENAMES): %s"),
+         g_message (_("The filename \"%s\" couldn't be converted to UTF-8. "
+                      "(try setting the environment variable G_FILENAME_ENCODING): %s"),
                     escaped_str,
                     error->message ? error->message : _("Invalid UTF-8"));
          g_free (escaped_str);
@@ -3155,7 +3126,7 @@ open_new_dir (gchar       *dir_name,
       if (stat_subdirs)
        {
          /* Here we know path->str is a "system charset" string */
-         if (stat (path->str, &ent_sbuf) >= 0 && S_ISDIR (ent_sbuf.st_mode))
+         if (g_stat (path->str, &ent_sbuf) >= 0 && S_ISDIR (ent_sbuf.st_mode))
            sent->entries[n_entries].is_dir = TRUE;
          else
            /* stat may fail, and we don't mind, since it could be a
@@ -3191,7 +3162,7 @@ check_dir (gchar       *dir_name,
    */
 
   static struct {
-    gchar *name;
+    const gchar name[5];
     gboolean present;
     struct stat statbuf;
   } no_stat_dirs[] = {
@@ -3209,7 +3180,7 @@ check_dir (gchar       *dir_name,
       initialized = TRUE;
       for (i = 0; i < n_no_stat_dirs; i++)
        {
-         if (stat (no_stat_dirs[i].name, &no_stat_dirs[i].statbuf) == 0)
+         if (g_stat (no_stat_dirs[i].name, &no_stat_dirs[i].statbuf) == 0)
            no_stat_dirs[i].present = TRUE;
        }
     }
@@ -3221,7 +3192,7 @@ check_dir (gchar       *dir_name,
       return FALSE;
     }
   
-  if (stat (sys_dir_name, result) < 0)
+  if (g_stat (sys_dir_name, result) < 0)
     {
       g_free (sys_dir_name);
       cmpl_errno = errno;
@@ -3363,7 +3334,7 @@ correct_dir_fullname (CompletionDir* cmpl_dir)
          return FALSE;
        }
       
-      if (stat (sys_filename, &sbuf) < 0)
+      if (g_stat (sys_filename, &sbuf) < 0)
        {
          g_free (sys_filename);
          cmpl_errno = errno;
@@ -3397,7 +3368,7 @@ correct_dir_fullname (CompletionDir* cmpl_dir)
          return FALSE;
        }
       
-      if (stat (sys_filename, &sbuf) < 0)
+      if (g_stat (sys_filename, &sbuf) < 0)
        {
          g_free (sys_filename);
          cmpl_errno = errno;
@@ -3455,7 +3426,7 @@ correct_parent (CompletionDir *cmpl_dir,
       return FALSE;
     }
   
-  if (stat (sys_filename, &parbuf) < 0)
+  if (g_stat (sys_filename, &parbuf) < 0)
     {
       g_free (sys_filename);
       cmpl_errno = errno;
@@ -3546,12 +3517,11 @@ static PossibleCompletion*
 attempt_homedir_completion (gchar           *text_to_complete,
                            CompletionState *cmpl_state)
 {
-  gint index, length;
+  gint index;
 
   if (!cmpl_state->user_dir_name_buffer &&
       !get_pwdb (cmpl_state))
     return NULL;
-  length = strlen (text_to_complete) - 1;
 
   cmpl_state->user_completion_index += 1;
 
@@ -3691,7 +3661,7 @@ find_completion_dir (gchar          *text_to_complete,
       for (i = 0; i < dir->sent->entry_count; i += 1)
        {
          if (dir->sent->entries[i].is_dir &&
-             _gtk_fnmatch (pat_buf, dir->sent->entries[i].entry_name))
+             _gtk_fnmatch (pat_buf, dir->sent->entries[i].entry_name, TRUE))
            {
              if (found)
                {
@@ -3841,7 +3811,7 @@ attempt_file_completion (CompletionState *cmpl_state)
     {
       if (dir->sent->entries[dir->cmpl_index].is_dir)
        {
-         if (_gtk_fnmatch (pat_buf, dir->sent->entries[dir->cmpl_index].entry_name))
+         if (_gtk_fnmatch (pat_buf, dir->sent->entries[dir->cmpl_index].entry_name, TRUE))
            {
              CompletionDir* new_dir;
 
@@ -3889,7 +3859,7 @@ attempt_file_completion (CompletionState *cmpl_state)
       append_completion_text (dir->sent->entries[dir->cmpl_index].entry_name, cmpl_state);
 
       cmpl_state->the_completion.is_a_completion =
-       _gtk_fnmatch (pat_buf, dir->sent->entries[dir->cmpl_index].entry_name);
+       _gtk_fnmatch (pat_buf, dir->sent->entries[dir->cmpl_index].entry_name, TRUE);
 
       cmpl_state->the_completion.is_directory = dir->sent->entries[dir->cmpl_index].is_dir;
       if (dir->sent->entries[dir->cmpl_index].is_dir)
@@ -3973,10 +3943,8 @@ get_pwdb (CompletionState* cmpl_state)
 
 error:
 
-  if (cmpl_state->user_dir_name_buffer)
-    g_free (cmpl_state->user_dir_name_buffer);
-  if (cmpl_state->user_directories)
-    g_free (cmpl_state->user_directories);
+  g_free (cmpl_state->user_dir_name_buffer);
+  g_free (cmpl_state->user_directories);
 
   cmpl_state->user_dir_name_buffer = NULL;
   cmpl_state->user_directories = NULL;
@@ -4019,3 +3987,62 @@ cmpl_strerror (gint err)
   else
     return g_strerror (err);
 }
+
+#ifdef G_OS_WIN32
+
+/* DLL ABI stability backward compatibility versions */
+
+#undef gtk_file_selection_get_filename
+
+G_CONST_RETURN gchar*
+gtk_file_selection_get_filename (GtkFileSelection *filesel)
+{
+  static gchar retval[MAXPATHLEN*2+1];
+  gchar *tem;
+
+  tem = g_locale_from_utf8 (gtk_file_selection_get_filename_utf8 (filesel),
+                           -1, NULL, NULL, NULL);
+
+  strncpy (retval, tem, sizeof (retval) - 1);
+  retval[sizeof (retval) - 1] = '\0';
+  g_free (tem);
+
+  return retval;
+}
+
+#undef gtk_file_selection_set_filename
+
+void
+gtk_file_selection_set_filename (GtkFileSelection *filesel,
+                                const gchar      *filename)
+{
+  gchar *utf8_filename = g_locale_to_utf8 (filename, -1, NULL, NULL, NULL);
+  gtk_file_selection_set_filename_utf8 (filesel, utf8_filename);
+  g_free (utf8_filename);
+}
+
+#undef gtk_file_selection_get_selections
+
+gchar **
+gtk_file_selection_get_selections (GtkFileSelection *filesel)
+{
+  int i = 0;
+  gchar **selections = gtk_file_selection_get_selections_utf8 (filesel);
+
+  if (selections != NULL)
+    while (selections[i] != NULL)
+      {
+       gchar *tem = selections[i];
+       selections[i] = g_locale_from_utf8 (selections[i],
+                                           -1, NULL, NULL, NULL);
+       g_free (tem);
+       i++;
+      }
+
+  return selections;
+}
+
+#endif /* G_OS_WIN32 */
+
+#define __GTK_FILESEL_C__
+#include "gtkaliasdef.c"