diff options
Diffstat (limited to 'src/nautilus-location-bar.c')
-rw-r--r-- | src/nautilus-location-bar.c | 355 |
1 files changed, 5 insertions, 350 deletions
diff --git a/src/nautilus-location-bar.c b/src/nautilus-location-bar.c index 8efbd45c5..fd4092dfd 100644 --- a/src/nautilus-location-bar.c +++ b/src/nautilus-location-bar.c @@ -33,14 +33,15 @@ #include <config.h> #include "nautilus-location-bar.h" +#include "nautilus-location-entry.h" #include "nautilus-window-private.h" #include "nautilus-window.h" #include <eel/eel-accessibility.h> #include <eel/eel-glib-extensions.h> #include <eel/eel-gtk-macros.h> +#include <eel/eel-input-event-box.h> #include <eel/eel-stock-dialogs.h> #include <eel/eel-string.h> -#include <eel/eel-input-event-box.h> #include <eel/eel-vfs-extensions.h> #include <gtk/gtkdnd.h> #include <gtk/gtksignal.h> @@ -48,7 +49,6 @@ #include <libgnomeui/gnome-stock-icons.h> #include <libgnomeui/gnome-uidefs.h> #include <libgnomevfs/gnome-vfs.h> -#include <libnautilus-private/nautilus-entry.h> #include <libnautilus-private/nautilus-icon-dnd.h> #include <libnautilus/nautilus-clipboard.h> #include <stdio.h> @@ -250,290 +250,6 @@ style_set_handler (GtkWidget *widget, GtkStyle *previous_style) gtk_widget_set_size_request (widget, width, -1); } -static gboolean -have_broken_filenames (void) -{ - static gboolean initialized = FALSE; - static gboolean broken; - - if (initialized) { - return broken; - } - - broken = g_getenv ("G_BROKEN_FILENAMES") != NULL; - - initialized = TRUE; - - return broken; -} - - -/* utility routine to determine the string to expand to. If we don't have anything yet, accept - the whole string, otherwise accept the largest part common to both */ - -static char * -accumulate_name_utf8 (char *full_name, char *candidate_name) -{ - char *result_name, *str1, *str2; - - if (!g_utf8_validate (candidate_name, -1, NULL)) { - return full_name; - } - - if (full_name == NULL) { - result_name = g_strdup (candidate_name); - } else { - result_name = full_name; - if (!eel_str_has_prefix (full_name, candidate_name)) { - str1 = full_name; - str2 = candidate_name; - - while ((g_utf8_get_char (str1) == g_utf8_get_char (str2))) { - str1 = g_utf8_next_char (str1); - str2 = g_utf8_next_char (str2); - } - *str1 = '\0'; - } - } - - return result_name; -} - -static char * -accumulate_name_locale (char *full_name, char *candidate_name) -{ - char *result_name, *str1, *str2; - - if (full_name == NULL) - result_name = g_strdup (candidate_name); - else { - result_name = full_name; - if (!eel_str_has_prefix (full_name, candidate_name)) { - str1 = full_name; - str2 = candidate_name; - - while (*str1 == *str2) { - str1++; - str2++; - } - *str1 = '\0'; - } - } - - return result_name; -} - -/* utility routine to load the file info list for the current directory, if necessary */ -static void -get_file_info_list (NautilusLocationBar *bar, const char* dir_name) -{ - GnomeVFSResult result; - - if (eel_strcmp (bar->details->current_directory, dir_name) != 0) { - g_free (bar->details->current_directory); - if (bar->details->file_info_list) { - gnome_vfs_file_info_list_free (bar->details->file_info_list); - bar->details->file_info_list = NULL; - } - - bar->details->current_directory = g_strdup (dir_name); - result = gnome_vfs_directory_list_load (&bar->details->file_info_list, dir_name, - GNOME_VFS_FILE_INFO_DEFAULT); - if (result != GNOME_VFS_OK) { - if (bar->details->file_info_list) { - gnome_vfs_file_info_list_free (bar->details->file_info_list); - bar->details->file_info_list = NULL; - } - } - } -} - -/* routine that performs the tab expansion using gnome-vfs. Extract the directory name and - incomplete basename, then iterate through the directory trying to complete it. If we - find something, add it to the entry */ - -static gboolean -try_to_expand_path (gpointer callback_data) -{ - NautilusLocationBar *bar; - - GnomeVFSFileInfo *current_file_info; - GList *element; - GnomeVFSURI *uri; - GtkEditable *editable; - - char *base_name_uri_escaped; - char *base_name; - char *base_name_utf8; - char *user_location; - char *current_path; - char *dir_name; - char *expand_text; - char *expand_text_utf8; - char *expand_name; - char *insert_text; - - int base_name_length; - int user_location_length; - int expand_text_length; - int pos; - - bar = NAUTILUS_LOCATION_BAR (callback_data); - editable = GTK_EDITABLE (bar->details->entry); - user_location = gtk_editable_get_chars (editable, 0, -1); - bar->details->idle_id = 0; - - /* if it's just '~' don't expand because slash shouldn't be appended */ - if (eel_strcmp (user_location, "~") == 0) { - g_free (user_location); - return FALSE; - } - - /* Trailing whitespace is OK here since the cursor is known to - be at the end of the text and therefor after the whitespace. */ - current_path = eel_make_uri_from_input_with_trailing_ws (user_location); - if (!eel_istr_has_prefix (current_path, "file://")) { - g_free (user_location); - g_free (current_path); - return FALSE; - } - - /* We already completed if we have a trailing '/' */ - if (current_path[strlen (current_path) - 1] == GNOME_VFS_URI_PATH_CHR) { - g_free (user_location); - g_free (current_path); - return FALSE; - } - - user_location_length = g_utf8_strlen (user_location, -1); - - g_free (user_location); - - uri = gnome_vfs_uri_new (current_path); - - base_name_uri_escaped = gnome_vfs_uri_extract_short_name (uri); - if (base_name_uri_escaped == NULL) { - base_name = NULL; - } else { - base_name = gnome_vfs_unescape_string (base_name_uri_escaped, NULL); - } - g_free (base_name_uri_escaped); - - if (base_name == NULL) { - gnome_vfs_uri_unref (uri); - g_free (current_path); - return FALSE; - } - - dir_name = gnome_vfs_uri_extract_dirname (uri); - - gnome_vfs_uri_unref (uri); - uri = NULL; - - /* get file info for the directory, if it hasn't changed since last time */ - get_file_info_list (bar, dir_name); - if (bar->details->file_info_list == NULL) { - g_free (dir_name); - g_free (base_name); - g_free (current_path); - return FALSE; - } - - /* iterate through the directory, keeping the intersection of all the names that - have the current basename as a prefix. */ - expand_text = NULL; - for (element = bar->details->file_info_list; element != NULL; element = element->next) { - current_file_info = element->data; - if (eel_str_has_prefix (current_file_info->name, base_name)) { - if (current_file_info->type == GNOME_VFS_FILE_TYPE_DIRECTORY) { - expand_name = g_strconcat (current_file_info->name, "/", NULL); - } else { - expand_name = g_strdup (current_file_info->name); - } - if (have_broken_filenames()) { - expand_text = accumulate_name_locale (expand_text, expand_name); - } else { - expand_text = accumulate_name_utf8 (expand_text, expand_name); - } - g_free (expand_name); - } - } - - if (have_broken_filenames ()) { - if (expand_text) { - expand_text_utf8 = g_locale_to_utf8 (expand_text, -1, NULL, NULL, NULL); - g_free (expand_text); - expand_text = expand_text_utf8; - } - - base_name_utf8 = g_locale_to_utf8 (base_name, -1, NULL, NULL, NULL); - g_free (base_name); - base_name = base_name_utf8; - } - - /* if we've got something, add it to the entry */ - if (expand_text != NULL && base_name != NULL) { - expand_text_length = g_utf8_strlen (expand_text, -1); - base_name_length = g_utf8_strlen (base_name, -1); - - if (!eel_str_has_suffix (base_name, expand_text) - && base_name_length < expand_text_length) { - insert_text = g_utf8_offset_to_pointer (expand_text, base_name_length); - pos = user_location_length; - gtk_editable_insert_text (editable, - insert_text, - g_utf8_strlen (insert_text, -1), - &pos); - - pos = user_location_length; - gtk_editable_select_region (editable, pos, -1); - } - } - g_free (expand_text); - - g_free (dir_name); - g_free (base_name); - g_free (current_path); - - return FALSE; -} - -/* Until we have a more elegant solution, this is how we figure out if - * the GtkEntry inserted characters, assuming that the return value is - * TRUE indicating that the GtkEntry consumed the key event for some - * reason. This is a clone of code from GtkEntry. - */ -static gboolean -entry_would_have_inserted_characters (const GdkEventKey *event) -{ - switch (event->keyval) { - case GDK_BackSpace: - case GDK_Clear: - case GDK_Insert: - case GDK_Delete: - case GDK_Home: - case GDK_End: - case GDK_KP_Home: - case GDK_KP_End: - case GDK_Left: - case GDK_Right: - case GDK_KP_Left: - case GDK_KP_Right: - case GDK_Return: - return FALSE; - default: - if (event->keyval >= 0x20 && event->keyval <= 0xFF) { - if ((event->state & GDK_CONTROL_MASK) != 0) { - return FALSE; - } - if ((event->state & GDK_MOD1_MASK) != 0) { - return FALSE; - } - } - return event->length > 0; - } -} - static int get_editable_number_of_chars (GtkEditable *editable) { @@ -556,71 +272,12 @@ set_position_and_selection_to_end (GtkEditable *editable) gtk_editable_set_position (editable, end); } -static gboolean -position_and_selection_are_at_end (GtkEditable *editable) -{ - int end; - int start_sel, end_sel; - - end = get_editable_number_of_chars (editable); - if (gtk_editable_get_selection_bounds (editable, &start_sel, &end_sel)) { - if (start_sel != end || end_sel != end) { - return FALSE; - } - } - return gtk_editable_get_position (editable) == end; -} - static void editable_event_after_callback (GtkEntry *entry, GdkEvent *event, gpointer user_data) { - GtkEditable *editable; - GdkEventKey *keyevent; - NautilusLocationBar *bar; - - if (event->type != GDK_KEY_PRESS) { - return; - } - - editable = GTK_EDITABLE (entry); - keyevent = (GdkEventKey *)event; - bar = NAUTILUS_LOCATION_BAR (user_data); - - /* After typing the right arrow key we move the selection to - * the end, if we have a valid selection - since this is most - * likely an auto-completion. We ignore shift / control since - * they can validly be used to extend the selection. - */ - if ((keyevent->keyval == GDK_Right || keyevent->keyval == GDK_End) && - !(keyevent->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK)) && - gtk_editable_get_selection_bounds (editable, NULL, NULL)) { - set_position_and_selection_to_end (editable); - } - - /* Only do expanding when we are typing at the end of the - * text. Do the expand at idle time to avoid slowing down - * typing when the directory is large. Only trigger the expand - * when we type a key that would have inserted characters. - */ - if (position_and_selection_are_at_end (editable)) { - if (entry_would_have_inserted_characters (keyevent)) { - if (bar->details->idle_id == 0) { - bar->details->idle_id = g_idle_add (try_to_expand_path, bar); - } - } - } else { - /* FIXME: Also might be good to do this when you click - * to change the position or selection. - */ - if (bar->details->idle_id != 0) { - g_source_remove (bar->details->idle_id); - bar->details->idle_id = 0; - } - } - - nautilus_location_bar_update_label (bar); + nautilus_location_bar_update_label (NAUTILUS_LOCATION_BAR (user_data)); } static void @@ -721,15 +378,13 @@ nautilus_location_bar_init (NautilusLocationBar *bar) gtk_box_pack_start (GTK_BOX (hbox), event_box, FALSE, TRUE, GNOME_PAD_SMALL); - entry = nautilus_entry_new (); - - nautilus_entry_set_special_tab_handling (NAUTILUS_ENTRY (entry), TRUE); + entry = nautilus_location_entry_new (); g_signal_connect_object (entry, "activate", G_CALLBACK (nautilus_navigation_bar_location_changed), bar, G_CONNECT_SWAPPED); g_signal_connect_object (entry, "event_after", - G_CALLBACK (editable_event_after_callback), bar, 0); + G_CALLBACK (editable_event_after_callback), bar, G_CONNECT_AFTER); gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0); |