FmPathList* fm_path_list_new_from_uri_list(const char* uri_list) { char** uris = g_strsplit(uri_list, "\r\n", -1); FmPathList* pl = fm_path_list_new_from_uris((const char **)uris); g_strfreev(uris); return pl; }
gboolean fm_dnd_dest_drag_data_received(FmDndDest* dd, GdkDragContext *drag_context, gint x, gint y, GtkSelectionData *sel_data, guint info, guint time) { FmList* files = NULL; GtkWidget *dest_widget = dd->widget; if(info == FM_DND_DEST_TARGET_FM_LIST) { if((sel_data->length >= 0) && (sel_data->format==8)) { /* get the pointer */ memcpy(&files, sel_data->data, sel_data->length); if(files) fm_list_ref(files); if(files) { FmFileInfo* fi = FM_FILE_INFO(fm_list_peek_head(files)); /* get the device of the first dragged source file */ if(fm_path_is_native(fi->path)) dd->src_dev = fi->dev; else dd->src_fs_id = fi->fs_id; } } } else if(info == FM_DND_DEST_TARGET_URI_LIST) { if((sel_data->length >= 0) && (sel_data->format==8)) { gchar **uris; uris = gtk_selection_data_get_uris( sel_data ); files = fm_path_list_new_from_uris((const char **)uris); g_free(uris); if(files) { GFileInfo* inf; FmPath* path = FM_PATH(fm_list_peek_head(files)); GFile* gf = fm_path_to_gfile(path); const char* attr = fm_path_is_native(path) ? G_FILE_ATTRIBUTE_UNIX_DEVICE : G_FILE_ATTRIBUTE_ID_FILESYSTEM; inf = g_file_query_info(gf, attr, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, NULL); g_object_unref(gf); if(fm_path_is_native(path)) dd->src_dev = g_file_info_get_attribute_uint32(inf, G_FILE_ATTRIBUTE_UNIX_DEVICE); else dd->src_fs_id = g_intern_string(g_file_info_get_attribute_string(inf, G_FILE_ATTRIBUTE_ID_FILESYSTEM)); g_object_unref(inf); } } } else if(info == FM_DND_DEST_TARGET_XDS) /* X direct save */ { if( sel_data->format == 8 && sel_data->length == 1 && sel_data->data[0] == 'F') { gdk_property_change(GDK_DRAWABLE(drag_context->source_window), xds_target_atom, gdk_atom_intern_static_string("text/plain"), 8, GDK_PROP_MODE_REPLACE, (const guchar *)"", 0); } else if(sel_data->format == 8 && sel_data->length == 1 && sel_data->data[0] == 'S') { /* XDS succeeds */ } gtk_drag_finish(drag_context, TRUE, FALSE, time); return TRUE; } else return FALSE; /* remove previously cached source files. */ if(G_UNLIKELY(dd->src_files)) { fm_list_unref(dd->src_files); dd->src_files = NULL; } dd->src_files = files; dd->waiting_data = FALSE; dd->info_type = info; return TRUE; }
gboolean fm_clipboard_paste_files(GtkWidget* dest_widget, FmPath* dest_dir) { GdkDisplay* dpy = dest_widget ? gtk_widget_get_display(dest_widget) : gdk_display_get_default(); GtkClipboard* clip = gtk_clipboard_get_for_display(dpy, GDK_SELECTION_CLIPBOARD); FmPathList* files; char** uris, **uri; GdkAtom atom; int type = 0; GdkAtom *avail_targets; int n, i; /* get all available targets currently in the clipboard. */ if( !gtk_clipboard_wait_for_targets(clip, &avail_targets, &n) ) return FALSE; /* check gnome and xfce compatible format first */ atom = gdk_atom_intern_static_string(targets[GNOME_COPIED_FILES-1].target); for(i = 0; i < n; ++i) { if(avail_targets[i] == atom) { type = GNOME_COPIED_FILES; break; } } if( 0 == type ) /* x-special/gnome-copied-files is not found. */ { /* check uri-list */ atom = gdk_atom_intern_static_string(targets[URI_LIST-1].target); for(i = 0; i < n; ++i) { if(avail_targets[i] == atom) { type = URI_LIST; break; } } if( 0 == type ) /* text/uri-list is not found. */ { /* finally, fallback to UTF-8 string */ atom = gdk_atom_intern_static_string(targets[UTF8_STRING-1].target); for(i = 0; i < n; ++i) { if(avail_targets[i] == atom) { type = UTF8_STRING; break; } } } } g_free(avail_targets); if( type ) { GtkSelectionData* data = gtk_clipboard_wait_for_contents(clip, atom); char* pdata = (char*)data->data; /* FIXME: is it safe to assume the clipboard data is null-terminalted? * According to the source code in gtkselection.c, gtk+ seems to * includes an extra byte at the end of GtkSelectionData::data, so * this should be safe. */ pdata[data->length] = '\0'; /* make sure the data is null-terminated. */ is_cut = FALSE; switch(type) { case GNOME_COPIED_FILES: is_cut = g_str_has_prefix(pdata, "cut\n"); while(*pdata && *pdata != '\n') ++pdata; ++pdata; /* the following parts is actually a uri-list, so don't break here. */ case URI_LIST: uris = g_uri_list_extract_uris(pdata); if( type != GNOME_COPIED_FILES ) { /* if we're not handling x-special/gnome-copied-files, check * if information from KDE is available. */ is_cut = check_kde_curselection(clip); } break; case UTF8_STRING: /* FIXME: how should we treat UTF-8 strings? URIs or filenames? */ uris = g_uri_list_extract_uris(pdata); break; } gtk_selection_data_free(data); if(uris) { files = fm_path_list_new_from_uris((const char **)uris); g_strfreev(uris); if( is_cut ) fm_move_files(files, dest_dir); else fm_copy_files(files, dest_dir); fm_list_unref(files); return TRUE; } } return FALSE; }