diff options
author | Benjamin Otte <otte@redhat.com> | 2011-11-04 16:14:01 +0100 |
---|---|---|
committer | Benjamin Otte <otte@redhat.com> | 2011-12-16 20:09:12 +0100 |
commit | 9d09028970f8798b4661544022f79debb22427ba (patch) | |
tree | 79fc236c0b948c653fde34a77a99d893930f9258 /gtk/gtkfilechooserentry.c | |
parent | 036195e7a89c6e257039af0d93f61dfe9a812546 (diff) | |
download | gtk+-9d09028970f8798b4661544022f79debb22427ba.tar.gz |
filechooserentry: Move _gtk_file_system_parse()
It's very specific to the file chooser entry, so it's better kept there.
It's also not used anywhere else in the code.
Diffstat (limited to 'gtk/gtkfilechooserentry.c')
-rw-r--r-- | gtk/gtkfilechooserentry.c | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/gtk/gtkfilechooserentry.c b/gtk/gtkfilechooserentry.c index 901d3e67c7..c491e65e32 100644 --- a/gtk/gtkfilechooserentry.c +++ b/gtk/gtkfilechooserentry.c @@ -418,6 +418,144 @@ beep (GtkFileChooserEntry *chooser_entry) gtk_widget_error_bell (GTK_WIDGET (chooser_entry)); } +static gboolean +is_valid_scheme_character (char c) +{ + return g_ascii_isalnum (c) || c == '+' || c == '-' || c == '.'; +} + +static gboolean +has_uri_scheme (const char *str) +{ + const char *p; + + p = str; + + if (!is_valid_scheme_character (*p)) + return FALSE; + + do + p++; + while (is_valid_scheme_character (*p)); + + return (strncmp (p, "://", 3) == 0); +} + +static gboolean +_gtk_file_system_parse (GtkFileSystem *file_system, + GFile *base_file, + const gchar *str, + GFile **folder, + gchar **file_part, + GError **error) +{ + GFile *file; + gboolean result = FALSE; + gboolean is_dir = FALSE; + gchar *last_slash = NULL; + gboolean is_uri; + + if (str && *str) + is_dir = (str [strlen (str) - 1] == G_DIR_SEPARATOR); + + last_slash = strrchr (str, G_DIR_SEPARATOR); + + is_uri = has_uri_scheme (str); + + if (is_uri) + { + const char *colon; + const char *slash_after_hostname; + + colon = strchr (str, ':'); + g_assert (colon != NULL); + g_assert (strncmp (colon, "://", 3) == 0); + + slash_after_hostname = strchr (colon + 3, '/'); + + if (slash_after_hostname == NULL) + { + /* We don't have a full hostname yet. So, don't switch the folder + * until we have seen a full hostname. Otherwise, completion will + * happen for every character the user types for the hostname. + */ + + *folder = NULL; + *file_part = NULL; + g_set_error (error, + GTK_FILE_CHOOSER_ERROR, + GTK_FILE_CHOOSER_ERROR_INCOMPLETE_HOSTNAME, + "Incomplete hostname"); + return FALSE; + } + } + + if (str[0] == '~' || g_path_is_absolute (str) || is_uri) + file = g_file_parse_name (str); + else + { + if (base_file) + file = g_file_resolve_relative_path (base_file, str); + else + { + *folder = NULL; + *file_part = NULL; + g_set_error (error, + GTK_FILE_CHOOSER_ERROR, + GTK_FILE_CHOOSER_ERROR_BAD_FILENAME, + _("Invalid path")); + return FALSE; + } + } + + if (base_file && g_file_equal (base_file, file)) + { + /* this is when user types '.', could be the + * beginning of a hidden file, ./ or ../ + */ + *folder = g_object_ref (file); + *file_part = g_strdup (str); + result = TRUE; + } + else if (is_dir) + { + /* it's a dir, or at least it ends with the dir separator */ + *folder = g_object_ref (file); + *file_part = g_strdup (""); + result = TRUE; + } + else + { + GFile *parent_file; + + parent_file = g_file_get_parent (file); + + if (!parent_file) + { + g_set_error (error, + GTK_FILE_CHOOSER_ERROR, + GTK_FILE_CHOOSER_ERROR_NONEXISTENT, + "Could not get parent file"); + *folder = NULL; + *file_part = NULL; + } + else + { + *folder = parent_file; + result = TRUE; + + if (last_slash) + *file_part = g_strdup (last_slash + 1); + else + *file_part = g_strdup (str); + } + } + + g_object_unref (file); + + return result; +} + /* Determines if the completion model has entries with a common prefix relative * to the current contents of the entry. Also, if there's one and only one such * path, stores it in unique_path_ret. |