Beispiel #1
0
/**
 * fm_path_new_for_uri
 * @path_name: a URI with special characters escaped.
 * Encoded URI such as http://wiki.lxde.org/zh/%E9%A6%96%E9%A0%81
 * will be unescaped.
 *
 * You can call fm_path_to_uri () to convert a FmPath to a escaped URI
 * string.
 *
 * Returns: a newly created FmPath for the path. You have to call
 * fm_path_unref () when it's no longer needed.
 */
static FmPath *_fm_path_new_for_uri_internal (const char *uri, gboolean need_unescape)
{
    FmPath *path, *root;
    const char *rel_path;
    
    if (!uri || !*uri)
        return fm_path_ref (root_path);

    root = _fm_path_new_uri_root (uri, strlen (uri), &rel_path, need_unescape);
    
    if (*rel_path)
    {
        if (need_unescape)
            rel_path = g_uri_unescape_string (rel_path, NULL);
        
        path = fm_path_new_relative (root, rel_path);
        fm_path_unref (root);
        
        if (need_unescape)
            g_free ((char*)rel_path);
    }
    else
    {
        path = root;
    }
    return path;
}
Beispiel #2
0
static void fm_path_entry_paste_and_go(GtkMenuItem *menuitem, GtkEntry *entry)
{
    GtkClipboard* clipboard = gtk_clipboard_get_for_display(
        gtk_widget_get_display (GTK_WIDGET (menuitem)),GDK_SELECTION_CLIPBOARD);

    gchar* full_path = gtk_clipboard_wait_for_text(clipboard);

    if (full_path)
    {

        FmPathEntryPrivate *priv  = FM_PATH_ENTRY_GET_PRIVATE(entry);

        if(priv->path)
            fm_path_unref(priv->path);

        /* special handling for home dir */
        if(full_path[0] == '~' && full_path[1] == G_DIR_SEPARATOR)
            priv->path = fm_path_new_relative(fm_path_get_home(), full_path + 2);
        else if(full_path[0] == '~' && full_path[1] == 0)
            priv->path = fm_path_ref(fm_path_get_home());
        else
            priv->path = fm_path_new_for_str(full_path);

        gchar * disp_name = fm_path_display_name(priv->path, FALSE);
        gtk_entry_set_text(entry, disp_name);
        g_free(disp_name);

        gtk_editable_set_position(GTK_EDITABLE(entry), -1);

        g_free(full_path);

        fm_path_entry_activate(FM_PATH_ENTRY(entry));
    }
}
Beispiel #3
0
static void  fm_path_entry_on_activate(GtkEntry *entry, gpointer user_data)
{
    FmPathEntryPrivate *priv  = FM_PATH_ENTRY_GET_PRIVATE(entry);
    const char* full_path;
    char* disp_name;
    /* convert current path string to FmPath here */

    full_path = gtk_entry_get_text(entry);
    if(priv->path)
        fm_path_unref(priv->path);

    /* special handling for home dir */
    if(full_path[0] == '~' && full_path[1] == G_DIR_SEPARATOR)
        priv->path = fm_path_new_relative(fm_path_get_home(), full_path + 2);
    else if(full_path[0] == '~' && full_path[1] == 0)
        priv->path = fm_path_ref(fm_path_get_home());
    else
        priv->path = fm_path_new_for_str(full_path);

    disp_name = fm_path_display_name(priv->path, FALSE);
    gtk_entry_set_text(entry, disp_name);
    g_free(disp_name);

    gtk_editable_set_position(GTK_EDITABLE(entry), -1);
}
Beispiel #4
0
FmPath* AppMenuView::selectedAppDesktopPath() {
  AppMenuViewItem* item = selectedItem();
  if(item && item->isApp()) {
    char* mpath = menu_cache_dir_make_path(MENU_CACHE_DIR(item));
    FmPath* path = fm_path_new_relative(fm_path_get_apps_menu(),
                                        mpath + 13 /* skip "/Applications" */);
    g_free(mpath);
    return path;
  }
  return NULL;
}
Beispiel #5
0
/**
 * fm_path_new_relative
 * @parent: a parent path
 * @rel: a path relative to @parent in glib filename encoding.  (can be
 * non-UTF-8). However this should not be a escaped ASCII string used in
 * URI. If you're building a relative path for a URI, and the relative
 * path is escaped, you have to unescape it first.
 *
 * For example, if @parent is "http://wiki.lxde.org/" and @rel is
 * "zh/%E9%A6%96%E9%A0%81", you have to unescape the relative path
 * prior to passing it to fm_path_new_relative ().
 *
 * If @parent is NULL, this works the same as fm_path_new_for_str (@rel)
 *
 * Returns: a newly created FmPath for the path. You have to call
 * fm_path_unref () when it's no longer needed.
 */
FmPath *fm_path_new_relative (FmPath *parent, const char *rel)
{
    FmPath *path;
    
    if (G_UNLIKELY (!rel || !*rel)) // relative path is empty
        return parent ? fm_path_ref (parent) : fm_path_ref (root_path); // return parent

    if (G_LIKELY (parent))
    {
        char *sep;
        
        // remove leading slashes
        while (*rel == '/')
            ++rel;
        
        if (!*rel)
            path = fm_path_ref (parent);
        else
        {
#if 0       // FIXME_pcm: Let's optimize this later. Make things working first is more important.
            // use some pre-defined paths when possible
            if (G_UNLIKELY (parent == root_path))
            {
                if (strcmp (home_dir + 1, rel) == 0)
                    return fm_path_ref (home_path);
                if (strcmp (desktop_dir + 1, rel) == 0)
                    return fm_path_ref (desktop_dir);
            }
#endif

            sep = strchr (rel, '/');
            if (sep)
            {
                FmPath *new_parent = fm_path_new_child_len (parent, rel, sep - rel);
                path = fm_path_new_relative (new_parent, sep + 1);
                fm_path_unref (new_parent);
            }
            else
            {
                path = fm_path_new_child (parent, rel);
            }
        }
    }
    else // this is actaully a full path
        path = fm_path_new_for_str (rel);
    
    return path;
}
Beispiel #6
0
/**
 * fm_app_menu_view_dup_selected_app_desktop_path
 * @view: a widget
 *
 * Retrieves #FmPath to selected application from the widget as a child
 * below fm_path_get_apps_menu() root path. Return %NULL if there is no
 * application selected.
 * The returned data should be freed with fm_path_unref() after usage.
 *
 * Returns: (transfer full): path to selected application file.
 *
 * Since: 1.2.0
 */
FmPath * fm_app_menu_view_dup_selected_app_desktop_path(GtkTreeView* view)
{
    GtkTreeIter it;
    GtkTreeSelection* sel = gtk_tree_view_get_selection(view);
    /* FIXME: this should be checked if it's exactly app menu tree! */
    if(gtk_tree_selection_get_selected(sel, NULL, &it))
    {
        MenuCacheItem* item;
        gtk_tree_model_get(GTK_TREE_MODEL(store), &it, COL_ITEM, &item, -1);
        if(item && menu_cache_item_get_type(item) == MENU_CACHE_TYPE_APP)
        {
            char *mpath = menu_cache_dir_make_path(MENU_CACHE_DIR(item));
            FmPath *path = fm_path_new_relative(fm_path_get_apps_menu(),
                                                mpath+13 /* skip "/Applications" */);
            g_free(mpath);
            return path;
        }
    }
    return NULL;
}
Beispiel #7
0
/**
 * fm_path_new_for_path
 * @path_name: a POSIX path.
 *
 * Returns: a newly created FmPath for the path. You have to call
 * fm_path_unref () when it's no longer needed.
 */
FmPath *fm_path_new_for_path (const char *path_name)
{
    FmPath *path;
    
    if (!path_name || !*path_name)
        return fm_path_ref (root_path);

    // some special cases
    if (G_LIKELY (path_name[0] == '/'))
    {
        if (G_UNLIKELY (path_name[1] == '\0')) // pathname is /
            path = fm_path_ref (root_path);
        else
            path = fm_path_new_relative (root_path, path_name + 1);
    }
    else
    {
        // pathname should be absolute path. otherwise its invalid
        path = fm_path_ref (root_path); // return root
    }
    
    return path;
}
Beispiel #8
0
FmPath* fm_path_new(const char* path)
{
	const char* sep;
    /* FIXME: need to canonicalize paths */

    if( path[0] == '/' ) /* if this is a absolute native path */
    {
        if (path[1])
            return fm_path_new_relative(root, path + 1);
        else
            /* special case: handle root dir */
            return fm_path_ref( root );
    }
    else if ( path[0] == '~' && (path[1] == '\0' || path[1]=='/') ) /* home dir */
    {
        ++path;
        return *path ? fm_path_new_relative(home, path) : fm_path_ref(home);
    }
	else /* then this should be a URL */
	{
        FmPath* parent, *ret;
        char* colon = strchr(path, ':');
        char* hier_part;
        char* rest;
        int root_len;

        if( !colon ) /* this shouldn't happen */
            return NULL; /* invalid path FIXME: should we treat it as relative path? */

        /* FIXME: convert file:/// to local native path */
        hier_part = colon+1;
        if( hier_part[0] == '/' )
        {
            if(hier_part[1] == '/') /* this is a scheme:// form URI */
                rest = hier_part + 2;
            else /* a malformed URI */
                rest = hier_part + 1;

            if(*rest == '/') /* :/// means there is no authoraty part */
                ++rest;
            else /* we are now at autority part, something like <username>@domain/ */
            {
                while( *rest && *rest != '/' )
                    ++rest;
                if(*rest == '/')
                    ++rest;
            }

            if( strncmp(path, "trash:", 6) == 0 ) /* in trash:// */
            {
                if(*rest)
                    return fm_path_new_relative(trash_root, rest);
                else
                    return fm_path_ref(trash_root);
            }
            /* other URIs */
        }
        else /* this URI doesn't have //, like mailto: */
        {
            /* FIXME: is this useful to file managers? */
            rest = colon + 1;
        }
        root_len = (rest - path);
        parent = fm_path_new_child_len(NULL, path, root_len);
        if(*rest)
        {
            ret = fm_path_new_relative(parent, rest);
            fm_path_unref(parent);
        }
        else
            ret = parent;
        return ret;
	}
	return fm_path_new_relative(NULL, path);
}
Beispiel #9
0
FmPath* fm_path_new_relative(FmPath* parent, const char* relative_path)
{
	FmPath* path;
	const char* sep;
	gsize name_len;

    /* FIXME: need to canonicalize paths */
	if(parent == root)
	{
		if( 0 == strncmp(relative_path, home_dir + 1, home_len - 1) ) /* in home dir */
		{
			if( relative_path[home_len - 1] == '\0' ) /* this is the home dir */
            {
				if(G_LIKELY(home))
					return fm_path_ref(home);
				else
					goto _resolve_relative_path;
            }
			if( 0 == strncmp(relative_path, desktop_dir + home_len + 1, desktop_len - home_len -1) ) /* in desktop dir */
			{
				if(relative_path[desktop_len - 1] == '\0') /* this is the desktop dir */
					return fm_path_ref(desktop);
				return fm_path_new_relative(desktop, relative_path + desktop_len + 1);
			}
		}
	}
_resolve_relative_path:
	sep = strchr(relative_path, '/');
	if(sep)
	{
        char* end = sep;

        while(*end && *end == '/') /* prevent tailing slash or duplicated slashes. */
            ++end;

        name_len = (sep - relative_path);
        if(relative_path[0] == '.' && (name_len == 1 || (name_len == 2  && relative_path[1] == '.')) ) /* . or .. */
        {
            if(name_len == 1) /* . => current dir */
            {
                relative_path = end;
                if(*end == '\0')
                    return fm_path_ref(parent); /* . is the last component */
                else
                {
                    relative_path = end; /* skip this component */
                    goto _resolve_relative_path;
                }
            }
            else /* .. jump to parent dir => */
            {
                if(parent->parent)
                    parent = fm_path_ref(parent->parent);
            }
        }
        else
            parent = fm_path_new_child_len(parent, relative_path, name_len);

        if(*end != '\0')
        {
            relative_path = end;
            path = fm_path_new_relative(parent, relative_path);
            fm_path_unref(parent);
        }
        else /* this is tailing slash */
            path = parent;
	}
	else /* this is the last component in the path */
	{
		name_len = strlen(relative_path);
        if(relative_path[0] == '.' && (name_len == 1 || (name_len == 2  && relative_path[1] == '.')) ) /* . or .. */
        {
            if(name_len == 1) /* . => current dir */
                path = fm_path_ref(parent); /* . is the last component */
            else /* .. jump to parent dir => */
            {
                if(parent->parent)
                    path = fm_path_ref(parent->parent);
                else
                    path = fm_path_ref(parent);
            }
        }
        else
    		path = fm_path_new_child_len(parent, relative_path, name_len);
	}
	return path;
}