#include <pwd.h>
#endif
-#include <glib.h> /* Include early to get G_OS_WIN32 and
- * G_WITH_CYGWIN */
+#include <glib.h> /* Include early to get G_OS_WIN32 etc */
-#if defined(G_OS_WIN32) || defined(G_WITH_CYGWIN)
+#if defined(G_PLATFORM_WIN32)
#include <ctype.h>
#define STRICT
#include <windows.h>
#undef STRICT
-#endif /* G_OS_WIN32 || G_WITH_CYGWIN */
-#ifdef HAVE_WINSOCK_H
+#endif /* G_PLATFORM_WIN32 */
+#ifdef G_OS_WIN32
#include <winsock.h> /* For gethostname */
#endif
-#include "fnmatch.h"
-
#include "gdk/gdkkeysyms.h"
#include "gtkbutton.h"
#include "gtkcellrenderertext.h"
#include "gtkfilesel.h"
#include "gtkhbox.h"
#include "gtkhbbox.h"
+#include "gtkintl.h"
#include "gtklabel.h"
#include "gtkliststore.h"
#include "gtkmain.h"
+#include "gtkprivate.h"
#include "gtkscrolledwindow.h"
#include "gtkstock.h"
-#include "gtksignal.h"
#include "gtktreeselection.h"
#include "gtktreeview.h"
#include "gtkvbox.h"
#include "gtkoptionmenu.h"
#include "gtkdialog.h"
#include "gtkmessagedialog.h"
-#include "gtkintl.h"
#include "gtkdnd.h"
#include "gtkeventbox.h"
#endif
#endif /* G_OS_WIN32 */
+#ifdef G_WITH_CYGWIN
+#include <sys/cygwin.h> /* For cygwin_conv_to_posix_path */
+#endif
+
#define DIR_LIST_WIDTH 180
#define DIR_LIST_HEIGHT 180
#define FILE_LIST_WIDTH 180
* match by first_diff_index()
*/
#define PATTERN_MATCH -1
-/* The arguments used by all fnmatch() calls below
- */
-#define FNMATCH_FLAGS (FNM_PATHNAME | FNM_PERIOD)
-
#define CMPL_ERRNO_TOO_LONG ((1<<16)-1)
#define CMPL_ERRNO_DID_NOT_CONVERT ((1<<16)-2)
*/
struct _CompletionDirSent
{
+#ifndef G_PLATFORM_WIN32
ino_t inode;
time_t mtime;
dev_t device;
+#endif
gint entry_count;
struct _CompletionDirEntry *entries;
{
gboolean is_dir;
gchar *entry_name;
+ gchar *sort_key;
};
struct _CompletionUserDir
/* When the user selects a non-directory, call cmpl_completion_fullname
* to get the full name of the selected file.
*/
-static gchar* cmpl_completion_fullname (const gchar*, CompletionState* cmpl_state);
+static const gchar* cmpl_completion_fullname (const gchar*, CompletionState* cmpl_state);
/* Directory operations. */
static CompletionDir* open_ref_dir (gchar* text_to_complete,
gchar** remaining_text,
CompletionState* cmpl_state);
-#if !defined(G_OS_WIN32) && !defined(G_WITH_CYGWIN)
+#ifndef G_PLATFORM_WIN32
static gboolean check_dir (gchar *dir_name,
struct stat *result,
gboolean *stat_subdirs);
static gint correct_dir_fullname (CompletionDir* cmpl_dir);
static gint correct_parent (CompletionDir* cmpl_dir,
struct stat *sbuf);
-#ifndef G_OS_WIN32
+#ifndef G_PLATFORM_WIN32
static gchar* find_parent_dir_fullname (gchar* dirname);
#endif
static CompletionDir* attach_dir (CompletionDirSent* sent,
gint new_text_length,
gint *position,
gpointer user_data);
+static void gtk_file_selection_update_fileops (GtkFileSelection *filesel);
static void gtk_file_selection_file_activate (GtkTreeView *tree_view,
GtkTreePath *path,
static void free_selected_names (GPtrArray *names);
-#if !defined(G_OS_WIN32) && !defined(G_WITH_CYGWIN)
-#define compare_filenames(a, b) strcmp(a, b)
+#ifndef G_PLATFORM_WIN32
+
+#define compare_utf8_filenames(a, b) strcmp(a, b)
+#define compare_sys_filenames(a, b) strcmp(a, b)
+
#else
-#define compare_filenames(a, b) g_ascii_strcasecmp(a, b)
-#endif
+static gint
+compare_utf8_filenames (const gchar *a,
+ const gchar *b)
+{
+ gchar *a_folded, *b_folded;
+ gint retval;
+
+ a_folded = g_utf8_strdown (a, -1);
+ b_folded = g_utf8_strdown (b, -1);
+
+ retval = strcmp (a_folded, b_folded);
+
+ g_free (a_folded);
+ g_free (b_folded);
+
+ return retval;
+}
+
+static gint
+compare_sys_filenames (const gchar *a,
+ const gchar *b)
+{
+ gchar *a_utf8, *b_utf8;
+ gint retval;
+
+ a_utf8 = g_filename_to_utf8 (a, -1, NULL, NULL, NULL);
+ b_utf8 = g_filename_to_utf8 (b, -1, NULL, NULL, NULL);
+
+ retval = compare_utf8_filenames (a_utf8, b_utf8);
+
+ g_free (a_utf8);
+ g_free (b_utf8);
+
+ return retval;
+}
+
+#endif
static GtkWindowClass *parent_class = NULL;
/*
* Take the path currently in the file selection
* entry field and translate as necessary from
- * a WIN32 style to CYGWIN32 style path. For
+ * a Win32 style to Cygwin style path. For
* instance translate:
* x:\somepath\file.jpg
* to:
- * //x/somepath/file.jpg
+ * /cygdrive/x/somepath/file.jpg
*
* Replace the path in the selection text field.
* Return a boolean value concerning whether a
translate_win32_path (GtkFileSelection *filesel)
{
int updated = 0;
- gchar *path;
+ const gchar *path;
+ gchar newPath[MAX_PATH];
/*
* Retrieve the current path
*/
path = gtk_entry_get_text (GTK_ENTRY (filesel->selection_entry));
- /*
- * Translate only if this looks like a DOS-ish
- * path... First handle any drive letters.
- */
- if (isalpha (path[0]) && (path[1] == ':')) {
- /*
- * This part kind of stinks... It isn't possible
- * to know if there is enough space in the current
- * string for the extra character required in this
- * conversion. Assume that there isn't enough space
- * and use the set function on the text field to
- * set the newly created string.
- */
- gchar *newPath = g_strdup_printf ("//%c/%s", path[0], (path + 3));
- gtk_entry_set_text (GTK_ENTRY (filesel->selection_entry), newPath);
-
- path = newPath;
- updated = 1;
- }
+ cygwin_conv_to_posix_path (path, newPath);
+ updated = (strcmp (path, newPath) != 0);
- /*
- * Now, replace backslashes with forward slashes
- * if necessary.
- */
- if (strchr (path, '\\'))
- {
- int index;
- for (index = 0; path[index] != '\0'; index++)
- if (path[index] == '\\')
- path[index] = '/';
-
- updated = 1;
- }
+ if (updated)
+ gtk_entry_set_text (GTK_ENTRY (filesel->selection_entry), newPath);
return updated;
}
#endif
-GtkType
+GType
gtk_file_selection_get_type (void)
{
- static GtkType file_selection_type = 0;
+ static GType file_selection_type = 0;
if (!file_selection_type)
{
- static const GtkTypeInfo filesel_info =
+ static const GTypeInfo filesel_info =
{
- "GtkFileSelection",
- sizeof (GtkFileSelection),
sizeof (GtkFileSelectionClass),
- (GtkClassInitFunc) gtk_file_selection_class_init,
- (GtkObjectInitFunc) gtk_file_selection_init,
- /* reserved_1 */ NULL,
- /* reserved_2 */ NULL,
- (GtkClassInitFunc) NULL,
+ 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 = gtk_type_unique (GTK_TYPE_DIALOG, &filesel_info);
+ file_selection_type =
+ g_type_register_static (GTK_TYPE_DIALOG, "GtkFileSelection",
+ &filesel_info, 0);
}
return file_selection_type;
object_class = (GtkObjectClass*) class;
widget_class = (GtkWidgetClass*) class;
- parent_class = gtk_type_class (GTK_TYPE_DIALOG);
+ parent_class = g_type_class_peek_parent (class);
gobject_class->finalize = gtk_file_selection_finalize;
gobject_class->set_property = gtk_file_selection_set_property;
PROP_FILENAME,
g_param_spec_string ("filename",
_("Filename"),
- _("The currently selected filename."),
+ _("The currently selected filename"),
NULL,
G_PARAM_READABLE | G_PARAM_WRITABLE));
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."),
+ _("Whether buttons for creating/manipulating files should be displayed"),
FALSE,
G_PARAM_READABLE |
G_PARAM_WRITABLE));
PROP_SELECT_MULTIPLE,
g_param_spec_boolean ("select_multiple",
_("Select multiple"),
- _("Whether to allow multiple files to be selected."),
+ _("Whether to allow multiple files to be selected"),
FALSE,
G_PARAM_READABLE |
G_PARAM_WRITABLE));
gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
gtk_tree_view_append_column (GTK_TREE_VIEW (filesel->dir_list), column);
- gtk_widget_set_usize (filesel->dir_list, DIR_LIST_WIDTH, DIR_LIST_HEIGHT);
+ gtk_widget_set_size_request (filesel->dir_list,
+ DIR_LIST_WIDTH, DIR_LIST_HEIGHT);
g_signal_connect (filesel->dir_list, "row_activated",
G_CALLBACK (gtk_file_selection_dir_activate), filesel);
gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
gtk_tree_view_append_column (GTK_TREE_VIEW (filesel->file_list), column);
- gtk_widget_set_usize (filesel->file_list, FILE_LIST_WIDTH, FILE_LIST_HEIGHT);
+ gtk_widget_set_size_request (filesel->file_list,
+ FILE_LIST_WIDTH, FILE_LIST_HEIGHT);
g_signal_connect (filesel->file_list, "row_activated",
G_CALLBACK (gtk_file_selection_file_activate), filesel);
g_signal_connect (gtk_tree_view_get_selection (GTK_TREE_VIEW (filesel->file_list)), "changed",
gtk_widget_show (eventbox);
filesel->selection_entry = gtk_entry_new ();
- gtk_signal_connect (GTK_OBJECT (filesel->selection_entry), "key_press_event",
- (GtkSignalFunc) gtk_file_selection_key_press, filesel);
- gtk_signal_connect (GTK_OBJECT (filesel->selection_entry), "insert_text",
- (GtkSignalFunc) gtk_file_selection_insert_text, NULL);
- gtk_signal_connect_object (GTK_OBJECT (filesel->selection_entry), "focus_in_event",
- (GtkSignalFunc) grab_default,
- GTK_OBJECT (filesel->ok_button));
- gtk_signal_connect_object (GTK_OBJECT (filesel->selection_entry), "activate",
- (GtkSignalFunc) gtk_button_clicked,
- GTK_OBJECT (filesel->ok_button));
+ g_signal_connect (filesel->selection_entry, "key_press_event",
+ G_CALLBACK (gtk_file_selection_key_press), filesel);
+ g_signal_connect (filesel->selection_entry, "insert_text",
+ G_CALLBACK (gtk_file_selection_insert_text), NULL);
+ g_signal_connect_swapped (filesel->selection_entry, "changed",
+ G_CALLBACK (gtk_file_selection_update_fileops), filesel);
+ g_signal_connect_swapped (filesel->selection_entry, "focus_in_event",
+ G_CALLBACK (grab_default),
+ filesel->ok_button);
+ g_signal_connect_swapped (filesel->selection_entry, "activate",
+ G_CALLBACK (gtk_button_clicked),
+ filesel->ok_button);
+
gtk_box_pack_start (GTK_BOX (entry_vbox), filesel->selection_entry, TRUE, TRUE, 0);
gtk_widget_show (filesel->selection_entry);
+ gtk_label_set_mnemonic_widget (GTK_LABEL (filesel->selection_text),
+ filesel->selection_entry);
+
if (!cmpl_state_okay (filesel->cmpl_state))
{
gchar err_buf[256];
- sprintf (err_buf, _("Folder unreadable: %s"), cmpl_strerror (cmpl_errno));
+ g_snprintf (err_buf, sizeof (err_buf), _("Folder unreadable: %s"), cmpl_strerror (cmpl_errno));
gtk_label_set_text (GTK_LABEL (filesel->selection_text), err_buf);
}
else
{
GtkWidget *dialog;
+ gchar *filename_utf8;
+
+ /* Conversion back to UTF-8 should always succeed for the result
+ * of g_filename_from_uri()
+ */
+ filename_utf8 = g_filename_to_utf8 (filename, -1, NULL, NULL, NULL);
+ g_assert (filename_utf8);
dialog = gtk_message_dialog_new (GTK_WINDOW (widget),
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_QUESTION,
GTK_BUTTONS_YES_NO,
_("The file \"%s\" resides on another machine (called %s) and may not be available to this program.\n"
- "Are you sure that you want to select it?"), filename, hostname);
+ "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);
}
else
{
- g_print ("Setting text: '%s'\n", file);
- gtk_selection_data_set_text (selection_data, file, -1);
+ gchar *filename_utf8 = g_filename_to_utf8 (file, -1, NULL, NULL, NULL);
+ g_assert (filename_utf8);
+ gtk_selection_data_set_text (selection_data, filename_utf8, -1);
+ g_free (filename_utf8);
}
}
}
file_selection_setup_dnd (GtkFileSelection *filesel)
{
GtkWidget *eventbox;
- static GtkTargetEntry drop_types[] = {
+ static const GtkTargetEntry drop_types[] = {
{ "text/uri-list", 0, TARGET_URILIST}
};
static gint n_drop_types = sizeof(drop_types)/sizeof(drop_types[0]);
- static GtkTargetEntry drag_types[] = {
+ static const GtkTargetEntry drag_types[] = {
{ "text/uri-list", 0, TARGET_URILIST},
{ "UTF8_STRING", 0, TARGET_UTF8_STRING },
{ "STRING", 0, 0 },
drop_types, n_drop_types,
GDK_ACTION_COPY);
- gtk_signal_connect (GTK_OBJECT(filesel), "drag_data_received",
- GTK_SIGNAL_FUNC(filenames_dropped), NULL);
+ g_signal_connect (filesel, "drag_data_received",
+ G_CALLBACK (filenames_dropped), NULL);
eventbox = gtk_widget_get_parent (filesel->selection_text);
gtk_drag_source_set (eventbox,
drag_types, n_drag_types,
GDK_ACTION_COPY);
- gtk_signal_connect (GTK_OBJECT (eventbox),
- "drag_data_get",
- GTK_SIGNAL_FUNC (filenames_drag_get),
- filesel);
+ g_signal_connect (eventbox, "drag_data_get",
+ G_CALLBACK (filenames_drag_get), filesel);
}
GtkWidget*
{
GtkFileSelection *filesel;
- filesel = gtk_type_new (GTK_TYPE_FILE_SELECTION);
+ filesel = g_object_new (GTK_TYPE_FILE_SELECTION, NULL);
gtk_window_set_title (GTK_WINDOW (filesel), title);
gtk_dialog_set_has_separator (GTK_DIALOG (filesel), FALSE);
if (!filesel->fileop_c_dir)
{
filesel->fileop_c_dir = gtk_button_new_with_mnemonic (_("_New Folder"));
- gtk_signal_connect (GTK_OBJECT (filesel->fileop_c_dir), "clicked",
- (GtkSignalFunc) gtk_file_selection_create_dir,
- (gpointer) filesel);
+ g_signal_connect (filesel->fileop_c_dir, "clicked",
+ G_CALLBACK (gtk_file_selection_create_dir),
+ filesel);
gtk_box_pack_start (GTK_BOX (filesel->button_area),
filesel->fileop_c_dir, TRUE, TRUE, 0);
gtk_widget_show (filesel->fileop_c_dir);
if (!filesel->fileop_del_file)
{
filesel->fileop_del_file = gtk_button_new_with_mnemonic (_("De_lete File"));
- gtk_signal_connect (GTK_OBJECT (filesel->fileop_del_file), "clicked",
- (GtkSignalFunc) gtk_file_selection_delete_file,
- (gpointer) filesel);
+ g_signal_connect (filesel->fileop_del_file, "clicked",
+ G_CALLBACK (gtk_file_selection_delete_file),
+ filesel);
gtk_box_pack_start (GTK_BOX (filesel->button_area),
filesel->fileop_del_file, TRUE, TRUE, 0);
gtk_widget_show (filesel->fileop_del_file);
if (!filesel->fileop_ren_file)
{
filesel->fileop_ren_file = gtk_button_new_with_mnemonic (_("_Rename File"));
- gtk_signal_connect (GTK_OBJECT (filesel->fileop_ren_file), "clicked",
- (GtkSignalFunc) gtk_file_selection_rename_file,
- (gpointer) filesel);
+ g_signal_connect (filesel->fileop_ren_file, "clicked",
+ G_CALLBACK (gtk_file_selection_rename_file),
+ filesel);
gtk_box_pack_start (GTK_BOX (filesel->button_area),
filesel->fileop_ren_file, TRUE, TRUE, 0);
gtk_widget_show (filesel->fileop_ren_file);
}
+
+ gtk_file_selection_update_fileops (filesel);
+
g_object_notify (G_OBJECT (filesel), "show_fileops");
- gtk_widget_queue_resize (GTK_WIDGET (filesel));
}
void
+/**
+ * gtk_file_selection_set_filename:
+ * @filesel: a #GtkFileSelection.
+ * @filename: a string to set as the default file name.
+ *
+ * Sets a default path for the file requestor. If @filename includes a
+ * directory path, then the requestor will open with that path as its
+ * current working directory.
+ *
+ * This has the consequence that in order to open the requestor with a
+ * working directory and an empty filename, @filename must have a trailing
+ * directory separator.
+ *
+ * The encoding of @filename is the on-disk encoding, which
+ * may not be UTF-8. See g_filename_from_utf8().
+ **/
void
gtk_file_selection_set_filename (GtkFileSelection *filesel,
const gchar *filename)
{
gchar *buf;
const char *name, *last_slash;
+ char *filename_utf8;
g_return_if_fail (GTK_IS_FILE_SELECTION (filesel));
g_return_if_fail (filename != NULL);
- last_slash = strrchr (filename, G_DIR_SEPARATOR);
+ filename_utf8 = g_filename_to_utf8 (filename, -1, NULL, NULL, NULL);
+ g_return_if_fail (filename_utf8 != NULL);
+
+ last_slash = strrchr (filename_utf8, G_DIR_SEPARATOR);
if (!last_slash)
{
buf = g_strdup ("");
- name = filename;
+ name = filename_utf8;
}
else
{
- buf = g_strdup (filename);
- buf[last_slash - filename + 1] = 0;
+ buf = g_strdup (filename_utf8);
+ buf[last_slash - filename_utf8 + 1] = 0;
name = last_slash + 1;
}
gtk_entry_set_text (GTK_ENTRY (filesel->selection_entry), name);
g_free (buf);
g_object_notify (G_OBJECT (filesel), "filename");
+
+ g_free (filename_utf8);
}
/**
* @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
+ * (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.
G_CONST_RETURN gchar*
gtk_file_selection_get_filename (GtkFileSelection *filesel)
{
- static gchar nothing[2] = "";
+ static const gchar nothing[2] = "";
static gchar something[MAXPATHLEN*2];
char *sys_filename;
const char *text;
gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
- gtk_signal_connect_object (GTK_OBJECT (dialog), "response",
- (GtkSignalFunc) gtk_widget_destroy,
- (gpointer) dialog);
+ g_signal_connect_swapped (dialog, "response",
+ G_CALLBACK (gtk_widget_destroy),
+ dialog);
gtk_widget_show (dialog);
}
fs->fileop_dialog = NULL;
}
+static gboolean
+entry_is_empty (GtkEntry *entry)
+{
+ const gchar *text = gtk_entry_get_text (entry);
+
+ return *text == '\0';
+}
+
+static void
+gtk_file_selection_fileop_entry_changed (GtkEntry *entry,
+ GtkWidget *button)
+{
+ gtk_widget_set_sensitive (button, !entry_is_empty (entry));
+}
static void
gtk_file_selection_create_dir_confirmed (GtkWidget *widget,
/* main dialog */
dialog = gtk_dialog_new ();
fs->fileop_dialog = dialog;
- gtk_signal_connect (GTK_OBJECT (dialog), "destroy",
- (GtkSignalFunc) gtk_file_selection_fileop_destroy,
- (gpointer) fs);
+ g_signal_connect (dialog, "destroy",
+ G_CALLBACK (gtk_file_selection_fileop_destroy),
+ fs);
gtk_window_set_title (GTK_WINDOW (dialog), _("New Folder"));
gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (fs));
gtk_box_pack_start (GTK_BOX (vbox), fs->fileop_entry,
TRUE, TRUE, 5);
GTK_WIDGET_SET_FLAGS (fs->fileop_entry, GTK_CAN_DEFAULT);
+ gtk_entry_set_activates_default (GTK_ENTRY (fs->fileop_entry), TRUE);
gtk_widget_show (fs->fileop_entry);
/* buttons */
- button = gtk_button_new_from_stock (GTK_STOCK_CANCEL);
- gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
- (GtkSignalFunc) gtk_widget_destroy,
- (gpointer) dialog);
- gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area),
- button, TRUE, TRUE, 0);
- GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
- gtk_widget_grab_default (button);
- gtk_widget_show (button);
+ button = gtk_dialog_add_button (GTK_DIALOG (dialog),
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
+ g_signal_connect_swapped (button, "clicked",
+ G_CALLBACK (gtk_widget_destroy),
+ dialog);
gtk_widget_grab_focus (fs->fileop_entry);
- button = gtk_button_new_with_label (_("Create"));
- gtk_signal_connect (GTK_OBJECT (button), "clicked",
- (GtkSignalFunc) gtk_file_selection_create_dir_confirmed,
- (gpointer) fs);
- gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area),
- button, TRUE, TRUE, 0);
- GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
- gtk_widget_show (button);
+ button = gtk_dialog_add_button (GTK_DIALOG (dialog),
+ _("C_reate"), GTK_RESPONSE_OK);
+ gtk_widget_set_sensitive (button, FALSE);
+ g_signal_connect (button, "clicked",
+ G_CALLBACK (gtk_file_selection_create_dir_confirmed),
+ fs);
+ g_signal_connect (fs->fileop_entry, "changed",
+ G_CALLBACK (gtk_file_selection_fileop_entry_changed),
+ button);
+
+ gtk_widget_grab_default (button);
gtk_widget_show (dialog);
}
GTK_BUTTONS_NONE,
_("Really delete file \"%s\" ?"), filename);
- gtk_signal_connect (GTK_OBJECT (dialog), "destroy",
- (GtkSignalFunc) gtk_file_selection_fileop_destroy,
- (gpointer) fs);
+ g_signal_connect (dialog, "destroy",
+ G_CALLBACK (gtk_file_selection_fileop_destroy),
+ fs);
gtk_window_set_title (GTK_WINDOW (dialog), _("Delete File"));
gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CANCEL);
- g_signal_connect (G_OBJECT (dialog), "response",
+ g_signal_connect (dialog, "response",
G_CALLBACK (gtk_file_selection_delete_file_response),
fs);
/* main dialog */
fs->fileop_dialog = dialog = gtk_dialog_new ();
- gtk_signal_connect (GTK_OBJECT (dialog), "destroy",
- (GtkSignalFunc) gtk_file_selection_fileop_destroy,
- (gpointer) fs);
+ g_signal_connect (dialog, "destroy",
+ G_CALLBACK (gtk_file_selection_fileop_destroy),
+ fs);
gtk_window_set_title (GTK_WINDOW (dialog), _("Rename File"));
gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (fs));
gtk_box_pack_start (GTK_BOX (vbox), fs->fileop_entry,
TRUE, TRUE, 5);
GTK_WIDGET_SET_FLAGS (fs->fileop_entry, GTK_CAN_DEFAULT);
+ gtk_entry_set_activates_default (GTK_ENTRY (fs->fileop_entry), TRUE);
gtk_widget_show (fs->fileop_entry);
gtk_entry_set_text (GTK_ENTRY (fs->fileop_entry), fs->fileop_file);
0, strlen (fs->fileop_file));
/* buttons */
- button = gtk_button_new_from_stock (GTK_STOCK_CANCEL);
- gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
- (GtkSignalFunc) gtk_widget_destroy,
- (gpointer) dialog);
- gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area),
- button, TRUE, TRUE, 0);
- GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
- gtk_widget_grab_default (button);
- gtk_widget_show (button);
+ button = gtk_dialog_add_button (GTK_DIALOG (dialog),
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
+ g_signal_connect_swapped (button, "clicked",
+ G_CALLBACK (gtk_widget_destroy),
+ dialog);
gtk_widget_grab_focus (fs->fileop_entry);
- button = gtk_button_new_with_label (_("Rename"));
- gtk_signal_connect (GTK_OBJECT (button), "clicked",
- (GtkSignalFunc) gtk_file_selection_rename_file_confirmed,
- (gpointer) fs);
- gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area),
- button, TRUE, TRUE, 0);
- GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
- gtk_widget_show (button);
+ button = gtk_dialog_add_button (GTK_DIALOG (dialog),
+ _("_Rename"), GTK_RESPONSE_OK);
+ g_signal_connect (button, "clicked",
+ G_CALLBACK (gtk_file_selection_rename_file_confirmed),
+ fs);
+ g_signal_connect (fs->fileop_entry, "changed",
+ G_CALLBACK (gtk_file_selection_fileop_entry_changed),
+ button);
+
+ gtk_widget_grab_default (button);
gtk_widget_show (dialog);
}
if (!filename)
{
gdk_display_beep (gtk_widget_get_display (widget));
- gtk_signal_emit_stop_by_name (GTK_OBJECT (widget), "insert_text");
+ g_signal_stop_emission_by_name (widget, "insert_text");
return FALSE;
}
return TRUE;
}
+static void
+gtk_file_selection_update_fileops (GtkFileSelection *fs)
+{
+ gboolean sensitive;
+
+ if (!fs->selection_entry)
+ return;
+
+ sensitive = !entry_is_empty (GTK_ENTRY (fs->selection_entry));
+
+ if (fs->fileop_del_file)
+ gtk_widget_set_sensitive (fs->fileop_del_file, sensitive);
+
+ if (fs->fileop_ren_file)
+ gtk_widget_set_sensitive (fs->fileop_ren_file, sensitive);
+}
+
static gint
gtk_file_selection_key_press (GtkWidget *widget,
GdkEventKey *event,
fs->history_list = g_list_append (fs->history_list, callback_arg);
- gtk_signal_connect (GTK_OBJECT (menu_item), "activate",
- (GtkSignalFunc) gtk_file_selection_history_callback,
- (gpointer) fs);
+ g_signal_connect (menu_item, "activate",
+ G_CALLBACK (gtk_file_selection_history_callback),
+ fs);
gtk_menu_shell_append (GTK_MENU_SHELL (fs->history_menu), menu_item);
gtk_widget_show (menu_item);
}
/* Check to see if the selection was a drive selector */
if (isalpha (filename[0]) && (filename[1] == ':'))
{
- /* It is... map it to a CYGWIN32 drive */
- gchar *temp_filename = g_strdup_printf ("//%c/", tolower (filename[0]));
+ gchar temp_filename[MAX_PATH];
+ int len;
+ cygwin_conv_to_posix_path (filename, temp_filename);
+
+ /* we need trailing '/'. */
+ len = strlen (temp_filename);
+ if (len > 0 && temp_filename[len-1] != '/')
+ {
+ temp_filename[len] = '/';
+ temp_filename[len+1] = '\0';
+ }
+
if (free_old)
g_free (filename);
- return temp_filename;
+ return g_strdup (temp_filename);
}
-#else
- return filename;
#endif /* G_WITH_CYGWIN */
+ return filename;
}
static void
gtk_tree_model_get_iter (model, &iter, path);
gtk_tree_model_get (model, &iter, FILE_COLUMN, &filename, -1);
filename = get_real_filename (filename, TRUE);
-
gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), filename);
gtk_button_clicked (GTK_BUTTON (fs->ok_button));
gtk_tree_model_get_iter (model, &iter, path);
gtk_tree_model_get (model, &iter, DIR_COLUMN, &filename, -1);
+ filename = get_real_filename (filename, TRUE);
gtk_file_selection_populate (fs, filename, FALSE, FALSE);
g_free (filename);
}
-#if defined(G_OS_WIN32) || defined(G_WITH_CYGWIN)
+#ifdef G_PLATFORM_WIN32
static void
win32_gtk_add_drives_to_dir_list (GtkListStore *model)
while (*textPtr != '\0')
{
/* Ignore floppies (?) */
- if ((tolower (textPtr[0]) != 'a') && (tolower (textPtr[0]) != 'b'))
+ if (GetDriveType (textPtr) != DRIVE_REMOVABLE)
{
/* Build the actual displayable string */
- sprintf (formatBuffer, "%c:\\", toupper (textPtr[0]));
+ g_snprintf (formatBuffer, sizeof (formatBuffer), "%c:\\", toupper (textPtr[0]));
/* Add to the list */
gtk_list_store_append (model, &iter);
}
#endif
+static gchar *
+escape_underscores (const gchar *str)
+{
+ GString *result = g_string_new (NULL);
+ while (*str)
+ {
+ if (*str == '_')
+ g_string_append_c (result, '_');
+
+ g_string_append_c (result, *str);
+ str++;
+ }
+
+ return g_string_free (result, FALSE);
+}
+
static void
gtk_file_selection_populate (GtkFileSelection *fs,
gchar *rel_path,
poss = cmpl_next_completion (cmpl_state);
}
-#if defined(G_OS_WIN32) || defined(G_WITH_CYGWIN)
+#ifdef G_PLATFORM_WIN32
/* For Windows, add drives as potential selections */
win32_gtk_add_drives_to_dir_list (dir_model);
#endif
if (!did_recurse)
{
if (fs->selection_entry)
- gtk_entry_set_position (GTK_ENTRY (fs->selection_entry), selection_index);
+ gtk_editable_set_position (GTK_EDITABLE (fs->selection_entry),
+ selection_index);
if (fs->selection_entry)
{
- sel_text = g_strconcat (_("Selection: "),
- cmpl_reference_position (cmpl_state),
- NULL);
+ char *escaped = escape_underscores (cmpl_reference_position (cmpl_state));
+ sel_text = g_strconcat (_("_Selection: "), escaped, NULL);
+ g_free (escaped);
- gtk_label_set_text (GTK_LABEL (fs->selection_text), sel_text);
+ gtk_label_set_text_with_mnemonic (GTK_LABEL (fs->selection_text), sel_text);
g_free (sel_text);
}
{
gchar err_buf[256];
- sprintf (err_buf, _("Folder unreadable: %s"), cmpl_strerror (cmpl_errno));
+ g_snprintf (err_buf, sizeof (err_buf), _("Folder unreadable: %s"), cmpl_strerror (cmpl_errno));
/* BEEP gdk_beep(); */
/* A common case is selecting a range of files from top to bottom,
* so quickly check for that to avoid looping over the entire list
*/
- if (compare_filenames (g_ptr_array_index (old_names, old_names->len - 1),
- g_ptr_array_index (new_names, new_names->len - 1)) != 0)
+ if (compare_utf8_filenames (g_ptr_array_index (old_names, old_names->len - 1),
+ g_ptr_array_index (new_names, new_names->len - 1)) != 0)
index = new_names->len - 1;
else
{
*/
while (i < old_names->len && j < new_names->len)
{
- cmp = compare_filenames (g_ptr_array_index (old_names, i),
- g_ptr_array_index (new_names, j));
+ cmp = compare_utf8_filenames (g_ptr_array_index (old_names, i),
+ g_ptr_array_index (new_names, j));
if (cmp < 0)
{
i++;
* was selected, which is used for subsequent range selections.
* So search up from there.
*/
- if (compare_filenames (fs->last_selected,
- g_ptr_array_index (new_names, 0)) == 0)
+ if (fs->last_selected &&
+ compare_utf8_filenames (fs->last_selected,
+ g_ptr_array_index (new_names, 0)) == 0)
index = new_names->len - 1;
else
index = 0;
entry = gtk_entry_get_text (GTK_ENTRY (fs->selection_entry));
if ((entry != NULL) && (fs->last_selected != NULL) &&
- (compare_filenames (entry, fs->last_selected) == 0))
+ (compare_utf8_filenames (entry, fs->last_selected) == 0))
gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), "");
}
* in the file list. The first file in the list is equivalent to what
* gtk_file_selection_get_filename() would return.
*
- * 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
+ * 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.
*
* Return value: a newly-allocated %NULL-terminated array of strings. Use
gchar *filename, *dirname;
gchar *current, *buf;
gint i, count;
+ gboolean unselected_entry;
g_return_val_if_fail (GTK_IS_FILE_SELECTION (filesel), NULL);
selections = g_new (gchar *, 2);
count = 0;
- selections[count++] = filename;
+ unselected_entry = TRUE;
if (names != NULL)
{
current = g_build_filename (dirname, buf, NULL);
g_free (buf);
- if (compare_filenames (current, filename) != 0)
- selections[count++] = current;
- else
- g_free (current);
+ selections[count++] = current;
+
+ if (unselected_entry && compare_sys_filenames (current, filename) == 0)
+ unselected_entry = FALSE;
}
g_free (dirname);
}
+ if (unselected_entry)
+ selections[count++] = filename;
+ else
+ g_free (filename);
+
selections[count] = NULL;
return selections;
return cmpl_state->last_valid_char;
}
-static gchar*
+static const gchar*
cmpl_completion_fullname (const gchar *text,
CompletionState *cmpl_state)
{
- static char nothing[2] = "";
+ static const char nothing[2] = "";
if (!cmpl_state_okay (cmpl_state))
{
{
gint i;
for (i = 0; i < sent->entry_count; i++)
- g_free (sent->entries[i].entry_name);
+ {
+ g_free (sent->entries[i].entry_name);
+ g_free (sent->entries[i].sort_key);
+ }
g_free (sent->entries);
g_free (sent);
}
gchar **remaining_text,
CompletionState *cmpl_state)
{
+#ifdef HAVE_PWD_H
gchar* first_slash;
+#endif
PossibleCompletion *poss;
prune_memory_usage (cmpl_state);
if (text_to_complete[0] == '/' && text_to_complete[1] == '/')
{
char root_dir[5];
- sprintf (root_dir, "//%c", text_to_complete[2]);
+ g_snprintf (root_dir, sizeof (root_dir), "//%c", text_to_complete[2]);
new_dir = open_dir (root_dir, cmpl_state);
p = strrchr (tmp, G_DIR_SEPARATOR);
if (p)
{
- if (p == tmp)
+ if (p + 1 == g_path_skip_root (tmp))
p++;
*p = '\0';
-
new_dir = open_dir (tmp, cmpl_state);
if (new_dir)
*remaining_text = text_to_complete +
- ((p == tmp + 1) ? (p - tmp) : (p + 1 - tmp));
+ ((p == g_path_skip_root (tmp)) ? (p - tmp) : (p + 1 - tmp));
}
else
{
gchar *sys_dir_name;
sent = g_new (CompletionDirSent, 1);
+#ifndef G_PLATFORM_WIN32
sent->mtime = sbuf->st_mtime;
sent->inode = sbuf->st_ino;
sent->device = sbuf->st_dev;
-
+#endif
path = g_string_sized_new (2*MAXPATHLEN + 10);
sys_dir_name = g_filename_from_utf8 (dir_name, -1, NULL, NULL, NULL);
while ((dirent = g_dir_read_name (directory)) != NULL)
entry_count++;
+ entry_count += 2; /* For ".",".." */
sent->entries = g_new (CompletionDirEntry, entry_count);
sent->entry_count = entry_count;
{
GError *error = NULL;
- dirent = g_dir_read_name (directory);
-
- if (!dirent)
+ if (i == 0)
+ dirent = ".";
+ else if (i == 1)
+ dirent = "..";
+ else
{
- g_warning ("Failure reading folder '%s'", sys_dir_name);
- g_dir_close (directory);
- g_free (sys_dir_name);
- return NULL;
+ dirent = g_dir_read_name (directory);
+ if (!dirent) /* Directory changed */
+ break;
}
sent->entries[n_entries].entry_name = g_filename_to_utf8 (dirent, -1, NULL, NULL, &error);
if (sent->entries[n_entries].entry_name == NULL
|| !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"),
- dirent,
- error->message ? error->message : _("Invalid Utf-8"));
+ escaped_str,
+ error->message ? error->message : _("Invalid UTF-8"));
+ g_free (escaped_str);
g_clear_error (&error);
continue;
}
g_clear_error (&error);
+ sent->entries[n_entries].sort_key = g_utf8_collate_key (sent->entries[n_entries].entry_name, -1);
+
g_string_assign (path, sys_dir_name);
if (path->str[path->len-1] != G_DIR_SEPARATOR)
{
return sent;
}
-#if !defined(G_OS_WIN32) && !defined(G_WITH_CYGWIN)
+#ifndef G_PLATFORM_WIN32
static gboolean
check_dir (gchar *dir_name,
open_dir (gchar *dir_name,
CompletionState *cmpl_state)
{
+#ifndef G_PLATFORM_WIN32
struct stat sbuf;
gboolean stat_subdirs;
- CompletionDirSent *sent;
GList* cdsl;
+#endif
+ CompletionDirSent *sent;
-#if !defined(G_OS_WIN32) && !defined(G_WITH_CYGWIN)
+#ifndef G_PLATFORM_WIN32
if (!check_dir (dir_name, &sbuf, &stat_subdirs))
return NULL;
cdsl = cdsl->next;
}
-#else
- stat_subdirs = TRUE;
-#endif
sent = open_new_dir (dir_name, &sbuf, stat_subdirs);
+#else
+ sent = open_new_dir (dir_name, NULL, TRUE);
+#endif
if (sent)
{
struct stat parbuf;
gchar *last_slash;
gchar *first_slash;
+#ifndef G_PLATFORM_WIN32
gchar *new_name;
+#endif
gchar *sys_filename;
gchar c = 0;
}
g_free (sys_filename);
-#ifndef G_OS_WIN32 /* No inode numbers on Win32 */
+#ifndef G_PLATFORM_WIN32 /* No inode numbers on Win32 */
if (parbuf.st_ino == sbuf->st_ino && parbuf.st_dev == sbuf->st_dev)
/* it wasn't a link */
return TRUE;
return TRUE;
}
-#ifndef G_OS_WIN32
+#ifndef G_PLATFORM_WIN32
static gchar*
find_parent_dir_fullname (gchar* dirname)
if (chdir (sys_dirname) != 0 || chdir ("..") != 0)
{
+ cmpl_errno = errno;
+ chdir (sys_orig_dir);
g_free (sys_dirname);
g_free (sys_orig_dir);
- cmpl_errno = errno;
return NULL;
}
g_free (sys_dirname);
#endif
-#if defined(G_OS_WIN32) || defined(G_WITH_CYGWIN)
+#ifdef G_PLATFORM_WIN32
+/* FIXME: determine whether we should casefold all Unicode letters
+ * here, too (and in in first_diff_index() walk through the strings with
+ * g_utf8_next_char()), or if this folding isn't actually needed at
+ * all.
+ */
#define FOLD(c) (tolower(c))
#else
#define FOLD(c) (c)
for (i = 0; i < dir->sent->entry_count; i += 1)
{
if (dir->sent->entries[i].is_dir &&
- fnmatch (pat_buf, dir->sent->entries[i].entry_name,
- FNMATCH_FLAGS)!= FNM_NOMATCH)
+ _gtk_fnmatch (pat_buf, dir->sent->entries[i].entry_name))
{
if (found)
{
{
g_free (pat_buf);
return NULL;
- }
+}
next->cmpl_parent = dir;
if (cmpl_state->updated_text_alloc < cmpl_len + 1)
{
+ cmpl_state->updated_text_alloc = 2*cmpl_len;
cmpl_state->updated_text =
(gchar*)g_realloc (cmpl_state->updated_text,
cmpl_state->updated_text_alloc);
- cmpl_state->updated_text_alloc = 2*cmpl_len;
}
if (cmpl_state->updated_text_len < 0)
{
if (dir->sent->entries[dir->cmpl_index].is_dir)
{
- if (fnmatch (pat_buf, dir->sent->entries[dir->cmpl_index].entry_name,
- FNMATCH_FLAGS) != FNM_NOMATCH)
+ if (_gtk_fnmatch (pat_buf, dir->sent->entries[dir->cmpl_index].entry_name))
{
CompletionDir* new_dir;
append_completion_text (dir->sent->entries[dir->cmpl_index].entry_name, cmpl_state);
cmpl_state->the_completion.is_a_completion =
- fnmatch (pat_buf, dir->sent->entries[dir->cmpl_index].entry_name,
- FNMATCH_FLAGS) != FNM_NOMATCH;
+ _gtk_fnmatch (pat_buf, dir->sent->entries[dir->cmpl_index].entry_name);
cmpl_state->the_completion.is_directory = dir->sent->entries[dir->cmpl_index].is_dir;
if (dir->sent->entries[dir->cmpl_index].is_dir)
compare_cmpl_dir (const void *a,
const void *b)
{
- return compare_filenames ((((CompletionDirEntry*)a))->entry_name,
- (((CompletionDirEntry*)b))->entry_name);
+
+ return strcmp (((CompletionDirEntry*)a)->sort_key,
+ (((CompletionDirEntry*)b))->sort_key);
}
static gint